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();
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();
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
;
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1613 attr
->aspath
= aspath_parse(
1615 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1616 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr
->aspath
) {
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1621 "Malformed AS path from %s, length is %d", peer
->host
,
1623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1632 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1636 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1640 /* Set aspath attribute flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1647 struct attr
*const attr
)
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1654 * So do the checks later, i.e. here
1656 struct aspath
*aspath
;
1658 /* Confederation sanity check. */
1659 if ((peer
->sort
== BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr
->aspath
))
1661 || (peer
->sort
== BGP_PEER_EBGP
1662 && aspath_confed_check(attr
->aspath
))) {
1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1665 return BGP_ATTR_PARSE_WITHDRAW
;
1668 /* First AS check for EBGP. */
1669 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1670 if (peer
->sort
== BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1672 flog_err(EC_BGP_ATTR_FIRST_AS
,
1673 "%s incorrect first AS (must be %u)",
1674 peer
->host
, peer
->as
);
1675 return BGP_ATTR_PARSE_WITHDRAW
;
1679 /* Codification of AS 0 Processing */
1680 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1682 EC_BGP_ATTR_MAL_AS_PATH
,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1685 return BGP_ATTR_PARSE_WITHDRAW
;
1688 /* local-as prepend */
1689 if (peer
->change_local_as
1690 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1691 aspath
= aspath_dup(attr
->aspath
);
1692 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1693 aspath_unintern(&attr
->aspath
);
1694 attr
->aspath
= aspath_intern(aspath
);
1697 return BGP_ATTR_PARSE_PROCEED
;
1700 /* Parse AS4 path information. This function is another wrapper of
1702 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1703 struct aspath
**as4_path
)
1705 struct peer
*const peer
= args
->peer
;
1706 struct attr
*const attr
= args
->attr
;
1707 const bgp_size_t length
= args
->length
;
1709 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1711 /* In case of IBGP, length will be zero. */
1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1714 "Malformed AS4 path from %s, length is %d", peer
->host
,
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1725 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1733 /* Set aspath attribute flag. */
1734 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1736 return BGP_ATTR_PARSE_PROCEED
;
1740 * Check that the nexthop attribute is valid.
1742 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1745 struct bgp
*bgp
= peer
->bgp
;
1747 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1748 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1750 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1752 data
[0] = BGP_ATTR_FLAG_TRANS
;
1753 data
[1] = BGP_ATTR_NEXT_HOP
;
1754 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1755 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1756 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1757 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1759 return BGP_ATTR_PARSE_ERROR
;
1762 return BGP_ATTR_PARSE_PROCEED
;
1765 /* Nexthop attribute. */
1766 static enum bgp_attr_parse_ret
1767 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1769 struct peer
*const peer
= args
->peer
;
1770 struct attr
*const attr
= args
->attr
;
1771 const bgp_size_t length
= args
->length
;
1773 /* Check nexthop attribute length. */
1775 flog_err(EC_BGP_ATTR_LEN
,
1776 "Nexthop attribute length isn't four [%d]", length
);
1778 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1782 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1785 return BGP_ATTR_PARSE_PROCEED
;
1788 /* MED atrribute. */
1789 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1791 struct peer
*const peer
= args
->peer
;
1792 struct attr
*const attr
= args
->attr
;
1793 const bgp_size_t length
= args
->length
;
1797 flog_err(EC_BGP_ATTR_LEN
,
1798 "MED attribute length isn't four [%d]", length
);
1800 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1804 attr
->med
= stream_getl(peer
->curr
);
1806 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1808 return BGP_ATTR_PARSE_PROCEED
;
1811 /* Local preference attribute. */
1812 static enum bgp_attr_parse_ret
1813 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1815 struct peer
*const peer
= args
->peer
;
1816 struct attr
*const attr
= args
->attr
;
1817 const bgp_size_t length
= args
->length
;
1819 /* if received from an internal neighbor, it SHALL be considered
1820 * malformed if its length is not equal to 4. If malformed, the
1821 * UPDATE message SHALL be handled using the approach of "treat-as-
1824 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1825 flog_err(EC_BGP_ATTR_LEN
,
1826 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1827 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1831 /* If it is contained in an UPDATE message that is received from an
1832 external peer, then this attribute MUST be ignored by the
1833 receiving speaker. */
1834 if (peer
->sort
== BGP_PEER_EBGP
) {
1835 STREAM_FORWARD_GETP(peer
->curr
, length
);
1836 return BGP_ATTR_PARSE_PROCEED
;
1839 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1841 /* Set the local-pref flag. */
1842 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1844 return BGP_ATTR_PARSE_PROCEED
;
1847 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1851 /* Atomic aggregate. */
1852 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1854 struct peer
*const peer
= args
->peer
;
1855 struct attr
*const attr
= args
->attr
;
1856 const bgp_size_t length
= args
->length
;
1860 flog_err(EC_BGP_ATTR_LEN
,
1861 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1863 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1867 if (peer
->discard_attrs
[args
->type
])
1870 /* Set atomic aggregate flag. */
1871 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1873 return BGP_ATTR_PARSE_PROCEED
;
1876 stream_forward_getp(peer
->curr
, length
);
1878 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1879 zlog_debug("%pBP: Ignoring attribute %s", peer
,
1880 lookup_msg(attr_str
, args
->type
, NULL
));
1882 return BGP_ATTR_PARSE_PROCEED
;
1885 /* Aggregator attribute */
1886 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1888 struct peer
*const peer
= args
->peer
;
1889 struct attr
*const attr
= args
->attr
;
1890 const bgp_size_t length
= args
->length
;
1895 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1896 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1897 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1900 if (length
!= wantedlen
) {
1901 flog_err(EC_BGP_ATTR_LEN
,
1902 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1904 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1908 if (peer
->discard_attrs
[args
->type
])
1909 goto aggregator_ignore
;
1911 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1912 aggregator_as
= stream_getl(peer
->curr
);
1914 aggregator_as
= stream_getw(peer
->curr
);
1916 attr
->aggregator_as
= aggregator_as
;
1917 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1919 /* Codification of AS 0 Processing */
1920 if (aggregator_as
== BGP_AS_ZERO
) {
1921 flog_err(EC_BGP_ATTR_LEN
,
1922 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1923 peer
->host
, aspath_print(attr
->aspath
));
1925 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1926 char attr_str
[BUFSIZ
] = {0};
1928 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1930 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1933 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1936 return BGP_ATTR_PARSE_PROCEED
;
1939 stream_forward_getp(peer
->curr
, length
);
1941 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1942 zlog_debug("%pBP: Ignoring attribute %s", peer
,
1943 lookup_msg(attr_str
, args
->type
, NULL
));
1945 return BGP_ATTR_PARSE_PROCEED
;
1948 /* New Aggregator attribute */
1949 static enum bgp_attr_parse_ret
1950 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1951 as_t
*as4_aggregator_as
,
1952 struct in_addr
*as4_aggregator_addr
)
1954 struct peer
*const peer
= args
->peer
;
1955 struct attr
*const attr
= args
->attr
;
1956 const bgp_size_t length
= args
->length
;
1960 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1962 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1966 if (peer
->discard_attrs
[args
->type
])
1967 goto as4_aggregator_ignore
;
1969 aggregator_as
= stream_getl(peer
->curr
);
1971 *as4_aggregator_as
= aggregator_as
;
1972 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1974 /* Codification of AS 0 Processing */
1975 if (aggregator_as
== BGP_AS_ZERO
) {
1976 flog_err(EC_BGP_ATTR_LEN
,
1977 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1978 peer
->host
, aspath_print(attr
->aspath
));
1980 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1981 char attr_str
[BUFSIZ
] = {0};
1983 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1985 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1988 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1991 return BGP_ATTR_PARSE_PROCEED
;
1993 as4_aggregator_ignore
:
1994 stream_forward_getp(peer
->curr
, length
);
1996 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1997 zlog_debug("%pBP: Ignoring attribute %s", peer
,
1998 lookup_msg(attr_str
, args
->type
, NULL
));
2000 return BGP_ATTR_PARSE_PROCEED
;
2003 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
2005 static enum bgp_attr_parse_ret
2006 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
2007 struct aspath
*as4_path
, as_t as4_aggregator
,
2008 struct in_addr
*as4_aggregator_addr
)
2010 int ignore_as4_path
= 0;
2011 struct aspath
*newpath
;
2013 if (!attr
->aspath
) {
2014 /* NULL aspath shouldn't be possible as bgp_attr_parse should
2016 * checked that all well-known, mandatory attributes were
2019 * Can only be a problem with peer itself - hard error
2021 return BGP_ATTR_PARSE_ERROR
;
2024 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
2025 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2027 * It is worth a warning though, because the peer really
2028 * should not send them
2030 if (BGP_DEBUG(as4
, AS4
)) {
2031 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
2032 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
2033 "AS4 capable peer, yet it sent");
2036 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2037 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2039 "AS4 capable peer, yet it sent");
2042 return BGP_ATTR_PARSE_PROCEED
;
2045 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2046 * because that may override AS4_PATH
2048 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2049 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2051 * if the as_number in aggregator is not AS_TRANS,
2052 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2053 * and the Aggregator shall be taken as
2054 * info on the aggregating node, and the AS_PATH
2055 * shall be taken as the AS_PATH
2057 * the Aggregator shall be ignored and the
2058 * AS4_AGGREGATOR shall be taken as the
2059 * Aggregating node and the AS_PATH is to be
2060 * constructed "as in all other cases"
2062 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2064 if (BGP_DEBUG(as4
, AS4
))
2066 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2068 ignore_as4_path
= 1;
2070 /* "New_aggregator shall be taken as aggregator"
2072 attr
->aggregator_as
= as4_aggregator
;
2073 attr
->aggregator_addr
.s_addr
=
2074 as4_aggregator_addr
->s_addr
;
2077 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2078 * That is bogus - but reading the conditions
2079 * we have to handle AS4_AGGREGATOR as if it were
2080 * AGGREGATOR in that case
2082 if (BGP_DEBUG(as4
, AS4
))
2084 "[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",
2086 attr
->aggregator_as
= as4_aggregator
;
2087 /* sweep it under the carpet and simulate a "good"
2089 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2093 /* need to reconcile NEW_AS_PATH and AS_PATH */
2094 if (!ignore_as4_path
2095 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2096 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2098 return BGP_ATTR_PARSE_ERROR
;
2100 aspath_unintern(&attr
->aspath
);
2101 attr
->aspath
= aspath_intern(newpath
);
2103 return BGP_ATTR_PARSE_PROCEED
;
2106 /* Community attribute. */
2107 static enum bgp_attr_parse_ret
2108 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2110 struct peer
*const peer
= args
->peer
;
2111 struct attr
*const attr
= args
->attr
;
2112 const bgp_size_t length
= args
->length
;
2115 bgp_attr_set_community(attr
, NULL
);
2116 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2120 if (peer
->discard_attrs
[args
->type
])
2121 goto community_ignore
;
2123 bgp_attr_set_community(
2125 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2127 /* XXX: fix community_parse to use stream API and remove this */
2128 stream_forward_getp(peer
->curr
, length
);
2130 /* The Community attribute SHALL be considered malformed if its
2131 * length is not a non-zero multiple of 4.
2133 if (!bgp_attr_get_community(attr
))
2134 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2137 return BGP_ATTR_PARSE_PROCEED
;
2140 stream_forward_getp(peer
->curr
, length
);
2142 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2143 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2144 lookup_msg(attr_str
, args
->type
, NULL
));
2146 return BGP_ATTR_PARSE_PROCEED
;
2149 /* Originator ID attribute. */
2150 static enum bgp_attr_parse_ret
2151 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2153 struct peer
*const peer
= args
->peer
;
2154 struct attr
*const attr
= args
->attr
;
2155 const bgp_size_t length
= args
->length
;
2157 /* if received from an internal neighbor, it SHALL be considered
2158 * malformed if its length is not equal to 4. If malformed, the
2159 * UPDATE message SHALL be handled using the approach of "treat-as-
2163 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2166 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2170 if (peer
->discard_attrs
[args
->type
])
2171 goto originator_id_ignore
;
2173 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2175 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2177 return BGP_ATTR_PARSE_PROCEED
;
2179 originator_id_ignore
:
2180 stream_forward_getp(peer
->curr
, length
);
2182 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2183 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2184 lookup_msg(attr_str
, args
->type
, NULL
));
2186 return BGP_ATTR_PARSE_PROCEED
;
2189 /* Cluster list attribute. */
2190 static enum bgp_attr_parse_ret
2191 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2193 struct peer
*const peer
= args
->peer
;
2194 struct attr
*const attr
= args
->attr
;
2195 const bgp_size_t length
= args
->length
;
2197 /* if received from an internal neighbor, it SHALL be considered
2198 * malformed if its length is not a non-zero multiple of 4. If
2199 * malformed, the UPDATE message SHALL be handled using the approach
2200 * of "treat-as-withdraw".
2202 if (length
== 0 || length
% 4) {
2203 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2205 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2209 if (peer
->discard_attrs
[args
->type
])
2210 goto cluster_list_ignore
;
2212 bgp_attr_set_cluster(
2213 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2216 /* XXX: Fix cluster_parse to use stream API and then remove this */
2217 stream_forward_getp(peer
->curr
, length
);
2219 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2221 return BGP_ATTR_PARSE_PROCEED
;
2223 cluster_list_ignore
:
2224 stream_forward_getp(peer
->curr
, length
);
2226 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2227 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2228 lookup_msg(attr_str
, args
->type
, NULL
));
2230 return BGP_ATTR_PARSE_PROCEED
;
2233 /* Multiprotocol reachability information parse. */
2234 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2235 struct bgp_nlri
*mp_update
)
2239 iana_safi_t pkt_safi
;
2241 bgp_size_t nlri_len
;
2244 struct peer
*const peer
= args
->peer
;
2245 struct attr
*const attr
= args
->attr
;
2246 const bgp_size_t length
= args
->length
;
2248 /* Set end of packet. */
2249 s
= BGP_INPUT(peer
);
2250 start
= stream_get_getp(s
);
2252 /* safe to read statically sized header? */
2253 #define BGP_MP_REACH_MIN_SIZE 5
2254 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2255 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2256 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2257 __func__
, peer
->host
, (unsigned long)length
);
2258 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2261 /* Load AFI, SAFI. */
2262 pkt_afi
= stream_getw(s
);
2263 pkt_safi
= stream_getc(s
);
2265 /* Convert AFI, SAFI to internal values, check. */
2266 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2267 /* Log if AFI or SAFI is unrecognized. This is not an error
2269 * the attribute is otherwise malformed.
2271 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2273 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2274 peer
->host
, iana_afi2str(pkt_afi
),
2275 iana_safi2str(pkt_safi
));
2276 return BGP_ATTR_PARSE_ERROR
;
2279 /* Get nexthop length. */
2280 attr
->mp_nexthop_len
= stream_getc(s
);
2282 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2284 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2285 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2286 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2289 /* Nexthop length check. */
2290 switch (attr
->mp_nexthop_len
) {
2292 if (safi
!= SAFI_FLOWSPEC
) {
2293 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2294 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2295 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2298 case BGP_ATTR_NHLEN_VPNV4
:
2299 stream_getl(s
); /* RD high */
2300 stream_getl(s
); /* RD low */
2302 * NOTE: intentional fall through
2303 * - for consistency in rx processing
2305 * The following comment is to signal GCC this intention
2306 * and suppress the warning
2309 case BGP_ATTR_NHLEN_IPV4
:
2310 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2311 /* Probably needed for RFC 2283 */
2312 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2313 memcpy(&attr
->nexthop
.s_addr
,
2314 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2316 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2317 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2318 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2319 stream_getl(s
); /* RD high */
2320 stream_getl(s
); /* RD low */
2322 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2323 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2324 if (!peer
->nexthop
.ifp
) {
2325 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2327 return BGP_ATTR_PARSE_WITHDRAW
;
2329 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2332 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2333 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2334 if (attr
->mp_nexthop_len
2335 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2336 stream_getl(s
); /* RD high */
2337 stream_getl(s
); /* RD low */
2339 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2340 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2341 if (!peer
->nexthop
.ifp
) {
2342 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",
2344 return BGP_ATTR_PARSE_WITHDRAW
;
2346 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2348 if (attr
->mp_nexthop_len
2349 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2350 stream_getl(s
); /* RD high */
2351 stream_getl(s
); /* RD low */
2353 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2354 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2355 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2357 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2358 peer
->host
, &attr
->mp_nexthop_global
,
2359 &attr
->mp_nexthop_local
);
2361 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2363 if (!peer
->nexthop
.ifp
) {
2364 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2366 return BGP_ATTR_PARSE_WITHDRAW
;
2368 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2371 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2372 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2373 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2377 zlog_info("%s: %s sent SNPA which couldn't be read",
2378 __func__
, peer
->host
);
2379 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2384 if ((val
= stream_getc(s
)))
2386 EC_BGP_DEFUNCT_SNPA_LEN
,
2387 "%s sent non-zero value, %u, for defunct SNPA-length field",
2391 /* must have nrli_len, what is left of the attribute */
2392 nlri_len
= LEN_LEFT
;
2393 if (nlri_len
> STREAM_READABLE(s
)) {
2394 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2395 __func__
, peer
->host
);
2396 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2400 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2401 __func__
, peer
->host
);
2403 mp_update
->afi
= afi
;
2404 mp_update
->safi
= safi
;
2405 return BGP_ATTR_PARSE_EOR
;
2408 mp_update
->afi
= afi
;
2409 mp_update
->safi
= safi
;
2410 mp_update
->nlri
= stream_pnt(s
);
2411 mp_update
->length
= nlri_len
;
2413 stream_forward_getp(s
, nlri_len
);
2415 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2417 return BGP_ATTR_PARSE_PROCEED
;
2421 /* Multiprotocol unreachable parse */
2422 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2423 struct bgp_nlri
*mp_withdraw
)
2428 iana_safi_t pkt_safi
;
2430 uint16_t withdraw_len
;
2431 struct peer
*const peer
= args
->peer
;
2432 struct attr
*const attr
= args
->attr
;
2433 const bgp_size_t length
= args
->length
;
2437 #define BGP_MP_UNREACH_MIN_SIZE 3
2438 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2439 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2441 pkt_afi
= stream_getw(s
);
2442 pkt_safi
= stream_getc(s
);
2444 /* Convert AFI, SAFI to internal values, check. */
2445 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2446 /* Log if AFI or SAFI is unrecognized. This is not an error
2448 * the attribute is otherwise malformed.
2450 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2452 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2453 peer
->host
, iana_afi2str(pkt_afi
),
2454 iana_safi2str(pkt_safi
));
2455 return BGP_ATTR_PARSE_ERROR
;
2458 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2460 mp_withdraw
->afi
= afi
;
2461 mp_withdraw
->safi
= safi
;
2462 mp_withdraw
->nlri
= stream_pnt(s
);
2463 mp_withdraw
->length
= withdraw_len
;
2465 stream_forward_getp(s
, withdraw_len
);
2467 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2469 return BGP_ATTR_PARSE_PROCEED
;
2472 /* Large Community attribute. */
2473 static enum bgp_attr_parse_ret
2474 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2476 struct peer
*const peer
= args
->peer
;
2477 struct attr
*const attr
= args
->attr
;
2478 const bgp_size_t length
= args
->length
;
2481 * Large community follows new attribute format.
2484 bgp_attr_set_lcommunity(attr
, NULL
);
2485 /* Empty extcomm doesn't seem to be invalid per se */
2486 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2490 if (peer
->discard_attrs
[args
->type
])
2491 goto large_community_ignore
;
2493 bgp_attr_set_lcommunity(
2494 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2495 /* XXX: fix ecommunity_parse to use stream API */
2496 stream_forward_getp(peer
->curr
, length
);
2498 if (!bgp_attr_get_lcommunity(attr
))
2499 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2502 return BGP_ATTR_PARSE_PROCEED
;
2504 large_community_ignore
:
2505 stream_forward_getp(peer
->curr
, length
);
2507 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2508 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2509 lookup_msg(attr_str
, args
->type
, NULL
));
2511 return BGP_ATTR_PARSE_PROCEED
;
2514 /* Extended Community attribute. */
2515 static enum bgp_attr_parse_ret
2516 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2518 struct peer
*const peer
= args
->peer
;
2519 struct attr
*const attr
= args
->attr
;
2520 const bgp_size_t length
= args
->length
;
2523 struct ecommunity
*ecomm
;
2526 bgp_attr_set_ecommunity(attr
, NULL
);
2527 /* Empty extcomm doesn't seem to be invalid per se */
2528 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2532 ecomm
= ecommunity_parse(
2533 stream_pnt(peer
->curr
), length
,
2534 CHECK_FLAG(peer
->flags
,
2535 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2536 bgp_attr_set_ecommunity(attr
, ecomm
);
2537 /* XXX: fix ecommunity_parse to use stream API */
2538 stream_forward_getp(peer
->curr
, length
);
2540 /* The Extended Community attribute SHALL be considered malformed if
2541 * its length is not a non-zero multiple of 8.
2543 if (!bgp_attr_get_ecommunity(attr
))
2544 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2547 /* Extract DF election preference and mobility sequence number */
2548 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2550 /* Extract MAC mobility sequence number, if any. */
2551 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2552 attr
->sticky
= sticky
;
2554 /* Check if this is a Gateway MAC-IP advertisement */
2555 attr
->default_gw
= bgp_attr_default_gw(attr
);
2557 /* Handle scenario where router flag ecommunity is not
2558 * set but default gw ext community is present.
2559 * Use default gateway, set and propogate R-bit.
2561 if (attr
->default_gw
)
2562 attr
->router_flag
= 1;
2564 /* Check EVPN Neighbor advertisement flags, R-bit */
2565 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2567 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2569 /* Extract the Rmac, if any */
2570 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2571 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2572 && bgp_mac_exist(&attr
->rmac
))
2573 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2577 /* Get the tunnel type from encap extended community */
2578 bgp_attr_extcom_tunnel_type(attr
,
2579 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2581 /* Extract link bandwidth, if any. */
2582 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2585 return BGP_ATTR_PARSE_PROCEED
;
2588 /* IPv6 Extended Community attribute. */
2589 static enum bgp_attr_parse_ret
2590 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2592 struct peer
*const peer
= args
->peer
;
2593 struct attr
*const attr
= args
->attr
;
2594 const bgp_size_t length
= args
->length
;
2595 struct ecommunity
*ipv6_ecomm
= NULL
;
2598 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2599 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2603 if (peer
->discard_attrs
[args
->type
])
2604 goto ipv6_ext_community_ignore
;
2606 ipv6_ecomm
= ecommunity_parse_ipv6(
2607 stream_pnt(peer
->curr
), length
,
2608 CHECK_FLAG(peer
->flags
,
2609 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2610 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2612 /* XXX: fix ecommunity_parse to use stream API */
2613 stream_forward_getp(peer
->curr
, length
);
2616 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2619 return BGP_ATTR_PARSE_PROCEED
;
2621 ipv6_ext_community_ignore
:
2622 stream_forward_getp(peer
->curr
, length
);
2624 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2625 zlog_debug("%pBP: Ignoring attribute %s", peer
,
2626 lookup_msg(attr_str
, args
->type
, NULL
));
2628 return BGP_ATTR_PARSE_PROCEED
;
2631 /* Parse Tunnel Encap attribute in an UPDATE */
2632 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2633 bgp_size_t length
, /* IN: attr's length field */
2634 struct attr
*attr
, /* IN: caller already allocated */
2635 uint8_t flag
, /* IN: attr's flags field */
2639 uint16_t tunneltype
= 0;
2641 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2643 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2644 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2646 "Tunnel Encap attribute flag isn't optional and transitive %d",
2648 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2649 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2654 if (BGP_ATTR_ENCAP
== type
) {
2655 /* read outer TLV type and length */
2656 uint16_t tlv_length
;
2660 "Tunnel Encap attribute not long enough to contain outer T,L");
2661 bgp_notify_send_with_data(
2662 peer
, BGP_NOTIFY_UPDATE_ERR
,
2663 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2666 tunneltype
= stream_getw(BGP_INPUT(peer
));
2667 tlv_length
= stream_getw(BGP_INPUT(peer
));
2670 if (tlv_length
!= length
) {
2671 zlog_info("%s: tlv_length(%d) != length(%d)",
2672 __func__
, tlv_length
, length
);
2676 while (length
>= 4) {
2677 uint16_t subtype
= 0;
2678 uint16_t sublength
= 0;
2679 struct bgp_attr_encap_subtlv
*tlv
;
2681 if (BGP_ATTR_ENCAP
== type
) {
2682 subtype
= stream_getc(BGP_INPUT(peer
));
2683 sublength
= stream_getc(BGP_INPUT(peer
));
2685 #ifdef ENABLE_BGP_VNC
2687 subtype
= stream_getw(BGP_INPUT(peer
));
2688 sublength
= stream_getw(BGP_INPUT(peer
));
2693 if (sublength
> length
) {
2695 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2697 bgp_notify_send_with_data(
2698 peer
, BGP_NOTIFY_UPDATE_ERR
,
2699 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2703 /* alloc and copy sub-tlv */
2704 /* TBD make sure these are freed when attributes are released */
2705 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2706 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2707 tlv
->type
= subtype
;
2708 tlv
->length
= sublength
;
2709 stream_get(tlv
->value
, peer
->curr
, sublength
);
2710 length
-= sublength
;
2712 /* attach tlv to encap chain */
2713 if (BGP_ATTR_ENCAP
== type
) {
2714 struct bgp_attr_encap_subtlv
*stlv_last
;
2715 for (stlv_last
= attr
->encap_subtlvs
;
2716 stlv_last
&& stlv_last
->next
;
2717 stlv_last
= stlv_last
->next
)
2720 stlv_last
->next
= tlv
;
2722 attr
->encap_subtlvs
= tlv
;
2724 #ifdef ENABLE_BGP_VNC
2726 struct bgp_attr_encap_subtlv
*stlv_last
;
2727 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2728 bgp_attr_get_vnc_subtlvs(attr
);
2730 for (stlv_last
= vnc_subtlvs
;
2731 stlv_last
&& stlv_last
->next
;
2732 stlv_last
= stlv_last
->next
)
2735 stlv_last
->next
= tlv
;
2737 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2742 if (BGP_ATTR_ENCAP
== type
) {
2743 attr
->encap_tunneltype
= tunneltype
;
2747 /* spurious leftover data */
2749 "Tunnel Encap attribute length is bad: %d leftover octets",
2751 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2752 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2761 /* SRv6 Service Data Sub-Sub-TLV attribute
2762 * draft-ietf-bess-srv6-services-07
2764 static enum bgp_attr_parse_ret
2765 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2767 struct peer
*const peer
= args
->peer
;
2768 struct attr
*const attr
= args
->attr
;
2769 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2770 transposition_len
, transposition_offset
;
2772 size_t headersz
= sizeof(type
) + sizeof(length
);
2774 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2777 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2778 headersz
, STREAM_READABLE(peer
->curr
));
2779 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2783 type
= stream_getc(peer
->curr
);
2784 length
= stream_getw(peer
->curr
);
2786 if (STREAM_READABLE(peer
->curr
) < length
) {
2789 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2790 length
, STREAM_READABLE(peer
->curr
));
2791 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2795 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2798 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2799 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2801 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2805 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2806 if (STREAM_READABLE(peer
->curr
) <
2807 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2810 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2811 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2812 STREAM_READABLE(peer
->curr
));
2813 return bgp_attr_malformed(
2814 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2818 loc_block_len
= stream_getc(peer
->curr
);
2819 loc_node_len
= stream_getc(peer
->curr
);
2820 func_len
= stream_getc(peer
->curr
);
2821 arg_len
= stream_getc(peer
->curr
);
2822 transposition_len
= stream_getc(peer
->curr
);
2823 transposition_offset
= stream_getc(peer
->curr
);
2825 /* Log SRv6 Service Data Sub-Sub-TLV */
2826 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2828 "%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",
2829 __func__
, loc_block_len
, loc_node_len
, func_len
,
2830 arg_len
, transposition_len
,
2831 transposition_offset
);
2834 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2835 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2836 attr
->srv6_l3vpn
->func_len
= func_len
;
2837 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2838 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2839 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2843 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2845 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2848 stream_forward_getp(peer
->curr
, length
);
2851 return BGP_ATTR_PARSE_PROCEED
;
2854 /* SRv6 Service Sub-TLV attribute
2855 * draft-ietf-bess-srv6-services-07
2857 static enum bgp_attr_parse_ret
2858 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2860 struct peer
*const peer
= args
->peer
;
2861 struct attr
*const attr
= args
->attr
;
2862 struct in6_addr ipv6_sid
;
2863 uint8_t type
, sid_flags
;
2864 uint16_t length
, endpoint_behavior
;
2865 size_t headersz
= sizeof(type
) + sizeof(length
);
2866 enum bgp_attr_parse_ret err
;
2868 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2871 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2872 headersz
, STREAM_READABLE(peer
->curr
));
2873 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2877 type
= stream_getc(peer
->curr
);
2878 length
= stream_getw(peer
->curr
);
2880 if (STREAM_READABLE(peer
->curr
) < length
) {
2883 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2884 length
, STREAM_READABLE(peer
->curr
));
2885 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2889 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2890 if (STREAM_READABLE(peer
->curr
) <
2891 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2894 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2895 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2896 STREAM_READABLE(peer
->curr
));
2897 return bgp_attr_malformed(
2898 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2901 stream_getc(peer
->curr
);
2902 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2903 sid_flags
= stream_getc(peer
->curr
);
2904 endpoint_behavior
= stream_getw(peer
->curr
);
2905 stream_getc(peer
->curr
);
2907 /* Log SRv6 Service Sub-TLV */
2908 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2910 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2911 __func__
, &ipv6_sid
, sid_flags
,
2914 /* Configure from Info */
2915 if (attr
->srv6_l3vpn
) {
2916 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2917 "Prefix SID SRv6 L3VPN field repeated");
2918 return bgp_attr_malformed(
2919 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2921 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2922 sizeof(struct bgp_attr_srv6_l3vpn
));
2923 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2924 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2925 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2926 attr
->srv6_l3vpn
->loc_block_len
= 0;
2927 attr
->srv6_l3vpn
->loc_node_len
= 0;
2928 attr
->srv6_l3vpn
->func_len
= 0;
2929 attr
->srv6_l3vpn
->arg_len
= 0;
2930 attr
->srv6_l3vpn
->transposition_len
= 0;
2931 attr
->srv6_l3vpn
->transposition_offset
= 0;
2933 // Sub-Sub-TLV found
2934 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2935 err
= bgp_attr_srv6_service_data(args
);
2937 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2941 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2944 /* Placeholder code for unsupported type */
2946 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2948 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2951 stream_forward_getp(peer
->curr
, length
);
2954 return BGP_ATTR_PARSE_PROCEED
;
2958 * Read an individual SID value returning how much data we have read
2959 * Returns 0 if there was an error that needs to be passed up the stack
2961 static enum bgp_attr_parse_ret
2962 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2963 struct bgp_attr_parser_args
*args
)
2965 struct peer
*const peer
= args
->peer
;
2966 struct attr
*const attr
= args
->attr
;
2967 uint32_t label_index
;
2968 struct in6_addr ipv6_sid
;
2970 uint32_t srgb_range
;
2972 uint8_t sid_type
, sid_flags
;
2974 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2975 if (STREAM_READABLE(peer
->curr
) < length
2976 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2977 flog_err(EC_BGP_ATTR_LEN
,
2978 "Prefix SID label index length is %hu instead of %u",
2979 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2980 return bgp_attr_malformed(args
,
2981 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2985 /* Ignore flags and reserved */
2986 stream_getc(peer
->curr
);
2987 stream_getw(peer
->curr
);
2989 /* Fetch the label index and see if it is valid. */
2990 label_index
= stream_getl(peer
->curr
);
2991 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2992 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2995 /* Store label index; subsequently, we'll check on
2997 attr
->label_index
= label_index
;
3000 /* Placeholder code for the IPv6 SID type */
3001 else if (type
== BGP_PREFIX_SID_IPV6
) {
3002 if (STREAM_READABLE(peer
->curr
) < length
3003 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
3004 flog_err(EC_BGP_ATTR_LEN
,
3005 "Prefix SID IPv6 length is %hu instead of %u",
3006 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
3007 return bgp_attr_malformed(args
,
3008 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3012 /* Ignore reserved */
3013 stream_getc(peer
->curr
);
3014 stream_getw(peer
->curr
);
3016 stream_get(&ipv6_sid
, peer
->curr
, 16);
3019 /* Placeholder code for the Originator SRGB type */
3020 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
3022 * ietf-idr-bgp-prefix-sid-05:
3023 * Length is the total length of the value portion of the
3024 * TLV: 2 + multiple of 6.
3026 * peer->curr stream readp should be at the beginning of the 16
3027 * bit flag field at this point in the code.
3031 * Check that the TLV length field is sane: at least 2 bytes of
3032 * flag, and at least 1 SRGB (these are 6 bytes each)
3034 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
3037 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3039 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3040 return bgp_attr_malformed(
3041 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3046 * Check that we actually have at least as much data as
3047 * specified by the length field
3049 if (STREAM_READABLE(peer
->curr
) < length
) {
3050 flog_err(EC_BGP_ATTR_LEN
,
3051 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
3052 length
, STREAM_READABLE(peer
->curr
));
3053 return bgp_attr_malformed(
3054 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3059 * Check that the portion of the TLV containing the sequence of
3060 * SRGBs corresponds to a multiple of the SRGB size; to get
3061 * that length, we skip the 16 bit flags field
3063 stream_getw(peer
->curr
);
3065 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
3068 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3069 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3070 return bgp_attr_malformed(
3071 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3075 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
3077 for (int i
= 0; i
< srgb_count
; i
++) {
3078 stream_get(&srgb_base
, peer
->curr
, 3);
3079 stream_get(&srgb_range
, peer
->curr
, 3);
3083 /* Placeholder code for the VPN-SID Service type */
3084 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
3085 if (STREAM_READABLE(peer
->curr
) < length
3086 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
3087 flog_err(EC_BGP_ATTR_LEN
,
3088 "Prefix SID VPN SID length is %hu instead of %u",
3089 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
3090 return bgp_attr_malformed(args
,
3091 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3095 /* Parse VPN-SID Sub-TLV */
3096 stream_getc(peer
->curr
); /* reserved */
3097 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3098 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3099 stream_get(&ipv6_sid
, peer
->curr
,
3100 sizeof(ipv6_sid
)); /* sid_value */
3102 /* Log VPN-SID Sub-TLV */
3103 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3105 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3106 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3108 /* Configure from Info */
3109 if (attr
->srv6_vpn
) {
3110 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3111 "Prefix SID SRv6 VPN field repeated");
3112 return bgp_attr_malformed(
3113 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3115 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3116 sizeof(struct bgp_attr_srv6_vpn
));
3117 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3118 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3119 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3122 /* Placeholder code for the SRv6 L3 Service type */
3123 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3124 if (STREAM_READABLE(peer
->curr
) < length
) {
3127 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3128 length
, STREAM_READABLE(peer
->curr
));
3129 return bgp_attr_malformed(args
,
3130 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3134 /* ignore reserved */
3135 stream_getc(peer
->curr
);
3137 return bgp_attr_srv6_service(args
);
3140 /* Placeholder code for Unsupported TLV */
3143 if (STREAM_READABLE(peer
->curr
) < length
) {
3146 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3147 length
, STREAM_READABLE(peer
->curr
));
3148 return bgp_attr_malformed(
3149 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3153 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3155 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3158 stream_forward_getp(peer
->curr
, length
);
3161 return BGP_ATTR_PARSE_PROCEED
;
3164 /* Prefix SID attribute
3165 * draft-ietf-idr-bgp-prefix-sid-05
3167 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3169 struct peer
*const peer
= args
->peer
;
3170 struct attr
*const attr
= args
->attr
;
3171 enum bgp_attr_parse_ret ret
;
3173 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3177 size_t headersz
= sizeof(type
) + sizeof(length
);
3178 size_t psid_parsed_length
= 0;
3180 while (STREAM_READABLE(peer
->curr
) > 0
3181 && psid_parsed_length
< args
->length
) {
3183 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3186 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3187 headersz
, STREAM_READABLE(peer
->curr
));
3188 return bgp_attr_malformed(
3189 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3193 type
= stream_getc(peer
->curr
);
3194 length
= stream_getw(peer
->curr
);
3196 if (STREAM_READABLE(peer
->curr
) < length
) {
3199 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3200 length
, STREAM_READABLE(peer
->curr
));
3201 return bgp_attr_malformed(args
,
3202 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3206 ret
= bgp_attr_psid_sub(type
, length
, args
);
3208 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3211 psid_parsed_length
+= length
+ headersz
;
3213 if (psid_parsed_length
> args
->length
) {
3216 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3217 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3218 return bgp_attr_malformed(
3219 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3224 return BGP_ATTR_PARSE_PROCEED
;
3227 /* PMSI tunnel attribute (RFC 6514)
3228 * Basic validation checks done here.
3230 static enum bgp_attr_parse_ret
3231 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3233 struct peer
*const peer
= args
->peer
;
3234 struct attr
*const attr
= args
->attr
;
3235 const bgp_size_t length
= args
->length
;
3237 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3239 /* Verify that the receiver is expecting "ingress replication" as we
3240 * can only support that.
3242 if (length
< attr_parse_len
) {
3243 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3245 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3248 stream_getc(peer
->curr
); /* Flags */
3249 tnl_type
= stream_getc(peer
->curr
);
3250 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3251 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3252 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3253 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3256 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3258 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3259 "Bad PMSI tunnel attribute length %d for IR",
3261 return bgp_attr_malformed(
3262 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3267 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3268 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3269 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3271 /* Forward read pointer of input stream. */
3272 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3274 return BGP_ATTR_PARSE_PROCEED
;
3277 /* AIGP attribute (rfc7311) */
3278 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3280 struct peer
*const peer
= args
->peer
;
3281 struct attr
*const attr
= args
->attr
;
3282 const bgp_size_t length
= args
->length
;
3283 uint8_t *s
= stream_pnt(peer
->curr
);
3286 /* If an AIGP attribute is received on a BGP session for which
3287 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3288 * as if it were an unrecognized non-transitive attribute.
3289 * That is, it "MUST be quietly ignored and not passed along to
3291 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3292 * sessions between members of the same BGP Confederation,
3293 * the default value of AIGP_SESSION SHOULD be "enabled".
3295 if (peer
->sort
== BGP_PEER_EBGP
&&
3296 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3298 "%pBP received AIGP attribute, but eBGP peer do not support it",
3303 if (peer
->discard_attrs
[args
->type
])
3306 if (!bgp_attr_aigp_valid(s
, length
))
3309 /* Extract AIGP Metric TLV */
3310 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3311 bgp_attr_set_aigp_metric(attr
, aigp
);
3314 stream_forward_getp(peer
->curr
, length
);
3316 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3317 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3318 lookup_msg(attr_str
, args
->type
, NULL
));
3320 return BGP_ATTR_PARSE_PROCEED
;
3323 /* OTC attribute. */
3324 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3326 struct peer
*const peer
= args
->peer
;
3327 struct attr
*const attr
= args
->attr
;
3328 const bgp_size_t length
= args
->length
;
3332 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3334 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3338 if (peer
->discard_attrs
[args
->type
])
3341 attr
->otc
= stream_getl(peer
->curr
);
3343 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3344 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3348 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3350 return BGP_ATTR_PARSE_PROCEED
;
3353 stream_forward_getp(peer
->curr
, length
);
3355 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3356 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3357 lookup_msg(attr_str
, args
->type
, NULL
));
3359 return BGP_ATTR_PARSE_PROCEED
;
3362 /* BGP unknown attribute treatment. */
3363 static enum bgp_attr_parse_ret
3364 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3366 bgp_size_t total
= args
->total
;
3367 struct transit
*transit
;
3368 struct peer
*const peer
= args
->peer
;
3369 struct attr
*const attr
= args
->attr
;
3370 uint8_t *const startp
= args
->startp
;
3371 const uint8_t type
= args
->type
;
3372 const uint8_t flag
= args
->flags
;
3373 const bgp_size_t length
= args
->length
;
3375 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3377 "%s Unknown attribute is received (type %d, length %d)",
3378 peer
->host
, type
, length
);
3380 /* Forward read pointer of input stream. */
3381 stream_forward_getp(peer
->curr
, length
);
3383 if (peer
->discard_attrs
[type
]) {
3384 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3385 zlog_debug("%pBP: Ignoring attribute %s", peer
,
3386 lookup_msg(attr_str
, args
->type
, NULL
));
3388 return BGP_ATTR_PARSE_PROCEED
;
3391 /* If any of the mandatory well-known attributes are not recognized,
3392 then the Error Subcode is set to Unrecognized Well-known
3393 Attribute. The Data field contains the unrecognized attribute
3394 (type, length and value). */
3395 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3396 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3400 /* Unrecognized non-transitive optional attributes must be quietly
3401 ignored and not passed along to other BGP peers. */
3402 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3403 return BGP_ATTR_PARSE_PROCEED
;
3405 /* If a path with recognized transitive optional attribute is
3406 accepted and passed along to other BGP peers and the Partial bit
3407 in the Attribute Flags octet is set to 1 by some previous AS, it
3408 is not set back to 0 by the current AS. */
3409 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3411 /* Store transitive attribute to the end of attr->transit. */
3412 transit
= bgp_attr_get_transit(attr
);
3414 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3416 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3417 transit
->length
+ total
);
3419 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3420 transit
->length
+= total
;
3421 bgp_attr_set_transit(attr
, transit
);
3423 return BGP_ATTR_PARSE_PROCEED
;
3426 /* Well-known attribute check. */
3427 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3431 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3433 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3434 return BGP_ATTR_PARSE_PROCEED
;
3436 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3437 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3438 are present, it should. Check for any other attribute being present
3441 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3442 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3443 return BGP_ATTR_PARSE_PROCEED
;
3445 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3446 type
= BGP_ATTR_ORIGIN
;
3448 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3449 type
= BGP_ATTR_AS_PATH
;
3451 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3453 * NLRI is empty. We can't easily check NLRI empty here though.
3455 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3456 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3457 type
= BGP_ATTR_NEXT_HOP
;
3459 if (peer
->sort
== BGP_PEER_IBGP
3460 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3461 type
= BGP_ATTR_LOCAL_PREF
;
3463 /* If any of the well-known mandatory attributes are not present
3464 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3467 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3468 "%s Missing well-known attribute %s.", peer
->host
,
3469 lookup_msg(attr_str
, type
, NULL
));
3470 return BGP_ATTR_PARSE_WITHDRAW
;
3472 return BGP_ATTR_PARSE_PROCEED
;
3475 /* Read attribute of update packet. This function is called from
3476 bgp_update_receive() in bgp_packet.c. */
3477 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3479 struct bgp_nlri
*mp_update
,
3480 struct bgp_nlri
*mp_withdraw
)
3482 enum bgp_attr_parse_ret ret
;
3486 uint8_t *startp
, *endp
;
3488 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3489 /* we need the as4_path only until we have synthesized the as_path with
3491 /* same goes for as4_aggregator */
3492 struct aspath
*as4_path
= NULL
;
3493 as_t as4_aggregator
= 0;
3494 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3495 struct transit
*transit
;
3497 /* Initialize bitmap. */
3498 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3500 /* End pointer of BGP attribute. */
3501 endp
= BGP_INPUT_PNT(peer
) + size
;
3503 /* Get attributes to the end of attribute length. */
3504 while (BGP_INPUT_PNT(peer
) < endp
) {
3505 /* Check remaining length check.*/
3506 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3507 /* XXX warning: long int format, int arg (arg 5) */
3509 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3510 "%s: error BGP attribute length %lu is smaller than min len",
3512 (unsigned long)(endp
3513 - stream_pnt(BGP_INPUT(peer
))));
3515 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3516 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3517 ret
= BGP_ATTR_PARSE_ERROR
;
3521 /* Fetch attribute flag and type. */
3522 startp
= BGP_INPUT_PNT(peer
);
3523 /* "The lower-order four bits of the Attribute Flags octet are
3524 unused. They MUST be zero when sent and MUST be ignored when
3526 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3527 type
= stream_getc(BGP_INPUT(peer
));
3529 /* Check whether Extended-Length applies and is in bounds */
3530 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3531 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3533 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3534 "%s: Extended length set, but just %lu bytes of attr header",
3536 (unsigned long)(endp
3537 - stream_pnt(BGP_INPUT(peer
))));
3539 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3540 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3541 ret
= BGP_ATTR_PARSE_ERROR
;
3545 /* Check extended attribue length bit. */
3546 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3547 length
= stream_getw(BGP_INPUT(peer
));
3549 length
= stream_getc(BGP_INPUT(peer
));
3551 /* If any attribute appears more than once in the UPDATE
3552 message, then the Error Subcode is set to Malformed Attribute
3555 if (CHECK_BITMAP(seen
, type
)) {
3557 EC_BGP_ATTRIBUTE_REPEATED
,
3558 "%s: error BGP attribute type %d appears twice in a message",
3561 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3562 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3563 ret
= BGP_ATTR_PARSE_ERROR
;
3567 /* Set type to bitmap to check duplicate attribute. `type' is
3568 unsigned char so it never overflow bitmap range. */
3570 SET_BITMAP(seen
, type
);
3572 /* Overflow check. */
3573 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3575 if (attr_endp
> endp
) {
3577 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3578 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3579 peer
->host
, type
, length
, size
, attr_endp
,
3583 * If any recognized attribute has an Attribute
3584 * Length that conflicts with the expected length
3585 * (based on the attribute type code), then the
3586 * Error Subcode MUST be set to Attribute Length
3587 * Error. The Data field MUST contain the erroneous
3588 * attribute (type, length, and value).
3590 * We do not currently have a good way to determine the
3591 * length of the attribute independent of the length
3592 * received in the message. Instead we send the
3593 * minimum between the amount of data we have and the
3594 * amount specified by the attribute length field.
3596 * Instead of directly passing in the packet buffer and
3597 * offset we use the stream_get* functions to read into
3598 * a stack buffer, since they perform bounds checking
3599 * and we are working with untrusted data.
3601 unsigned char ndata
[peer
->max_packet_size
];
3602 memset(ndata
, 0x00, sizeof(ndata
));
3604 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3605 /* Rewind to end of flag field */
3606 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3608 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3610 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3612 size_t atl
= attr_endp
- startp
;
3613 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3614 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3616 bgp_notify_send_with_data(
3617 peer
, BGP_NOTIFY_UPDATE_ERR
,
3618 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3621 ret
= BGP_ATTR_PARSE_ERROR
;
3625 struct bgp_attr_parser_args attr_args
= {
3632 .total
= attr_endp
- startp
,
3636 /* If any recognized attribute has Attribute Flags that conflict
3637 with the Attribute Type Code, then the Error Subcode is set
3639 Attribute Flags Error. The Data field contains the erroneous
3640 attribute (type, length and value). */
3641 if (bgp_attr_flag_invalid(&attr_args
)) {
3642 ret
= bgp_attr_malformed(
3643 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3645 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3650 /* OK check attribute and store it's value. */
3652 case BGP_ATTR_ORIGIN
:
3653 ret
= bgp_attr_origin(&attr_args
);
3655 case BGP_ATTR_AS_PATH
:
3656 ret
= bgp_attr_aspath(&attr_args
);
3658 case BGP_ATTR_AS4_PATH
:
3659 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3661 case BGP_ATTR_NEXT_HOP
:
3662 ret
= bgp_attr_nexthop(&attr_args
);
3664 case BGP_ATTR_MULTI_EXIT_DISC
:
3665 ret
= bgp_attr_med(&attr_args
);
3667 case BGP_ATTR_LOCAL_PREF
:
3668 ret
= bgp_attr_local_pref(&attr_args
);
3670 case BGP_ATTR_ATOMIC_AGGREGATE
:
3671 ret
= bgp_attr_atomic(&attr_args
);
3673 case BGP_ATTR_AGGREGATOR
:
3674 ret
= bgp_attr_aggregator(&attr_args
);
3676 case BGP_ATTR_AS4_AGGREGATOR
:
3677 ret
= bgp_attr_as4_aggregator(&attr_args
,
3679 &as4_aggregator_addr
);
3681 case BGP_ATTR_COMMUNITIES
:
3682 ret
= bgp_attr_community(&attr_args
);
3684 case BGP_ATTR_LARGE_COMMUNITIES
:
3685 ret
= bgp_attr_large_community(&attr_args
);
3687 case BGP_ATTR_ORIGINATOR_ID
:
3688 ret
= bgp_attr_originator_id(&attr_args
);
3690 case BGP_ATTR_CLUSTER_LIST
:
3691 ret
= bgp_attr_cluster_list(&attr_args
);
3693 case BGP_ATTR_MP_REACH_NLRI
:
3694 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3696 case BGP_ATTR_MP_UNREACH_NLRI
:
3697 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3699 case BGP_ATTR_EXT_COMMUNITIES
:
3700 ret
= bgp_attr_ext_communities(&attr_args
);
3702 #ifdef ENABLE_BGP_VNC_ATTR
3705 case BGP_ATTR_ENCAP
:
3706 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3709 case BGP_ATTR_PREFIX_SID
:
3710 ret
= bgp_attr_prefix_sid(&attr_args
);
3712 case BGP_ATTR_PMSI_TUNNEL
:
3713 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3715 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3716 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3719 ret
= bgp_attr_otc(&attr_args
);
3722 ret
= bgp_attr_aigp(&attr_args
);
3725 ret
= bgp_attr_unknown(&attr_args
);
3729 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3730 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3731 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3732 ret
= BGP_ATTR_PARSE_ERROR
;
3736 if (ret
== BGP_ATTR_PARSE_EOR
) {
3740 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3741 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3742 "%s: Attribute %s, parse error", peer
->host
,
3743 lookup_msg(attr_str
, type
, NULL
));
3746 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3748 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3749 "%s: Attribute %s, parse error - treating as withdrawal",
3750 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3754 /* Check the fetched length. */
3755 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3756 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3757 "%s: BGP attribute %s, fetch error",
3758 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3759 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3760 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3761 ret
= BGP_ATTR_PARSE_ERROR
;
3767 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3768 * About Prefix-SID path attribute,
3769 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3770 * may only appear in a BGP Prefix-SID attribute attached to
3771 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3772 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3774 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3775 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3777 /* Check final read pointer is same as end pointer. */
3778 if (BGP_INPUT_PNT(peer
) != endp
) {
3779 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3780 "%s: BGP attribute %s, length mismatch", peer
->host
,
3781 lookup_msg(attr_str
, type
, NULL
));
3782 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3783 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3785 ret
= BGP_ATTR_PARSE_ERROR
;
3790 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3791 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3792 * This is implemented below and will result in a NOTIFICATION. If the
3793 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3794 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3795 * message SHOULD NOT be sent. This is implemented elsewhere.
3797 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3798 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3799 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3800 * speaker that receives the message SHOULD ignore this attribute.
3802 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3803 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3804 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3805 ret
= BGP_ATTR_PARSE_ERROR
;
3810 /* Check all mandatory well-known attributes are present */
3811 ret
= bgp_attr_check(peer
, attr
);
3816 * At this place we can see whether we got AS4_PATH and/or
3817 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3818 * We can not do this before we've read all attributes because
3819 * the as4 handling does not say whether AS4_PATH has to be sent
3820 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3821 * in relationship to AGGREGATOR.
3822 * So, to be defensive, we are not relying on any order and read
3823 * all attributes first, including these 32bit ones, and now,
3824 * afterwards, we look what and if something is to be done for as4.
3826 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3829 /* actually... this doesn't ever return failure currently, but
3830 * better safe than sorry */
3831 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3832 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3833 &as4_aggregator_addr
)) {
3834 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3835 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3836 ret
= BGP_ATTR_PARSE_ERROR
;
3841 * Finally do the checks on the aspath we did not do yet
3842 * because we waited for a potentially synthesized aspath.
3844 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3845 ret
= bgp_attr_aspath_check(peer
, attr
);
3846 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3850 ret
= BGP_ATTR_PARSE_PROCEED
;
3854 * At this stage, we have done all fiddling with as4, and the
3855 * resulting info is in attr->aggregator resp. attr->aspath so
3856 * we can chuck as4_aggregator and as4_path alltogether in order
3860 * unintern - it is in the hash
3861 * The flag that we got this is still there, but that
3862 * does not do any trouble
3864 aspath_unintern(&as4_path
);
3866 transit
= bgp_attr_get_transit(attr
);
3867 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3868 /* Finally intern unknown attribute. */
3870 bgp_attr_set_transit(attr
, transit_intern(transit
));
3871 if (attr
->encap_subtlvs
)
3872 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3874 #ifdef ENABLE_BGP_VNC
3875 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3876 bgp_attr_get_vnc_subtlvs(attr
);
3879 bgp_attr_set_vnc_subtlvs(
3881 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3885 transit_free(transit
);
3886 bgp_attr_set_transit(attr
, NULL
);
3889 bgp_attr_flush_encap(attr
);
3893 transit
= bgp_attr_get_transit(attr
);
3895 assert(transit
->refcnt
> 0);
3896 if (attr
->encap_subtlvs
)
3897 assert(attr
->encap_subtlvs
->refcnt
> 0);
3898 #ifdef ENABLE_BGP_VNC
3899 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3900 bgp_attr_get_vnc_subtlvs(attr
);
3903 assert(vnc_subtlvs
->refcnt
> 0);
3910 * Extract the tunnel type from extended community
3912 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3913 bgp_encap_types
*tunnel_type
)
3915 struct ecommunity
*ecom
;
3921 ecom
= bgp_attr_get_ecommunity(attr
);
3922 if (!ecom
|| !ecom
->size
)
3925 for (i
= 0; i
< ecom
->size
; i
++) {
3927 uint8_t type
, sub_type
;
3929 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3932 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3933 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3935 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3942 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3943 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3947 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3948 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3951 /* Set extended bit always to encode the attribute length as 2 bytes */
3952 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3953 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3954 sizep
= stream_get_endp(s
);
3955 stream_putw(s
, 0); /* Marker: Attribute length. */
3958 /* Convert AFI, SAFI to values for packet. */
3959 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3961 stream_putw(s
, pkt_afi
); /* AFI */
3962 stream_putc(s
, pkt_safi
); /* SAFI */
3966 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3967 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3968 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3969 else if (safi
== SAFI_FLOWSPEC
)
3972 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3975 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3980 case SAFI_MULTICAST
:
3981 case SAFI_LABELED_UNICAST
:
3983 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3987 stream_putl(s
, 0); /* RD = 0, per RFC */
3989 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3994 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3997 if (attr
->mp_nexthop_len
== 0)
3998 stream_putc(s
, 0); /* no nexthop for flowspec */
4000 stream_putc(s
, attr
->mp_nexthop_len
);
4001 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4006 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4013 case SAFI_MULTICAST
:
4014 case SAFI_LABELED_UNICAST
:
4016 if (attr
->mp_nexthop_len
4017 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
4019 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
4020 stream_put(s
, &attr
->mp_nexthop_global
,
4022 stream_put(s
, &attr
->mp_nexthop_local
,
4025 stream_putc(s
, IPV6_MAX_BYTELEN
);
4026 stream_put(s
, &attr
->mp_nexthop_global
,
4030 case SAFI_MPLS_VPN
: {
4031 if (attr
->mp_nexthop_len
==
4032 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
4034 stream_putl(s
, 0); /* RD = 0, per RFC */
4036 stream_put(s
, &attr
->mp_nexthop_global
,
4038 stream_putl(s
, 0); /* RD = 0, per RFC */
4040 stream_put(s
, &attr
->mp_nexthop_local
,
4044 stream_putl(s
, 0); /* RD = 0, per RFC */
4046 stream_put(s
, &attr
->mp_nexthop_global
,
4051 stream_putc(s
, IPV6_MAX_BYTELEN
);
4052 stream_put(s
, &attr
->mp_nexthop_global
,
4056 stream_putc(s
, 0); /* no nexthop for flowspec */
4060 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4065 if (safi
!= SAFI_FLOWSPEC
)
4067 EC_BGP_ATTR_NH_SEND_LEN
,
4068 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
4069 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
4073 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
4082 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
4083 const struct prefix
*p
,
4084 const struct prefix_rd
*prd
, mpls_label_t
*label
,
4085 uint32_t num_labels
, bool addpath_capable
,
4086 uint32_t addpath_tx_id
, struct attr
*attr
)
4091 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4094 if (addpath_capable
)
4095 stream_putl(s
, addpath_tx_id
);
4096 /* Label, RD, Prefix write. */
4097 stream_putc(s
, p
->prefixlen
+ 88);
4098 stream_put(s
, label
, BGP_LABEL_BYTES
);
4099 stream_put(s
, prd
->val
, 8);
4100 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
4103 if (afi
== AFI_L2VPN
)
4104 /* EVPN prefix - contents depend on type */
4105 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
,
4106 attr
, addpath_capable
,
4109 assert(!"Add encoding bits here for other AFI's");
4111 case SAFI_LABELED_UNICAST
:
4112 /* Prefix write with label. */
4113 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
4117 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
4118 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
4119 p
->u
.prefix_flowspec
.prefixlen
);
4123 case SAFI_MULTICAST
:
4124 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
4127 assert(!"Please add proper encoding of SAFI_ENCAP");
4132 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
4133 const struct prefix
*p
)
4135 int size
= PSIZE(p
->prefixlen
);
4140 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4143 case SAFI_MULTICAST
:
4149 /* This has to be wrong, but I don't know what to put here */
4150 assert(!"Do we try to use this?");
4152 case SAFI_LABELED_UNICAST
:
4153 size
+= BGP_LABEL_BYTES
;
4157 * TODO: Maximum possible for type-2, type-3 and type-5
4159 if (afi
== AFI_L2VPN
)
4162 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4165 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
4173 * Encodes the tunnel encapsulation attribute,
4174 * and with ENABLE_BGP_VNC the VNC attribute which uses
4175 * almost the same TLV format
4177 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4178 struct stream
*s
, struct attr
*attr
,
4181 unsigned int attrlenfield
= 0;
4182 unsigned int attrhdrlen
= 0;
4183 struct bgp_attr_encap_subtlv
*subtlvs
;
4184 struct bgp_attr_encap_subtlv
*st
;
4185 const char *attrname
;
4187 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4188 && (!attr
->encap_tunneltype
4189 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4193 case BGP_ATTR_ENCAP
:
4194 attrname
= "Tunnel Encap";
4195 subtlvs
= attr
->encap_subtlvs
;
4196 if (subtlvs
== NULL
) /* nothing to do */
4199 * The tunnel encap attr has an "outer" tlv.
4201 * L = total length of subtlvs,
4202 * V = concatenated subtlvs.
4204 attrlenfield
= 2 + 2; /* T + L */
4205 attrhdrlen
= 1 + 1; /* subTLV T + L */
4208 #ifdef ENABLE_BGP_VNC_ATTR
4211 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4212 if (subtlvs
== NULL
) /* nothing to do */
4214 attrlenfield
= 0; /* no outer T + L */
4215 attrhdrlen
= 2 + 2; /* subTLV T + L */
4223 /* compute attr length */
4224 for (st
= subtlvs
; st
; st
= st
->next
) {
4225 attrlenfield
+= (attrhdrlen
+ st
->length
);
4228 if (attrlenfield
> 0xffff) {
4229 zlog_info("%s attribute is too long (length=%d), can't send it",
4230 attrname
, attrlenfield
);
4234 if (attrlenfield
> 0xff) {
4235 /* 2-octet length field */
4237 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4238 | BGP_ATTR_FLAG_EXTLEN
);
4239 stream_putc(s
, attrtype
);
4240 stream_putw(s
, attrlenfield
& 0xffff);
4242 /* 1-octet length field */
4243 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4244 stream_putc(s
, attrtype
);
4245 stream_putc(s
, attrlenfield
& 0xff);
4248 if (attrtype
== BGP_ATTR_ENCAP
) {
4249 /* write outer T+L */
4250 stream_putw(s
, attr
->encap_tunneltype
);
4251 stream_putw(s
, attrlenfield
- 4);
4254 /* write each sub-tlv */
4255 for (st
= subtlvs
; st
; st
= st
->next
) {
4256 if (attrtype
== BGP_ATTR_ENCAP
) {
4257 stream_putc(s
, st
->type
);
4258 stream_putc(s
, st
->length
);
4259 #ifdef ENABLE_BGP_VNC
4261 stream_putw(s
, st
->type
);
4262 stream_putw(s
, st
->length
);
4265 stream_put(s
, st
->value
, st
->length
);
4269 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4271 /* Set MP attribute length. Don't count the (2) bytes used to encode
4273 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4276 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4278 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4279 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4280 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4281 PEER_FLAG_REMOVE_PRIVATE_AS
)
4282 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4283 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4284 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4285 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4286 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4287 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4292 /* Make attribute packet. */
4293 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4294 struct stream
*s
, struct attr
*attr
,
4295 struct bpacket_attr_vec_arr
*vecarr
,
4296 struct prefix
*p
, afi_t afi
, safi_t safi
,
4297 struct peer
*from
, struct prefix_rd
*prd
,
4298 mpls_label_t
*label
, uint32_t num_labels
,
4299 bool addpath_capable
, uint32_t addpath_tx_id
,
4300 struct bgp_path_info
*bpi
)
4303 size_t aspath_sizep
;
4304 struct aspath
*aspath
;
4305 int send_as4_path
= 0;
4306 int send_as4_aggregator
= 0;
4307 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4308 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4313 /* Remember current pointer. */
4314 cp
= stream_get_endp(s
);
4317 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4318 && !peer_cap_enhe(peer
, afi
, safi
))) {
4319 size_t mpattrlen_pos
= 0;
4321 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4323 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4324 num_labels
, addpath_capable
,
4325 addpath_tx_id
, attr
);
4326 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4329 /* Origin attribute. */
4330 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4331 stream_putc(s
, BGP_ATTR_ORIGIN
);
4333 stream_putc(s
, attr
->origin
);
4335 /* AS path attribute. */
4337 /* If remote-peer is EBGP */
4338 if (peer
->sort
== BGP_PEER_EBGP
4339 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4340 PEER_FLAG_AS_PATH_UNCHANGED
)
4341 || attr
->aspath
->segments
== NULL
)
4342 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4343 PEER_FLAG_RSERVER_CLIENT
))) {
4344 aspath
= aspath_dup(attr
->aspath
);
4346 /* Even though we may not be configured for confederations we
4348 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4349 aspath
= aspath_delete_confed_seq(aspath
);
4351 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4352 /* Stuff our path CONFED_ID on the front */
4353 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4355 if (peer
->change_local_as
) {
4356 /* If replace-as is specified, we only use the
4357 change_local_as when
4358 advertising routes. */
4359 if (!CHECK_FLAG(peer
->flags
,
4360 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4361 if (bgp_append_local_as(peer
, afi
,
4363 aspath
= aspath_add_seq(
4364 aspath
, peer
->local_as
);
4365 aspath
= aspath_add_seq(aspath
,
4366 peer
->change_local_as
);
4368 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4371 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4372 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4374 aspath
= aspath_dup(attr
->aspath
);
4375 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4377 aspath
= attr
->aspath
;
4379 /* If peer is not AS4 capable, then:
4380 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4381 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4383 * types are in it (i.e. exclude them if they are there)
4384 * AND do this only if there is at least one asnum > 65535 in the
4386 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4388 * all ASnums > 65535 to BGP_AS_TRANS
4391 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4392 stream_putc(s
, BGP_ATTR_AS_PATH
);
4393 aspath_sizep
= stream_get_endp(s
);
4395 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4397 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4400 if (!use32bit
&& aspath_has_as4(aspath
))
4402 1; /* we'll do this later, at the correct place */
4404 /* Nexthop attribute. */
4405 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4406 && !peer_cap_enhe(peer
, afi
, safi
)) {
4407 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4410 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4411 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4412 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4415 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4416 } else if (peer_cap_enhe(from
, afi
, safi
)
4417 || (nh_afi
== AFI_IP6
)) {
4419 * Likely this is the case when an IPv4 prefix was
4420 * received with Extended Next-hop capability in this
4421 * or another vrf and is now being advertised to
4422 * non-ENHE peers. Since peer_cap_enhe only checks
4423 * peers in this vrf, also check the nh_afi to catch
4424 * the case where the originator was in another vrf.
4425 * Setting the mandatory (ipv4) next-hop attribute here
4426 * to enable implicit next-hop self with correct A-F
4427 * (ipv4 address family).
4429 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4430 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4431 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4434 stream_put_ipv4(s
, 0);
4438 /* MED attribute. */
4439 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4440 || bgp
->maxmed_active
) {
4441 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4442 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4444 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4448 /* Local preference. */
4449 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4450 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4451 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4453 stream_putl(s
, attr
->local_pref
);
4456 /* Atomic aggregate. */
4457 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4458 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4459 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4464 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4465 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4466 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4467 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4470 /* AS4 capable peer */
4472 stream_putl(s
, attr
->aggregator_as
);
4474 /* 2-byte AS peer */
4477 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4479 if (attr
->aggregator_as
> UINT16_MAX
) {
4480 stream_putw(s
, BGP_AS_TRANS
);
4482 /* we have to send AS4_AGGREGATOR, too.
4483 * we'll do that later in order to send
4484 * attributes in ascending
4487 send_as4_aggregator
= 1;
4489 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4491 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4494 /* Community attribute. */
4495 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4496 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4497 struct community
*comm
= NULL
;
4499 comm
= bgp_attr_get_community(attr
);
4500 if (comm
->size
* 4 > 255) {
4502 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4503 | BGP_ATTR_FLAG_EXTLEN
);
4504 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4505 stream_putw(s
, comm
->size
* 4);
4508 BGP_ATTR_FLAG_OPTIONAL
4509 | BGP_ATTR_FLAG_TRANS
);
4510 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4511 stream_putc(s
, comm
->size
* 4);
4513 stream_put(s
, comm
->val
, comm
->size
* 4);
4517 * Large Community attribute.
4519 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4520 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4521 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4522 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4524 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4525 | BGP_ATTR_FLAG_EXTLEN
);
4526 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4528 lcom_length(bgp_attr_get_lcommunity(attr
)));
4531 BGP_ATTR_FLAG_OPTIONAL
4532 | BGP_ATTR_FLAG_TRANS
);
4533 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4535 lcom_length(bgp_attr_get_lcommunity(attr
)));
4537 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4538 lcom_length(bgp_attr_get_lcommunity(attr
)));
4541 /* Route Reflector. */
4542 if (peer
->sort
== BGP_PEER_IBGP
&& from
4543 && from
->sort
== BGP_PEER_IBGP
) {
4544 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4546 /* Originator ID. */
4547 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4548 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4551 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4552 stream_put_in_addr(s
, &attr
->originator_id
);
4554 stream_put_in_addr(s
, &from
->remote_id
);
4557 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4558 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4561 stream_putc(s
, cluster
->length
+ 4);
4562 /* If this peer configuration's parent BGP has
4564 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4565 stream_put_in_addr(s
, &bgp
->cluster_id
);
4567 stream_put_in_addr(s
, &bgp
->router_id
);
4568 stream_put(s
, cluster
->list
, cluster
->length
);
4571 /* If this peer configuration's parent BGP has
4573 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4574 stream_put_in_addr(s
, &bgp
->cluster_id
);
4576 stream_put_in_addr(s
, &bgp
->router_id
);
4580 /* Extended Communities attribute. */
4581 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4582 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4583 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4584 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4585 PEER_FLAG_RSERVER_CLIENT
) &&
4587 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4588 PEER_FLAG_RSERVER_CLIENT
);
4590 if (peer
->sort
== BGP_PEER_IBGP
||
4591 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4592 if (ecomm
->size
* 8 > 255) {
4594 BGP_ATTR_FLAG_OPTIONAL
4595 | BGP_ATTR_FLAG_TRANS
4596 | BGP_ATTR_FLAG_EXTLEN
);
4597 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4598 stream_putw(s
, ecomm
->size
* 8);
4601 BGP_ATTR_FLAG_OPTIONAL
4602 | BGP_ATTR_FLAG_TRANS
);
4603 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4604 stream_putc(s
, ecomm
->size
* 8);
4606 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4610 int ecom_tr_size
= 0;
4613 for (i
= 0; i
< ecomm
->size
; i
++) {
4614 pnt
= ecomm
->val
+ (i
* 8);
4617 if (CHECK_FLAG(tbit
,
4618 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4625 if (ecom_tr_size
* 8 > 255) {
4628 BGP_ATTR_FLAG_OPTIONAL
4629 | BGP_ATTR_FLAG_TRANS
4630 | BGP_ATTR_FLAG_EXTLEN
);
4632 BGP_ATTR_EXT_COMMUNITIES
);
4633 stream_putw(s
, ecom_tr_size
* 8);
4637 BGP_ATTR_FLAG_OPTIONAL
4638 | BGP_ATTR_FLAG_TRANS
);
4640 BGP_ATTR_EXT_COMMUNITIES
);
4641 stream_putc(s
, ecom_tr_size
* 8);
4644 for (i
= 0; i
< ecomm
->size
; i
++) {
4645 pnt
= ecomm
->val
+ (i
* 8);
4650 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4653 stream_put(s
, pnt
, 8);
4659 /* Label index attribute. */
4660 if (safi
== SAFI_LABELED_UNICAST
) {
4661 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4662 uint32_t label_index
;
4664 label_index
= attr
->label_index
;
4666 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4668 BGP_ATTR_FLAG_OPTIONAL
4669 | BGP_ATTR_FLAG_TRANS
);
4670 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4672 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4674 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4675 stream_putc(s
, 0); // reserved
4676 stream_putw(s
, 0); // flags
4677 stream_putl(s
, label_index
);
4682 /* SRv6 Service Information Attribute. */
4683 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4684 if (attr
->srv6_l3vpn
) {
4685 uint8_t subtlv_len
=
4686 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4688 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4689 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4690 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4691 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4692 | BGP_ATTR_FLAG_TRANS
);
4693 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4694 stream_putc(s
, attr_len
);
4695 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4696 stream_putw(s
, tlv_len
);
4697 stream_putc(s
, 0); /* reserved */
4698 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4699 stream_putw(s
, subtlv_len
);
4700 stream_putc(s
, 0); /* reserved */
4701 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4702 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4703 stream_putc(s
, 0); /* sid_flags */
4706 ->endpoint_behavior
); /* endpoint */
4707 stream_putc(s
, 0); /* reserved */
4710 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4713 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4714 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4715 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4716 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4717 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4718 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4719 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4720 } else if (attr
->srv6_vpn
) {
4721 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4722 | BGP_ATTR_FLAG_TRANS
);
4723 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4724 stream_putc(s
, 22); /* tlv len */
4725 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4726 stream_putw(s
, 0x13); /* tlv len */
4727 stream_putc(s
, 0x00); /* reserved */
4728 stream_putc(s
, 0x01); /* sid_type */
4729 stream_putc(s
, 0x00); /* sif_flags */
4730 stream_put(s
, &attr
->srv6_vpn
->sid
,
4731 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4735 if (send_as4_path
) {
4736 /* If the peer is NOT As4 capable, AND */
4737 /* there are ASnums > 65535 in path THEN
4738 * give out AS4_PATH */
4740 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4742 * Hm, I wonder... confederation things *should* only be at
4743 * the beginning of an aspath, right? Then we should use
4744 * aspath_delete_confed_seq for this, because it is already
4746 * Folks, talk to me: what is reasonable here!?
4748 aspath
= aspath_delete_confed_seq(aspath
);
4751 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4752 | BGP_ATTR_FLAG_EXTLEN
);
4753 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4754 aspath_sizep
= stream_get_endp(s
);
4756 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4759 if (aspath
!= attr
->aspath
)
4760 aspath_free(aspath
);
4762 if (send_as4_aggregator
) {
4763 /* send AS4_AGGREGATOR, at this place */
4764 /* this section of code moved here in order to ensure the
4766 * *ascending* order of attributes
4768 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4769 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4771 stream_putl(s
, attr
->aggregator_as
);
4772 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4775 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4776 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4777 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4778 /* Tunnel Encap attribute */
4779 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4781 #ifdef ENABLE_BGP_VNC_ATTR
4783 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4788 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4789 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4790 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4791 stream_putc(s
, 9); // Length
4792 stream_putc(s
, 0); // Flags
4793 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4794 stream_put(s
, &(attr
->label
),
4795 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4796 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4797 // Unicast tunnel endpoint IP address
4801 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4802 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4803 stream_putc(s
, BGP_ATTR_OTC
);
4805 stream_putl(s
, attr
->otc
);
4809 if (bpi
&& attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4810 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4811 peer
->sort
!= BGP_PEER_EBGP
)) {
4812 /* At the moment only AIGP Metric TLV exists for AIGP
4813 * attribute. If more comes in, do not forget to update
4814 * attr_len variable to include new ones.
4816 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4818 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4819 stream_putc(s
, BGP_ATTR_AIGP
);
4820 stream_putc(s
, attr_len
);
4821 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4824 /* Unknown transit attribute. */
4825 struct transit
*transit
= bgp_attr_get_transit(attr
);
4828 stream_put(s
, transit
->val
, transit
->length
);
4830 /* Return total size of attribute. */
4831 return stream_get_endp(s
) - cp
;
4834 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4836 unsigned long attrlen_pnt
;
4837 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4838 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4840 /* Set extended bit always to encode the attribute length as 2 bytes */
4841 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4842 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4844 attrlen_pnt
= stream_get_endp(s
);
4845 stream_putw(s
, 0); /* Length of this attribute. */
4847 /* Convert AFI, SAFI to values for packet. */
4848 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4850 stream_putw(s
, pkt_afi
);
4851 stream_putc(s
, pkt_safi
);
4856 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4857 afi_t afi
, safi_t safi
,
4858 const struct prefix_rd
*prd
,
4859 mpls_label_t
*label
, uint32_t num_labels
,
4860 bool addpath_capable
, uint32_t addpath_tx_id
,
4863 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4865 if (safi
== SAFI_LABELED_UNICAST
) {
4866 label
= (mpls_label_t
*)wlabel
;
4870 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4871 addpath_capable
, addpath_tx_id
, attr
);
4874 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4876 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4879 /* Initialization of attribute. */
4880 void bgp_attr_init(void)
4893 void bgp_attr_finish(void)
4898 ecommunity_finish();
4899 lcommunity_finish();
4906 /* Make attribute packet. */
4907 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4908 const struct prefix
*prefix
)
4913 struct aspath
*aspath
;
4914 bool addpath_capable
= false;
4915 uint32_t addpath_tx_id
= 0;
4916 struct attr
*attr
= bpi
->attr
;
4918 /* Remember current pointer. */
4919 cp
= stream_get_endp(s
);
4921 /* Place holder of length. */
4924 /* Origin attribute. */
4925 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4926 stream_putc(s
, BGP_ATTR_ORIGIN
);
4928 stream_putc(s
, attr
->origin
);
4930 aspath
= attr
->aspath
;
4932 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4933 stream_putc(s
, BGP_ATTR_AS_PATH
);
4934 aspath_lenp
= stream_get_endp(s
);
4937 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4939 /* Nexthop attribute. */
4940 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4941 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4942 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4943 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4945 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4948 /* MED attribute. */
4949 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4950 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4951 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4953 stream_putl(s
, attr
->med
);
4956 /* Local preference. */
4957 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4958 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4959 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4961 stream_putl(s
, attr
->local_pref
);
4964 /* Atomic aggregate. */
4965 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4966 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4967 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4972 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4973 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4974 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4976 stream_putl(s
, attr
->aggregator_as
);
4977 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4980 /* Community attribute. */
4981 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4982 struct community
*comm
= NULL
;
4984 comm
= bgp_attr_get_community(attr
);
4985 if (comm
->size
* 4 > 255) {
4987 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4988 | BGP_ATTR_FLAG_EXTLEN
);
4989 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4990 stream_putw(s
, comm
->size
* 4);
4993 BGP_ATTR_FLAG_OPTIONAL
4994 | BGP_ATTR_FLAG_TRANS
);
4995 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4996 stream_putc(s
, comm
->size
* 4);
4998 stream_put(s
, comm
->val
, comm
->size
* 4);
5001 /* Large Community attribute. */
5002 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
5003 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
5005 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
5006 | BGP_ATTR_FLAG_EXTLEN
);
5007 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
5009 lcom_length(bgp_attr_get_lcommunity(attr
)));
5012 BGP_ATTR_FLAG_OPTIONAL
5013 | BGP_ATTR_FLAG_TRANS
);
5014 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
5016 lcom_length(bgp_attr_get_lcommunity(attr
)));
5019 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
5020 lcom_length(bgp_attr_get_lcommunity(attr
)));
5023 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
5024 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
5025 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
5026 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
5029 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
5030 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
5031 sizep
= stream_get_endp(s
);
5034 stream_putc(s
, 0); /* Marker: Attribute length. */
5035 stream_putw(s
, AFI_IP6
); /* AFI */
5036 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
5039 stream_putc(s
, attr
->mp_nexthop_len
);
5040 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
5041 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
5042 stream_put(s
, &attr
->mp_nexthop_local
,
5049 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
5052 /* Set MP attribute length. */
5053 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
5057 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
5058 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5060 BGP_ATTR_FLAG_OPTIONAL
5061 | BGP_ATTR_FLAG_TRANS
);
5062 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
5064 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
5065 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
5066 stream_putc(s
, 0); // reserved
5067 stream_putw(s
, 0); // flags
5068 stream_putl(s
, attr
->label_index
);
5073 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
5074 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5075 stream_putc(s
, BGP_ATTR_OTC
);
5077 stream_putl(s
, attr
->otc
);
5081 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
5082 /* At the moment only AIGP Metric TLV exists for AIGP
5083 * attribute. If more comes in, do not forget to update
5084 * attr_len variable to include new ones.
5086 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
5088 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5089 stream_putc(s
, BGP_ATTR_AIGP
);
5090 stream_putc(s
, attr_len
);
5091 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
5094 /* Return total size of attribute. */
5095 len
= stream_get_endp(s
) - cp
- 2;
5096 stream_putw_at(s
, cp
, len
);
5099 void bgp_path_attribute_discard_vty(struct vty
*vty
, struct peer
*peer
,
5100 const char *discard_attrs
, bool set
)
5102 int i
, num_attributes
;
5108 /* If `no` command specified without arbitrary attributes,
5111 if (!discard_attrs
) {
5112 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5113 peer
->discard_attrs
[i
] = false;
5114 goto discard_soft_clear
;
5117 if (discard_attrs
) {
5118 frrstr_split(discard_attrs
, " ", &attributes
, &num_attributes
);
5121 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5122 peer
->discard_attrs
[i
] = false;
5124 for (i
= 0; i
< num_attributes
; i
++) {
5125 uint8_t attr_num
= strtoul(attributes
[i
], NULL
, 10);
5127 XFREE(MTYPE_TMP
, attributes
[i
]);
5129 /* Some of the attributes, just can't be ignored. */
5130 if (attr_num
== BGP_ATTR_ORIGIN
||
5131 attr_num
== BGP_ATTR_AS_PATH
||
5132 attr_num
== BGP_ATTR_NEXT_HOP
||
5133 attr_num
== BGP_ATTR_MULTI_EXIT_DISC
||
5134 attr_num
== BGP_ATTR_MP_REACH_NLRI
||
5135 attr_num
== BGP_ATTR_MP_UNREACH_NLRI
||
5136 attr_num
== BGP_ATTR_EXT_COMMUNITIES
) {
5138 "%% Can't discard path-attribute %s, ignoring.\n",
5139 lookup_msg(attr_str
, attr_num
, NULL
));
5143 /* Ignore local-pref, originator-id, cluster-list only
5146 if (peer
->sort
!= BGP_PEER_EBGP
&&
5147 (attr_num
== BGP_ATTR_LOCAL_PREF
||
5148 attr_num
== BGP_ATTR_ORIGINATOR_ID
||
5149 attr_num
== BGP_ATTR_CLUSTER_LIST
)) {
5151 "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5152 lookup_msg(attr_str
, attr_num
, NULL
));
5156 peer
->discard_attrs
[attr_num
] = set
;
5158 XFREE(MTYPE_TMP
, attributes
);
5160 /* Configuring path attributes to be discarded will trigger
5161 * an inbound Route Refresh to ensure that the routing table
5164 FOREACH_AFI_SAFI (afi
, safi
)
5165 peer_clear_soft(peer
, afi
, safi
, BGP_CLEAR_SOFT_IN
);