1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
38 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_aspath.h"
42 #include "bgpd/bgp_community.h"
43 #include "bgpd/bgp_debug.h"
44 #include "bgpd/bgp_errors.h"
45 #include "bgpd/bgp_label.h"
46 #include "bgpd/bgp_packet.h"
47 #include "bgpd/bgp_ecommunity.h"
48 #include "bgpd/bgp_lcommunity.h"
49 #include "bgpd/bgp_updgrp.h"
50 #include "bgpd/bgp_encap_types.h"
52 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
53 #include "bgp_encap_types.h"
54 #include "bgp_vnc_types.h"
57 #include "bgp_flowspec_private.h"
60 /* Attribute strings for logging. */
61 static const struct message attr_str
[] = {
62 {BGP_ATTR_ORIGIN
, "ORIGIN"},
63 {BGP_ATTR_AS_PATH
, "AS_PATH"},
64 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
65 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
66 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
67 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
68 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
69 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
70 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
71 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
72 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
73 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
74 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
75 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
76 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 {BGP_ATTR_OTC
, "OTC"},
80 #ifdef ENABLE_BGP_VNC_ATTR
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
86 {BGP_ATTR_AIGP
, "AIGP"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
= {};
123 struct cluster_list
*cluster
;
126 tmp
.list
= length
== 0 ? NULL
: pnt
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 if (cluster1
->list
== cluster2
->list
)
158 if (!cluster1
->list
|| !cluster2
->list
)
161 if (cluster1
->length
!= cluster2
->length
)
164 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
167 static void cluster_free(struct cluster_list
*cluster
)
169 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
170 XFREE(MTYPE_CLUSTER
, cluster
);
173 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
175 struct cluster_list
*find
;
177 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
183 static void cluster_unintern(struct cluster_list
**cluster
)
185 if ((*cluster
)->refcnt
)
186 (*cluster
)->refcnt
--;
188 if ((*cluster
)->refcnt
== 0) {
189 void *p
= hash_release(cluster_hash
, *cluster
);
190 assert(p
== *cluster
);
191 cluster_free(*cluster
);
196 static void cluster_init(void)
198 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
202 static void cluster_finish(void)
204 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
205 hash_free(cluster_hash
);
209 static struct hash
*encap_hash
= NULL
;
210 #ifdef ENABLE_BGP_VNC
211 static struct hash
*vnc_hash
= NULL
;
213 static struct hash
*srv6_l3vpn_hash
;
214 static struct hash
*srv6_vpn_hash
;
216 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
218 struct bgp_attr_encap_subtlv
*new;
219 struct bgp_attr_encap_subtlv
*tail
;
220 struct bgp_attr_encap_subtlv
*p
;
222 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
223 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
225 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
228 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 memcpy(tail
, p
, size
);
238 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
249 void bgp_attr_flush_encap(struct attr
*attr
)
254 if (attr
->encap_subtlvs
) {
255 encap_free(attr
->encap_subtlvs
);
256 attr
->encap_subtlvs
= NULL
;
258 #ifdef ENABLE_BGP_VNC
259 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
260 bgp_attr_get_vnc_subtlvs(attr
);
263 encap_free(vnc_subtlvs
);
264 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
270 * Compare encap sub-tlv chains
275 * This algorithm could be made faster if needed
277 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
278 const struct bgp_attr_encap_subtlv
*h2
)
280 const struct bgp_attr_encap_subtlv
*p
;
281 const struct bgp_attr_encap_subtlv
*q
;
285 if (h1
== NULL
|| h2
== NULL
)
288 for (p
= h1
; p
; p
= p
->next
) {
289 for (q
= h2
; q
; q
= q
->next
) {
290 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
291 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 for (p
= h2
; p
; p
= p
->next
) {
301 for (q
= h1
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
303 && !memcmp(p
->value
, q
->value
, p
->length
)) {
315 static void *encap_hash_alloc(void *p
)
317 /* Encap structure is already allocated. */
323 #ifdef ENABLE_BGP_VNC
328 static struct bgp_attr_encap_subtlv
*
329 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
331 struct bgp_attr_encap_subtlv
*find
;
332 struct hash
*hash
= encap_hash
;
333 #ifdef ENABLE_BGP_VNC
334 if (type
== VNC_SUBTLV_TYPE
)
338 find
= hash_get(hash
, encap
, encap_hash_alloc
);
346 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
347 encap_subtlv_type type
)
349 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
353 if (encap
->refcnt
== 0) {
354 struct hash
*hash
= encap_hash
;
355 #ifdef ENABLE_BGP_VNC
356 if (type
== VNC_SUBTLV_TYPE
)
359 hash_release(hash
, encap
);
365 static unsigned int encap_hash_key_make(const void *p
)
367 const struct bgp_attr_encap_subtlv
*encap
= p
;
369 return jhash(encap
->value
, encap
->length
, 0);
372 static bool encap_hash_cmp(const void *p1
, const void *p2
)
374 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
375 (const struct bgp_attr_encap_subtlv
*)p2
);
378 static void encap_init(void)
380 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
382 #ifdef ENABLE_BGP_VNC
383 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
388 static void encap_finish(void)
390 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
391 hash_free(encap_hash
);
393 #ifdef ENABLE_BGP_VNC
394 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
400 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
409 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
410 bgp_attr_get_evpn_overlay(a2
));
413 /* Unknown transit attribute. */
414 static struct hash
*transit_hash
;
416 static void transit_free(struct transit
*transit
)
418 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
419 XFREE(MTYPE_TRANSIT
, transit
);
422 static void *transit_hash_alloc(void *p
)
424 /* Transit structure is already allocated. */
428 static struct transit
*transit_intern(struct transit
*transit
)
430 struct transit
*find
;
432 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
434 transit_free(transit
);
440 static void transit_unintern(struct transit
**transit
)
442 if ((*transit
)->refcnt
)
443 (*transit
)->refcnt
--;
445 if ((*transit
)->refcnt
== 0) {
446 hash_release(transit_hash
, *transit
);
447 transit_free(*transit
);
452 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
461 ptr_get_be16(data
+ 1, &tlv_length
);
464 /* The value field of the AIGP TLV is always 8 octets
465 * long and its value is interpreted as an unsigned 64-bit
468 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
469 (void)ptr_get_be64(data
+ 3, aigp
);
471 /* If an AIGP attribute is received and its first AIGP
472 * TLV contains the maximum value 0xffffffffffffffff,
473 * the attribute SHOULD be considered to be malformed
474 * and SHOULD be discarded as specified in this section.
476 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
477 zlog_err("Bad AIGP TLV (%s) length: %llu",
478 BGP_AIGP_TLV_METRIC_DESC
,
479 BGP_AIGP_TLV_METRIC_MAX
);
487 length
-= tlv_length
;
493 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
495 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
498 return aigp
+ bpi
->nexthop
->metric
;
503 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
504 struct bgp_path_info
*bpi
)
506 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
507 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
508 stream_putq(s
, bgp_aigp_metric_total(bpi
));
511 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
518 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
525 ptr_get_be16(data
+ 1, &tlv_length
);
528 if (length
< tlv_length
) {
530 "Bad AIGP attribute length: %u, but TLV length: %u",
535 if (tlv_length
< 3) {
536 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
541 /* AIGP TLV, Length: 11 */
542 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
543 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
544 zlog_err("Bad AIGP TLV (%s) length: %u",
545 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
550 length
-= tlv_length
;
556 static void *srv6_l3vpn_hash_alloc(void *p
)
561 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
563 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
566 static struct bgp_attr_srv6_l3vpn
*
567 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
569 struct bgp_attr_srv6_l3vpn
*find
;
571 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
573 srv6_l3vpn_free(l3vpn
);
578 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
580 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
585 if (l3vpn
->refcnt
== 0) {
586 hash_release(srv6_l3vpn_hash
, l3vpn
);
587 srv6_l3vpn_free(l3vpn
);
592 static void *srv6_vpn_hash_alloc(void *p
)
597 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
599 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
602 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
604 struct bgp_attr_srv6_vpn
*find
;
606 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
613 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
615 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
620 if (vpn
->refcnt
== 0) {
621 hash_release(srv6_vpn_hash
, vpn
);
627 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
629 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
632 key
= jhash(&l3vpn
->sid
, 16, key
);
633 key
= jhash_1word(l3vpn
->sid_flags
, key
);
634 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
635 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
636 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
637 key
= jhash_1word(l3vpn
->func_len
, key
);
638 key
= jhash_1word(l3vpn
->arg_len
, key
);
639 key
= jhash_1word(l3vpn
->transposition_len
, key
);
640 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
644 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
646 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
647 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
649 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
650 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
651 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
652 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
653 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
654 && l3vpn1
->func_len
== l3vpn2
->func_len
655 && l3vpn1
->arg_len
== l3vpn2
->arg_len
656 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
657 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
660 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
661 const struct bgp_attr_srv6_l3vpn
*h2
)
665 else if (h1
== NULL
|| h2
== NULL
)
668 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
671 static unsigned int srv6_vpn_hash_key_make(const void *p
)
673 const struct bgp_attr_srv6_vpn
*vpn
= p
;
676 key
= jhash(&vpn
->sid
, 16, key
);
677 key
= jhash_1word(vpn
->sid_flags
, key
);
681 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
683 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
684 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
686 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
687 && vpn1
->sid_flags
== vpn2
->sid_flags
;
690 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
691 const struct bgp_attr_srv6_vpn
*h2
)
695 else if (h1
== NULL
|| h2
== NULL
)
698 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
701 static void srv6_init(void)
704 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
705 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
706 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
707 "BGP Prefix-SID SRv6-VPN-Service-TLV");
710 static void srv6_finish(void)
712 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
713 hash_free(srv6_l3vpn_hash
);
714 srv6_l3vpn_hash
= NULL
;
715 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
716 hash_free(srv6_vpn_hash
);
717 srv6_vpn_hash
= NULL
;
720 static unsigned int transit_hash_key_make(const void *p
)
722 const struct transit
*transit
= p
;
724 return jhash(transit
->val
, transit
->length
, 0);
727 static bool transit_hash_cmp(const void *p1
, const void *p2
)
729 const struct transit
*transit1
= p1
;
730 const struct transit
*transit2
= p2
;
732 return (transit1
->length
== transit2
->length
733 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
736 static void transit_init(void)
738 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
742 static void transit_finish(void)
744 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
745 hash_free(transit_hash
);
749 /* Attribute hash routines. */
750 static struct hash
*attrhash
;
752 unsigned long int attr_count(void)
754 return attrhash
->count
;
757 unsigned long int attr_unknown_count(void)
759 return transit_hash
->count
;
762 unsigned int attrhash_key_make(const void *p
)
764 const struct attr
*attr
= (struct attr
*)p
;
766 #define MIX(val) key = jhash_1word(val, key)
767 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
769 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
770 MIX3(attr
->local_pref
, attr
->aggregator_as
,
771 attr
->aggregator_addr
.s_addr
);
772 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
773 attr
->originator_id
.s_addr
);
774 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
777 MIX(aspath_key_make(attr
->aspath
));
778 if (bgp_attr_get_community(attr
))
779 MIX(community_hash_make(bgp_attr_get_community(attr
)));
780 if (bgp_attr_get_lcommunity(attr
))
781 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
782 if (bgp_attr_get_ecommunity(attr
))
783 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
784 if (bgp_attr_get_ipv6_ecommunity(attr
))
785 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
786 if (bgp_attr_get_cluster(attr
))
787 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
788 if (bgp_attr_get_transit(attr
))
789 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
790 if (attr
->encap_subtlvs
)
791 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
792 if (attr
->srv6_l3vpn
)
793 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
795 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
796 #ifdef ENABLE_BGP_VNC
797 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
798 bgp_attr_get_vnc_subtlvs(attr
);
800 MIX(encap_hash_key_make(vnc_subtlvs
));
802 MIX(attr
->mp_nexthop_len
);
803 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
804 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
805 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
806 MIX(attr
->rmap_table_id
);
810 MIX(bgp_attr_get_aigp_metric(attr
));
815 bool attrhash_cmp(const void *p1
, const void *p2
)
817 const struct attr
*attr1
= p1
;
818 const struct attr
*attr2
= p2
;
820 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
821 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
822 && attr1
->aspath
== attr2
->aspath
823 && bgp_attr_get_community(attr1
)
824 == bgp_attr_get_community(attr2
)
825 && attr1
->med
== attr2
->med
826 && attr1
->local_pref
== attr2
->local_pref
827 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
828 if (attr1
->aggregator_as
== attr2
->aggregator_as
829 && attr1
->aggregator_addr
.s_addr
830 == attr2
->aggregator_addr
.s_addr
831 && attr1
->weight
== attr2
->weight
832 && attr1
->tag
== attr2
->tag
833 && attr1
->label_index
== attr2
->label_index
834 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
835 && bgp_attr_get_ecommunity(attr1
)
836 == bgp_attr_get_ecommunity(attr2
)
837 && bgp_attr_get_ipv6_ecommunity(attr1
)
838 == bgp_attr_get_ipv6_ecommunity(attr2
)
839 && bgp_attr_get_lcommunity(attr1
)
840 == bgp_attr_get_lcommunity(attr2
)
841 && bgp_attr_get_cluster(attr1
)
842 == bgp_attr_get_cluster(attr2
)
843 && bgp_attr_get_transit(attr1
)
844 == bgp_attr_get_transit(attr2
)
845 && bgp_attr_get_aigp_metric(attr1
)
846 == bgp_attr_get_aigp_metric(attr2
)
847 && attr1
->rmap_table_id
== attr2
->rmap_table_id
848 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
849 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
850 #ifdef ENABLE_BGP_VNC
851 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
852 bgp_attr_get_vnc_subtlvs(attr2
))
854 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
855 &attr2
->mp_nexthop_global
)
856 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
857 &attr2
->mp_nexthop_local
)
858 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
859 &attr2
->mp_nexthop_global_in
)
860 && IPV4_ADDR_SAME(&attr1
->originator_id
,
861 &attr2
->originator_id
)
862 && overlay_index_same(attr1
, attr2
)
863 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
864 && attr1
->es_flags
== attr2
->es_flags
865 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
866 && attr1
->df_pref
== attr2
->df_pref
867 && attr1
->df_alg
== attr2
->df_alg
868 && attr1
->nh_ifindex
== attr2
->nh_ifindex
869 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
870 && attr1
->distance
== attr2
->distance
871 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
872 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
873 && attr1
->srte_color
== attr2
->srte_color
874 && attr1
->nh_type
== attr2
->nh_type
875 && attr1
->bh_type
== attr2
->bh_type
876 && attr1
->otc
== attr2
->otc
)
883 static void attrhash_init(void)
886 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
890 * special for hash_clean below
892 static void attr_vfree(void *attr
)
894 XFREE(MTYPE_ATTR
, attr
);
897 static void attrhash_finish(void)
899 hash_clean(attrhash
, attr_vfree
);
904 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
906 struct attr
*attr
= bucket
->data
;
907 struct in6_addr
*sid
= NULL
;
909 if (attr
->srv6_l3vpn
)
910 sid
= &attr
->srv6_l3vpn
->sid
;
911 else if (attr
->srv6_vpn
)
912 sid
= &attr
->srv6_vpn
->sid
;
914 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
918 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
919 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
920 attr
->origin
, attr
->weight
, attr
->label
, sid
);
923 void attr_show_all(struct vty
*vty
)
925 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
926 void *))attr_show_all_iterator
,
930 static void *bgp_attr_hash_alloc(void *p
)
932 struct attr
*val
= (struct attr
*)p
;
935 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
937 if (val
->encap_subtlvs
) {
938 val
->encap_subtlvs
= NULL
;
940 #ifdef ENABLE_BGP_VNC
941 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
942 bgp_attr_get_vnc_subtlvs(val
);
945 bgp_attr_set_vnc_subtlvs(val
, NULL
);
952 /* Internet argument attribute. */
953 struct attr
*bgp_attr_intern(struct attr
*attr
)
956 struct ecommunity
*ecomm
= NULL
;
957 struct ecommunity
*ipv6_ecomm
= NULL
;
958 struct lcommunity
*lcomm
= NULL
;
959 struct community
*comm
= NULL
;
961 /* Intern referenced structure. */
963 if (!attr
->aspath
->refcnt
)
964 attr
->aspath
= aspath_intern(attr
->aspath
);
966 attr
->aspath
->refcnt
++;
969 comm
= bgp_attr_get_community(attr
);
972 bgp_attr_set_community(attr
, community_intern(comm
));
977 ecomm
= bgp_attr_get_ecommunity(attr
);
980 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
985 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
987 if (!ipv6_ecomm
->refcnt
)
988 bgp_attr_set_ipv6_ecommunity(
989 attr
, ecommunity_intern(ipv6_ecomm
));
991 ipv6_ecomm
->refcnt
++;
994 lcomm
= bgp_attr_get_lcommunity(attr
);
997 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
1002 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1005 if (!cluster
->refcnt
)
1006 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1011 struct transit
*transit
= bgp_attr_get_transit(attr
);
1014 if (!transit
->refcnt
)
1015 bgp_attr_set_transit(attr
, transit_intern(transit
));
1019 if (attr
->encap_subtlvs
) {
1020 if (!attr
->encap_subtlvs
->refcnt
)
1021 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1024 attr
->encap_subtlvs
->refcnt
++;
1026 if (attr
->srv6_l3vpn
) {
1027 if (!attr
->srv6_l3vpn
->refcnt
)
1028 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1030 attr
->srv6_l3vpn
->refcnt
++;
1032 if (attr
->srv6_vpn
) {
1033 if (!attr
->srv6_vpn
->refcnt
)
1034 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1036 attr
->srv6_vpn
->refcnt
++;
1038 #ifdef ENABLE_BGP_VNC
1039 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1040 bgp_attr_get_vnc_subtlvs(attr
);
1043 if (!vnc_subtlvs
->refcnt
)
1044 bgp_attr_set_vnc_subtlvs(
1046 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1048 vnc_subtlvs
->refcnt
++;
1052 /* At this point, attr only contains intern'd pointers. that means
1053 * if we find it in attrhash, it has all the same pointers and we
1054 * correctly updated the refcounts on these.
1055 * If we don't find it, we need to allocate a one because in all
1056 * cases this returns a new reference to a hashed attr, but the input
1057 * wasn't on hash. */
1058 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1064 /* Make network statement's attribute. */
1065 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1068 memset(attr
, 0, sizeof(struct attr
));
1070 attr
->origin
= origin
;
1071 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1072 attr
->aspath
= aspath_empty(bgp
->asnotation
);
1073 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1074 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1076 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1077 attr
->label
= MPLS_INVALID_LABEL
;
1078 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1079 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1080 attr
->local_pref
= bgp
->default_local_pref
;
1085 /* Create the attributes for an aggregate */
1086 struct attr
*bgp_attr_aggregate_intern(
1087 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1088 struct community
*community
, struct ecommunity
*ecommunity
,
1089 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1090 uint8_t atomic_aggregate
, const struct prefix
*p
)
1094 route_map_result_t ret
;
1096 memset(&attr
, 0, sizeof(attr
));
1098 /* Origin attribute. */
1099 attr
.origin
= origin
;
1100 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1104 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1106 /* AS path attribute. */
1108 attr
.aspath
= aspath_intern(aspath
);
1110 attr
.aspath
= aspath_empty(bgp
->asnotation
);
1111 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1113 /* Next hop attribute. */
1114 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1117 uint32_t gshut
= COMMUNITY_GSHUT
;
1119 /* If we are not shutting down ourselves and we are
1120 * aggregating a route that contains the GSHUT community we
1121 * need to remove that community when creating the aggregate */
1122 if (!bgp_in_graceful_shutdown(bgp
)
1123 && community_include(community
, gshut
)) {
1124 community_del_val(community
, &gshut
);
1127 bgp_attr_set_community(&attr
, community
);
1131 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1134 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1136 if (bgp_in_graceful_shutdown(bgp
))
1137 bgp_attr_add_gshut_community(&attr
);
1139 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1140 attr
.label
= MPLS_INVALID_LABEL
;
1141 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1142 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1143 if (!aggregate
->as_set
|| atomic_aggregate
)
1144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1146 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1147 attr
.aggregator_as
= bgp
->confed_id
;
1149 attr
.aggregator_as
= bgp
->as
;
1150 attr
.aggregator_addr
= bgp
->router_id
;
1152 /* Apply route-map */
1153 if (aggregate
->rmap
.name
) {
1154 struct attr attr_tmp
= attr
;
1155 struct bgp_path_info rmap_path
;
1157 memset(&rmap_path
, 0, sizeof(rmap_path
));
1158 rmap_path
.peer
= bgp
->peer_self
;
1159 rmap_path
.attr
= &attr_tmp
;
1161 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1163 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1165 bgp
->peer_self
->rmap_type
= 0;
1167 if (ret
== RMAP_DENYMATCH
) {
1168 /* Free uninterned attribute. */
1169 bgp_attr_flush(&attr_tmp
);
1171 /* Unintern original. */
1172 aspath_unintern(&attr
.aspath
);
1176 if (bgp_in_graceful_shutdown(bgp
))
1177 bgp_attr_add_gshut_community(&attr_tmp
);
1179 new = bgp_attr_intern(&attr_tmp
);
1182 if (bgp_in_graceful_shutdown(bgp
))
1183 bgp_attr_add_gshut_community(&attr
);
1185 new = bgp_attr_intern(&attr
);
1188 /* Always release the 'intern()'ed AS Path. */
1189 aspath_unintern(&attr
.aspath
);
1194 /* Unintern just the sub-components of the attr, but not the attr */
1195 void bgp_attr_unintern_sub(struct attr
*attr
)
1197 struct ecommunity
*ecomm
= NULL
;
1198 struct ecommunity
*ipv6_ecomm
= NULL
;
1199 struct cluster_list
*cluster
;
1200 struct lcommunity
*lcomm
= NULL
;
1201 struct community
*comm
= NULL
;
1203 /* aspath refcount shoud be decrement. */
1204 aspath_unintern(&attr
->aspath
);
1205 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1207 comm
= bgp_attr_get_community(attr
);
1208 community_unintern(&comm
);
1209 bgp_attr_set_community(attr
, NULL
);
1211 ecomm
= bgp_attr_get_ecommunity(attr
);
1212 ecommunity_unintern(&ecomm
);
1213 bgp_attr_set_ecommunity(attr
, NULL
);
1215 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1216 ecommunity_unintern(&ipv6_ecomm
);
1217 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1219 lcomm
= bgp_attr_get_lcommunity(attr
);
1220 lcommunity_unintern(&lcomm
);
1221 bgp_attr_set_lcommunity(attr
, NULL
);
1223 cluster
= bgp_attr_get_cluster(attr
);
1225 cluster_unintern(&cluster
);
1226 bgp_attr_set_cluster(attr
, cluster
);
1228 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1230 struct transit
*transit
= bgp_attr_get_transit(attr
);
1233 transit_unintern(&transit
);
1234 bgp_attr_set_transit(attr
, transit
);
1237 if (attr
->encap_subtlvs
)
1238 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1240 #ifdef ENABLE_BGP_VNC
1241 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1242 bgp_attr_get_vnc_subtlvs(attr
);
1245 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1246 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1250 if (attr
->srv6_l3vpn
)
1251 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1254 srv6_vpn_unintern(&attr
->srv6_vpn
);
1257 /* Free bgp attribute and aspath. */
1258 void bgp_attr_unintern(struct attr
**pattr
)
1260 struct attr
*attr
= *pattr
;
1264 /* Decrement attribute reference. */
1269 /* If reference becomes zero then free attribute object. */
1270 if (attr
->refcnt
== 0) {
1271 ret
= hash_release(attrhash
, attr
);
1272 assert(ret
!= NULL
);
1273 XFREE(MTYPE_ATTR
, attr
);
1277 bgp_attr_unintern_sub(&tmp
);
1280 void bgp_attr_flush(struct attr
*attr
)
1282 struct ecommunity
*ecomm
;
1283 struct ecommunity
*ipv6_ecomm
;
1284 struct cluster_list
*cluster
;
1285 struct lcommunity
*lcomm
;
1286 struct community
*comm
;
1288 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1289 aspath_free(attr
->aspath
);
1290 attr
->aspath
= NULL
;
1292 comm
= bgp_attr_get_community(attr
);
1293 if (comm
&& !comm
->refcnt
)
1294 community_free(&comm
);
1295 bgp_attr_set_community(attr
, NULL
);
1297 ecomm
= bgp_attr_get_ecommunity(attr
);
1298 if (ecomm
&& !ecomm
->refcnt
)
1299 ecommunity_free(&ecomm
);
1300 bgp_attr_set_ecommunity(attr
, NULL
);
1302 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1303 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1304 ecommunity_free(&ipv6_ecomm
);
1305 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1307 lcomm
= bgp_attr_get_lcommunity(attr
);
1308 if (lcomm
&& !lcomm
->refcnt
)
1309 lcommunity_free(&lcomm
);
1310 bgp_attr_set_lcommunity(attr
, NULL
);
1312 cluster
= bgp_attr_get_cluster(attr
);
1313 if (cluster
&& !cluster
->refcnt
) {
1314 cluster_free(cluster
);
1315 bgp_attr_set_cluster(attr
, NULL
);
1318 struct transit
*transit
= bgp_attr_get_transit(attr
);
1320 if (transit
&& !transit
->refcnt
) {
1321 transit_free(transit
);
1322 bgp_attr_set_transit(attr
, NULL
);
1324 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1325 encap_free(attr
->encap_subtlvs
);
1326 attr
->encap_subtlvs
= NULL
;
1328 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1329 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1330 attr
->srv6_l3vpn
= NULL
;
1332 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1333 srv6_vpn_free(attr
->srv6_vpn
);
1334 attr
->srv6_vpn
= NULL
;
1336 #ifdef ENABLE_BGP_VNC
1337 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1338 bgp_attr_get_vnc_subtlvs(attr
);
1340 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1341 encap_free(vnc_subtlvs
);
1342 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1347 /* Implement draft-scudder-idr-optional-transitive behaviour and
1348 * avoid resetting sessions for malformed attributes which are
1349 * are partial/optional and hence where the error likely was not
1350 * introduced by the sending neighbour.
1352 static enum bgp_attr_parse_ret
1353 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1356 struct peer
*const peer
= args
->peer
;
1357 struct attr
*const attr
= args
->attr
;
1358 const uint8_t flags
= args
->flags
;
1359 /* startp and length must be special-cased, as whether or not to
1360 * send the attribute data with the NOTIFY depends on the error,
1361 * the caller therefore signals this with the seperate length argument
1363 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1365 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1366 char attr_str
[BUFSIZ
] = {0};
1368 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1370 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1373 /* Only relax error handling for eBGP peers */
1374 if (peer
->sort
!= BGP_PEER_EBGP
) {
1375 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1376 notify_datap
, length
);
1377 return BGP_ATTR_PARSE_ERROR
;
1380 /* Adjust the stream getp to the end of the attribute, in case we can
1381 * still proceed but the caller hasn't read all the attribute.
1383 stream_set_getp(BGP_INPUT(peer
),
1384 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1387 switch (args
->type
) {
1388 /* where an attribute is relatively inconsequential, e.g. it does not
1389 * affect route selection, and can be safely ignored, then any such
1390 * attributes which are malformed should just be ignored and the route
1391 * processed as normal.
1393 case BGP_ATTR_AS4_AGGREGATOR
:
1394 case BGP_ATTR_AGGREGATOR
:
1395 case BGP_ATTR_ATOMIC_AGGREGATE
:
1396 return BGP_ATTR_PARSE_PROCEED
;
1398 /* Core attributes, particularly ones which may influence route
1399 * selection, should be treat-as-withdraw.
1401 case BGP_ATTR_ORIGIN
:
1402 case BGP_ATTR_AS_PATH
:
1403 case BGP_ATTR_NEXT_HOP
:
1404 case BGP_ATTR_MULTI_EXIT_DISC
:
1405 case BGP_ATTR_LOCAL_PREF
:
1406 case BGP_ATTR_COMMUNITIES
:
1407 case BGP_ATTR_EXT_COMMUNITIES
:
1408 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1409 case BGP_ATTR_LARGE_COMMUNITIES
:
1410 case BGP_ATTR_ORIGINATOR_ID
:
1411 case BGP_ATTR_CLUSTER_LIST
:
1413 return BGP_ATTR_PARSE_WITHDRAW
;
1414 case BGP_ATTR_MP_REACH_NLRI
:
1415 case BGP_ATTR_MP_UNREACH_NLRI
:
1416 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1417 notify_datap
, length
);
1418 return BGP_ATTR_PARSE_ERROR
;
1421 /* Partial optional attributes that are malformed should not cause
1422 * the whole session to be reset. Instead treat it as a withdrawal
1423 * of the routes, if possible.
1425 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1426 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1427 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1428 return BGP_ATTR_PARSE_WITHDRAW
;
1430 /* default to reset */
1431 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1434 /* Find out what is wrong with the path attribute flag bits and log the error.
1435 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1436 Extended Length. Checking O/T/P bits at once implies, that the attribute
1437 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1438 non-transitive" attribute. */
1440 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1441 uint8_t desired_flags
/* how RFC says it must be */
1444 uint8_t seen
= 0, i
;
1445 uint8_t real_flags
= args
->flags
;
1446 const uint8_t attr_code
= args
->type
;
1448 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1449 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1450 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1451 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1452 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1453 flog_err(EC_BGP_ATTR_FLAG
,
1454 "%s attribute must%s be flagged as \"%s\"",
1455 lookup_msg(attr_str
, attr_code
, NULL
),
1456 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1459 attr_flag_str
[i
].str
);
1464 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1465 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1466 real_flags
, desired_flags
);
1470 /* Required flags for attributes. EXTLEN will be masked off when testing,
1471 * as will PARTIAL for optional+transitive attributes.
1473 const uint8_t attr_flags_values
[] = {
1474 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1475 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1478 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1479 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1481 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1483 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1484 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1485 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1486 [BGP_ATTR_EXT_COMMUNITIES
] =
1487 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1488 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1489 [BGP_ATTR_AS4_AGGREGATOR
] =
1490 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1491 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_LARGE_COMMUNITIES
] =
1493 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1494 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1495 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1497 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1498 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1500 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1502 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1504 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1505 const uint8_t flags
= args
->flags
;
1506 const uint8_t attr_code
= args
->type
;
1508 /* there may be attributes we don't know about */
1509 if (attr_code
> attr_flags_values_max
)
1511 if (attr_flags_values
[attr_code
] == 0)
1514 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1518 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1519 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1522 "%s well-known attributes must have transitive flag set (%x)",
1523 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1527 /* "For well-known attributes and for optional non-transitive
1529 * the Partial bit MUST be set to 0."
1531 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1532 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1533 flog_err(EC_BGP_ATTR_FLAG
,
1534 "%s well-known attribute must NOT have the partial flag set (%x)",
1535 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1538 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1539 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1540 flog_err(EC_BGP_ATTR_FLAG
,
1541 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1542 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1547 /* Optional transitive attributes may go through speakers that don't
1548 * reocgnise them and set the Partial bit.
1550 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1551 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1552 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1554 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1557 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1561 /* Get origin attribute of the update message. */
1562 static enum bgp_attr_parse_ret
1563 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1565 struct peer
*const peer
= args
->peer
;
1566 struct attr
*const attr
= args
->attr
;
1567 const bgp_size_t length
= args
->length
;
1569 /* If any recognized attribute has Attribute Length that conflicts
1570 with the expected length (based on the attribute type code), then
1571 the Error Subcode is set to Attribute Length Error. The Data
1572 field contains the erroneous attribute (type, length and
1575 flog_err(EC_BGP_ATTR_LEN
,
1576 "Origin attribute length is not one %d", length
);
1577 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1581 /* Fetch origin attribute. */
1582 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1584 /* If the ORIGIN attribute has an undefined value, then the Error
1585 Subcode is set to Invalid Origin Attribute. The Data field
1586 contains the unrecognized attribute (type, length and value). */
1587 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1588 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1589 flog_err(EC_BGP_ATTR_ORIGIN
,
1590 "Origin attribute value is invalid %d", attr
->origin
);
1591 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1595 /* Set oring attribute flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1601 /* Parse AS path information. This function is wrapper of
1603 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1605 struct attr
*const attr
= args
->attr
;
1606 struct peer
*const peer
= args
->peer
;
1607 const bgp_size_t length
= args
->length
;
1608 enum asnotation_mode asnotation
;
1610 asnotation
= bgp_get_asnotation(
1611 args
->peer
&& args
->peer
->bgp
? args
->peer
->bgp
: NULL
);
1613 * peer with AS4 => will get 4Byte ASnums
1614 * otherwise, will get 16 Bit
1617 aspath_parse(peer
->curr
, length
,
1618 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
) &&
1619 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
),
1622 /* In case of IBGP, length will be zero. */
1623 if (!attr
->aspath
) {
1624 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1625 "Malformed AS path from %s, length is %d", peer
->host
,
1627 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1631 /* Conformant BGP speakers SHOULD NOT send BGP
1632 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1633 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1634 * withdraw" error handling behavior as per [RFC7606].
1636 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1637 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1638 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1640 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1644 /* Set aspath attribute flag. */
1645 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1647 return BGP_ATTR_PARSE_PROCEED
;
1650 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1651 struct attr
*const attr
)
1653 /* These checks were part of bgp_attr_aspath, but with
1654 * as4 we should to check aspath things when
1655 * aspath synthesizing with as4_path has already taken place.
1656 * Otherwise we check ASPATH and use the synthesized thing, and that is
1658 * So do the checks later, i.e. here
1660 struct aspath
*aspath
;
1662 /* Confederation sanity check. */
1663 if ((peer
->sort
== BGP_PEER_CONFED
1664 && !aspath_left_confed_check(attr
->aspath
))
1665 || (peer
->sort
== BGP_PEER_EBGP
1666 && aspath_confed_check(attr
->aspath
))) {
1667 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1669 return BGP_ATTR_PARSE_WITHDRAW
;
1672 /* First AS check for EBGP. */
1673 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1674 if (peer
->sort
== BGP_PEER_EBGP
1675 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1676 flog_err(EC_BGP_ATTR_FIRST_AS
,
1677 "%s incorrect first AS (must be %u)",
1678 peer
->host
, peer
->as
);
1679 return BGP_ATTR_PARSE_WITHDRAW
;
1683 /* Codification of AS 0 Processing */
1684 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1686 EC_BGP_ATTR_MAL_AS_PATH
,
1687 "Malformed AS path, AS number is 0 in the path from %s",
1689 return BGP_ATTR_PARSE_WITHDRAW
;
1692 /* local-as prepend */
1693 if (peer
->change_local_as
1694 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1695 aspath
= aspath_dup(attr
->aspath
);
1696 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1697 aspath_unintern(&attr
->aspath
);
1698 attr
->aspath
= aspath_intern(aspath
);
1701 return BGP_ATTR_PARSE_PROCEED
;
1704 /* Parse AS4 path information. This function is another wrapper of
1706 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1707 struct aspath
**as4_path
)
1709 struct peer
*const peer
= args
->peer
;
1710 struct attr
*const attr
= args
->attr
;
1711 const bgp_size_t length
= args
->length
;
1712 enum asnotation_mode asnotation
;
1714 asnotation
= bgp_get_asnotation(peer
->bgp
);
1716 *as4_path
= aspath_parse(peer
->curr
, length
, 1, asnotation
);
1718 /* In case of IBGP, length will be zero. */
1720 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1721 "Malformed AS4 path from %s, length is %d", peer
->host
,
1723 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1727 /* Conformant BGP speakers SHOULD NOT send BGP
1728 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1729 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1730 * withdraw" error handling behavior as per [RFC7606].
1732 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1733 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1734 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1736 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1740 /* Set aspath attribute flag. */
1741 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1743 return BGP_ATTR_PARSE_PROCEED
;
1747 * Check that the nexthop attribute is valid.
1749 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1752 struct bgp
*bgp
= peer
->bgp
;
1754 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1755 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1757 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1759 data
[0] = BGP_ATTR_FLAG_TRANS
;
1760 data
[1] = BGP_ATTR_NEXT_HOP
;
1761 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1762 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1763 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1764 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1766 return BGP_ATTR_PARSE_ERROR
;
1769 return BGP_ATTR_PARSE_PROCEED
;
1772 /* Nexthop attribute. */
1773 static enum bgp_attr_parse_ret
1774 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1776 struct peer
*const peer
= args
->peer
;
1777 struct attr
*const attr
= args
->attr
;
1778 const bgp_size_t length
= args
->length
;
1780 /* Check nexthop attribute length. */
1782 flog_err(EC_BGP_ATTR_LEN
,
1783 "Nexthop attribute length isn't four [%d]", length
);
1785 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1789 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1790 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1792 return BGP_ATTR_PARSE_PROCEED
;
1795 /* MED atrribute. */
1796 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1798 struct peer
*const peer
= args
->peer
;
1799 struct attr
*const attr
= args
->attr
;
1800 const bgp_size_t length
= args
->length
;
1804 flog_err(EC_BGP_ATTR_LEN
,
1805 "MED attribute length isn't four [%d]", length
);
1807 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1811 attr
->med
= stream_getl(peer
->curr
);
1813 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1815 return BGP_ATTR_PARSE_PROCEED
;
1818 /* Local preference attribute. */
1819 static enum bgp_attr_parse_ret
1820 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1822 struct peer
*const peer
= args
->peer
;
1823 struct attr
*const attr
= args
->attr
;
1824 const bgp_size_t length
= args
->length
;
1826 /* if received from an internal neighbor, it SHALL be considered
1827 * malformed if its length is not equal to 4. If malformed, the
1828 * UPDATE message SHALL be handled using the approach of "treat-as-
1831 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1832 flog_err(EC_BGP_ATTR_LEN
,
1833 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1834 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1838 /* If it is contained in an UPDATE message that is received from an
1839 external peer, then this attribute MUST be ignored by the
1840 receiving speaker. */
1841 if (peer
->sort
== BGP_PEER_EBGP
) {
1842 STREAM_FORWARD_GETP(peer
->curr
, length
);
1843 return BGP_ATTR_PARSE_PROCEED
;
1846 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1848 /* Set the local-pref flag. */
1849 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1851 return BGP_ATTR_PARSE_PROCEED
;
1854 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1858 /* Atomic aggregate. */
1859 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1861 struct peer
*const peer
= args
->peer
;
1862 struct attr
*const attr
= args
->attr
;
1863 const bgp_size_t length
= args
->length
;
1867 flog_err(EC_BGP_ATTR_LEN
,
1868 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1870 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1874 if (peer
->discard_attrs
[args
->type
])
1877 /* Set atomic aggregate flag. */
1878 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1880 return BGP_ATTR_PARSE_PROCEED
;
1883 stream_forward_getp(peer
->curr
, length
);
1885 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1886 zlog_debug("%pBP: Ignoring attribute %s", peer
,
1887 lookup_msg(attr_str
, args
->type
, NULL
));
1889 return BGP_ATTR_PARSE_PROCEED
;
1892 /* Aggregator attribute */
1893 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1895 struct peer
*const peer
= args
->peer
;
1896 struct attr
*const attr
= args
->attr
;
1897 const bgp_size_t length
= args
->length
;
1902 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1903 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1904 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1907 if (length
!= wantedlen
) {
1908 flog_err(EC_BGP_ATTR_LEN
,
1909 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1911 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1915 if (peer
->discard_attrs
[args
->type
])
1916 goto aggregator_ignore
;
1918 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1919 aggregator_as
= stream_getl(peer
->curr
);
1921 aggregator_as
= stream_getw(peer
->curr
);
1923 attr
->aggregator_as
= aggregator_as
;
1924 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1926 /* Codification of AS 0 Processing */
1927 if (aggregator_as
== BGP_AS_ZERO
) {
1928 flog_err(EC_BGP_ATTR_LEN
,
1929 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1930 peer
->host
, aspath_print(attr
->aspath
));
1932 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1933 char attr_str
[BUFSIZ
] = {0};
1935 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1937 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1940 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1943 return BGP_ATTR_PARSE_PROCEED
;
1946 stream_forward_getp(peer
->curr
, length
);
1948 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1949 zlog_debug("%pBP: Ignoring attribute %s", peer
,
1950 lookup_msg(attr_str
, args
->type
, NULL
));
1952 return BGP_ATTR_PARSE_PROCEED
;
1955 /* New Aggregator attribute */
1956 static enum bgp_attr_parse_ret
1957 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1958 as_t
*as4_aggregator_as
,
1959 struct in_addr
*as4_aggregator_addr
)
1961 struct peer
*const peer
= args
->peer
;
1962 struct attr
*const attr
= args
->attr
;
1963 const bgp_size_t length
= args
->length
;
1967 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1969 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1973 if (peer
->discard_attrs
[args
->type
])
1974 goto as4_aggregator_ignore
;
1976 aggregator_as
= stream_getl(peer
->curr
);
1978 *as4_aggregator_as
= aggregator_as
;
1979 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1981 /* Codification of AS 0 Processing */
1982 if (aggregator_as
== BGP_AS_ZERO
) {
1983 flog_err(EC_BGP_ATTR_LEN
,
1984 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1985 peer
->host
, aspath_print(attr
->aspath
));
1987 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1988 char attr_str
[BUFSIZ
] = {0};
1990 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1992 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1995 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1998 return BGP_ATTR_PARSE_PROCEED
;
2000 as4_aggregator_ignore
:
2001 stream_forward_getp(peer
->curr
, length
);
2003 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2004 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2005 lookup_msg(attr_str
, args
->type
, NULL
));
2007 return BGP_ATTR_PARSE_PROCEED
;
2010 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
2012 static enum bgp_attr_parse_ret
2013 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
2014 struct aspath
*as4_path
, as_t as4_aggregator
,
2015 struct in_addr
*as4_aggregator_addr
)
2017 int ignore_as4_path
= 0;
2018 struct aspath
*newpath
;
2020 if (!attr
->aspath
) {
2021 /* NULL aspath shouldn't be possible as bgp_attr_parse should
2023 * checked that all well-known, mandatory attributes were
2026 * Can only be a problem with peer itself - hard error
2028 return BGP_ATTR_PARSE_ERROR
;
2031 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
2032 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2034 * It is worth a warning though, because the peer really
2035 * should not send them
2037 if (BGP_DEBUG(as4
, AS4
)) {
2038 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
2039 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
2040 "AS4 capable peer, yet it sent");
2043 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2044 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2046 "AS4 capable peer, yet it sent");
2049 return BGP_ATTR_PARSE_PROCEED
;
2052 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2053 * because that may override AS4_PATH
2055 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2056 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2058 * if the as_number in aggregator is not AS_TRANS,
2059 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2060 * and the Aggregator shall be taken as
2061 * info on the aggregating node, and the AS_PATH
2062 * shall be taken as the AS_PATH
2064 * the Aggregator shall be ignored and the
2065 * AS4_AGGREGATOR shall be taken as the
2066 * Aggregating node and the AS_PATH is to be
2067 * constructed "as in all other cases"
2069 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2071 if (BGP_DEBUG(as4
, AS4
))
2073 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2075 ignore_as4_path
= 1;
2077 /* "New_aggregator shall be taken as aggregator"
2079 attr
->aggregator_as
= as4_aggregator
;
2080 attr
->aggregator_addr
.s_addr
=
2081 as4_aggregator_addr
->s_addr
;
2084 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2085 * That is bogus - but reading the conditions
2086 * we have to handle AS4_AGGREGATOR as if it were
2087 * AGGREGATOR in that case
2089 if (BGP_DEBUG(as4
, AS4
))
2091 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
2093 attr
->aggregator_as
= as4_aggregator
;
2094 /* sweep it under the carpet and simulate a "good"
2096 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2100 /* need to reconcile NEW_AS_PATH and AS_PATH */
2101 if (!ignore_as4_path
2102 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2103 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2105 return BGP_ATTR_PARSE_ERROR
;
2107 aspath_unintern(&attr
->aspath
);
2108 attr
->aspath
= aspath_intern(newpath
);
2110 return BGP_ATTR_PARSE_PROCEED
;
2113 /* Community attribute. */
2114 static enum bgp_attr_parse_ret
2115 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2117 struct peer
*const peer
= args
->peer
;
2118 struct attr
*const attr
= args
->attr
;
2119 const bgp_size_t length
= args
->length
;
2122 bgp_attr_set_community(attr
, NULL
);
2123 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2127 if (peer
->discard_attrs
[args
->type
])
2128 goto community_ignore
;
2130 bgp_attr_set_community(
2132 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2134 /* XXX: fix community_parse to use stream API and remove this */
2135 stream_forward_getp(peer
->curr
, length
);
2137 /* The Community attribute SHALL be considered malformed if its
2138 * length is not a non-zero multiple of 4.
2140 if (!bgp_attr_get_community(attr
))
2141 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2144 return BGP_ATTR_PARSE_PROCEED
;
2147 stream_forward_getp(peer
->curr
, length
);
2149 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2150 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2151 lookup_msg(attr_str
, args
->type
, NULL
));
2153 return BGP_ATTR_PARSE_PROCEED
;
2156 /* Originator ID attribute. */
2157 static enum bgp_attr_parse_ret
2158 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2160 struct peer
*const peer
= args
->peer
;
2161 struct attr
*const attr
= args
->attr
;
2162 const bgp_size_t length
= args
->length
;
2164 /* if received from an internal neighbor, it SHALL be considered
2165 * malformed if its length is not equal to 4. If malformed, the
2166 * UPDATE message SHALL be handled using the approach of "treat-as-
2170 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2173 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2177 if (peer
->discard_attrs
[args
->type
])
2178 goto originator_id_ignore
;
2180 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2182 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2184 return BGP_ATTR_PARSE_PROCEED
;
2186 originator_id_ignore
:
2187 stream_forward_getp(peer
->curr
, length
);
2189 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2190 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2191 lookup_msg(attr_str
, args
->type
, NULL
));
2193 return BGP_ATTR_PARSE_PROCEED
;
2196 /* Cluster list attribute. */
2197 static enum bgp_attr_parse_ret
2198 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2200 struct peer
*const peer
= args
->peer
;
2201 struct attr
*const attr
= args
->attr
;
2202 const bgp_size_t length
= args
->length
;
2204 /* if received from an internal neighbor, it SHALL be considered
2205 * malformed if its length is not a non-zero multiple of 4. If
2206 * malformed, the UPDATE message SHALL be handled using the approach
2207 * of "treat-as-withdraw".
2209 if (length
== 0 || length
% 4) {
2210 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2212 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2216 if (peer
->discard_attrs
[args
->type
])
2217 goto cluster_list_ignore
;
2219 bgp_attr_set_cluster(
2220 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2223 /* XXX: Fix cluster_parse to use stream API and then remove this */
2224 stream_forward_getp(peer
->curr
, length
);
2226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2228 return BGP_ATTR_PARSE_PROCEED
;
2230 cluster_list_ignore
:
2231 stream_forward_getp(peer
->curr
, length
);
2233 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2234 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2235 lookup_msg(attr_str
, args
->type
, NULL
));
2237 return BGP_ATTR_PARSE_PROCEED
;
2240 /* Multiprotocol reachability information parse. */
2241 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2242 struct bgp_nlri
*mp_update
)
2246 iana_safi_t pkt_safi
;
2248 bgp_size_t nlri_len
;
2251 struct peer
*const peer
= args
->peer
;
2252 struct attr
*const attr
= args
->attr
;
2253 const bgp_size_t length
= args
->length
;
2255 /* Set end of packet. */
2256 s
= BGP_INPUT(peer
);
2257 start
= stream_get_getp(s
);
2259 /* safe to read statically sized header? */
2260 #define BGP_MP_REACH_MIN_SIZE 5
2261 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2262 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2263 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2264 __func__
, peer
->host
, (unsigned long)length
);
2265 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2268 /* Load AFI, SAFI. */
2269 pkt_afi
= stream_getw(s
);
2270 pkt_safi
= stream_getc(s
);
2272 /* Convert AFI, SAFI to internal values, check. */
2273 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2274 /* Log if AFI or SAFI is unrecognized. This is not an error
2276 * the attribute is otherwise malformed.
2278 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2280 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2281 peer
->host
, iana_afi2str(pkt_afi
),
2282 iana_safi2str(pkt_safi
));
2283 return BGP_ATTR_PARSE_ERROR
;
2286 /* Get nexthop length. */
2287 attr
->mp_nexthop_len
= stream_getc(s
);
2289 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2291 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2292 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2293 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2296 /* Nexthop length check. */
2297 switch (attr
->mp_nexthop_len
) {
2299 if (safi
!= SAFI_FLOWSPEC
) {
2300 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2301 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2302 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2305 case BGP_ATTR_NHLEN_VPNV4
:
2306 stream_getl(s
); /* RD high */
2307 stream_getl(s
); /* RD low */
2309 * NOTE: intentional fall through
2310 * - for consistency in rx processing
2312 * The following comment is to signal GCC this intention
2313 * and suppress the warning
2316 case BGP_ATTR_NHLEN_IPV4
:
2317 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2318 /* Probably needed for RFC 2283 */
2319 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2320 memcpy(&attr
->nexthop
.s_addr
,
2321 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2323 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2324 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2325 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2326 stream_getl(s
); /* RD high */
2327 stream_getl(s
); /* RD low */
2329 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2330 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2331 if (!peer
->nexthop
.ifp
) {
2332 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2334 return BGP_ATTR_PARSE_WITHDRAW
;
2336 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2339 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2340 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2341 if (attr
->mp_nexthop_len
2342 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2343 stream_getl(s
); /* RD high */
2344 stream_getl(s
); /* RD low */
2346 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2347 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2348 if (!peer
->nexthop
.ifp
) {
2349 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2351 return BGP_ATTR_PARSE_WITHDRAW
;
2353 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2355 if (attr
->mp_nexthop_len
2356 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2357 stream_getl(s
); /* RD high */
2358 stream_getl(s
); /* RD low */
2360 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2361 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2362 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2364 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2365 peer
->host
, &attr
->mp_nexthop_global
,
2366 &attr
->mp_nexthop_local
);
2368 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2370 if (!peer
->nexthop
.ifp
) {
2371 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2373 return BGP_ATTR_PARSE_WITHDRAW
;
2375 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2378 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2379 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2380 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2384 zlog_info("%s: %s sent SNPA which couldn't be read",
2385 __func__
, peer
->host
);
2386 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2391 if ((val
= stream_getc(s
)))
2393 EC_BGP_DEFUNCT_SNPA_LEN
,
2394 "%s sent non-zero value, %u, for defunct SNPA-length field",
2398 /* must have nrli_len, what is left of the attribute */
2399 nlri_len
= LEN_LEFT
;
2400 if (nlri_len
> STREAM_READABLE(s
)) {
2401 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2402 __func__
, peer
->host
);
2403 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2407 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2408 __func__
, peer
->host
);
2410 mp_update
->afi
= afi
;
2411 mp_update
->safi
= safi
;
2412 return BGP_ATTR_PARSE_EOR
;
2415 mp_update
->afi
= afi
;
2416 mp_update
->safi
= safi
;
2417 mp_update
->nlri
= stream_pnt(s
);
2418 mp_update
->length
= nlri_len
;
2420 stream_forward_getp(s
, nlri_len
);
2422 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2424 return BGP_ATTR_PARSE_PROCEED
;
2428 /* Multiprotocol unreachable parse */
2429 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2430 struct bgp_nlri
*mp_withdraw
)
2435 iana_safi_t pkt_safi
;
2437 uint16_t withdraw_len
;
2438 struct peer
*const peer
= args
->peer
;
2439 struct attr
*const attr
= args
->attr
;
2440 const bgp_size_t length
= args
->length
;
2444 #define BGP_MP_UNREACH_MIN_SIZE 3
2445 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2446 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2448 pkt_afi
= stream_getw(s
);
2449 pkt_safi
= stream_getc(s
);
2451 /* Convert AFI, SAFI to internal values, check. */
2452 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2453 /* Log if AFI or SAFI is unrecognized. This is not an error
2455 * the attribute is otherwise malformed.
2457 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2459 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2460 peer
->host
, iana_afi2str(pkt_afi
),
2461 iana_safi2str(pkt_safi
));
2462 return BGP_ATTR_PARSE_ERROR
;
2465 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2467 mp_withdraw
->afi
= afi
;
2468 mp_withdraw
->safi
= safi
;
2469 mp_withdraw
->nlri
= stream_pnt(s
);
2470 mp_withdraw
->length
= withdraw_len
;
2472 stream_forward_getp(s
, withdraw_len
);
2474 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2476 return BGP_ATTR_PARSE_PROCEED
;
2479 /* Large Community attribute. */
2480 static enum bgp_attr_parse_ret
2481 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2483 struct peer
*const peer
= args
->peer
;
2484 struct attr
*const attr
= args
->attr
;
2485 const bgp_size_t length
= args
->length
;
2488 * Large community follows new attribute format.
2491 bgp_attr_set_lcommunity(attr
, NULL
);
2492 /* Empty extcomm doesn't seem to be invalid per se */
2493 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2497 if (peer
->discard_attrs
[args
->type
])
2498 goto large_community_ignore
;
2500 bgp_attr_set_lcommunity(
2501 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2502 /* XXX: fix ecommunity_parse to use stream API */
2503 stream_forward_getp(peer
->curr
, length
);
2505 if (!bgp_attr_get_lcommunity(attr
))
2506 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2509 return BGP_ATTR_PARSE_PROCEED
;
2511 large_community_ignore
:
2512 stream_forward_getp(peer
->curr
, length
);
2514 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2515 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2516 lookup_msg(attr_str
, args
->type
, NULL
));
2518 return BGP_ATTR_PARSE_PROCEED
;
2521 /* Extended Community attribute. */
2522 static enum bgp_attr_parse_ret
2523 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2525 struct peer
*const peer
= args
->peer
;
2526 struct attr
*const attr
= args
->attr
;
2527 const bgp_size_t length
= args
->length
;
2530 struct ecommunity
*ecomm
;
2533 bgp_attr_set_ecommunity(attr
, NULL
);
2534 /* Empty extcomm doesn't seem to be invalid per se */
2535 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2539 ecomm
= ecommunity_parse(
2540 stream_pnt(peer
->curr
), length
,
2541 CHECK_FLAG(peer
->flags
,
2542 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2543 bgp_attr_set_ecommunity(attr
, ecomm
);
2544 /* XXX: fix ecommunity_parse to use stream API */
2545 stream_forward_getp(peer
->curr
, length
);
2547 /* The Extended Community attribute SHALL be considered malformed if
2548 * its length is not a non-zero multiple of 8.
2550 if (!bgp_attr_get_ecommunity(attr
))
2551 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2554 /* Extract DF election preference and mobility sequence number */
2555 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2557 /* Extract MAC mobility sequence number, if any. */
2558 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2559 attr
->sticky
= sticky
;
2561 /* Check if this is a Gateway MAC-IP advertisement */
2562 attr
->default_gw
= bgp_attr_default_gw(attr
);
2564 /* Handle scenario where router flag ecommunity is not
2565 * set but default gw ext community is present.
2566 * Use default gateway, set and propogate R-bit.
2568 if (attr
->default_gw
)
2569 attr
->router_flag
= 1;
2571 /* Check EVPN Neighbor advertisement flags, R-bit */
2572 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2574 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2576 /* Extract the Rmac, if any */
2577 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2578 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2579 && bgp_mac_exist(&attr
->rmac
))
2580 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2584 /* Get the tunnel type from encap extended community */
2585 bgp_attr_extcom_tunnel_type(attr
,
2586 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2588 /* Extract link bandwidth, if any. */
2589 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2592 return BGP_ATTR_PARSE_PROCEED
;
2595 /* IPv6 Extended Community attribute. */
2596 static enum bgp_attr_parse_ret
2597 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2599 struct peer
*const peer
= args
->peer
;
2600 struct attr
*const attr
= args
->attr
;
2601 const bgp_size_t length
= args
->length
;
2602 struct ecommunity
*ipv6_ecomm
= NULL
;
2605 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2606 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2610 if (peer
->discard_attrs
[args
->type
])
2611 goto ipv6_ext_community_ignore
;
2613 ipv6_ecomm
= ecommunity_parse_ipv6(
2614 stream_pnt(peer
->curr
), length
,
2615 CHECK_FLAG(peer
->flags
,
2616 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2617 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2619 /* XXX: fix ecommunity_parse to use stream API */
2620 stream_forward_getp(peer
->curr
, length
);
2623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2626 return BGP_ATTR_PARSE_PROCEED
;
2628 ipv6_ext_community_ignore
:
2629 stream_forward_getp(peer
->curr
, length
);
2631 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2632 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2633 lookup_msg(attr_str
, args
->type
, NULL
));
2635 return BGP_ATTR_PARSE_PROCEED
;
2638 /* Parse Tunnel Encap attribute in an UPDATE */
2639 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2640 bgp_size_t length
, /* IN: attr's length field */
2641 struct attr
*attr
, /* IN: caller already allocated */
2642 uint8_t flag
, /* IN: attr's flags field */
2646 uint16_t tunneltype
= 0;
2648 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2650 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2651 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2653 "Tunnel Encap attribute flag isn't optional and transitive %d",
2655 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2656 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2661 if (BGP_ATTR_ENCAP
== type
) {
2662 /* read outer TLV type and length */
2663 uint16_t tlv_length
;
2667 "Tunnel Encap attribute not long enough to contain outer T,L");
2668 bgp_notify_send_with_data(
2669 peer
, BGP_NOTIFY_UPDATE_ERR
,
2670 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2673 tunneltype
= stream_getw(BGP_INPUT(peer
));
2674 tlv_length
= stream_getw(BGP_INPUT(peer
));
2677 if (tlv_length
!= length
) {
2678 zlog_info("%s: tlv_length(%d) != length(%d)",
2679 __func__
, tlv_length
, length
);
2683 while (length
>= 4) {
2684 uint16_t subtype
= 0;
2685 uint16_t sublength
= 0;
2686 struct bgp_attr_encap_subtlv
*tlv
;
2688 if (BGP_ATTR_ENCAP
== type
) {
2689 subtype
= stream_getc(BGP_INPUT(peer
));
2690 sublength
= stream_getc(BGP_INPUT(peer
));
2692 #ifdef ENABLE_BGP_VNC
2694 subtype
= stream_getw(BGP_INPUT(peer
));
2695 sublength
= stream_getw(BGP_INPUT(peer
));
2700 if (sublength
> length
) {
2702 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2704 bgp_notify_send_with_data(
2705 peer
, BGP_NOTIFY_UPDATE_ERR
,
2706 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2710 /* alloc and copy sub-tlv */
2711 /* TBD make sure these are freed when attributes are released */
2712 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2713 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2714 tlv
->type
= subtype
;
2715 tlv
->length
= sublength
;
2716 stream_get(tlv
->value
, peer
->curr
, sublength
);
2717 length
-= sublength
;
2719 /* attach tlv to encap chain */
2720 if (BGP_ATTR_ENCAP
== type
) {
2721 struct bgp_attr_encap_subtlv
*stlv_last
;
2722 for (stlv_last
= attr
->encap_subtlvs
;
2723 stlv_last
&& stlv_last
->next
;
2724 stlv_last
= stlv_last
->next
)
2727 stlv_last
->next
= tlv
;
2729 attr
->encap_subtlvs
= tlv
;
2731 #ifdef ENABLE_BGP_VNC
2733 struct bgp_attr_encap_subtlv
*stlv_last
;
2734 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2735 bgp_attr_get_vnc_subtlvs(attr
);
2737 for (stlv_last
= vnc_subtlvs
;
2738 stlv_last
&& stlv_last
->next
;
2739 stlv_last
= stlv_last
->next
)
2742 stlv_last
->next
= tlv
;
2744 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2749 if (BGP_ATTR_ENCAP
== type
) {
2750 attr
->encap_tunneltype
= tunneltype
;
2754 /* spurious leftover data */
2756 "Tunnel Encap attribute length is bad: %d leftover octets",
2758 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2759 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2768 /* SRv6 Service Data Sub-Sub-TLV attribute
2769 * draft-ietf-bess-srv6-services-07
2771 static enum bgp_attr_parse_ret
2772 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2774 struct peer
*const peer
= args
->peer
;
2775 struct attr
*const attr
= args
->attr
;
2776 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2777 transposition_len
, transposition_offset
;
2779 size_t headersz
= sizeof(type
) + sizeof(length
);
2781 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2784 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2785 headersz
, STREAM_READABLE(peer
->curr
));
2786 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2790 type
= stream_getc(peer
->curr
);
2791 length
= stream_getw(peer
->curr
);
2793 if (STREAM_READABLE(peer
->curr
) < length
) {
2796 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2797 length
, STREAM_READABLE(peer
->curr
));
2798 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2802 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2805 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2806 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2808 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2812 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2813 if (STREAM_READABLE(peer
->curr
) <
2814 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2817 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2818 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2819 STREAM_READABLE(peer
->curr
));
2820 return bgp_attr_malformed(
2821 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2825 loc_block_len
= stream_getc(peer
->curr
);
2826 loc_node_len
= stream_getc(peer
->curr
);
2827 func_len
= stream_getc(peer
->curr
);
2828 arg_len
= stream_getc(peer
->curr
);
2829 transposition_len
= stream_getc(peer
->curr
);
2830 transposition_offset
= stream_getc(peer
->curr
);
2832 /* Log SRv6 Service Data Sub-Sub-TLV */
2833 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2835 "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2836 __func__
, loc_block_len
, loc_node_len
, func_len
,
2837 arg_len
, transposition_len
,
2838 transposition_offset
);
2841 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2842 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2843 attr
->srv6_l3vpn
->func_len
= func_len
;
2844 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2845 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2846 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2850 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2852 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2855 stream_forward_getp(peer
->curr
, length
);
2858 return BGP_ATTR_PARSE_PROCEED
;
2861 /* SRv6 Service Sub-TLV attribute
2862 * draft-ietf-bess-srv6-services-07
2864 static enum bgp_attr_parse_ret
2865 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2867 struct peer
*const peer
= args
->peer
;
2868 struct attr
*const attr
= args
->attr
;
2869 struct in6_addr ipv6_sid
;
2870 uint8_t type
, sid_flags
;
2871 uint16_t length
, endpoint_behavior
;
2872 size_t headersz
= sizeof(type
) + sizeof(length
);
2873 enum bgp_attr_parse_ret err
;
2875 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2878 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2879 headersz
, STREAM_READABLE(peer
->curr
));
2880 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2884 type
= stream_getc(peer
->curr
);
2885 length
= stream_getw(peer
->curr
);
2887 if (STREAM_READABLE(peer
->curr
) < length
) {
2890 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2891 length
, STREAM_READABLE(peer
->curr
));
2892 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2896 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2897 if (STREAM_READABLE(peer
->curr
) <
2898 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2901 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2902 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2903 STREAM_READABLE(peer
->curr
));
2904 return bgp_attr_malformed(
2905 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2908 stream_getc(peer
->curr
);
2909 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2910 sid_flags
= stream_getc(peer
->curr
);
2911 endpoint_behavior
= stream_getw(peer
->curr
);
2912 stream_getc(peer
->curr
);
2914 /* Log SRv6 Service Sub-TLV */
2915 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2917 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2918 __func__
, &ipv6_sid
, sid_flags
,
2921 /* Configure from Info */
2922 if (attr
->srv6_l3vpn
) {
2923 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2924 "Prefix SID SRv6 L3VPN field repeated");
2925 return bgp_attr_malformed(
2926 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2928 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2929 sizeof(struct bgp_attr_srv6_l3vpn
));
2930 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2931 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2932 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2933 attr
->srv6_l3vpn
->loc_block_len
= 0;
2934 attr
->srv6_l3vpn
->loc_node_len
= 0;
2935 attr
->srv6_l3vpn
->func_len
= 0;
2936 attr
->srv6_l3vpn
->arg_len
= 0;
2937 attr
->srv6_l3vpn
->transposition_len
= 0;
2938 attr
->srv6_l3vpn
->transposition_offset
= 0;
2940 // Sub-Sub-TLV found
2941 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2942 err
= bgp_attr_srv6_service_data(args
);
2944 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2948 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2951 /* Placeholder code for unsupported type */
2953 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2955 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2958 stream_forward_getp(peer
->curr
, length
);
2961 return BGP_ATTR_PARSE_PROCEED
;
2965 * Read an individual SID value returning how much data we have read
2966 * Returns 0 if there was an error that needs to be passed up the stack
2968 static enum bgp_attr_parse_ret
2969 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2970 struct bgp_attr_parser_args
*args
)
2972 struct peer
*const peer
= args
->peer
;
2973 struct attr
*const attr
= args
->attr
;
2974 uint32_t label_index
;
2975 struct in6_addr ipv6_sid
;
2977 uint32_t srgb_range
;
2979 uint8_t sid_type
, sid_flags
;
2981 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2982 if (STREAM_READABLE(peer
->curr
) < length
2983 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2984 flog_err(EC_BGP_ATTR_LEN
,
2985 "Prefix SID label index length is %hu instead of %u",
2986 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2987 return bgp_attr_malformed(args
,
2988 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2992 /* Ignore flags and reserved */
2993 stream_getc(peer
->curr
);
2994 stream_getw(peer
->curr
);
2996 /* Fetch the label index and see if it is valid. */
2997 label_index
= stream_getl(peer
->curr
);
2998 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2999 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3002 /* Store label index; subsequently, we'll check on
3004 attr
->label_index
= label_index
;
3007 /* Placeholder code for the IPv6 SID type */
3008 else if (type
== BGP_PREFIX_SID_IPV6
) {
3009 if (STREAM_READABLE(peer
->curr
) < length
3010 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
3011 flog_err(EC_BGP_ATTR_LEN
,
3012 "Prefix SID IPv6 length is %hu instead of %u",
3013 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
3014 return bgp_attr_malformed(args
,
3015 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3019 /* Ignore reserved */
3020 stream_getc(peer
->curr
);
3021 stream_getw(peer
->curr
);
3023 stream_get(&ipv6_sid
, peer
->curr
, 16);
3026 /* Placeholder code for the Originator SRGB type */
3027 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
3029 * ietf-idr-bgp-prefix-sid-05:
3030 * Length is the total length of the value portion of the
3031 * TLV: 2 + multiple of 6.
3033 * peer->curr stream readp should be at the beginning of the 16
3034 * bit flag field at this point in the code.
3038 * Check that the TLV length field is sane: at least 2 bytes of
3039 * flag, and at least 1 SRGB (these are 6 bytes each)
3041 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
3044 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3046 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3047 return bgp_attr_malformed(
3048 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3053 * Check that we actually have at least as much data as
3054 * specified by the length field
3056 if (STREAM_READABLE(peer
->curr
) < length
) {
3057 flog_err(EC_BGP_ATTR_LEN
,
3058 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
3059 length
, STREAM_READABLE(peer
->curr
));
3060 return bgp_attr_malformed(
3061 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3066 * Check that the portion of the TLV containing the sequence of
3067 * SRGBs corresponds to a multiple of the SRGB size; to get
3068 * that length, we skip the 16 bit flags field
3070 stream_getw(peer
->curr
);
3072 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
3075 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3076 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3077 return bgp_attr_malformed(
3078 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3082 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
3084 for (int i
= 0; i
< srgb_count
; i
++) {
3085 stream_get(&srgb_base
, peer
->curr
, 3);
3086 stream_get(&srgb_range
, peer
->curr
, 3);
3090 /* Placeholder code for the VPN-SID Service type */
3091 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
3092 if (STREAM_READABLE(peer
->curr
) < length
3093 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
3094 flog_err(EC_BGP_ATTR_LEN
,
3095 "Prefix SID VPN SID length is %hu instead of %u",
3096 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
3097 return bgp_attr_malformed(args
,
3098 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3102 /* Parse VPN-SID Sub-TLV */
3103 stream_getc(peer
->curr
); /* reserved */
3104 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3105 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3106 stream_get(&ipv6_sid
, peer
->curr
,
3107 sizeof(ipv6_sid
)); /* sid_value */
3109 /* Log VPN-SID Sub-TLV */
3110 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3112 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3113 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3115 /* Configure from Info */
3116 if (attr
->srv6_vpn
) {
3117 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3118 "Prefix SID SRv6 VPN field repeated");
3119 return bgp_attr_malformed(
3120 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3122 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3123 sizeof(struct bgp_attr_srv6_vpn
));
3124 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3125 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3126 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3129 /* Placeholder code for the SRv6 L3 Service type */
3130 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3131 if (STREAM_READABLE(peer
->curr
) < length
) {
3134 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3135 length
, STREAM_READABLE(peer
->curr
));
3136 return bgp_attr_malformed(args
,
3137 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3141 /* ignore reserved */
3142 stream_getc(peer
->curr
);
3144 return bgp_attr_srv6_service(args
);
3147 /* Placeholder code for Unsupported TLV */
3150 if (STREAM_READABLE(peer
->curr
) < length
) {
3153 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3154 length
, STREAM_READABLE(peer
->curr
));
3155 return bgp_attr_malformed(
3156 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3160 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3162 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3165 stream_forward_getp(peer
->curr
, length
);
3168 return BGP_ATTR_PARSE_PROCEED
;
3171 /* Prefix SID attribute
3172 * draft-ietf-idr-bgp-prefix-sid-05
3174 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3176 struct peer
*const peer
= args
->peer
;
3177 struct attr
*const attr
= args
->attr
;
3178 enum bgp_attr_parse_ret ret
;
3180 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3184 size_t headersz
= sizeof(type
) + sizeof(length
);
3185 size_t psid_parsed_length
= 0;
3187 while (STREAM_READABLE(peer
->curr
) > 0
3188 && psid_parsed_length
< args
->length
) {
3190 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3193 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3194 headersz
, STREAM_READABLE(peer
->curr
));
3195 return bgp_attr_malformed(
3196 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3200 type
= stream_getc(peer
->curr
);
3201 length
= stream_getw(peer
->curr
);
3203 if (STREAM_READABLE(peer
->curr
) < length
) {
3206 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3207 length
, STREAM_READABLE(peer
->curr
));
3208 return bgp_attr_malformed(args
,
3209 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3213 ret
= bgp_attr_psid_sub(type
, length
, args
);
3215 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3218 psid_parsed_length
+= length
+ headersz
;
3220 if (psid_parsed_length
> args
->length
) {
3223 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3224 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3225 return bgp_attr_malformed(
3226 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3231 return BGP_ATTR_PARSE_PROCEED
;
3234 /* PMSI tunnel attribute (RFC 6514)
3235 * Basic validation checks done here.
3237 static enum bgp_attr_parse_ret
3238 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3240 struct peer
*const peer
= args
->peer
;
3241 struct attr
*const attr
= args
->attr
;
3242 const bgp_size_t length
= args
->length
;
3244 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3246 /* Verify that the receiver is expecting "ingress replication" as we
3247 * can only support that.
3249 if (length
< attr_parse_len
) {
3250 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3252 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3255 stream_getc(peer
->curr
); /* Flags */
3256 tnl_type
= stream_getc(peer
->curr
);
3257 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3258 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3259 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3260 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3263 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3265 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3266 "Bad PMSI tunnel attribute length %d for IR",
3268 return bgp_attr_malformed(
3269 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3274 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3275 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3276 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3278 /* Forward read pointer of input stream. */
3279 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3281 return BGP_ATTR_PARSE_PROCEED
;
3284 /* AIGP attribute (rfc7311) */
3285 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3287 struct peer
*const peer
= args
->peer
;
3288 struct attr
*const attr
= args
->attr
;
3289 const bgp_size_t length
= args
->length
;
3290 uint8_t *s
= stream_pnt(peer
->curr
);
3293 /* If an AIGP attribute is received on a BGP session for which
3294 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3295 * as if it were an unrecognized non-transitive attribute.
3296 * That is, it "MUST be quietly ignored and not passed along to
3298 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3299 * sessions between members of the same BGP Confederation,
3300 * the default value of AIGP_SESSION SHOULD be "enabled".
3302 if (peer
->sort
== BGP_PEER_EBGP
&&
3303 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3305 "%pBP received AIGP attribute, but eBGP peer do not support it",
3310 if (peer
->discard_attrs
[args
->type
])
3313 if (!bgp_attr_aigp_valid(s
, length
))
3316 /* Extract AIGP Metric TLV */
3317 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3318 bgp_attr_set_aigp_metric(attr
, aigp
);
3321 stream_forward_getp(peer
->curr
, length
);
3323 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3324 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3325 lookup_msg(attr_str
, args
->type
, NULL
));
3327 return BGP_ATTR_PARSE_PROCEED
;
3330 /* OTC attribute. */
3331 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3333 struct peer
*const peer
= args
->peer
;
3334 struct attr
*const attr
= args
->attr
;
3335 const bgp_size_t length
= args
->length
;
3339 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3341 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3345 if (peer
->discard_attrs
[args
->type
])
3348 attr
->otc
= stream_getl(peer
->curr
);
3350 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3351 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3355 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3357 return BGP_ATTR_PARSE_PROCEED
;
3360 stream_forward_getp(peer
->curr
, length
);
3362 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3363 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3364 lookup_msg(attr_str
, args
->type
, NULL
));
3366 return BGP_ATTR_PARSE_PROCEED
;
3369 /* BGP unknown attribute treatment. */
3370 static enum bgp_attr_parse_ret
3371 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3373 bgp_size_t total
= args
->total
;
3374 struct transit
*transit
;
3375 struct peer
*const peer
= args
->peer
;
3376 struct attr
*const attr
= args
->attr
;
3377 uint8_t *const startp
= args
->startp
;
3378 const uint8_t type
= args
->type
;
3379 const uint8_t flag
= args
->flags
;
3380 const bgp_size_t length
= args
->length
;
3382 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3384 "%s Unknown attribute is received (type %d, length %d)",
3385 peer
->host
, type
, length
);
3387 /* Forward read pointer of input stream. */
3388 stream_forward_getp(peer
->curr
, length
);
3390 if (peer
->discard_attrs
[type
]) {
3391 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3392 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3393 lookup_msg(attr_str
, args
->type
, NULL
));
3395 return BGP_ATTR_PARSE_PROCEED
;
3398 /* If any of the mandatory well-known attributes are not recognized,
3399 then the Error Subcode is set to Unrecognized Well-known
3400 Attribute. The Data field contains the unrecognized attribute
3401 (type, length and value). */
3402 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3403 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3407 /* Unrecognized non-transitive optional attributes must be quietly
3408 ignored and not passed along to other BGP peers. */
3409 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3410 return BGP_ATTR_PARSE_PROCEED
;
3412 /* If a path with recognized transitive optional attribute is
3413 accepted and passed along to other BGP peers and the Partial bit
3414 in the Attribute Flags octet is set to 1 by some previous AS, it
3415 is not set back to 0 by the current AS. */
3416 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3418 /* Store transitive attribute to the end of attr->transit. */
3419 transit
= bgp_attr_get_transit(attr
);
3421 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3423 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3424 transit
->length
+ total
);
3426 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3427 transit
->length
+= total
;
3428 bgp_attr_set_transit(attr
, transit
);
3430 return BGP_ATTR_PARSE_PROCEED
;
3433 /* Well-known attribute check. */
3434 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3438 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3440 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3441 return BGP_ATTR_PARSE_PROCEED
;
3443 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3444 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3445 are present, it should. Check for any other attribute being present
3448 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3449 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3450 return BGP_ATTR_PARSE_PROCEED
;
3452 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3453 type
= BGP_ATTR_ORIGIN
;
3455 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3456 type
= BGP_ATTR_AS_PATH
;
3458 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3460 * NLRI is empty. We can't easily check NLRI empty here though.
3462 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3463 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3464 type
= BGP_ATTR_NEXT_HOP
;
3466 if (peer
->sort
== BGP_PEER_IBGP
3467 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3468 type
= BGP_ATTR_LOCAL_PREF
;
3470 /* If any of the well-known mandatory attributes are not present
3471 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3474 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3475 "%s Missing well-known attribute %s.", peer
->host
,
3476 lookup_msg(attr_str
, type
, NULL
));
3477 return BGP_ATTR_PARSE_WITHDRAW
;
3479 return BGP_ATTR_PARSE_PROCEED
;
3482 /* Read attribute of update packet. This function is called from
3483 bgp_update_receive() in bgp_packet.c. */
3484 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3486 struct bgp_nlri
*mp_update
,
3487 struct bgp_nlri
*mp_withdraw
)
3489 enum bgp_attr_parse_ret ret
;
3493 uint8_t *startp
, *endp
;
3495 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3496 /* we need the as4_path only until we have synthesized the as_path with
3498 /* same goes for as4_aggregator */
3499 struct aspath
*as4_path
= NULL
;
3500 as_t as4_aggregator
= 0;
3501 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3502 struct transit
*transit
;
3504 /* Initialize bitmap. */
3505 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3507 /* End pointer of BGP attribute. */
3508 endp
= BGP_INPUT_PNT(peer
) + size
;
3510 /* Get attributes to the end of attribute length. */
3511 while (BGP_INPUT_PNT(peer
) < endp
) {
3512 /* Check remaining length check.*/
3513 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3514 /* XXX warning: long int format, int arg (arg 5) */
3516 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3517 "%s: error BGP attribute length %lu is smaller than min len",
3519 (unsigned long)(endp
3520 - stream_pnt(BGP_INPUT(peer
))));
3522 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3523 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3524 ret
= BGP_ATTR_PARSE_ERROR
;
3528 /* Fetch attribute flag and type. */
3529 startp
= BGP_INPUT_PNT(peer
);
3530 /* "The lower-order four bits of the Attribute Flags octet are
3531 unused. They MUST be zero when sent and MUST be ignored when
3533 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3534 type
= stream_getc(BGP_INPUT(peer
));
3536 /* Check whether Extended-Length applies and is in bounds */
3537 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3538 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3540 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3541 "%s: Extended length set, but just %lu bytes of attr header",
3543 (unsigned long)(endp
3544 - stream_pnt(BGP_INPUT(peer
))));
3546 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3547 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3548 ret
= BGP_ATTR_PARSE_ERROR
;
3552 /* Check extended attribue length bit. */
3553 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3554 length
= stream_getw(BGP_INPUT(peer
));
3556 length
= stream_getc(BGP_INPUT(peer
));
3558 /* If any attribute appears more than once in the UPDATE
3559 message, then the Error Subcode is set to Malformed Attribute
3562 if (CHECK_BITMAP(seen
, type
)) {
3564 EC_BGP_ATTRIBUTE_REPEATED
,
3565 "%s: error BGP attribute type %d appears twice in a message",
3568 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3569 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3570 ret
= BGP_ATTR_PARSE_ERROR
;
3574 /* Set type to bitmap to check duplicate attribute. `type' is
3575 unsigned char so it never overflow bitmap range. */
3577 SET_BITMAP(seen
, type
);
3579 /* Overflow check. */
3580 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3582 if (attr_endp
> endp
) {
3584 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3585 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3586 peer
->host
, type
, length
, size
, attr_endp
,
3590 * If any recognized attribute has an Attribute
3591 * Length that conflicts with the expected length
3592 * (based on the attribute type code), then the
3593 * Error Subcode MUST be set to Attribute Length
3594 * Error. The Data field MUST contain the erroneous
3595 * attribute (type, length, and value).
3597 * We do not currently have a good way to determine the
3598 * length of the attribute independent of the length
3599 * received in the message. Instead we send the
3600 * minimum between the amount of data we have and the
3601 * amount specified by the attribute length field.
3603 * Instead of directly passing in the packet buffer and
3604 * offset we use the stream_get* functions to read into
3605 * a stack buffer, since they perform bounds checking
3606 * and we are working with untrusted data.
3608 unsigned char ndata
[peer
->max_packet_size
];
3609 memset(ndata
, 0x00, sizeof(ndata
));
3611 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3612 /* Rewind to end of flag field */
3613 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3615 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3617 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3619 size_t atl
= attr_endp
- startp
;
3620 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3621 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3623 bgp_notify_send_with_data(
3624 peer
, BGP_NOTIFY_UPDATE_ERR
,
3625 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3628 ret
= BGP_ATTR_PARSE_ERROR
;
3632 struct bgp_attr_parser_args attr_args
= {
3639 .total
= attr_endp
- startp
,
3643 /* If any recognized attribute has Attribute Flags that conflict
3644 with the Attribute Type Code, then the Error Subcode is set
3646 Attribute Flags Error. The Data field contains the erroneous
3647 attribute (type, length and value). */
3648 if (bgp_attr_flag_invalid(&attr_args
)) {
3649 ret
= bgp_attr_malformed(
3650 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3652 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3657 /* OK check attribute and store it's value. */
3659 case BGP_ATTR_ORIGIN
:
3660 ret
= bgp_attr_origin(&attr_args
);
3662 case BGP_ATTR_AS_PATH
:
3663 ret
= bgp_attr_aspath(&attr_args
);
3665 case BGP_ATTR_AS4_PATH
:
3666 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3668 case BGP_ATTR_NEXT_HOP
:
3669 ret
= bgp_attr_nexthop(&attr_args
);
3671 case BGP_ATTR_MULTI_EXIT_DISC
:
3672 ret
= bgp_attr_med(&attr_args
);
3674 case BGP_ATTR_LOCAL_PREF
:
3675 ret
= bgp_attr_local_pref(&attr_args
);
3677 case BGP_ATTR_ATOMIC_AGGREGATE
:
3678 ret
= bgp_attr_atomic(&attr_args
);
3680 case BGP_ATTR_AGGREGATOR
:
3681 ret
= bgp_attr_aggregator(&attr_args
);
3683 case BGP_ATTR_AS4_AGGREGATOR
:
3684 ret
= bgp_attr_as4_aggregator(&attr_args
,
3686 &as4_aggregator_addr
);
3688 case BGP_ATTR_COMMUNITIES
:
3689 ret
= bgp_attr_community(&attr_args
);
3691 case BGP_ATTR_LARGE_COMMUNITIES
:
3692 ret
= bgp_attr_large_community(&attr_args
);
3694 case BGP_ATTR_ORIGINATOR_ID
:
3695 ret
= bgp_attr_originator_id(&attr_args
);
3697 case BGP_ATTR_CLUSTER_LIST
:
3698 ret
= bgp_attr_cluster_list(&attr_args
);
3700 case BGP_ATTR_MP_REACH_NLRI
:
3701 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3703 case BGP_ATTR_MP_UNREACH_NLRI
:
3704 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3706 case BGP_ATTR_EXT_COMMUNITIES
:
3707 ret
= bgp_attr_ext_communities(&attr_args
);
3709 #ifdef ENABLE_BGP_VNC_ATTR
3712 case BGP_ATTR_ENCAP
:
3713 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3716 case BGP_ATTR_PREFIX_SID
:
3717 ret
= bgp_attr_prefix_sid(&attr_args
);
3719 case BGP_ATTR_PMSI_TUNNEL
:
3720 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3722 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3723 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3726 ret
= bgp_attr_otc(&attr_args
);
3729 ret
= bgp_attr_aigp(&attr_args
);
3732 ret
= bgp_attr_unknown(&attr_args
);
3736 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3737 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3738 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3739 ret
= BGP_ATTR_PARSE_ERROR
;
3743 if (ret
== BGP_ATTR_PARSE_EOR
) {
3747 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3748 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3749 "%s: Attribute %s, parse error", peer
->host
,
3750 lookup_msg(attr_str
, type
, NULL
));
3753 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3755 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3756 "%s: Attribute %s, parse error - treating as withdrawal",
3757 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3761 /* Check the fetched length. */
3762 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3763 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3764 "%s: BGP attribute %s, fetch error",
3765 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3766 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3767 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3768 ret
= BGP_ATTR_PARSE_ERROR
;
3774 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3775 * About Prefix-SID path attribute,
3776 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3777 * may only appear in a BGP Prefix-SID attribute attached to
3778 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3779 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3781 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3782 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3784 /* Check final read pointer is same as end pointer. */
3785 if (BGP_INPUT_PNT(peer
) != endp
) {
3786 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3787 "%s: BGP attribute %s, length mismatch", peer
->host
,
3788 lookup_msg(attr_str
, type
, NULL
));
3789 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3790 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3792 ret
= BGP_ATTR_PARSE_ERROR
;
3797 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3798 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3799 * This is implemented below and will result in a NOTIFICATION. If the
3800 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3801 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3802 * message SHOULD NOT be sent. This is implemented elsewhere.
3804 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3805 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3806 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3807 * speaker that receives the message SHOULD ignore this attribute.
3809 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3810 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3811 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3812 ret
= BGP_ATTR_PARSE_ERROR
;
3817 /* Check all mandatory well-known attributes are present */
3818 ret
= bgp_attr_check(peer
, attr
);
3823 * At this place we can see whether we got AS4_PATH and/or
3824 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3825 * We can not do this before we've read all attributes because
3826 * the as4 handling does not say whether AS4_PATH has to be sent
3827 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3828 * in relationship to AGGREGATOR.
3829 * So, to be defensive, we are not relying on any order and read
3830 * all attributes first, including these 32bit ones, and now,
3831 * afterwards, we look what and if something is to be done for as4.
3833 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3836 /* actually... this doesn't ever return failure currently, but
3837 * better safe than sorry */
3838 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3839 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3840 &as4_aggregator_addr
)) {
3841 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3842 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3843 ret
= BGP_ATTR_PARSE_ERROR
;
3848 * Finally do the checks on the aspath we did not do yet
3849 * because we waited for a potentially synthesized aspath.
3851 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3852 ret
= bgp_attr_aspath_check(peer
, attr
);
3853 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3857 ret
= BGP_ATTR_PARSE_PROCEED
;
3861 * At this stage, we have done all fiddling with as4, and the
3862 * resulting info is in attr->aggregator resp. attr->aspath so
3863 * we can chuck as4_aggregator and as4_path alltogether in order
3867 * unintern - it is in the hash
3868 * The flag that we got this is still there, but that
3869 * does not do any trouble
3871 aspath_unintern(&as4_path
);
3873 transit
= bgp_attr_get_transit(attr
);
3874 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3875 /* Finally intern unknown attribute. */
3877 bgp_attr_set_transit(attr
, transit_intern(transit
));
3878 if (attr
->encap_subtlvs
)
3879 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3881 #ifdef ENABLE_BGP_VNC
3882 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3883 bgp_attr_get_vnc_subtlvs(attr
);
3886 bgp_attr_set_vnc_subtlvs(
3888 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3892 transit_free(transit
);
3893 bgp_attr_set_transit(attr
, NULL
);
3896 bgp_attr_flush_encap(attr
);
3900 transit
= bgp_attr_get_transit(attr
);
3902 assert(transit
->refcnt
> 0);
3903 if (attr
->encap_subtlvs
)
3904 assert(attr
->encap_subtlvs
->refcnt
> 0);
3905 #ifdef ENABLE_BGP_VNC
3906 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3907 bgp_attr_get_vnc_subtlvs(attr
);
3910 assert(vnc_subtlvs
->refcnt
> 0);
3917 * Extract the tunnel type from extended community
3919 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3920 bgp_encap_types
*tunnel_type
)
3922 struct ecommunity
*ecom
;
3928 ecom
= bgp_attr_get_ecommunity(attr
);
3929 if (!ecom
|| !ecom
->size
)
3932 for (i
= 0; i
< ecom
->size
; i
++) {
3934 uint8_t type
, sub_type
;
3936 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3939 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3940 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3942 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3949 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3950 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3954 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3955 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3958 /* Set extended bit always to encode the attribute length as 2 bytes */
3959 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3960 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3961 sizep
= stream_get_endp(s
);
3962 stream_putw(s
, 0); /* Marker: Attribute length. */
3965 /* Convert AFI, SAFI to values for packet. */
3966 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3968 stream_putw(s
, pkt_afi
); /* AFI */
3969 stream_putc(s
, pkt_safi
); /* SAFI */
3973 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3974 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3975 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3976 else if (safi
== SAFI_FLOWSPEC
)
3979 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3982 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3987 case SAFI_MULTICAST
:
3988 case SAFI_LABELED_UNICAST
:
3990 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3994 stream_putl(s
, 0); /* RD = 0, per RFC */
3996 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
4001 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
4004 if (attr
->mp_nexthop_len
== 0)
4005 stream_putc(s
, 0); /* no nexthop for flowspec */
4007 stream_putc(s
, attr
->mp_nexthop_len
);
4008 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4013 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4020 case SAFI_MULTICAST
:
4021 case SAFI_LABELED_UNICAST
:
4023 if (attr
->mp_nexthop_len
4024 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
4026 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
4027 stream_put(s
, &attr
->mp_nexthop_global
,
4029 stream_put(s
, &attr
->mp_nexthop_local
,
4032 stream_putc(s
, IPV6_MAX_BYTELEN
);
4033 stream_put(s
, &attr
->mp_nexthop_global
,
4037 case SAFI_MPLS_VPN
: {
4038 if (attr
->mp_nexthop_len
==
4039 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
4041 stream_putl(s
, 0); /* RD = 0, per RFC */
4043 stream_put(s
, &attr
->mp_nexthop_global
,
4045 stream_putl(s
, 0); /* RD = 0, per RFC */
4047 stream_put(s
, &attr
->mp_nexthop_local
,
4051 stream_putl(s
, 0); /* RD = 0, per RFC */
4053 stream_put(s
, &attr
->mp_nexthop_global
,
4058 stream_putc(s
, IPV6_MAX_BYTELEN
);
4059 stream_put(s
, &attr
->mp_nexthop_global
,
4063 stream_putc(s
, 0); /* no nexthop for flowspec */
4067 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4072 if (safi
!= SAFI_FLOWSPEC
)
4074 EC_BGP_ATTR_NH_SEND_LEN
,
4075 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
4076 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
4080 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
4089 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
4090 const struct prefix
*p
,
4091 const struct prefix_rd
*prd
, mpls_label_t
*label
,
4092 uint32_t num_labels
, bool addpath_capable
,
4093 uint32_t addpath_tx_id
, struct attr
*attr
)
4098 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4101 if (addpath_capable
)
4102 stream_putl(s
, addpath_tx_id
);
4103 /* Label, RD, Prefix write. */
4104 stream_putc(s
, p
->prefixlen
+ 88);
4105 stream_put(s
, label
, BGP_LABEL_BYTES
);
4106 stream_put(s
, prd
->val
, 8);
4107 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
4110 if (afi
== AFI_L2VPN
)
4111 /* EVPN prefix - contents depend on type */
4112 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
,
4113 attr
, addpath_capable
,
4116 assert(!"Add encoding bits here for other AFI's");
4118 case SAFI_LABELED_UNICAST
:
4119 /* Prefix write with label. */
4120 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
4124 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
4125 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
4126 p
->u
.prefix_flowspec
.prefixlen
);
4130 case SAFI_MULTICAST
:
4131 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
4134 assert(!"Please add proper encoding of SAFI_ENCAP");
4139 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
4140 const struct prefix
*p
)
4142 int size
= PSIZE(p
->prefixlen
);
4147 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4150 case SAFI_MULTICAST
:
4156 /* This has to be wrong, but I don't know what to put here */
4157 assert(!"Do we try to use this?");
4159 case SAFI_LABELED_UNICAST
:
4160 size
+= BGP_LABEL_BYTES
;
4164 * TODO: Maximum possible for type-2, type-3 and type-5
4166 if (afi
== AFI_L2VPN
)
4169 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4172 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
4180 * Encodes the tunnel encapsulation attribute,
4181 * and with ENABLE_BGP_VNC the VNC attribute which uses
4182 * almost the same TLV format
4184 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4185 struct stream
*s
, struct attr
*attr
,
4188 unsigned int attrlenfield
= 0;
4189 unsigned int attrhdrlen
= 0;
4190 struct bgp_attr_encap_subtlv
*subtlvs
;
4191 struct bgp_attr_encap_subtlv
*st
;
4192 const char *attrname
;
4194 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4195 && (!attr
->encap_tunneltype
4196 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4200 case BGP_ATTR_ENCAP
:
4201 attrname
= "Tunnel Encap";
4202 subtlvs
= attr
->encap_subtlvs
;
4203 if (subtlvs
== NULL
) /* nothing to do */
4206 * The tunnel encap attr has an "outer" tlv.
4208 * L = total length of subtlvs,
4209 * V = concatenated subtlvs.
4211 attrlenfield
= 2 + 2; /* T + L */
4212 attrhdrlen
= 1 + 1; /* subTLV T + L */
4215 #ifdef ENABLE_BGP_VNC_ATTR
4218 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4219 if (subtlvs
== NULL
) /* nothing to do */
4221 attrlenfield
= 0; /* no outer T + L */
4222 attrhdrlen
= 2 + 2; /* subTLV T + L */
4230 /* compute attr length */
4231 for (st
= subtlvs
; st
; st
= st
->next
) {
4232 attrlenfield
+= (attrhdrlen
+ st
->length
);
4235 if (attrlenfield
> 0xffff) {
4236 zlog_info("%s attribute is too long (length=%d), can't send it",
4237 attrname
, attrlenfield
);
4241 if (attrlenfield
> 0xff) {
4242 /* 2-octet length field */
4244 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4245 | BGP_ATTR_FLAG_EXTLEN
);
4246 stream_putc(s
, attrtype
);
4247 stream_putw(s
, attrlenfield
& 0xffff);
4249 /* 1-octet length field */
4250 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4251 stream_putc(s
, attrtype
);
4252 stream_putc(s
, attrlenfield
& 0xff);
4255 if (attrtype
== BGP_ATTR_ENCAP
) {
4256 /* write outer T+L */
4257 stream_putw(s
, attr
->encap_tunneltype
);
4258 stream_putw(s
, attrlenfield
- 4);
4261 /* write each sub-tlv */
4262 for (st
= subtlvs
; st
; st
= st
->next
) {
4263 if (attrtype
== BGP_ATTR_ENCAP
) {
4264 stream_putc(s
, st
->type
);
4265 stream_putc(s
, st
->length
);
4266 #ifdef ENABLE_BGP_VNC
4268 stream_putw(s
, st
->type
);
4269 stream_putw(s
, st
->length
);
4272 stream_put(s
, st
->value
, st
->length
);
4276 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4278 /* Set MP attribute length. Don't count the (2) bytes used to encode
4280 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4283 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4285 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4286 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4287 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4288 PEER_FLAG_REMOVE_PRIVATE_AS
)
4289 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4290 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4291 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4292 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4293 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4294 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4299 /* Make attribute packet. */
4300 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4301 struct stream
*s
, struct attr
*attr
,
4302 struct bpacket_attr_vec_arr
*vecarr
,
4303 struct prefix
*p
, afi_t afi
, safi_t safi
,
4304 struct peer
*from
, struct prefix_rd
*prd
,
4305 mpls_label_t
*label
, uint32_t num_labels
,
4306 bool addpath_capable
, uint32_t addpath_tx_id
,
4307 struct bgp_path_info
*bpi
)
4310 size_t aspath_sizep
;
4311 struct aspath
*aspath
;
4312 int send_as4_path
= 0;
4313 int send_as4_aggregator
= 0;
4314 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4315 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4320 /* Remember current pointer. */
4321 cp
= stream_get_endp(s
);
4324 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4325 && !peer_cap_enhe(peer
, afi
, safi
))) {
4326 size_t mpattrlen_pos
= 0;
4328 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4330 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4331 num_labels
, addpath_capable
,
4332 addpath_tx_id
, attr
);
4333 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4336 /* Origin attribute. */
4337 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4338 stream_putc(s
, BGP_ATTR_ORIGIN
);
4340 stream_putc(s
, attr
->origin
);
4342 /* AS path attribute. */
4344 /* If remote-peer is EBGP */
4345 if (peer
->sort
== BGP_PEER_EBGP
4346 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4347 PEER_FLAG_AS_PATH_UNCHANGED
)
4348 || attr
->aspath
->segments
== NULL
)
4349 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4350 PEER_FLAG_RSERVER_CLIENT
))) {
4351 aspath
= aspath_dup(attr
->aspath
);
4353 /* Even though we may not be configured for confederations we
4355 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4356 aspath
= aspath_delete_confed_seq(aspath
);
4358 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4359 /* Stuff our path CONFED_ID on the front */
4360 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4362 if (peer
->change_local_as
) {
4363 /* If replace-as is specified, we only use the
4364 change_local_as when
4365 advertising routes. */
4366 if (!CHECK_FLAG(peer
->flags
,
4367 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4368 if (bgp_append_local_as(peer
, afi
,
4370 aspath
= aspath_add_seq(
4371 aspath
, peer
->local_as
);
4372 aspath
= aspath_add_seq(aspath
,
4373 peer
->change_local_as
);
4375 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4378 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4379 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4381 aspath
= aspath_dup(attr
->aspath
);
4382 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4384 aspath
= attr
->aspath
;
4386 /* If peer is not AS4 capable, then:
4387 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4388 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4390 * types are in it (i.e. exclude them if they are there)
4391 * AND do this only if there is at least one asnum > 65535 in the
4393 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4395 * all ASnums > 65535 to BGP_AS_TRANS
4398 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4399 stream_putc(s
, BGP_ATTR_AS_PATH
);
4400 aspath_sizep
= stream_get_endp(s
);
4402 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4404 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4407 if (!use32bit
&& aspath_has_as4(aspath
))
4409 1; /* we'll do this later, at the correct place */
4411 /* Nexthop attribute. */
4412 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4413 && !peer_cap_enhe(peer
, afi
, safi
)) {
4414 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4416 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4417 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4418 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4419 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4422 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4423 } else if (peer_cap_enhe(from
, afi
, safi
)
4424 || (nh_afi
== AFI_IP6
)) {
4426 * Likely this is the case when an IPv4 prefix was
4427 * received with Extended Next-hop capability in this
4428 * or another vrf and is now being advertised to
4429 * non-ENHE peers. Since peer_cap_enhe only checks
4430 * peers in this vrf, also check the nh_afi to catch
4431 * the case where the originator was in another vrf.
4432 * Setting the mandatory (ipv4) next-hop attribute here
4433 * to enable implicit next-hop self with correct A-F
4434 * (ipv4 address family).
4436 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4437 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4438 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4441 stream_put_ipv4(s
, 0);
4445 /* MED attribute. */
4446 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4447 || bgp
->maxmed_active
) {
4448 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4449 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4451 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4455 /* Local preference. */
4456 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4457 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4458 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4460 stream_putl(s
, attr
->local_pref
);
4463 /* Atomic aggregate. */
4464 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4465 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4466 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4471 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4472 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4473 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4474 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4477 /* AS4 capable peer */
4479 stream_putl(s
, attr
->aggregator_as
);
4481 /* 2-byte AS peer */
4484 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4486 if (attr
->aggregator_as
> UINT16_MAX
) {
4487 stream_putw(s
, BGP_AS_TRANS
);
4489 /* we have to send AS4_AGGREGATOR, too.
4490 * we'll do that later in order to send
4491 * attributes in ascending
4494 send_as4_aggregator
= 1;
4496 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4498 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4501 /* Community attribute. */
4502 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4503 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4504 struct community
*comm
= NULL
;
4506 comm
= bgp_attr_get_community(attr
);
4507 if (comm
->size
* 4 > 255) {
4509 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4510 | BGP_ATTR_FLAG_EXTLEN
);
4511 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4512 stream_putw(s
, comm
->size
* 4);
4515 BGP_ATTR_FLAG_OPTIONAL
4516 | BGP_ATTR_FLAG_TRANS
);
4517 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4518 stream_putc(s
, comm
->size
* 4);
4520 stream_put(s
, comm
->val
, comm
->size
* 4);
4524 * Large Community attribute.
4526 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4527 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4528 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4529 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4531 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4532 | BGP_ATTR_FLAG_EXTLEN
);
4533 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4535 lcom_length(bgp_attr_get_lcommunity(attr
)));
4538 BGP_ATTR_FLAG_OPTIONAL
4539 | BGP_ATTR_FLAG_TRANS
);
4540 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4542 lcom_length(bgp_attr_get_lcommunity(attr
)));
4544 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4545 lcom_length(bgp_attr_get_lcommunity(attr
)));
4548 /* Route Reflector. */
4549 if (peer
->sort
== BGP_PEER_IBGP
&& from
4550 && from
->sort
== BGP_PEER_IBGP
) {
4551 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4553 /* Originator ID. */
4554 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4555 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4558 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4559 stream_put_in_addr(s
, &attr
->originator_id
);
4561 stream_put_in_addr(s
, &from
->remote_id
);
4564 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4565 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4568 stream_putc(s
, cluster
->length
+ 4);
4569 /* If this peer configuration's parent BGP has
4571 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4572 stream_put_in_addr(s
, &bgp
->cluster_id
);
4574 stream_put_in_addr(s
, &bgp
->router_id
);
4575 stream_put(s
, cluster
->list
, cluster
->length
);
4578 /* If this peer configuration's parent BGP has
4580 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4581 stream_put_in_addr(s
, &bgp
->cluster_id
);
4583 stream_put_in_addr(s
, &bgp
->router_id
);
4587 /* Extended Communities attribute. */
4588 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4589 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4590 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4591 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4592 PEER_FLAG_RSERVER_CLIENT
) &&
4594 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4595 PEER_FLAG_RSERVER_CLIENT
);
4597 if (peer
->sort
== BGP_PEER_IBGP
||
4598 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4599 if (ecomm
->size
* 8 > 255) {
4601 BGP_ATTR_FLAG_OPTIONAL
4602 | BGP_ATTR_FLAG_TRANS
4603 | BGP_ATTR_FLAG_EXTLEN
);
4604 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4605 stream_putw(s
, ecomm
->size
* 8);
4608 BGP_ATTR_FLAG_OPTIONAL
4609 | BGP_ATTR_FLAG_TRANS
);
4610 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4611 stream_putc(s
, ecomm
->size
* 8);
4613 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4617 int ecom_tr_size
= 0;
4620 for (i
= 0; i
< ecomm
->size
; i
++) {
4621 pnt
= ecomm
->val
+ (i
* 8);
4624 if (CHECK_FLAG(tbit
,
4625 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4632 if (ecom_tr_size
* 8 > 255) {
4635 BGP_ATTR_FLAG_OPTIONAL
4636 | BGP_ATTR_FLAG_TRANS
4637 | BGP_ATTR_FLAG_EXTLEN
);
4639 BGP_ATTR_EXT_COMMUNITIES
);
4640 stream_putw(s
, ecom_tr_size
* 8);
4644 BGP_ATTR_FLAG_OPTIONAL
4645 | BGP_ATTR_FLAG_TRANS
);
4647 BGP_ATTR_EXT_COMMUNITIES
);
4648 stream_putc(s
, ecom_tr_size
* 8);
4651 for (i
= 0; i
< ecomm
->size
; i
++) {
4652 pnt
= ecomm
->val
+ (i
* 8);
4657 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4660 stream_put(s
, pnt
, 8);
4666 /* Label index attribute. */
4667 if (safi
== SAFI_LABELED_UNICAST
) {
4668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4669 uint32_t label_index
;
4671 label_index
= attr
->label_index
;
4673 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4675 BGP_ATTR_FLAG_OPTIONAL
4676 | BGP_ATTR_FLAG_TRANS
);
4677 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4679 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4681 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4682 stream_putc(s
, 0); // reserved
4683 stream_putw(s
, 0); // flags
4684 stream_putl(s
, label_index
);
4689 /* SRv6 Service Information Attribute. */
4690 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4691 if (attr
->srv6_l3vpn
) {
4692 uint8_t subtlv_len
=
4693 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4695 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4696 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4697 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4698 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4699 | BGP_ATTR_FLAG_TRANS
);
4700 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4701 stream_putc(s
, attr_len
);
4702 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4703 stream_putw(s
, tlv_len
);
4704 stream_putc(s
, 0); /* reserved */
4705 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4706 stream_putw(s
, subtlv_len
);
4707 stream_putc(s
, 0); /* reserved */
4708 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4709 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4710 stream_putc(s
, 0); /* sid_flags */
4713 ->endpoint_behavior
); /* endpoint */
4714 stream_putc(s
, 0); /* reserved */
4717 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4720 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4721 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4722 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4723 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4724 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4725 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4726 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4727 } else if (attr
->srv6_vpn
) {
4728 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4729 | BGP_ATTR_FLAG_TRANS
);
4730 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4731 stream_putc(s
, 22); /* tlv len */
4732 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4733 stream_putw(s
, 0x13); /* tlv len */
4734 stream_putc(s
, 0x00); /* reserved */
4735 stream_putc(s
, 0x01); /* sid_type */
4736 stream_putc(s
, 0x00); /* sif_flags */
4737 stream_put(s
, &attr
->srv6_vpn
->sid
,
4738 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4742 if (send_as4_path
) {
4743 /* If the peer is NOT As4 capable, AND */
4744 /* there are ASnums > 65535 in path THEN
4745 * give out AS4_PATH */
4747 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4749 * Hm, I wonder... confederation things *should* only be at
4750 * the beginning of an aspath, right? Then we should use
4751 * aspath_delete_confed_seq for this, because it is already
4753 * Folks, talk to me: what is reasonable here!?
4755 aspath
= aspath_delete_confed_seq(aspath
);
4758 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4759 | BGP_ATTR_FLAG_EXTLEN
);
4760 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4761 aspath_sizep
= stream_get_endp(s
);
4763 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4766 if (aspath
!= attr
->aspath
)
4767 aspath_free(aspath
);
4769 if (send_as4_aggregator
) {
4770 /* send AS4_AGGREGATOR, at this place */
4771 /* this section of code moved here in order to ensure the
4773 * *ascending* order of attributes
4775 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4776 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4778 stream_putl(s
, attr
->aggregator_as
);
4779 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4782 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4783 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4784 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4785 /* Tunnel Encap attribute */
4786 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4788 #ifdef ENABLE_BGP_VNC_ATTR
4790 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4795 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4796 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4797 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4798 stream_putc(s
, 9); // Length
4799 stream_putc(s
, 0); // Flags
4800 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4801 stream_put(s
, &(attr
->label
),
4802 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4803 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4804 // Unicast tunnel endpoint IP address
4808 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4809 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4810 stream_putc(s
, BGP_ATTR_OTC
);
4812 stream_putl(s
, attr
->otc
);
4816 if (bpi
&& attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4817 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4818 peer
->sort
!= BGP_PEER_EBGP
)) {
4819 /* At the moment only AIGP Metric TLV exists for AIGP
4820 * attribute. If more comes in, do not forget to update
4821 * attr_len variable to include new ones.
4823 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4825 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4826 stream_putc(s
, BGP_ATTR_AIGP
);
4827 stream_putc(s
, attr_len
);
4828 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4831 /* Unknown transit attribute. */
4832 struct transit
*transit
= bgp_attr_get_transit(attr
);
4835 stream_put(s
, transit
->val
, transit
->length
);
4837 /* Return total size of attribute. */
4838 return stream_get_endp(s
) - cp
;
4841 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4843 unsigned long attrlen_pnt
;
4844 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4845 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4847 /* Set extended bit always to encode the attribute length as 2 bytes */
4848 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4849 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4851 attrlen_pnt
= stream_get_endp(s
);
4852 stream_putw(s
, 0); /* Length of this attribute. */
4854 /* Convert AFI, SAFI to values for packet. */
4855 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4857 stream_putw(s
, pkt_afi
);
4858 stream_putc(s
, pkt_safi
);
4863 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4864 afi_t afi
, safi_t safi
,
4865 const struct prefix_rd
*prd
,
4866 mpls_label_t
*label
, uint32_t num_labels
,
4867 bool addpath_capable
, uint32_t addpath_tx_id
,
4870 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4872 if (safi
== SAFI_LABELED_UNICAST
) {
4873 label
= (mpls_label_t
*)wlabel
;
4877 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4878 addpath_capable
, addpath_tx_id
, attr
);
4881 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4883 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4886 /* Initialization of attribute. */
4887 void bgp_attr_init(void)
4900 void bgp_attr_finish(void)
4905 ecommunity_finish();
4906 lcommunity_finish();
4913 /* Make attribute packet. */
4914 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4915 const struct prefix
*prefix
)
4920 struct aspath
*aspath
;
4921 bool addpath_capable
= false;
4922 uint32_t addpath_tx_id
= 0;
4923 struct attr
*attr
= bpi
->attr
;
4925 /* Remember current pointer. */
4926 cp
= stream_get_endp(s
);
4928 /* Place holder of length. */
4931 /* Origin attribute. */
4932 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4933 stream_putc(s
, BGP_ATTR_ORIGIN
);
4935 stream_putc(s
, attr
->origin
);
4937 aspath
= attr
->aspath
;
4939 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4940 stream_putc(s
, BGP_ATTR_AS_PATH
);
4941 aspath_lenp
= stream_get_endp(s
);
4944 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4946 /* Nexthop attribute. */
4947 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4948 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4949 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4950 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4952 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4955 /* MED attribute. */
4956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4957 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4958 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4960 stream_putl(s
, attr
->med
);
4963 /* Local preference. */
4964 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4965 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4966 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4968 stream_putl(s
, attr
->local_pref
);
4971 /* Atomic aggregate. */
4972 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4973 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4974 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4979 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4980 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4981 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4983 stream_putl(s
, attr
->aggregator_as
);
4984 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4987 /* Community attribute. */
4988 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4989 struct community
*comm
= NULL
;
4991 comm
= bgp_attr_get_community(attr
);
4992 if (comm
->size
* 4 > 255) {
4994 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4995 | BGP_ATTR_FLAG_EXTLEN
);
4996 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4997 stream_putw(s
, comm
->size
* 4);
5000 BGP_ATTR_FLAG_OPTIONAL
5001 | BGP_ATTR_FLAG_TRANS
);
5002 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
5003 stream_putc(s
, comm
->size
* 4);
5005 stream_put(s
, comm
->val
, comm
->size
* 4);
5008 /* Large Community attribute. */
5009 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
5010 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
5012 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
5013 | BGP_ATTR_FLAG_EXTLEN
);
5014 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
5016 lcom_length(bgp_attr_get_lcommunity(attr
)));
5019 BGP_ATTR_FLAG_OPTIONAL
5020 | BGP_ATTR_FLAG_TRANS
);
5021 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
5023 lcom_length(bgp_attr_get_lcommunity(attr
)));
5026 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
5027 lcom_length(bgp_attr_get_lcommunity(attr
)));
5030 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
5031 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
5032 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
5033 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
5036 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
5037 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
5038 sizep
= stream_get_endp(s
);
5041 stream_putc(s
, 0); /* Marker: Attribute length. */
5042 stream_putw(s
, AFI_IP6
); /* AFI */
5043 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
5046 stream_putc(s
, attr
->mp_nexthop_len
);
5047 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
5048 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
5049 stream_put(s
, &attr
->mp_nexthop_local
,
5056 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
5059 /* Set MP attribute length. */
5060 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
5064 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
5065 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5067 BGP_ATTR_FLAG_OPTIONAL
5068 | BGP_ATTR_FLAG_TRANS
);
5069 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
5071 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
5072 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
5073 stream_putc(s
, 0); // reserved
5074 stream_putw(s
, 0); // flags
5075 stream_putl(s
, attr
->label_index
);
5080 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
5081 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5082 stream_putc(s
, BGP_ATTR_OTC
);
5084 stream_putl(s
, attr
->otc
);
5088 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
5089 /* At the moment only AIGP Metric TLV exists for AIGP
5090 * attribute. If more comes in, do not forget to update
5091 * attr_len variable to include new ones.
5093 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
5095 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5096 stream_putc(s
, BGP_ATTR_AIGP
);
5097 stream_putc(s
, attr_len
);
5098 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
5101 /* Return total size of attribute. */
5102 len
= stream_get_endp(s
) - cp
- 2;
5103 stream_putw_at(s
, cp
, len
);
5106 void bgp_path_attribute_discard_vty(struct vty
*vty
, struct peer
*peer
,
5107 const char *discard_attrs
, bool set
)
5109 int i
, num_attributes
;
5115 /* If `no` command specified without arbitrary attributes,
5118 if (!discard_attrs
) {
5119 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5120 peer
->discard_attrs
[i
] = false;
5121 goto discard_soft_clear
;
5124 if (discard_attrs
) {
5125 frrstr_split(discard_attrs
, " ", &attributes
, &num_attributes
);
5128 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5129 peer
->discard_attrs
[i
] = false;
5131 for (i
= 0; i
< num_attributes
; i
++) {
5132 uint8_t attr_num
= strtoul(attributes
[i
], NULL
, 10);
5134 XFREE(MTYPE_TMP
, attributes
[i
]);
5136 /* Some of the attributes, just can't be ignored. */
5137 if (attr_num
== BGP_ATTR_ORIGIN
||
5138 attr_num
== BGP_ATTR_AS_PATH
||
5139 attr_num
== BGP_ATTR_NEXT_HOP
||
5140 attr_num
== BGP_ATTR_MULTI_EXIT_DISC
||
5141 attr_num
== BGP_ATTR_MP_REACH_NLRI
||
5142 attr_num
== BGP_ATTR_MP_UNREACH_NLRI
||
5143 attr_num
== BGP_ATTR_EXT_COMMUNITIES
) {
5145 "%% Can't discard path-attribute %s, ignoring.\n",
5146 lookup_msg(attr_str
, attr_num
, NULL
));
5150 /* Ignore local-pref, originator-id, cluster-list only
5153 if (peer
->sort
!= BGP_PEER_EBGP
&&
5154 (attr_num
== BGP_ATTR_LOCAL_PREF
||
5155 attr_num
== BGP_ATTR_ORIGINATOR_ID
||
5156 attr_num
== BGP_ATTR_CLUSTER_LIST
)) {
5158 "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5159 lookup_msg(attr_str
, attr_num
, NULL
));
5163 peer
->discard_attrs
[attr_num
] = set
;
5165 XFREE(MTYPE_TMP
, attributes
);
5167 /* Configuring path attributes to be discarded will trigger
5168 * an inbound Route Refresh to ensure that the routing table
5171 FOREACH_AFI_SAFI (afi
, safi
)
5172 peer_clear_soft(peer
, afi
, safi
, BGP_CLEAR_SOFT_IN
);