1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2016 6WIND
3 * Copyright (C) 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
7 * FRRouting is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * FRRouting is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "bgpd/bgp_attr_evpn.h"
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_table.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_mplsvpn.h"
41 #include "bgpd/bgp_label.h"
42 #include "bgpd/bgp_evpn.h"
43 #include "bgpd/bgp_evpn_private.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_encap_types.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_zebra.h"
51 * Definitions and external declarations.
53 extern struct zclient
*zclient
;
55 DEFINE_QOBJ_TYPE(bgpevpn
)
59 * Static function declarations
61 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
62 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
63 struct bgp_info
**ri
);
64 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
);
73 static unsigned int vni_hash_key_make(void *p
)
75 struct bgpevpn
*vpn
= p
;
76 return (jhash_1word(vpn
->vni
, 0));
80 * Comparison function for vni hash
82 static int vni_hash_cmp(const void *p1
, const void *p2
)
84 const struct bgpevpn
*vpn1
= p1
;
85 const struct bgpevpn
*vpn2
= p2
;
91 return (vpn1
->vni
== vpn2
->vni
);
95 * Make import route target hash key.
97 static unsigned int import_rt_hash_key_make(void *p
)
99 struct irt_node
*irt
= p
;
100 char *pnt
= irt
->rt
.val
;
101 unsigned int key
= 0;
117 * Comparison function for import rt hash
119 static int import_rt_hash_cmp(const void *p1
, const void *p2
)
121 const struct irt_node
*irt1
= p1
;
122 const struct irt_node
*irt2
= p2
;
124 if (irt1
== NULL
&& irt2
== NULL
)
127 if (irt1
== NULL
|| irt2
== NULL
)
130 return (memcmp(irt1
->rt
.val
, irt2
->rt
.val
, ECOMMUNITY_SIZE
) == 0);
134 * Create a new import_rt
136 static struct irt_node
*import_rt_new(struct bgp
*bgp
,
137 struct ecommunity_val
*rt
)
139 struct irt_node
*irt
;
144 irt
= XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT
, sizeof(struct irt_node
));
149 irt
->vnis
= list_new();
152 if (!hash_get(bgp
->import_rt_hash
, irt
, hash_alloc_intern
)) {
153 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
161 * Free the import rt node
163 static void import_rt_free(struct bgp
*bgp
, struct irt_node
*irt
)
165 hash_release(bgp
->import_rt_hash
, irt
);
166 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
170 * Function to lookup Import RT node - used to map a RT to set of
171 * VNIs importing routes with that RT.
173 static struct irt_node
*lookup_import_rt(struct bgp
*bgp
,
174 struct ecommunity_val
*rt
)
176 struct irt_node
*irt
;
179 memset(&tmp
, 0, sizeof(struct irt_node
));
180 memcpy(&tmp
.rt
, rt
, ECOMMUNITY_SIZE
);
181 irt
= hash_lookup(bgp
->import_rt_hash
, &tmp
);
186 * Is specified VNI present on the RT's list of "importing" VNIs?
188 static int is_vni_present_in_irt_vnis(struct list
*vnis
, struct bgpevpn
*vpn
)
190 struct listnode
*node
, *nnode
;
191 struct bgpevpn
*tmp_vpn
;
193 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, tmp_vpn
)) {
202 * Compare Route Targets.
204 static int evpn_route_target_cmp(struct ecommunity
*ecom1
,
205 struct ecommunity
*ecom2
)
213 if (!ecom1
&& !ecom2
)
216 if (ecom1
->str
&& !ecom2
->str
)
219 if (!ecom1
->str
&& ecom2
->str
)
222 if (!ecom1
->str
&& !ecom2
->str
)
225 return strcmp(ecom1
->str
, ecom2
->str
);
229 * Mask off global-admin field of specified extended community (RT),
230 * just retain the local-admin field.
232 static inline void mask_ecom_global_admin(struct ecommunity_val
*dst
,
233 struct ecommunity_val
*src
)
239 if (type
== ECOMMUNITY_ENCODE_AS
) {
240 dst
->val
[2] = dst
->val
[3] = 0;
241 } else if (type
== ECOMMUNITY_ENCODE_AS4
242 || type
== ECOMMUNITY_ENCODE_IP
) {
243 dst
->val
[2] = dst
->val
[3] = 0;
244 dst
->val
[4] = dst
->val
[5] = 0;
249 * Map one RT to specified VNI.
251 static void map_vni_to_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
252 struct ecommunity_val
*eval
)
254 struct irt_node
*irt
;
255 struct ecommunity_val eval_tmp
;
257 /* If using "automatic" RT, we only care about the local-admin
259 * This is to facilitate using VNI as the RT for EBGP peering too.
261 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
262 if (!is_import_rt_configured(vpn
))
263 mask_ecom_global_admin(&eval_tmp
, eval
);
265 irt
= lookup_import_rt(bgp
, &eval_tmp
);
266 if (irt
&& irt
->vnis
)
267 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
268 /* Already mapped. */
272 irt
= import_rt_new(bgp
, &eval_tmp
);
276 /* Add VNI to the hash list for this RT. */
277 listnode_add(irt
->vnis
, vpn
);
281 * Unmap specified VNI from specified RT. If there are no other
282 * VNIs for this RT, then the RT hash is deleted.
284 static void unmap_vni_from_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
285 struct irt_node
*irt
)
287 /* Delete VNI from hash list for this RT. */
288 listnode_delete(irt
->vnis
, vpn
);
289 if (!listnode_head(irt
->vnis
)) {
290 list_free(irt
->vnis
);
291 import_rt_free(bgp
, irt
);
296 * Create RT extended community automatically from passed information:
297 * of the form AS:VNI.
298 * NOTE: We use only the lower 16 bits of the AS. This is sufficient as
299 * the need is to get a RT value that will be unique across different
300 * VNIs but the same across routers (in the same AS) for a particular
303 static void form_auto_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
, struct list
*rtl
)
305 struct ecommunity_val eval
;
306 struct ecommunity
*ecomadd
;
308 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
310 ecomadd
= ecommunity_new();
311 ecommunity_add_val(ecomadd
, &eval
);
312 listnode_add_sort(rtl
, ecomadd
);
316 * Derive RD and RT for a VNI automatically. Invoked at the time of
319 static void derive_rd_rt_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
321 bgp_evpn_derive_auto_rd(bgp
, vpn
);
322 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
323 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
327 * Add (update) or delete MACIP from zebra.
329 static int bgp_zebra_send_remote_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
330 struct prefix_evpn
*p
,
331 struct in_addr remote_vtep_ip
, int add
,
336 char buf1
[ETHER_ADDR_STRLEN
];
337 char buf2
[INET6_ADDRSTRLEN
];
338 char buf3
[INET6_ADDRSTRLEN
];
341 if (!zclient
|| zclient
->sock
< 0)
344 /* Don't try to register if Zebra doesn't know of this instance. */
345 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
351 zclient_create_header(s
, add
? ZEBRA_REMOTE_MACIP_ADD
352 : ZEBRA_REMOTE_MACIP_DEL
,
354 stream_putl(s
, vpn
->vni
);
355 stream_put(s
, &p
->prefix
.mac
.octet
, ETH_ALEN
); /* Mac Addr */
356 /* IP address length and IP address, if any. */
357 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
360 ipa_len
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BYTELEN
362 stream_putl(s
, ipa_len
);
363 stream_put(s
, &p
->prefix
.ip
.ip
.addr
, ipa_len
);
365 stream_put_in_addr(s
, &remote_vtep_ip
);
367 /* TX MAC sticky status */
369 stream_putc(s
, sticky
);
371 stream_putw_at(s
, 0, stream_get_endp(s
));
373 if (bgp_debug_zebra(NULL
))
374 zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s",
375 add
? "ADD" : "DEL", vpn
->vni
,
376 sticky
? "sticky " : "",
377 prefix_mac2str(&p
->prefix
.mac
, buf1
, sizeof(buf1
)),
378 ipaddr2str(&p
->prefix
.ip
, buf3
, sizeof(buf3
)),
379 inet_ntop(AF_INET
, &remote_vtep_ip
, buf2
,
382 return zclient_send_message(zclient
);
386 * Add (update) or delete remote VTEP from zebra.
388 static int bgp_zebra_send_remote_vtep(struct bgp
*bgp
, struct bgpevpn
*vpn
,
389 struct prefix_evpn
*p
, int add
)
394 if (!zclient
|| zclient
->sock
< 0)
397 /* Don't try to register if Zebra doesn't know of this instance. */
398 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
404 zclient_create_header(s
, add
? ZEBRA_REMOTE_VTEP_ADD
405 : ZEBRA_REMOTE_VTEP_DEL
,
407 stream_putl(s
, vpn
->vni
);
408 if (IS_EVPN_PREFIX_IPADDR_V4(p
))
409 stream_put_in_addr(s
, &p
->prefix
.ip
.ipaddr_v4
);
410 else if (IS_EVPN_PREFIX_IPADDR_V6(p
)) {
412 "Bad remote IP when trying to %s remote VTEP for VNI %u",
413 add
? "ADD" : "DEL", vpn
->vni
);
417 stream_putw_at(s
, 0, stream_get_endp(s
));
419 if (bgp_debug_zebra(NULL
))
420 zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
421 add
? "ADD" : "DEL", vpn
->vni
,
422 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
424 return zclient_send_message(zclient
);
428 * Build extended communities for EVPN route. RT and ENCAP are
429 * applicable to all routes.
431 static void build_evpn_route_extcomm(struct bgpevpn
*vpn
, struct attr
*attr
)
433 struct ecommunity ecom_encap
;
434 struct ecommunity ecom_sticky
;
435 struct ecommunity_val eval
;
436 struct ecommunity_val eval_sticky
;
437 bgp_encap_types tnl_type
;
438 struct listnode
*node
, *nnode
;
439 struct ecommunity
*ecom
;
443 tnl_type
= BGP_ENCAP_TYPE_VXLAN
;
444 memset(&ecom_encap
, 0, sizeof(ecom_encap
));
445 encode_encap_extcomm(tnl_type
, &eval
);
447 ecom_encap
.val
= (u_int8_t
*)eval
.val
;
450 attr
->ecommunity
= ecommunity_dup(&ecom_encap
);
452 /* Add the export RTs */
453 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
454 attr
->ecommunity
= ecommunity_merge(attr
->ecommunity
, ecom
);
458 memset(&ecom_sticky
, 0, sizeof(ecom_sticky
));
459 encode_mac_mobility_extcomm(1, seqnum
, &eval_sticky
);
460 ecom_sticky
.size
= 1;
461 ecom_sticky
.val
= (u_int8_t
*)eval_sticky
.val
;
463 ecommunity_merge(attr
->ecommunity
, &ecom_sticky
);
466 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
470 * Add MAC mobility extended community to attribute.
472 static void add_mac_mobility_to_attr(u_int32_t seq_num
, struct attr
*attr
)
474 struct ecommunity ecom_tmp
;
475 struct ecommunity_val eval
;
476 u_int8_t
*ecom_val_ptr
;
483 encode_mac_mobility_extcomm(0, seq_num
, &eval
);
485 /* Find current MM ecommunity */
488 if (attr
->ecommunity
) {
489 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
490 pnt
= attr
->ecommunity
->val
+ (i
* 8);
494 if (type
== ECOMMUNITY_ENCODE_EVPN
496 == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
) {
498 (u_int8_t
*)(attr
->ecommunity
->val
505 /* Update the existing MM ecommunity */
507 memcpy(ecom_val_ptr
, eval
.val
, sizeof(char) * ECOMMUNITY_SIZE
);
509 /* Add MM to existing */
511 memset(&ecom_tmp
, 0, sizeof(ecom_tmp
));
513 ecom_tmp
.val
= (u_int8_t
*)eval
.val
;
516 ecommunity_merge(attr
->ecommunity
, &ecom_tmp
);
520 /* Install EVPN route into zebra. */
521 static int evpn_zebra_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
522 struct prefix_evpn
*p
,
523 struct in_addr remote_vtep_ip
, u_char sticky
)
527 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
528 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
531 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 1);
536 /* Uninstall EVPN route from zebra. */
537 static int evpn_zebra_uninstall(struct bgp
*bgp
, struct bgpevpn
*vpn
,
538 struct prefix_evpn
*p
,
539 struct in_addr remote_vtep_ip
)
543 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
544 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
547 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 0);
553 * Due to MAC mobility, the prior "local" best route has been supplanted
554 * by a "remote" best route. The prior route has to be deleted and withdrawn
557 static void evpn_delete_old_local_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
559 struct bgp_info
*old_local
)
561 struct bgp_node
*global_rn
;
563 afi_t afi
= AFI_L2VPN
;
564 safi_t safi
= SAFI_EVPN
;
566 /* Locate route node in the global EVPN routing table. Note that
567 * this table is a 2-level tree (RD-level + Prefix-level) similar to
570 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
571 (struct prefix
*)&rn
->p
, &vpn
->prd
);
573 /* Delete route entry in the global EVPN table. */
574 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
576 /* Schedule for processing - withdraws to peers happen from
580 bgp_process(bgp
, global_rn
, afi
, safi
);
581 bgp_unlock_node(global_rn
);
584 /* Delete route entry in the VNI route table, caller to remove. */
585 bgp_info_delete(rn
, old_local
);
589 * Calculate the best path for an EVPN route. Install/update best path in zebra,
592 static int evpn_route_select_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
595 struct bgp_info
*old_select
, *new_select
;
596 struct bgp_info_pair old_and_new
;
597 afi_t afi
= AFI_L2VPN
;
598 safi_t safi
= SAFI_EVPN
;
601 /* Compute the best path. */
602 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
604 old_select
= old_and_new
.old
;
605 new_select
= old_and_new
.new;
607 /* If the best path hasn't changed - see if there is still something to
611 if (old_select
&& old_select
== new_select
612 && old_select
->type
== ZEBRA_ROUTE_BGP
613 && old_select
->sub_type
== BGP_ROUTE_NORMAL
614 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
615 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
616 && !bgp
->addpath_tx_used
[afi
][safi
]) {
617 if (bgp_zebra_has_route_changed(rn
, old_select
))
618 ret
= evpn_zebra_install(bgp
, vpn
,
619 (struct prefix_evpn
*)&rn
->p
,
620 old_select
->attr
->nexthop
,
621 old_select
->attr
->sticky
);
622 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
623 bgp_zebra_clear_route_change_flags(rn
);
627 /* If the user did a "clear" this flag will be set */
628 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
630 /* bestpath has changed; update relevant fields and install or uninstall
631 * into the zebra RIB.
633 if (old_select
|| new_select
)
634 bgp_bump_version(rn
);
637 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
639 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
640 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
641 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
644 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
645 && new_select
->sub_type
== BGP_ROUTE_NORMAL
) {
646 ret
= evpn_zebra_install(bgp
, vpn
, (struct prefix_evpn
*)&rn
->p
,
647 new_select
->attr
->nexthop
,
648 new_select
->attr
->sticky
);
649 /* If an old best existed and it was a "local" route, the only
651 * it would be supplanted is due to MAC mobility procedures. So,
653 * need to do an implicit delete and withdraw that route from
656 if (old_select
&& old_select
->peer
== bgp
->peer_self
657 && old_select
->type
== ZEBRA_ROUTE_BGP
658 && old_select
->sub_type
== BGP_ROUTE_STATIC
)
659 evpn_delete_old_local_route(bgp
, vpn
, rn
, old_select
);
661 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
662 && old_select
->sub_type
== BGP_ROUTE_NORMAL
)
663 ret
= evpn_zebra_uninstall(bgp
, vpn
,
664 (struct prefix_evpn
*)&rn
->p
,
665 old_select
->attr
->nexthop
);
668 /* Clear any route change flags. */
669 bgp_zebra_clear_route_change_flags(rn
);
671 /* Reap old select bgp_info, if it has been removed */
672 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
673 bgp_info_reap(rn
, old_select
);
680 * Return true if the local ri for this rn has sticky set
682 static int evpn_route_is_sticky(struct bgp
*bgp
, struct bgp_node
*rn
)
684 struct bgp_info
*tmp_ri
;
685 struct bgp_info
*local_ri
;
688 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
689 if (tmp_ri
->peer
== bgp
->peer_self
690 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
691 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
698 return local_ri
->attr
->sticky
;
702 * Create or update EVPN route entry. This could be in the VNI route table
703 * or the global route table.
705 static int update_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
706 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
707 struct attr
*attr
, int add
, int vni_table
,
708 struct bgp_info
**ri
, u_char flags
)
710 struct bgp_info
*tmp_ri
;
711 struct bgp_info
*local_ri
, *remote_ri
;
712 struct attr
*attr_new
;
713 mpls_label_t label
= MPLS_INVALID_LABEL
;
714 int route_change
= 1;
719 /* See if this is an update of an existing route, or a new add. Also,
720 * identify if already known from remote, and if so, the one with the
721 * highest sequence number; this is only when adding to the VNI routing
724 local_ri
= remote_ri
= NULL
;
725 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
726 if (tmp_ri
->peer
== bgp
->peer_self
727 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
728 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
731 if (tmp_ri
->type
== ZEBRA_ROUTE_BGP
732 && tmp_ri
->sub_type
== BGP_ROUTE_NORMAL
733 && CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
)) {
736 else if (mac_mobility_seqnum(tmp_ri
->attr
)
737 > mac_mobility_seqnum(remote_ri
->attr
))
743 /* If route doesn't exist already, create a new one, if told to.
744 * Otherwise act based on whether the attributes of the route have
747 if (!local_ri
&& !add
)
751 /* When learnt locally for the first time but already known from
752 * remote, we have to initiate appropriate MAC mobility steps.
754 * is applicable when updating the VNI routing table.
755 * We need to skip mobility steps for g/w macs (local mac on g/w
756 * SVI) advertised in EVPN.
757 * This will ensure that local routes are preferred for g/w macs
759 if (remote_ri
&& !CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_GW
)) {
760 u_int32_t cur_seqnum
;
762 /* Add MM extended community to route. */
763 cur_seqnum
= mac_mobility_seqnum(remote_ri
->attr
);
764 add_mac_mobility_to_attr(cur_seqnum
+ 1, attr
);
767 /* Add (or update) attribute to hash. */
768 attr_new
= bgp_attr_intern(attr
);
770 /* Extract MAC mobility sequence number, if any. */
771 attr_new
->mm_seqnum
=
772 bgp_attr_mac_mobility_seqnum(attr_new
, &sticky
);
773 attr_new
->sticky
= sticky
;
775 /* Create new route with its attribute. */
776 tmp_ri
= info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0,
777 bgp
->peer_self
, attr_new
, rn
);
778 SET_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
);
779 bgp_info_extra_get(tmp_ri
);
781 /* The VNI goes into the 'label' field of the route */
782 vni2label(vpn
->vni
, &label
);
784 memcpy(&tmp_ri
->extra
->label
, &label
, BGP_LABEL_BYTES
);
785 bgp_info_add(rn
, tmp_ri
);
788 if (attrhash_cmp(tmp_ri
->attr
, attr
)
789 && !CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
792 /* The attribute has changed. */
793 /* Add (or update) attribute to hash. */
794 attr_new
= bgp_attr_intern(attr
);
795 bgp_info_set_flag(rn
, tmp_ri
, BGP_INFO_ATTR_CHANGED
);
797 /* Restore route, if needed. */
798 if (CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
799 bgp_info_restore(rn
, tmp_ri
);
801 /* Unintern existing, set to new. */
802 bgp_attr_unintern(&tmp_ri
->attr
);
803 tmp_ri
->attr
= attr_new
;
804 tmp_ri
->uptime
= bgp_clock();
808 /* Return back the route entry. */
814 * Create or update EVPN route (of type based on prefix) for specified VNI
815 * and schedule for processing.
817 static int update_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
818 struct prefix_evpn
*p
, u_char flags
)
822 struct attr
*attr_new
;
824 afi_t afi
= AFI_L2VPN
;
825 safi_t safi
= SAFI_EVPN
;
828 memset(&attr
, 0, sizeof(struct attr
));
830 /* Build path-attribute for this route. */
831 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
832 attr
.nexthop
= vpn
->originator_ip
;
833 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
834 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
835 attr
.sticky
= CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_STICKY
) ? 1 : 0;
837 /* Set up RT and ENCAP extended community. */
838 build_evpn_route_extcomm(vpn
, &attr
);
840 /* First, create (or fetch) route node within the VNI. */
841 /* NOTE: There is no RD here. */
842 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
844 /* Create or update route entry. */
845 route_change
= update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
850 /* Perform route selection; this is just to set the flags correctly
851 * as local route in the VNI always wins.
853 evpn_route_select_install(bgp
, vpn
, rn
);
856 /* If this is a new route or some attribute has changed, export the
857 * route to the global table. The route will be advertised to peers
858 * from there. Note that this table is a 2-level tree (RD-level +
859 * Prefix-level) similar to L3VPN routes.
862 struct bgp_info
*global_ri
;
864 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
865 (struct prefix
*)p
, &vpn
->prd
);
866 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, attr_new
, 1, 0,
869 /* Schedule for processing and unlock node. */
870 bgp_process(bgp
, rn
, afi
, safi
);
874 /* Unintern temporary. */
875 aspath_unintern(&attr
.aspath
);
881 * Delete EVPN route entry. This could be in the VNI route table
882 * or the global route table.
884 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
885 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
886 struct bgp_info
**ri
)
888 struct bgp_info
*tmp_ri
;
892 /* Now, find matching route. */
893 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
)
894 if (tmp_ri
->peer
== bgp
->peer_self
895 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
896 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
901 /* Mark route for delete. */
903 bgp_info_delete(rn
, tmp_ri
);
907 * Delete EVPN route (of type based on prefix) for specified VNI and
908 * schedule for processing.
910 static int delete_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
911 struct prefix_evpn
*p
)
913 struct bgp_node
*rn
, *global_rn
;
915 afi_t afi
= AFI_L2VPN
;
916 safi_t safi
= SAFI_EVPN
;
918 /* First, locate the route node within the VNI. If it doesn't exist,
920 * is nothing further to do.
922 /* NOTE: There is no RD here. */
923 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
927 /* Next, locate route node in the global EVPN routing table. Note that
928 * this table is a 2-level tree (RD-level + Prefix-level) similar to
931 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
932 (struct prefix
*)p
, &vpn
->prd
);
934 /* Delete route entry in the global EVPN table. */
935 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
937 /* Schedule for processing - withdraws to peers happen from
941 bgp_process(bgp
, global_rn
, afi
, safi
);
942 bgp_unlock_node(global_rn
);
945 /* Delete route entry in the VNI route table. This can just be removed.
947 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
949 bgp_info_reap(rn
, ri
);
956 * Update all type-2 (MACIP) local routes for this VNI - these should also
957 * be scheduled for advertise to peers.
959 static int update_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
966 struct attr attr_sticky
;
967 struct attr
*attr_new
;
971 memset(&attr
, 0, sizeof(struct attr
));
972 memset(&attr_sticky
, 0, sizeof(struct attr
));
974 /* Build path-attribute - all type-2 routes for this VNI will share the
975 * same path attribute.
977 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
978 bgp_attr_default_set(&attr_sticky
, BGP_ORIGIN_IGP
);
979 attr
.nexthop
= vpn
->originator_ip
;
980 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
981 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
982 attr_sticky
.nexthop
= vpn
->originator_ip
;
983 attr_sticky
.mp_nexthop_global_in
= vpn
->originator_ip
;
984 attr_sticky
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
985 attr_sticky
.sticky
= 1;
987 /* Set up RT, ENCAP and sticky MAC extended community. */
988 build_evpn_route_extcomm(vpn
, &attr
);
989 build_evpn_route_extcomm(vpn
, &attr_sticky
);
991 /* Walk this VNI's route table and update local type-2 routes. For any
992 * routes updated, update corresponding entry in the global table too.
994 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
995 rn
= bgp_route_next(rn
)) {
996 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
997 struct bgp_node
*rd_rn
;
998 struct bgp_info
*global_ri
;
1000 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1003 if (evpn_route_is_sticky(bgp
, rn
))
1004 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
,
1005 &attr_sticky
, 0, 1, &ri
, 0);
1007 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
1010 /* If a local route exists for this prefix, we need to update
1011 * the global routing table too.
1016 /* Perform route selection; this is just to set the flags
1018 * as local route in the VNI always wins.
1020 evpn_route_select_install(bgp
, vpn
, rn
);
1022 attr_new
= ri
->attr
;
1024 /* Update route in global routing table. */
1025 rd_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1026 (struct prefix
*)evp
, &vpn
->prd
);
1028 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rd_rn
, attr_new
, 0,
1031 /* Schedule for processing and unlock node. */
1032 bgp_process(bgp
, rd_rn
, afi
, safi
);
1033 bgp_unlock_node(rd_rn
);
1036 /* Unintern temporary. */
1037 aspath_unintern(&attr
.aspath
);
1038 aspath_unintern(&attr_sticky
.aspath
);
1044 * Delete all type-2 (MACIP) local routes for this VNI - only from the
1045 * global routing table. These are also scheduled for withdraw from peers.
1047 static int delete_global_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1051 struct bgp_node
*rdrn
, *rn
;
1052 struct bgp_table
*table
;
1053 struct bgp_info
*ri
;
1058 rdrn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)&vpn
->prd
);
1059 if (rdrn
&& rdrn
->info
) {
1060 table
= (struct bgp_table
*)rdrn
->info
;
1061 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1062 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1064 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1067 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1069 bgp_process(bgp
, rn
, afi
, safi
);
1073 /* Unlock RD node. */
1075 bgp_unlock_node(rdrn
);
1081 * Delete all type-2 (MACIP) local routes for this VNI - from the global
1082 * table as well as the per-VNI route table.
1084 static int delete_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1088 struct bgp_node
*rn
;
1089 struct bgp_info
*ri
;
1094 /* First, walk the global route table for this VNI's type-2 local
1096 * EVPN routes are a 2-level table, first get the RD table.
1098 delete_global_type2_routes(bgp
, vpn
);
1100 /* Next, walk this VNI's route table and delete local type-2 routes. */
1101 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1102 rn
= bgp_route_next(rn
)) {
1103 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1105 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1108 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1110 /* Route entry in local table gets deleted immediately. */
1112 bgp_info_reap(rn
, ri
);
1119 * Delete all routes in the per-VNI route table.
1121 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1123 struct bgp_node
*rn
;
1124 struct bgp_info
*ri
, *nextri
;
1126 /* Walk this VNI's route table and delete all routes. */
1127 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1128 rn
= bgp_route_next(rn
)) {
1129 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1131 bgp_info_delete(rn
, ri
);
1132 bgp_info_reap(rn
, ri
);
1140 * Update (and advertise) local routes for a VNI. Invoked upon the VNI
1141 * export RT getting modified or change to tunnel IP. Note that these
1142 * situations need the route in the per-VNI table as well as the global
1143 * table to be updated (as attributes change).
1145 static int update_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1148 struct prefix_evpn p
;
1150 /* Update and advertise the type-3 route (only one) followed by the
1151 * locally learnt type-2 routes (MACIP) - for this VNI.
1153 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1154 ret
= update_evpn_route(bgp
, vpn
, &p
, 0);
1158 return update_all_type2_routes(bgp
, vpn
);
1162 * Delete (and withdraw) local routes for specified VNI from the global
1163 * table and per-VNI table. After this, remove all other routes from
1164 * the per-VNI table. Invoked upon the VNI being deleted or EVPN
1165 * (advertise-all-vni) being disabled.
1167 static int delete_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1170 struct prefix_evpn p
;
1172 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1173 * followed by type-3 routes (only one) - for this VNI.
1175 ret
= delete_all_type2_routes(bgp
, vpn
);
1179 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1180 ret
= delete_evpn_route(bgp
, vpn
, &p
);
1184 /* Delete all routes from the per-VNI table. */
1185 return delete_all_vni_routes(bgp
, vpn
);
1189 * There is a tunnel endpoint IP address change for this VNI,
1190 * need to re-advertise routes with the new nexthop.
1192 static int handle_tunnel_ip_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1193 struct in_addr originator_ip
)
1195 struct prefix_evpn p
;
1197 /* If VNI is not live, we only need to update the originator ip */
1198 if (!is_vni_live(vpn
)) {
1199 vpn
->originator_ip
= originator_ip
;
1203 /* Need to withdraw type-3 route as the originator IP is part
1206 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1207 delete_evpn_route(bgp
, vpn
, &p
);
1209 /* Update the tunnel IP and re-advertise all routes for this VNI. */
1210 vpn
->originator_ip
= originator_ip
;
1211 return update_routes_for_vni(bgp
, vpn
);
1215 * Install route entry into the VNI routing table and invoke route selection.
1217 static int install_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1218 struct prefix_evpn
*p
,
1219 struct bgp_info
*parent_ri
)
1221 struct bgp_node
*rn
;
1222 struct bgp_info
*ri
;
1223 struct attr
*attr_new
;
1226 /* Create (or fetch) route within the VNI. */
1227 /* NOTE: There is no RD here. */
1228 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
1230 /* Check if route entry is already present. */
1231 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1233 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1237 /* Add (or update) attribute to hash. */
1238 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1240 /* Create new route with its attribute. */
1241 ri
= info_make(parent_ri
->type
, parent_ri
->sub_type
, 0,
1242 parent_ri
->peer
, attr_new
, rn
);
1243 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
1244 bgp_info_extra_get(ri
);
1245 ri
->extra
->parent
= parent_ri
;
1246 if (parent_ri
->extra
)
1247 memcpy(&ri
->extra
->label
, &parent_ri
->extra
->label
,
1249 bgp_info_add(rn
, ri
);
1251 if (attrhash_cmp(ri
->attr
, parent_ri
->attr
)
1252 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1253 bgp_unlock_node(rn
);
1256 /* The attribute has changed. */
1257 /* Add (or update) attribute to hash. */
1258 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1260 /* Restore route, if needed. */
1261 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
1262 bgp_info_restore(rn
, ri
);
1264 /* Mark if nexthop has changed. */
1265 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
, &attr_new
->nexthop
))
1266 SET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1268 /* Unintern existing, set to new. */
1269 bgp_attr_unintern(&ri
->attr
);
1270 ri
->attr
= attr_new
;
1271 ri
->uptime
= bgp_clock();
1274 /* Perform route selection and update zebra, if required. */
1275 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1281 * Uninstall route entry from the VNI routing table and send message
1282 * to zebra, if appropriate.
1284 static int uninstall_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1285 struct prefix_evpn
*p
,
1286 struct bgp_info
*parent_ri
)
1288 struct bgp_node
*rn
;
1289 struct bgp_info
*ri
;
1292 /* Locate route within the VNI. */
1293 /* NOTE: There is no RD here. */
1294 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
1298 /* Find matching route entry. */
1299 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1301 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1307 /* Mark entry for deletion */
1308 bgp_info_delete(rn
, ri
);
1310 /* Perform route selection and update zebra, if required. */
1311 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1313 /* Unlock route node. */
1314 bgp_unlock_node(rn
);
1320 * Given a route entry and a VNI, see if this route entry should be
1321 * imported into the VNI i.e., RTs match.
1323 static int is_route_matching_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1324 struct bgp_info
*ri
)
1326 struct attr
*attr
= ri
->attr
;
1327 struct ecommunity
*ecom
;
1331 /* Route should have valid RT to be even considered. */
1332 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1335 ecom
= attr
->ecommunity
;
1336 if (!ecom
|| !ecom
->size
)
1339 /* For each extended community RT, see if it matches this VNI. If any RT
1340 * matches, we're done.
1342 for (i
= 0; i
< ecom
->size
; i
++) {
1344 u_char type
, sub_type
;
1345 struct ecommunity_val
*eval
;
1346 struct ecommunity_val eval_tmp
;
1347 struct irt_node
*irt
;
1349 /* Only deal with RTs */
1350 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1351 eval
= (struct ecommunity_val
*)(ecom
->val
1352 + (i
* ECOMMUNITY_SIZE
));
1355 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1358 /* See if this RT matches specified VNIs import RTs */
1359 irt
= lookup_import_rt(bgp
, eval
);
1360 if (irt
&& irt
->vnis
)
1361 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1364 /* Also check for non-exact match. In this, we mask out the AS
1366 * only check on the local-admin sub-field. This is to
1368 * VNI as the RT for EBGP peering too.
1371 if (type
== ECOMMUNITY_ENCODE_AS
1372 || type
== ECOMMUNITY_ENCODE_AS4
1373 || type
== ECOMMUNITY_ENCODE_IP
) {
1374 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1375 mask_ecom_global_admin(&eval_tmp
, eval
);
1376 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1378 if (irt
&& irt
->vnis
)
1379 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1387 * Install or uninstall routes of specified type that are appropriate for this
1390 static int install_uninstall_routes_for_vni(struct bgp
*bgp
,
1391 struct bgpevpn
*vpn
,
1392 bgp_evpn_route_type rtype
,
1397 struct bgp_node
*rd_rn
, *rn
;
1398 struct bgp_table
*table
;
1399 struct bgp_info
*ri
;
1405 /* Walk entire global routing table and evaluate routes which could be
1406 * imported into this VPN. Note that we cannot just look at the routes
1408 * the VNI's RD - remote routes applicable for this VNI could have any
1411 /* EVPN routes are a 2-level table. */
1412 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1413 rd_rn
= bgp_route_next(rd_rn
)) {
1414 table
= (struct bgp_table
*)(rd_rn
->info
);
1418 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1419 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1421 if (evp
->prefix
.route_type
!= rtype
)
1424 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1425 /* Consider "valid" remote routes applicable for
1427 if (!(CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1428 && ri
->type
== ZEBRA_ROUTE_BGP
1429 && ri
->sub_type
== BGP_ROUTE_NORMAL
))
1432 if (is_route_matching_for_vni(bgp
, vpn
, ri
)) {
1434 ret
= install_evpn_route_entry(
1437 ret
= uninstall_evpn_route_entry(
1442 "%u: Failed to %s EVPN %s route in VNI %u",
1446 rtype
== BGP_EVPN_MAC_IP_ROUTE
1461 * Install any existing remote routes applicable for this VNI into its
1462 * routing table. This is invoked when a VNI becomes "live" or its Import
1465 static int install_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1469 /* Install type-3 routes followed by type-2 routes - the ones applicable
1472 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1477 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1482 * Uninstall any existing remote routes for this VNI. One scenario in which
1483 * this is invoked is upon an import RT change.
1485 static int uninstall_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1489 /* Uninstall type-2 routes followed by type-3 routes - the ones
1493 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1498 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1503 * Install or uninstall route in matching VNIs (list).
1505 static int install_uninstall_route_in_vnis(struct bgp
*bgp
, afi_t afi
,
1506 safi_t safi
, struct prefix_evpn
*evp
,
1507 struct bgp_info
*ri
,
1508 struct list
*vnis
, int install
)
1510 struct bgpevpn
*vpn
;
1511 struct listnode
*node
, *nnode
;
1513 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, vpn
)) {
1516 if (!is_vni_live(vpn
))
1520 ret
= install_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1522 ret
= uninstall_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1525 zlog_err("%u: Failed to %s EVPN %s route in VNI %u",
1526 bgp
->vrf_id
, install
? "install" : "uninstall",
1527 evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1539 * Install or uninstall route for appropriate VNIs.
1541 static int install_uninstall_evpn_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1542 struct prefix
*p
, struct bgp_info
*ri
,
1545 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
1546 struct attr
*attr
= ri
->attr
;
1547 struct ecommunity
*ecom
;
1552 /* Only type-2 and type-3 routes go into a L2 VNI. */
1553 if (!(evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1554 || evp
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
))
1557 /* If we don't have Route Target, nothing much to do. */
1558 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1561 ecom
= attr
->ecommunity
;
1562 if (!ecom
|| !ecom
->size
)
1565 /* For each extended community RT, see which VNIs match and import
1566 * the route into matching VNIs.
1568 for (i
= 0; i
< ecom
->size
; i
++) {
1570 u_char type
, sub_type
;
1571 struct ecommunity_val
*eval
;
1572 struct ecommunity_val eval_tmp
;
1573 struct irt_node
*irt
;
1575 /* Only deal with RTs */
1576 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1577 eval
= (struct ecommunity_val
*)(ecom
->val
1578 + (i
* ECOMMUNITY_SIZE
));
1581 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1584 /* Are we interested in this RT? */
1585 irt
= lookup_import_rt(bgp
, eval
);
1586 if (irt
&& irt
->vnis
)
1587 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1590 /* Also check for non-exact match. In this, we mask out the AS
1592 * only check on the local-admin sub-field. This is to
1594 * VNI as the RT for EBGP peering too.
1597 if (type
== ECOMMUNITY_ENCODE_AS
1598 || type
== ECOMMUNITY_ENCODE_AS4
1599 || type
== ECOMMUNITY_ENCODE_IP
) {
1600 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1601 mask_ecom_global_admin(&eval_tmp
, eval
);
1602 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1604 if (irt
&& irt
->vnis
)
1605 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1613 * Update and advertise local routes for a VNI. Invoked upon router-id
1614 * change. Note that the processing is done only on the global route table
1615 * using routes that already exist in the per-VNI table.
1617 static int update_advertise_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1619 struct prefix_evpn p
;
1620 struct bgp_node
*rn
, *global_rn
;
1621 struct bgp_info
*ri
, *global_ri
;
1623 afi_t afi
= AFI_L2VPN
;
1624 safi_t safi
= SAFI_EVPN
;
1626 /* Locate type-3 route for VNI in the per-VNI table and use its
1627 * attributes to create and advertise the type-3 route for this VNI
1628 * in the global table.
1630 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1631 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1632 if (!rn
) /* unexpected */
1634 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1635 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
1636 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1638 if (!ri
) /* unexpected */
1642 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1643 (struct prefix
*)&p
, &vpn
->prd
);
1644 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1, 0, &ri
,
1647 /* Schedule for processing and unlock node. */
1648 bgp_process(bgp
, global_rn
, afi
, safi
);
1649 bgp_unlock_node(global_rn
);
1651 /* Now, walk this VNI's route table and use the route and its attribute
1652 * to create and schedule route in global table.
1654 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1655 rn
= bgp_route_next(rn
)) {
1656 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1658 /* Identify MAC-IP local routes. */
1659 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1662 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1663 if (ri
->peer
== bgp
->peer_self
1664 && ri
->type
== ZEBRA_ROUTE_BGP
1665 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1670 /* Create route in global routing table using this route entry's
1674 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1675 (struct prefix
*)evp
, &vpn
->prd
);
1677 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1,
1680 /* Schedule for processing and unlock node. */
1681 bgp_process(bgp
, global_rn
, afi
, safi
);
1682 bgp_unlock_node(global_rn
);
1689 * Delete (and withdraw) local routes for a VNI - only from the global
1690 * table. Invoked upon router-id change.
1692 static int delete_withdraw_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1695 struct prefix_evpn p
;
1696 struct bgp_node
*global_rn
;
1697 struct bgp_info
*ri
;
1698 afi_t afi
= AFI_L2VPN
;
1699 safi_t safi
= SAFI_EVPN
;
1701 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1702 * for this VNI - from the global table.
1704 ret
= delete_global_type2_routes(bgp
, vpn
);
1708 /* Remove type-3 route for this VNI from global table. */
1709 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1710 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1711 (struct prefix
*)&p
, &vpn
->prd
);
1713 /* Delete route entry in the global EVPN table. */
1714 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
1716 /* Schedule for processing - withdraws to peers happen from
1720 bgp_process(bgp
, global_rn
, afi
, safi
);
1721 bgp_unlock_node(global_rn
);
1728 * Handle router-id change. Update and advertise local routes corresponding
1729 * to this VNI from peers. Note that this is invoked after updating the
1730 * router-id. The routes in the per-VNI table are used to create routes in
1731 * the global table and schedule them.
1733 static void update_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1735 struct bgpevpn
*vpn
;
1737 vpn
= (struct bgpevpn
*)backet
->data
;
1740 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1744 /* Skip VNIs with configured RD. */
1745 if (is_rd_configured(vpn
))
1748 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1749 update_advertise_vni_routes(bgp
, vpn
);
1753 * Handle router-id change. Delete and withdraw local routes corresponding
1754 * to this VNI from peers. Note that this is invoked prior to updating
1755 * the router-id and is done only on the global route table, the routes
1756 * are needed in the per-VNI table to re-advertise with new router id.
1758 static void withdraw_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1760 struct bgpevpn
*vpn
;
1762 vpn
= (struct bgpevpn
*)backet
->data
;
1765 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1769 /* Skip VNIs with configured RD. */
1770 if (is_rd_configured(vpn
))
1773 delete_withdraw_vni_routes(bgp
, vpn
);
1777 * Process received EVPN type-2 route (advertise or withdraw).
1779 static int process_type2_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1780 struct attr
*attr
, u_char
*pfx
, int psize
,
1781 u_int32_t addpath_id
)
1783 struct prefix_rd prd
;
1784 struct prefix_evpn p
;
1787 mpls_label_t
*label_pnt
;
1790 /* Type-2 route should be either 33, 37 or 49 bytes or an
1791 * additional 3 bytes if there is a second label (VNI):
1792 * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1),
1793 * MAC Addr (6), IP len (1), IP (0, 4 or 16),
1794 * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3)
1796 if (psize
!= 33 && psize
!= 37 && psize
!= 49 && psize
!= 36
1797 && psize
!= 40 && psize
!= 52) {
1798 zlog_err("%u:%s - Rx EVPN Type-2 NLRI with invalid length %d",
1799 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1803 /* Make prefix_rd */
1804 prd
.family
= AF_UNSPEC
;
1806 memcpy(&prd
.val
, pfx
, 8);
1809 /* Make EVPN prefix. */
1810 memset(&p
, 0, sizeof(struct prefix_evpn
));
1812 p
.prefixlen
= EVPN_TYPE_2_ROUTE_PREFIXLEN
;
1813 p
.prefix
.route_type
= BGP_EVPN_MAC_IP_ROUTE
;
1815 /* Skip over Ethernet Seg Identifier for now. */
1818 /* Skip over Ethernet Tag for now. */
1821 /* Get the MAC Addr len */
1822 macaddr_len
= *pfx
++;
1824 /* Get the MAC Addr */
1825 if (macaddr_len
== (ETH_ALEN
* 8)) {
1826 memcpy(&p
.prefix
.mac
.octet
, pfx
, ETH_ALEN
);
1830 "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d",
1831 peer
->bgp
->vrf_id
, peer
->host
, macaddr_len
);
1837 ipaddr_len
= *pfx
++;
1838 if (ipaddr_len
!= 0 && ipaddr_len
!= IPV4_MAX_BITLEN
1839 && ipaddr_len
!= IPV6_MAX_BITLEN
) {
1841 "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d",
1842 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1847 ipaddr_len
/= 8; /* Convert to bytes. */
1848 p
.prefix
.ip
.ipa_type
= (ipaddr_len
== IPV4_MAX_BYTELEN
)
1851 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, ipaddr_len
);
1855 /* Get the VNI (in MPLS label field). */
1856 /* Note: We ignore the second VNI, if any. */
1857 label_pnt
= (mpls_label_t
*)pfx
;
1859 /* Process the route. */
1861 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1862 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1863 &prd
, label_pnt
, 0, NULL
);
1865 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1866 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1867 &prd
, label_pnt
, NULL
);
1872 * Process received EVPN type-3 route (advertise or withdraw).
1874 static int process_type3_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1875 struct attr
*attr
, u_char
*pfx
, int psize
,
1876 u_int32_t addpath_id
)
1878 struct prefix_rd prd
;
1879 struct prefix_evpn p
;
1883 /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
1884 * IP len (1) and IP (4 or 16).
1886 if (psize
!= 17 && psize
!= 29) {
1887 zlog_err("%u:%s - Rx EVPN Type-3 NLRI with invalid length %d",
1888 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1892 /* Make prefix_rd */
1893 prd
.family
= AF_UNSPEC
;
1895 memcpy(&prd
.val
, pfx
, 8);
1898 /* Make EVPN prefix. */
1899 memset(&p
, 0, sizeof(struct prefix_evpn
));
1901 p
.prefixlen
= EVPN_TYPE_3_ROUTE_PREFIXLEN
;
1902 p
.prefix
.route_type
= BGP_EVPN_IMET_ROUTE
;
1904 /* Skip over Ethernet Tag for now. */
1908 ipaddr_len
= *pfx
++;
1909 if (ipaddr_len
== IPV4_MAX_BITLEN
) {
1910 p
.prefix
.ip
.ipa_type
= IPADDR_V4
;
1911 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, IPV4_MAX_BYTELEN
);
1914 "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
1915 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1919 /* Process the route. */
1921 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1922 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1923 &prd
, NULL
, 0, NULL
);
1925 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1926 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1932 * Process received EVPN type-5 route (advertise or withdraw).
1934 static int process_type5_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1935 struct attr
*attr
, u_char
*pfx
, int psize
,
1936 u_int32_t addpath_id
, int withdraw
)
1938 struct prefix_rd prd
;
1939 struct prefix_evpn p
;
1940 struct bgp_route_evpn evpn
;
1943 mpls_label_t
*label_pnt
;
1946 /* Type-5 route should be 34 or 58 bytes:
1947 * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
1948 * GW (4 or 16) and VNI (3).
1949 * Note that the IP and GW should both be IPv4 or both IPv6.
1951 if (psize
!= 34 && psize
!= 58) {
1952 zlog_err("%u:%s - Rx EVPN Type-5 NLRI with invalid length %d",
1953 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1957 /* Make prefix_rd */
1958 prd
.family
= AF_UNSPEC
;
1960 memcpy(&prd
.val
, pfx
, 8);
1963 /* Make EVPN prefix. */
1964 memset(&p
, 0, sizeof(struct prefix_evpn
));
1966 p
.prefix
.route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
1968 /* Additional information outside of prefix - ESI and GW IP */
1969 memset(&evpn
, 0, sizeof(evpn
));
1972 memcpy(&evpn
.eth_s_id
.val
, pfx
, 10);
1975 /* Fetch Ethernet Tag. */
1976 memcpy(ð_tag
, pfx
, 4);
1977 p
.prefix
.eth_tag
= ntohl(eth_tag
);
1980 /* Fetch IP prefix length. */
1982 if (ippfx_len
> IPV6_MAX_BITLEN
) {
1984 "%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d",
1985 peer
->bgp
->vrf_id
, peer
->host
, ippfx_len
);
1988 p
.prefix
.ip_prefix_length
= ippfx_len
;
1990 /* Determine IPv4 or IPv6 prefix */
1991 /* Since the address and GW are from the same family, this just becomes
1992 * a simple check on the total size.
1995 SET_IPADDR_V4(&p
.prefix
.ip
);
1996 memcpy(&p
.prefix
.ip
.ipaddr_v4
, pfx
, 4);
1998 memcpy(&evpn
.gw_ip
.ipv4
, pfx
, 4);
2000 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
2002 SET_IPADDR_V6(&p
.prefix
.ip
);
2003 memcpy(&p
.prefix
.ip
.ipaddr_v6
, pfx
, 16);
2005 memcpy(&evpn
.gw_ip
.ipv6
, pfx
, 16);
2007 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV6
;
2010 label_pnt
= (mpls_label_t
*)pfx
;
2012 /* Process the route. */
2014 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2015 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2016 &prd
, label_pnt
, 0, &evpn
);
2018 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2019 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2020 &prd
, label_pnt
, &evpn
);
2025 static void evpn_mpattr_encode_type5(struct stream
*s
, struct prefix
*p
,
2026 struct prefix_rd
*prd
, mpls_label_t
*label
,
2031 struct evpn_addr
*p_evpn_p
;
2033 memset(&temp
, 0, 16);
2034 if (p
->family
!= AF_EVPN
)
2036 p_evpn_p
= &(p
->u
.prefix_evpn
);
2038 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2041 len
= 32; /* ipv6 */
2042 stream_putc(s
, BGP_EVPN_IP_PREFIX_ROUTE
);
2043 /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
2044 stream_putc(s
, 8 + 10 + 4 + 1 + len
+ 3);
2045 stream_put(s
, prd
->val
, 8);
2047 stream_put(s
, &(attr
->evpn_overlay
.eth_s_id
), 10);
2049 stream_put(s
, &temp
, 10);
2050 stream_putl(s
, p_evpn_p
->eth_tag
);
2051 stream_putc(s
, p_evpn_p
->ip_prefix_length
);
2052 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2053 stream_put_ipv4(s
, p_evpn_p
->ip
.ipaddr_v4
.s_addr
);
2055 stream_put(s
, &p_evpn_p
->ip
.ipaddr_v6
, 16);
2057 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2059 attr
->evpn_overlay
.gw_ip
.ipv4
.s_addr
);
2061 stream_put(s
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), 16);
2063 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2064 stream_put_ipv4(s
, 0);
2066 stream_put(s
, &temp
, 16);
2070 stream_put(s
, label
, 3);
2076 * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled.
2078 static void cleanup_vni_on_disable(struct hash_backet
*backet
, struct bgp
*bgp
)
2080 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2082 /* Remove EVPN routes and schedule for processing. */
2083 delete_routes_for_vni(bgp
, vpn
);
2085 /* Clear "live" flag and see if hash needs to be freed. */
2086 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2087 if (!is_vni_configured(vpn
))
2088 bgp_evpn_free(bgp
, vpn
);
2092 * Free a VNI entry; iterator function called during cleanup.
2094 static void free_vni_entry(struct hash_backet
*backet
, struct bgp
*bgp
)
2096 struct bgpevpn
*vpn
;
2098 vpn
= (struct bgpevpn
*)backet
->data
;
2099 delete_all_vni_routes(bgp
, vpn
);
2100 bgp_evpn_free(bgp
, vpn
);
2109 * Handle change to BGP router id. This is invoked twice by the change
2110 * handler, first before the router id has been changed and then after
2111 * the router id has been changed. The first invocation will result in
2112 * local routes for all VNIs being deleted and withdrawn and the next
2113 * will result in the routes being re-advertised.
2115 void bgp_evpn_handle_router_id_update(struct bgp
*bgp
, int withdraw
)
2118 hash_iterate(bgp
->vnihash
,
2119 (void (*)(struct hash_backet
*,
2120 void *))withdraw_router_id_vni
,
2123 hash_iterate(bgp
->vnihash
,
2124 (void (*)(struct hash_backet
*,
2125 void *))update_router_id_vni
,
2130 * Handle change to export RT - update and advertise local routes.
2132 int bgp_evpn_handle_export_rt_change(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2134 return update_routes_for_vni(bgp
, vpn
);
2138 * Handle change to RD. This is invoked twice by the change handler,
2139 * first before the RD has been changed and then after the RD has
2140 * been changed. The first invocation will result in local routes
2141 * of this VNI being deleted and withdrawn and the next will result
2142 * in the routes being re-advertised.
2144 void bgp_evpn_handle_rd_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2148 delete_withdraw_vni_routes(bgp
, vpn
);
2150 update_advertise_vni_routes(bgp
, vpn
);
2154 * Install routes for this VNI. Invoked upon change to Import RT.
2156 int bgp_evpn_install_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2158 return install_routes_for_vni(bgp
, vpn
);
2162 * Uninstall all routes installed for this VNI. Invoked upon change
2165 int bgp_evpn_uninstall_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2167 return uninstall_routes_for_vni(bgp
, vpn
);
2171 * Function to display "tag" in route as a VNI.
2173 char *bgp_evpn_label2str(mpls_label_t
*label
, char *buf
, int len
)
2177 vni
= label2vni(label
);
2178 snprintf(buf
, len
, "%u", vni
);
2183 * Function to convert evpn route to string.
2184 * NOTE: We don't use prefix2str as the output here is a bit different.
2186 char *bgp_evpn_route2str(struct prefix_evpn
*p
, char *buf
, int len
)
2188 char buf1
[ETHER_ADDR_STRLEN
];
2189 char buf2
[PREFIX2STR_BUFFER
];
2191 if (p
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
) {
2192 snprintf(buf
, len
, "[%d]:[0]:[%d]:[%s]", p
->prefix
.route_type
,
2193 IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BITLEN
2195 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
2196 } else if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
2197 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
2198 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]",
2199 p
->prefix
.route_type
, 8 * ETH_ALEN
,
2200 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2205 family
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? AF_INET
2207 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]",
2208 p
->prefix
.route_type
, 8 * ETH_ALEN
,
2209 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2211 family
== AF_INET
? IPV4_MAX_BITLEN
2213 inet_ntop(family
, &p
->prefix
.ip
.ip
.addr
, buf2
,
2214 PREFIX2STR_BUFFER
));
2217 /* For EVPN route types not supported yet. */
2224 * Encode EVPN prefix in Update (MP_REACH)
2226 void bgp_evpn_encode_prefix(struct stream
*s
, struct prefix
*p
,
2227 struct prefix_rd
*prd
, mpls_label_t
*label
,
2228 struct attr
*attr
, int addpath_encode
,
2229 u_int32_t addpath_tx_id
)
2231 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
2235 stream_putl(s
, addpath_tx_id
);
2238 stream_putc(s
, evp
->prefix
.route_type
);
2240 switch (evp
->prefix
.route_type
) {
2241 case BGP_EVPN_MAC_IP_ROUTE
:
2242 if (IS_EVPN_PREFIX_IPADDR_V4(evp
))
2243 ipa_len
= IPV4_MAX_BYTELEN
;
2244 else if (IS_EVPN_PREFIX_IPADDR_V6(evp
))
2245 ipa_len
= IPV6_MAX_BYTELEN
;
2246 stream_putc(s
, 33 + ipa_len
); // 1 VNI
2247 stream_put(s
, prd
->val
, 8); /* RD */
2248 stream_put(s
, 0, 10); /* ESI */
2249 stream_putl(s
, 0); /* Ethernet Tag ID */
2250 stream_putc(s
, 8 * ETH_ALEN
); /* Mac Addr Len - bits */
2251 stream_put(s
, evp
->prefix
.mac
.octet
, 6); /* Mac Addr */
2252 stream_putc(s
, 8 * ipa_len
); /* IP address Length */
2254 stream_put(s
, &evp
->prefix
.ip
.ip
.addr
,
2256 stream_put(s
, label
,
2257 BGP_LABEL_BYTES
); /* VNI is contained in 'tag' */
2260 case BGP_EVPN_IMET_ROUTE
:
2261 stream_putc(s
, 17); // TODO: length - assumes IPv4 address
2262 stream_put(s
, prd
->val
, 8); /* RD */
2263 stream_putl(s
, 0); /* Ethernet Tag ID */
2264 stream_putc(s
, IPV4_MAX_BITLEN
); /* IP address Length - bits */
2265 /* Originating Router's IP Addr */
2266 stream_put_in_addr(s
, &evp
->prefix
.ip
.ipaddr_v4
);
2269 case BGP_EVPN_IP_PREFIX_ROUTE
:
2270 /* TODO: AddPath support. */
2271 evpn_mpattr_encode_type5(s
, p
, prd
, label
, attr
);
2279 int bgp_nlri_parse_evpn(struct peer
*peer
, struct attr
*attr
,
2280 struct bgp_nlri
*packet
, int withdraw
)
2286 u_int32_t addpath_id
;
2287 int addpath_encoded
;
2293 /* Check peer status. */
2294 if (peer
->status
!= Established
) {
2295 zlog_err("%u:%s - EVPN update received in state %d",
2296 peer
->bgp
->vrf_id
, peer
->host
, peer
->status
);
2300 /* Start processing the NLRI - there may be multiple in the MP_REACH */
2302 lim
= pnt
+ packet
->length
;
2304 safi
= packet
->safi
;
2308 (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
2309 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2310 PEER_CAP_ADDPATH_AF_TX_RCV
));
2312 for (; pnt
< lim
; pnt
+= psize
) {
2313 /* Clear prefix structure. */
2314 memset(&p
, 0, sizeof(struct prefix
));
2316 /* Deal with path-id if AddPath is supported. */
2317 if (addpath_encoded
) {
2318 /* When packet overflow occurs return immediately. */
2319 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
2322 addpath_id
= ntohl(*((uint32_t *)pnt
));
2323 pnt
+= BGP_ADDPATH_ID_LEN
;
2326 /* All EVPN NLRI types start with type and length. */
2331 psize
= rlen
= *pnt
++;
2333 /* When packet overflow occur return immediately. */
2334 if (pnt
+ psize
> lim
)
2338 case BGP_EVPN_MAC_IP_ROUTE
:
2339 if (process_type2_route(peer
, afi
, safi
,
2340 withdraw
? NULL
: attr
, pnt
,
2341 psize
, addpath_id
)) {
2343 "%u:%s - Error in processing EVPN type-2 NLRI size %d",
2344 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2349 case BGP_EVPN_IMET_ROUTE
:
2350 if (process_type3_route(peer
, afi
, safi
,
2351 withdraw
? NULL
: attr
, pnt
,
2352 psize
, addpath_id
)) {
2354 "%u:%s - Error in processing EVPN type-3 NLRI size %d",
2355 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2360 case BGP_EVPN_IP_PREFIX_ROUTE
:
2361 if (process_type5_route(peer
, afi
, safi
, attr
, pnt
,
2362 psize
, addpath_id
, withdraw
)) {
2364 "%u:%s - Error in processing EVPN type-5 NLRI size %d",
2365 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2375 /* Packet length consistency check. */
2384 * Map the RTs (configured or automatically derived) of a VNI to the VNI.
2385 * The mapping will be used during route processing.
2387 void bgp_evpn_map_vni_to_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2390 struct ecommunity_val
*eval
;
2391 struct listnode
*node
, *nnode
;
2392 struct ecommunity
*ecom
;
2394 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2395 for (i
= 0; i
< ecom
->size
; i
++) {
2396 eval
= (struct ecommunity_val
*)(ecom
->val
2398 * ECOMMUNITY_SIZE
));
2399 map_vni_to_rt(bgp
, vpn
, eval
);
2405 * Unmap the RTs (configured or automatically derived) of a VNI from the VNI.
2407 void bgp_evpn_unmap_vni_from_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2410 struct ecommunity_val
*eval
;
2411 struct listnode
*node
, *nnode
;
2412 struct ecommunity
*ecom
;
2414 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2415 for (i
= 0; i
< ecom
->size
; i
++) {
2416 struct irt_node
*irt
;
2417 struct ecommunity_val eval_tmp
;
2419 eval
= (struct ecommunity_val
*)(ecom
->val
2421 * ECOMMUNITY_SIZE
));
2422 /* If using "automatic" RT, we only care about the
2423 * local-admin sub-field.
2424 * This is to facilitate using VNI as the RT for EBGP
2427 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
2428 if (!is_import_rt_configured(vpn
))
2429 mask_ecom_global_admin(&eval_tmp
, eval
);
2431 irt
= lookup_import_rt(bgp
, &eval_tmp
);
2433 unmap_vni_from_rt(bgp
, vpn
, irt
);
2439 * Derive Import RT automatically for VNI and map VNI to RT.
2440 * The mapping will be used during route processing.
2442 void bgp_evpn_derive_auto_rt_import(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2444 form_auto_rt(bgp
, vpn
, vpn
->import_rtl
);
2445 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2448 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2452 * Derive Export RT automatically for VNI.
2454 void bgp_evpn_derive_auto_rt_export(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2456 form_auto_rt(bgp
, vpn
, vpn
->export_rtl
);
2457 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2461 * Derive RD automatically for VNI using passed information - it
2462 * is of the form RouterId:unique-id-for-vni.
2464 void bgp_evpn_derive_auto_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2468 vpn
->prd
.family
= AF_UNSPEC
;
2469 vpn
->prd
.prefixlen
= 64;
2470 sprintf(buf
, "%s:%hu", inet_ntoa(bgp
->router_id
), vpn
->rd_id
);
2471 str2prefix_rd(buf
, &vpn
->prd
);
2472 UNSET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2478 struct bgpevpn
*bgp_evpn_lookup_vni(struct bgp
*bgp
, vni_t vni
)
2480 struct bgpevpn
*vpn
;
2483 memset(&tmp
, 0, sizeof(struct bgpevpn
));
2485 vpn
= hash_lookup(bgp
->vnihash
, &tmp
);
2490 * Create a new vpn - invoked upon configuration or zebra notification.
2492 struct bgpevpn
*bgp_evpn_new(struct bgp
*bgp
, vni_t vni
,
2493 struct in_addr originator_ip
)
2495 struct bgpevpn
*vpn
;
2500 vpn
= XCALLOC(MTYPE_BGP_EVPN
, sizeof(struct bgpevpn
));
2504 /* Set values - RD and RT set to defaults. */
2506 vpn
->originator_ip
= originator_ip
;
2508 /* Initialize route-target import and export lists */
2509 vpn
->import_rtl
= list_new();
2510 vpn
->import_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2511 vpn
->export_rtl
= list_new();
2512 vpn
->export_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2513 bf_assign_index(bgp
->rd_idspace
, vpn
->rd_id
);
2514 derive_rd_rt_for_vni(bgp
, vpn
);
2516 /* Initialize EVPN route table. */
2517 vpn
->route_table
= bgp_table_init(AFI_L2VPN
, SAFI_EVPN
);
2520 if (!hash_get(bgp
->vnihash
, vpn
, hash_alloc_intern
)) {
2521 XFREE(MTYPE_BGP_EVPN
, vpn
);
2524 QOBJ_REG(vpn
, bgpevpn
);
2529 * Free a given VPN - called in multiple scenarios such as zebra
2530 * notification, configuration being deleted, advertise-all-vni disabled etc.
2531 * This just frees appropriate memory, caller should have taken other
2534 void bgp_evpn_free(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2536 bgp_table_unlock(vpn
->route_table
);
2537 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2538 list_delete(vpn
->import_rtl
);
2539 list_delete(vpn
->export_rtl
);
2540 vpn
->import_rtl
= NULL
;
2541 vpn
->export_rtl
= NULL
;
2542 bf_release_index(bgp
->rd_idspace
, vpn
->rd_id
);
2543 hash_release(bgp
->vnihash
, vpn
);
2545 XFREE(MTYPE_BGP_EVPN
, vpn
);
2549 * Import route into matching VNI(s).
2551 int bgp_evpn_import_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2552 struct prefix
*p
, struct bgp_info
*ri
)
2554 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 1);
2558 * Unimport route from matching VNI(s).
2560 int bgp_evpn_unimport_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2561 struct prefix
*p
, struct bgp_info
*ri
)
2563 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 0);
2567 * Handle del of a local MACIP.
2569 int bgp_evpn_local_macip_del(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2572 struct bgpevpn
*vpn
;
2573 struct prefix_evpn p
;
2575 if (!bgp
->vnihash
) {
2576 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2580 /* Lookup VNI hash - should exist. */
2581 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2582 if (!vpn
|| !is_vni_live(vpn
)) {
2583 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP DEL",
2584 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2588 /* Remove EVPN type-2 route and schedule for processing. */
2589 build_evpn_type2_prefix(&p
, mac
, ip
);
2590 delete_evpn_route(bgp
, vpn
, &p
);
2596 * Handle add of a local MACIP.
2598 int bgp_evpn_local_macip_add(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2599 struct ipaddr
*ip
, u_char flags
)
2601 struct bgpevpn
*vpn
;
2602 struct prefix_evpn p
;
2604 if (!bgp
->vnihash
) {
2605 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2609 /* Lookup VNI hash - should exist. */
2610 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2611 if (!vpn
|| !is_vni_live(vpn
)) {
2612 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP ADD",
2613 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2617 /* Create EVPN type-2 route and schedule for processing. */
2618 build_evpn_type2_prefix(&p
, mac
, ip
);
2619 if (update_evpn_route(bgp
, vpn
, &p
, flags
)) {
2620 char buf
[ETHER_ADDR_STRLEN
];
2621 char buf2
[INET6_ADDRSTRLEN
];
2624 "%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s",
2625 bgp
->vrf_id
, vpn
->vni
,
2626 CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_STICKY
) ? "sticky gateway"
2628 prefix_mac2str(mac
, buf
, sizeof(buf
)),
2629 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2637 * Handle del of a local VNI.
2639 int bgp_evpn_local_vni_del(struct bgp
*bgp
, vni_t vni
)
2641 struct bgpevpn
*vpn
;
2643 if (!bgp
->vnihash
) {
2644 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2648 /* Locate VNI hash */
2649 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2651 zlog_warn("%u: VNI hash entry for VNI %u not found at DEL",
2656 /* Remove all local EVPN routes and schedule for processing (to
2657 * withdraw from peers).
2659 delete_routes_for_vni(bgp
, vpn
);
2661 /* Clear "live" flag and see if hash needs to be freed. */
2662 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2663 if (!is_vni_configured(vpn
))
2664 bgp_evpn_free(bgp
, vpn
);
2670 * Handle add (or update) of a local VNI. The only VNI change we care
2671 * about is change to local-tunnel-ip.
2673 int bgp_evpn_local_vni_add(struct bgp
*bgp
, vni_t vni
,
2674 struct in_addr originator_ip
)
2676 struct bgpevpn
*vpn
;
2677 struct prefix_evpn p
;
2679 if (!bgp
->vnihash
) {
2680 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2684 /* Lookup VNI. If present and no change, exit. */
2685 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2687 if (is_vni_live(vpn
)
2688 && IPV4_ADDR_SAME(&vpn
->originator_ip
, &originator_ip
))
2689 /* Probably some other param has changed that we don't
2693 /* Local tunnel endpoint IP address has changed */
2694 handle_tunnel_ip_change(bgp
, vpn
, originator_ip
);
2697 /* Create or update as appropriate. */
2699 vpn
= bgp_evpn_new(bgp
, vni
, originator_ip
);
2702 "%u: Failed to allocate VNI entry for VNI %u - at Add",
2708 /* if the VNI is live already, there is nothibng more to do */
2709 if (is_vni_live(vpn
))
2712 /* Mark as "live" */
2713 SET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2715 /* Create EVPN type-3 route and schedule for processing. */
2716 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
2717 if (update_evpn_route(bgp
, vpn
, &p
, 0)) {
2718 zlog_err("%u: Type3 route creation failure for VNI %u",
2723 /* If we have learnt and retained remote routes (VTEPs, MACs) for this
2727 install_routes_for_vni(bgp
, vpn
);
2729 /* If we are advertising gateway mac-ip
2730 It needs to be conveyed again to zebra */
2731 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
, vpn
->vni
);
2737 * Cleanup EVPN information on disable - Need to delete and withdraw
2738 * EVPN routes from peers.
2740 void bgp_evpn_cleanup_on_disable(struct bgp
*bgp
)
2742 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2743 void *))cleanup_vni_on_disable
,
2748 * Cleanup EVPN information - invoked at the time of bgpd exit or when the
2749 * BGP instance (default) is being freed.
2751 void bgp_evpn_cleanup(struct bgp
*bgp
)
2754 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2755 void *))free_vni_entry
,
2757 if (bgp
->import_rt_hash
)
2758 hash_free(bgp
->import_rt_hash
);
2759 bgp
->import_rt_hash
= NULL
;
2761 hash_free(bgp
->vnihash
);
2762 bgp
->vnihash
= NULL
;
2763 bf_free(bgp
->rd_idspace
);
2767 * Initialization for EVPN
2770 * hash for RT to VNI
2771 * unique rd id space for auto derivation of RD for VNIs
2773 void bgp_evpn_init(struct bgp
*bgp
)
2776 hash_create(vni_hash_key_make
, vni_hash_cmp
, "BGP VNI Hash");
2777 bgp
->import_rt_hash
=
2778 hash_create(import_rt_hash_key_make
, import_rt_hash_cmp
,
2779 "BGP Import RT Hash");
2780 bf_init(bgp
->rd_idspace
, UINT16_MAX
);
2781 /*assign 0th index in the bitfield, so that we start with id 1*/
2782 bf_assign_zero_index(bgp
->rd_idspace
);