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"
50 * Definitions and external declarations.
52 extern struct zclient
*zclient
;
54 DEFINE_QOBJ_TYPE(bgpevpn
)
58 * Static function declarations
60 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
61 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
62 struct bgp_info
**ri
);
63 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
);
72 static unsigned int vni_hash_key_make(void *p
)
74 struct bgpevpn
*vpn
= p
;
75 return (jhash_1word(vpn
->vni
, 0));
79 * Comparison function for vni hash
81 static int vni_hash_cmp(const void *p1
, const void *p2
)
83 const struct bgpevpn
*vpn1
= p1
;
84 const struct bgpevpn
*vpn2
= p2
;
90 return (vpn1
->vni
== vpn2
->vni
);
94 * Make import route target hash key.
96 static unsigned int import_rt_hash_key_make(void *p
)
98 struct irt_node
*irt
= p
;
99 char *pnt
= irt
->rt
.val
;
100 unsigned int key
= 0;
116 * Comparison function for import rt hash
118 static int import_rt_hash_cmp(const void *p1
, const void *p2
)
120 const struct irt_node
*irt1
= p1
;
121 const struct irt_node
*irt2
= p2
;
123 if (irt1
== NULL
&& irt2
== NULL
)
126 if (irt1
== NULL
|| irt2
== NULL
)
129 return (memcmp(irt1
->rt
.val
, irt2
->rt
.val
, ECOMMUNITY_SIZE
) == 0);
133 * Create a new import_rt
135 static struct irt_node
*import_rt_new(struct bgp
*bgp
,
136 struct ecommunity_val
*rt
)
138 struct irt_node
*irt
;
143 irt
= XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT
, sizeof(struct irt_node
));
148 irt
->vnis
= list_new();
151 if (!hash_get(bgp
->import_rt_hash
, irt
, hash_alloc_intern
)) {
152 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
160 * Free the import rt node
162 static void import_rt_free(struct bgp
*bgp
, struct irt_node
*irt
)
164 hash_release(bgp
->import_rt_hash
, irt
);
165 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
169 * Function to lookup Import RT node - used to map a RT to set of
170 * VNIs importing routes with that RT.
172 static struct irt_node
*lookup_import_rt(struct bgp
*bgp
,
173 struct ecommunity_val
*rt
)
175 struct irt_node
*irt
;
178 memset(&tmp
, 0, sizeof(struct irt_node
));
179 memcpy(&tmp
.rt
, rt
, ECOMMUNITY_SIZE
);
180 irt
= hash_lookup(bgp
->import_rt_hash
, &tmp
);
185 * Is specified VNI present on the RT's list of "importing" VNIs?
187 static int is_vni_present_in_irt_vnis(struct list
*vnis
, struct bgpevpn
*vpn
)
189 struct listnode
*node
, *nnode
;
190 struct bgpevpn
*tmp_vpn
;
192 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, tmp_vpn
)) {
201 * Compare Route Targets.
203 static int evpn_route_target_cmp(struct ecommunity
*ecom1
,
204 struct ecommunity
*ecom2
)
212 if (!ecom1
&& !ecom2
)
215 if (ecom1
->str
&& !ecom2
->str
)
218 if (!ecom1
->str
&& ecom2
->str
)
221 if (!ecom1
->str
&& !ecom2
->str
)
224 return strcmp(ecom1
->str
, ecom2
->str
);
228 * Mask off global-admin field of specified extended community (RT),
229 * just retain the local-admin field.
231 static inline void mask_ecom_global_admin(struct ecommunity_val
*dst
,
232 struct ecommunity_val
*src
)
238 if (type
== ECOMMUNITY_ENCODE_AS
) {
239 dst
->val
[2] = dst
->val
[3] = 0;
240 } else if (type
== ECOMMUNITY_ENCODE_AS4
241 || type
== ECOMMUNITY_ENCODE_IP
) {
242 dst
->val
[2] = dst
->val
[3] = 0;
243 dst
->val
[4] = dst
->val
[5] = 0;
248 * Map one RT to specified VNI.
250 static void map_vni_to_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
251 struct ecommunity_val
*eval
)
253 struct irt_node
*irt
;
254 struct ecommunity_val eval_tmp
;
256 /* If using "automatic" RT, we only care about the local-admin
258 * This is to facilitate using VNI as the RT for EBGP peering too.
260 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
261 if (!is_import_rt_configured(vpn
))
262 mask_ecom_global_admin(&eval_tmp
, eval
);
264 irt
= lookup_import_rt(bgp
, &eval_tmp
);
265 if (irt
&& irt
->vnis
)
266 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
267 /* Already mapped. */
271 irt
= import_rt_new(bgp
, &eval_tmp
);
275 /* Add VNI to the hash list for this RT. */
276 listnode_add(irt
->vnis
, vpn
);
280 * Unmap specified VNI from specified RT. If there are no other
281 * VNIs for this RT, then the RT hash is deleted.
283 static void unmap_vni_from_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
284 struct irt_node
*irt
)
286 /* Delete VNI from hash list for this RT. */
287 listnode_delete(irt
->vnis
, vpn
);
288 if (!listnode_head(irt
->vnis
)) {
289 list_free(irt
->vnis
);
290 import_rt_free(bgp
, irt
);
295 * Create RT extended community automatically from passed information:
296 * of the form AS:VNI.
297 * NOTE: We use only the lower 16 bits of the AS. This is sufficient as
298 * the need is to get a RT value that will be unique across different
299 * VNIs but the same across routers (in the same AS) for a particular
302 static void form_auto_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
, struct list
*rtl
)
304 struct ecommunity_val eval
;
305 struct ecommunity
*ecomadd
;
307 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
309 ecomadd
= ecommunity_new();
310 ecommunity_add_val(ecomadd
, &eval
);
311 listnode_add_sort(rtl
, ecomadd
);
315 * Derive RD and RT for a VNI automatically. Invoked at the time of
318 static void derive_rd_rt_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
320 bgp_evpn_derive_auto_rd(bgp
, vpn
);
321 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
322 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
326 * Add (update) or delete MACIP from zebra.
328 static int bgp_zebra_send_remote_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
329 struct prefix_evpn
*p
,
330 struct in_addr remote_vtep_ip
, int add
,
335 char buf1
[ETHER_ADDR_STRLEN
];
336 char buf2
[INET6_ADDRSTRLEN
];
337 char buf3
[INET6_ADDRSTRLEN
];
340 if (!zclient
|| zclient
->sock
< 0)
343 /* Don't try to register if Zebra doesn't know of this instance. */
344 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
350 zclient_create_header(
351 s
, add
? ZEBRA_REMOTE_MACIP_ADD
: ZEBRA_REMOTE_MACIP_DEL
,
353 stream_putl(s
, vpn
->vni
);
354 stream_put(s
, &p
->prefix
.mac
.octet
, ETHER_ADDR_LEN
); /* Mac Addr */
355 /* IP address length and IP address, if any. */
356 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
359 ipa_len
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BYTELEN
361 stream_putl(s
, ipa_len
);
362 stream_put(s
, &p
->prefix
.ip
.ip
.addr
, ipa_len
);
364 stream_put_in_addr(s
, &remote_vtep_ip
);
366 /* TX MAC sticky status */
368 stream_putc(s
, sticky
);
370 stream_putw_at(s
, 0, stream_get_endp(s
));
372 if (bgp_debug_zebra(NULL
))
373 zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s",
374 add
? "ADD" : "DEL", vpn
->vni
,
375 sticky
? "sticky " : "",
376 prefix_mac2str(&p
->prefix
.mac
, buf1
, sizeof(buf1
)),
377 ipaddr2str(&p
->prefix
.ip
, buf3
, sizeof(buf3
)),
378 inet_ntop(AF_INET
, &remote_vtep_ip
, buf2
,
381 return zclient_send_message(zclient
);
385 * Add (update) or delete remote VTEP from zebra.
387 static int bgp_zebra_send_remote_vtep(struct bgp
*bgp
, struct bgpevpn
*vpn
,
388 struct prefix_evpn
*p
, int add
)
393 if (!zclient
|| zclient
->sock
< 0)
396 /* Don't try to register if Zebra doesn't know of this instance. */
397 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
403 zclient_create_header(
404 s
, add
? ZEBRA_REMOTE_VTEP_ADD
: ZEBRA_REMOTE_VTEP_DEL
,
406 stream_putl(s
, vpn
->vni
);
407 if (IS_EVPN_PREFIX_IPADDR_V4(p
))
408 stream_put_in_addr(s
, &p
->prefix
.ip
.ipaddr_v4
);
409 else if (IS_EVPN_PREFIX_IPADDR_V6(p
)) {
411 "Bad remote IP when trying to %s remote VTEP for VNI %u",
412 add
? "ADD" : "DEL", vpn
->vni
);
416 stream_putw_at(s
, 0, stream_get_endp(s
));
418 if (bgp_debug_zebra(NULL
))
419 zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
420 add
? "ADD" : "DEL", vpn
->vni
,
421 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
423 return zclient_send_message(zclient
);
427 * Build extended communities for EVPN route. RT and ENCAP are
428 * applicable to all routes.
430 static void build_evpn_route_extcomm(struct bgpevpn
*vpn
, struct attr
*attr
)
432 struct ecommunity ecom_encap
;
433 struct ecommunity ecom_sticky
;
434 struct ecommunity_val eval
;
435 struct ecommunity_val eval_sticky
;
436 bgp_encap_types tnl_type
;
437 struct listnode
*node
, *nnode
;
438 struct ecommunity
*ecom
;
442 tnl_type
= BGP_ENCAP_TYPE_VXLAN
;
443 memset(&ecom_encap
, 0, sizeof(ecom_encap
));
444 encode_encap_extcomm(tnl_type
, &eval
);
446 ecom_encap
.val
= (u_int8_t
*)eval
.val
;
449 attr
->ecommunity
= ecommunity_dup(&ecom_encap
);
451 /* Add the export RTs */
452 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
453 attr
->ecommunity
= ecommunity_merge(attr
->ecommunity
, ecom
);
457 memset(&ecom_sticky
, 0, sizeof(ecom_sticky
));
458 encode_mac_mobility_extcomm(1, seqnum
, &eval_sticky
);
459 ecom_sticky
.size
= 1;
460 ecom_sticky
.val
= (u_int8_t
*)eval_sticky
.val
;
462 ecommunity_merge(attr
->ecommunity
, &ecom_sticky
);
465 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
469 * Add MAC mobility extended community to attribute.
471 static void add_mac_mobility_to_attr(u_int32_t seq_num
, struct attr
*attr
)
473 struct ecommunity ecom_tmp
;
474 struct ecommunity_val eval
;
475 struct ecommunity
*ecom_mm
;
482 encode_mac_mobility_extcomm(0, seq_num
, &eval
);
484 /* Find current MM ecommunity */
487 if (attr
->ecommunity
) {
488 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
489 pnt
= attr
->ecommunity
->val
+ (i
* 8);
493 if (type
== ECOMMUNITY_ENCODE_EVPN
495 == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
) {
496 ecom_mm
= (struct ecommunity
*)
497 attr
->ecommunity
->val
504 /* Update the existing MM ecommunity */
506 memcpy(ecom_mm
->val
, eval
.val
, sizeof(char) * ECOMMUNITY_SIZE
);
508 /* Add MM to existing */
510 memset(&ecom_tmp
, 0, sizeof(ecom_tmp
));
512 ecom_tmp
.val
= (u_int8_t
*)eval
.val
;
515 ecommunity_merge(attr
->ecommunity
, &ecom_tmp
);
519 /* Install EVPN route into zebra. */
520 static int evpn_zebra_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
521 struct prefix_evpn
*p
,
522 struct in_addr remote_vtep_ip
, u_char sticky
)
526 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
527 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
530 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 1);
535 /* Uninstall EVPN route from zebra. */
536 static int evpn_zebra_uninstall(struct bgp
*bgp
, struct bgpevpn
*vpn
,
537 struct prefix_evpn
*p
,
538 struct in_addr remote_vtep_ip
)
542 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
543 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
546 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 0);
552 * Due to MAC mobility, the prior "local" best route has been supplanted
553 * by a "remote" best route. The prior route has to be deleted and withdrawn
556 static void evpn_delete_old_local_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
558 struct bgp_info
*old_local
)
560 struct bgp_node
*global_rn
;
562 afi_t afi
= AFI_L2VPN
;
563 safi_t safi
= SAFI_EVPN
;
565 /* Locate route node in the global EVPN routing table. Note that
566 * this table is a 2-level tree (RD-level + Prefix-level) similar to
569 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
570 (struct prefix
*)&rn
->p
, &vpn
->prd
);
572 /* Delete route entry in the global EVPN table. */
573 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
575 /* Schedule for processing - withdraws to peers happen from
579 bgp_process(bgp
, global_rn
, afi
, safi
);
580 bgp_unlock_node(global_rn
);
583 /* Delete route entry in the VNI route table, caller to remove. */
584 bgp_info_delete(rn
, old_local
);
588 * Calculate the best path for an EVPN route. Install/update best path in zebra,
591 static int evpn_route_select_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
594 struct bgp_info
*old_select
, *new_select
;
595 struct bgp_info_pair old_and_new
;
596 afi_t afi
= AFI_L2VPN
;
597 safi_t safi
= SAFI_EVPN
;
600 /* Compute the best path. */
601 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
603 old_select
= old_and_new
.old
;
604 new_select
= old_and_new
.new;
606 /* If the best path hasn't changed - see if there is still something to
610 if (old_select
&& old_select
== new_select
611 && old_select
->type
== ZEBRA_ROUTE_BGP
612 && old_select
->sub_type
== BGP_ROUTE_NORMAL
613 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
614 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
615 && !bgp
->addpath_tx_used
[afi
][safi
]) {
616 if (bgp_zebra_has_route_changed(rn
, old_select
))
617 ret
= evpn_zebra_install(bgp
, vpn
,
618 (struct prefix_evpn
*)&rn
->p
,
619 old_select
->attr
->nexthop
,
620 old_select
->attr
->sticky
);
621 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
622 bgp_zebra_clear_route_change_flags(rn
);
626 /* If the user did a "clear" this flag will be set */
627 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
629 /* bestpath has changed; update relevant fields and install or uninstall
630 * into the zebra RIB.
632 if (old_select
|| new_select
)
633 bgp_bump_version(rn
);
636 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
638 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
639 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
640 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
643 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
644 && new_select
->sub_type
== BGP_ROUTE_NORMAL
) {
645 ret
= evpn_zebra_install(bgp
, vpn
, (struct prefix_evpn
*)&rn
->p
,
646 new_select
->attr
->nexthop
,
647 new_select
->attr
->sticky
);
648 /* If an old best existed and it was a "local" route, the only
650 * it would be supplanted is due to MAC mobility procedures. So,
652 * need to do an implicit delete and withdraw that route from
655 if (old_select
&& old_select
->peer
== bgp
->peer_self
656 && old_select
->type
== ZEBRA_ROUTE_BGP
657 && old_select
->sub_type
== BGP_ROUTE_STATIC
)
658 evpn_delete_old_local_route(bgp
, vpn
, rn
, old_select
);
660 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
661 && old_select
->sub_type
== BGP_ROUTE_NORMAL
)
662 ret
= evpn_zebra_uninstall(bgp
, vpn
,
663 (struct prefix_evpn
*)&rn
->p
,
664 old_select
->attr
->nexthop
);
667 /* Clear any route change flags. */
668 bgp_zebra_clear_route_change_flags(rn
);
670 /* Reap old select bgp_info, if it has been removed */
671 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
672 bgp_info_reap(rn
, old_select
);
679 * Return true if the local ri for this rn has sticky set
681 static int evpn_route_is_sticky(struct bgp
*bgp
, struct bgp_node
*rn
)
683 struct bgp_info
*tmp_ri
;
684 struct bgp_info
*local_ri
;
687 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
688 if (tmp_ri
->peer
== bgp
->peer_self
689 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
690 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
697 return local_ri
->attr
->sticky
;
701 * Create or update EVPN route entry. This could be in the VNI route table
702 * or the global route table.
704 static int update_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
705 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
706 struct attr
*attr
, int add
, int vni_table
,
707 struct bgp_info
**ri
)
709 struct bgp_info
*tmp_ri
;
710 struct bgp_info
*local_ri
, *remote_ri
;
711 struct attr
*attr_new
;
712 mpls_label_t label
= MPLS_INVALID_LABEL
;
713 int route_change
= 1;
718 /* See if this is an update of an existing route, or a new add. Also,
719 * identify if already known from remote, and if so, the one with the
720 * highest sequence number; this is only when adding to the VNI routing
723 local_ri
= remote_ri
= NULL
;
724 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
725 if (tmp_ri
->peer
== bgp
->peer_self
726 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
727 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
730 if (tmp_ri
->type
== ZEBRA_ROUTE_BGP
731 && tmp_ri
->sub_type
== BGP_ROUTE_NORMAL
732 && CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
)) {
735 else if (mac_mobility_seqnum(tmp_ri
->attr
)
736 > mac_mobility_seqnum(remote_ri
->attr
))
742 /* If route doesn't exist already, create a new one, if told to.
743 * Otherwise act based on whether the attributes of the route have
746 if (!local_ri
&& !add
)
750 /* When learnt locally for the first time but already known from
751 * remote, we have to initiate appropriate MAC mobility steps.
753 * is applicable when updating the VNI routing table.
756 u_int32_t cur_seqnum
;
758 /* Add MM extended community to route. */
759 cur_seqnum
= mac_mobility_seqnum(remote_ri
->attr
);
760 add_mac_mobility_to_attr(cur_seqnum
+ 1, attr
);
763 /* Add (or update) attribute to hash. */
764 attr_new
= bgp_attr_intern(attr
);
766 /* Extract MAC mobility sequence number, if any. */
767 attr_new
->mm_seqnum
=
768 bgp_attr_mac_mobility_seqnum(attr_new
, &sticky
);
769 attr_new
->sticky
= sticky
;
771 /* Create new route with its attribute. */
772 tmp_ri
= info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0,
773 bgp
->peer_self
, attr_new
, rn
);
774 SET_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
);
775 bgp_info_extra_get(tmp_ri
);
777 /* The VNI goes into the 'label' field of the route */
778 vni2label(vpn
->vni
, &label
);
780 memcpy(&tmp_ri
->extra
->label
, &label
, BGP_LABEL_BYTES
);
781 bgp_info_add(rn
, tmp_ri
);
784 if (attrhash_cmp(tmp_ri
->attr
, attr
)
785 && !CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
788 /* The attribute has changed. */
789 /* Add (or update) attribute to hash. */
790 attr_new
= bgp_attr_intern(attr
);
791 bgp_info_set_flag(rn
, tmp_ri
, BGP_INFO_ATTR_CHANGED
);
793 /* Restore route, if needed. */
794 if (CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
795 bgp_info_restore(rn
, tmp_ri
);
797 /* Unintern existing, set to new. */
798 bgp_attr_unintern(&tmp_ri
->attr
);
799 tmp_ri
->attr
= attr_new
;
800 tmp_ri
->uptime
= bgp_clock();
804 /* Return back the route entry. */
810 * Create or update EVPN route (of type based on prefix) for specified VNI
811 * and schedule for processing.
813 static int update_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
814 struct prefix_evpn
*p
, u_char sticky
)
818 struct attr
*attr_new
;
820 afi_t afi
= AFI_L2VPN
;
821 safi_t safi
= SAFI_EVPN
;
824 memset(&attr
, 0, sizeof(struct attr
));
826 /* Build path-attribute for this route. */
827 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
828 attr
.nexthop
= vpn
->originator_ip
;
829 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
830 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
831 attr
.sticky
= sticky
;
833 /* Set up RT and ENCAP extended community. */
834 build_evpn_route_extcomm(vpn
, &attr
);
836 /* First, create (or fetch) route node within the VNI. */
837 /* NOTE: There is no RD here. */
838 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
840 /* Create or update route entry. */
841 route_change
= update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
846 /* Perform route selection; this is just to set the flags correctly
847 * as local route in the VNI always wins.
849 evpn_route_select_install(bgp
, vpn
, rn
);
852 /* If this is a new route or some attribute has changed, export the
853 * route to the global table. The route will be advertised to peers
854 * from there. Note that this table is a 2-level tree (RD-level +
855 * Prefix-level) similar to L3VPN routes.
858 struct bgp_info
*global_ri
;
860 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
861 (struct prefix
*)p
, &vpn
->prd
);
862 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, attr_new
, 1, 0,
865 /* Schedule for processing and unlock node. */
866 bgp_process(bgp
, rn
, afi
, safi
);
870 /* Unintern temporary. */
871 aspath_unintern(&attr
.aspath
);
877 * Delete EVPN route entry. This could be in the VNI route table
878 * or the global route table.
880 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
881 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
882 struct bgp_info
**ri
)
884 struct bgp_info
*tmp_ri
;
888 /* Now, find matching route. */
889 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
)
890 if (tmp_ri
->peer
== bgp
->peer_self
891 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
892 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
897 /* Mark route for delete. */
899 bgp_info_delete(rn
, tmp_ri
);
903 * Delete EVPN route (of type based on prefix) for specified VNI and
904 * schedule for processing.
906 static int delete_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
907 struct prefix_evpn
*p
)
909 struct bgp_node
*rn
, *global_rn
;
911 afi_t afi
= AFI_L2VPN
;
912 safi_t safi
= SAFI_EVPN
;
914 /* First, locate the route node within the VNI. If it doesn't exist,
916 * is nothing further to do.
918 /* NOTE: There is no RD here. */
919 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
923 /* Next, locate route node in the global EVPN routing table. Note that
924 * this table is a 2-level tree (RD-level + Prefix-level) similar to
927 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
928 (struct prefix
*)p
, &vpn
->prd
);
930 /* Delete route entry in the global EVPN table. */
931 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
933 /* Schedule for processing - withdraws to peers happen from
937 bgp_process(bgp
, global_rn
, afi
, safi
);
938 bgp_unlock_node(global_rn
);
941 /* Delete route entry in the VNI route table. This can just be removed.
943 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
945 bgp_info_reap(rn
, ri
);
952 * Update all type-2 (MACIP) local routes for this VNI - these should also
953 * be scheduled for advertise to peers.
955 static int update_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
962 struct attr attr_sticky
;
963 struct attr
*attr_new
;
967 memset(&attr
, 0, sizeof(struct attr
));
968 memset(&attr_sticky
, 0, sizeof(struct attr
));
970 /* Build path-attribute - all type-2 routes for this VNI will share the
971 * same path attribute.
973 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
974 bgp_attr_default_set(&attr_sticky
, BGP_ORIGIN_IGP
);
975 attr
.nexthop
= vpn
->originator_ip
;
976 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
977 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
978 attr_sticky
.nexthop
= vpn
->originator_ip
;
979 attr_sticky
.mp_nexthop_global_in
= vpn
->originator_ip
;
980 attr_sticky
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
981 attr_sticky
.sticky
= 1;
983 /* Set up RT, ENCAP and sticky MAC extended community. */
984 build_evpn_route_extcomm(vpn
, &attr
);
985 build_evpn_route_extcomm(vpn
, &attr_sticky
);
987 /* Walk this VNI's route table and update local type-2 routes. For any
988 * routes updated, update corresponding entry in the global table too.
990 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
991 rn
= bgp_route_next(rn
)) {
992 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
993 struct bgp_node
*rd_rn
;
994 struct bgp_info
*global_ri
;
996 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
999 if (evpn_route_is_sticky(bgp
, rn
))
1000 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
,
1001 &attr_sticky
, 0, 1, &ri
);
1003 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
1006 /* If a local route exists for this prefix, we need to update
1007 * the global routing table too.
1012 /* Perform route selection; this is just to set the flags
1014 * as local route in the VNI always wins.
1016 evpn_route_select_install(bgp
, vpn
, rn
);
1018 attr_new
= ri
->attr
;
1020 /* Update route in global routing table. */
1021 rd_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1022 (struct prefix
*)evp
, &vpn
->prd
);
1024 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rd_rn
, attr_new
, 0,
1027 /* Schedule for processing and unlock node. */
1028 bgp_process(bgp
, rd_rn
, afi
, safi
);
1029 bgp_unlock_node(rd_rn
);
1032 /* Unintern temporary. */
1033 aspath_unintern(&attr
.aspath
);
1034 aspath_unintern(&attr_sticky
.aspath
);
1040 * Delete all type-2 (MACIP) local routes for this VNI - only from the
1041 * global routing table. These are also scheduled for withdraw from peers.
1043 static int delete_global_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1047 struct bgp_node
*rdrn
, *rn
;
1048 struct bgp_table
*table
;
1049 struct bgp_info
*ri
;
1054 rdrn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)&vpn
->prd
);
1055 if (rdrn
&& rdrn
->info
) {
1056 table
= (struct bgp_table
*)rdrn
->info
;
1057 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1058 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1060 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1063 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1065 bgp_process(bgp
, rn
, afi
, safi
);
1069 /* Unlock RD node. */
1071 bgp_unlock_node(rdrn
);
1077 * Delete all type-2 (MACIP) local routes for this VNI - from the global
1078 * table as well as the per-VNI route table.
1080 static int delete_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1084 struct bgp_node
*rn
;
1085 struct bgp_info
*ri
;
1090 /* First, walk the global route table for this VNI's type-2 local
1092 * EVPN routes are a 2-level table, first get the RD table.
1094 delete_global_type2_routes(bgp
, vpn
);
1096 /* Next, walk this VNI's route table and delete local type-2 routes. */
1097 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1098 rn
= bgp_route_next(rn
)) {
1099 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1101 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1104 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1106 /* Route entry in local table gets deleted immediately. */
1108 bgp_info_reap(rn
, ri
);
1115 * Delete all routes in the per-VNI route table.
1117 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1119 struct bgp_node
*rn
;
1120 struct bgp_info
*ri
, *nextri
;
1122 /* Walk this VNI's route table and delete all routes. */
1123 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1124 rn
= bgp_route_next(rn
)) {
1125 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1127 bgp_info_delete(rn
, ri
);
1128 bgp_info_reap(rn
, ri
);
1136 * Update (and advertise) local routes for a VNI. Invoked upon the VNI
1137 * export RT getting modified or change to tunnel IP. Note that these
1138 * situations need the route in the per-VNI table as well as the global
1139 * table to be updated (as attributes change).
1141 static int update_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1144 struct prefix_evpn p
;
1146 /* Update and advertise the type-3 route (only one) followed by the
1147 * locally learnt type-2 routes (MACIP) - for this VNI.
1149 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1150 ret
= update_evpn_route(bgp
, vpn
, &p
, 0);
1154 return update_all_type2_routes(bgp
, vpn
);
1158 * Delete (and withdraw) local routes for specified VNI from the global
1159 * table and per-VNI table. After this, remove all other routes from
1160 * the per-VNI table. Invoked upon the VNI being deleted or EVPN
1161 * (advertise-all-vni) being disabled.
1163 static int delete_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1166 struct prefix_evpn p
;
1168 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1169 * followed by type-3 routes (only one) - for this VNI.
1171 ret
= delete_all_type2_routes(bgp
, vpn
);
1175 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1176 ret
= delete_evpn_route(bgp
, vpn
, &p
);
1180 /* Delete all routes from the per-VNI table. */
1181 return delete_all_vni_routes(bgp
, vpn
);
1185 * There is a tunnel endpoint IP address change for this VNI,
1186 * need to re-advertise routes with the new nexthop.
1188 static int handle_tunnel_ip_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1189 struct in_addr originator_ip
)
1191 struct prefix_evpn p
;
1193 /* Need to withdraw type-3 route as the originator IP is part
1196 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1197 delete_evpn_route(bgp
, vpn
, &p
);
1199 /* Update the tunnel IP and re-advertise all routes for this VNI. */
1200 vpn
->originator_ip
= originator_ip
;
1201 return update_routes_for_vni(bgp
, vpn
);
1205 * Install route entry into the VNI routing table and invoke route selection.
1207 static int install_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1208 struct prefix_evpn
*p
,
1209 struct bgp_info
*parent_ri
)
1211 struct bgp_node
*rn
;
1212 struct bgp_info
*ri
;
1213 struct attr
*attr_new
;
1216 /* Create (or fetch) route within the VNI. */
1217 /* NOTE: There is no RD here. */
1218 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
1220 /* Check if route entry is already present. */
1221 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1223 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1227 /* Add (or update) attribute to hash. */
1228 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1230 /* Create new route with its attribute. */
1231 ri
= info_make(parent_ri
->type
, parent_ri
->sub_type
, 0,
1232 parent_ri
->peer
, attr_new
, rn
);
1233 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
1234 bgp_info_extra_get(ri
);
1235 ri
->extra
->parent
= parent_ri
;
1236 if (parent_ri
->extra
)
1237 memcpy(&ri
->extra
->label
, &parent_ri
->extra
->label
,
1239 bgp_info_add(rn
, ri
);
1241 if (attrhash_cmp(ri
->attr
, parent_ri
->attr
)
1242 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1243 bgp_unlock_node(rn
);
1246 /* The attribute has changed. */
1247 /* Add (or update) attribute to hash. */
1248 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1250 /* Restore route, if needed. */
1251 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
1252 bgp_info_restore(rn
, ri
);
1254 /* Mark if nexthop has changed. */
1255 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
, &attr_new
->nexthop
))
1256 SET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1258 /* Unintern existing, set to new. */
1259 bgp_attr_unintern(&ri
->attr
);
1260 ri
->attr
= attr_new
;
1261 ri
->uptime
= bgp_clock();
1264 /* Perform route selection and update zebra, if required. */
1265 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1271 * Uninstall route entry from the VNI routing table and send message
1272 * to zebra, if appropriate.
1274 static int uninstall_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1275 struct prefix_evpn
*p
,
1276 struct bgp_info
*parent_ri
)
1278 struct bgp_node
*rn
;
1279 struct bgp_info
*ri
;
1282 /* Locate route within the VNI. */
1283 /* NOTE: There is no RD here. */
1284 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
1288 /* Find matching route entry. */
1289 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1291 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1297 /* Mark entry for deletion */
1298 bgp_info_delete(rn
, ri
);
1300 /* Perform route selection and update zebra, if required. */
1301 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1303 /* Unlock route node. */
1304 bgp_unlock_node(rn
);
1310 * Given a route entry and a VNI, see if this route entry should be
1311 * imported into the VNI i.e., RTs match.
1313 static int is_route_matching_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1314 struct bgp_info
*ri
)
1316 struct attr
*attr
= ri
->attr
;
1317 struct ecommunity
*ecom
;
1321 /* Route should have valid RT to be even considered. */
1322 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1325 ecom
= attr
->ecommunity
;
1326 if (!ecom
|| !ecom
->size
)
1329 /* For each extended community RT, see if it matches this VNI. If any RT
1330 * matches, we're done.
1332 for (i
= 0; i
< ecom
->size
; i
++) {
1334 u_char type
, sub_type
;
1335 struct ecommunity_val
*eval
;
1336 struct ecommunity_val eval_tmp
;
1337 struct irt_node
*irt
;
1339 /* Only deal with RTs */
1340 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1341 eval
= (struct ecommunity_val
*)(ecom
->val
1342 + (i
* ECOMMUNITY_SIZE
));
1345 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1348 /* See if this RT matches specified VNIs import RTs */
1349 irt
= lookup_import_rt(bgp
, eval
);
1350 if (irt
&& irt
->vnis
)
1351 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1354 /* Also check for non-exact match. In this, we mask out the AS
1356 * only check on the local-admin sub-field. This is to
1358 * VNI as the RT for EBGP peering too.
1361 if (type
== ECOMMUNITY_ENCODE_AS
1362 || type
== ECOMMUNITY_ENCODE_AS4
1363 || type
== ECOMMUNITY_ENCODE_IP
) {
1364 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1365 mask_ecom_global_admin(&eval_tmp
, eval
);
1366 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1368 if (irt
&& irt
->vnis
)
1369 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1377 * Install or uninstall routes of specified type that are appropriate for this
1380 static int install_uninstall_routes_for_vni(struct bgp
*bgp
,
1381 struct bgpevpn
*vpn
,
1382 bgp_evpn_route_type rtype
,
1387 struct bgp_node
*rd_rn
, *rn
;
1388 struct bgp_table
*table
;
1389 struct bgp_info
*ri
;
1395 /* Walk entire global routing table and evaluate routes which could be
1396 * imported into this VPN. Note that we cannot just look at the routes
1398 * the VNI's RD - remote routes applicable for this VNI could have any
1401 /* EVPN routes are a 2-level table. */
1402 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1403 rd_rn
= bgp_route_next(rd_rn
)) {
1404 table
= (struct bgp_table
*)(rd_rn
->info
);
1408 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1409 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1411 if (evp
->prefix
.route_type
!= rtype
)
1414 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1415 /* Consider "valid" remote routes applicable for
1417 if (!(CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1418 && ri
->type
== ZEBRA_ROUTE_BGP
1419 && ri
->sub_type
== BGP_ROUTE_NORMAL
))
1422 if (is_route_matching_for_vni(bgp
, vpn
, ri
)) {
1424 ret
= install_evpn_route_entry(
1427 ret
= uninstall_evpn_route_entry(
1432 "%u: Failed to %s EVPN %s route in VNI %u",
1436 rtype
== BGP_EVPN_MAC_IP_ROUTE
1451 * Install any existing remote routes applicable for this VNI into its
1452 * routing table. This is invoked when a VNI becomes "live" or its Import
1455 static int install_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1459 /* Install type-3 routes followed by type-2 routes - the ones applicable
1462 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1467 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1472 * Uninstall any existing remote routes for this VNI. One scenario in which
1473 * this is invoked is upon an import RT change.
1475 static int uninstall_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1479 /* Uninstall type-2 routes followed by type-3 routes - the ones
1483 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1488 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1493 * Install or uninstall route in matching VNIs (list).
1495 static int install_uninstall_route_in_vnis(struct bgp
*bgp
, afi_t afi
,
1496 safi_t safi
, struct prefix_evpn
*evp
,
1497 struct bgp_info
*ri
,
1498 struct list
*vnis
, int install
)
1500 struct bgpevpn
*vpn
;
1501 struct listnode
*node
, *nnode
;
1503 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, vpn
)) {
1506 if (!is_vni_live(vpn
))
1510 ret
= install_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1512 ret
= uninstall_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1515 zlog_err("%u: Failed to %s EVPN %s route in VNI %u",
1516 bgp
->vrf_id
, install
? "install" : "uninstall",
1517 evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1529 * Install or uninstall route for appropriate VNIs.
1531 static int install_uninstall_evpn_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1532 struct prefix
*p
, struct bgp_info
*ri
,
1535 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
1536 struct attr
*attr
= ri
->attr
;
1537 struct ecommunity
*ecom
;
1542 /* Only type-2 and type-3 routes go into a L2 VNI. */
1543 if (!(evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1544 || evp
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
))
1547 /* If we don't have Route Target, nothing much to do. */
1548 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1551 ecom
= attr
->ecommunity
;
1552 if (!ecom
|| !ecom
->size
)
1555 /* For each extended community RT, see which VNIs match and import
1556 * the route into matching VNIs.
1558 for (i
= 0; i
< ecom
->size
; i
++) {
1560 u_char type
, sub_type
;
1561 struct ecommunity_val
*eval
;
1562 struct ecommunity_val eval_tmp
;
1563 struct irt_node
*irt
;
1565 /* Only deal with RTs */
1566 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1567 eval
= (struct ecommunity_val
*)(ecom
->val
1568 + (i
* ECOMMUNITY_SIZE
));
1571 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1574 /* Are we interested in this RT? */
1575 irt
= lookup_import_rt(bgp
, eval
);
1576 if (irt
&& irt
->vnis
)
1577 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1580 /* Also check for non-exact match. In this, we mask out the AS
1582 * only check on the local-admin sub-field. This is to
1584 * VNI as the RT for EBGP peering too.
1587 if (type
== ECOMMUNITY_ENCODE_AS
1588 || type
== ECOMMUNITY_ENCODE_AS4
1589 || type
== ECOMMUNITY_ENCODE_IP
) {
1590 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1591 mask_ecom_global_admin(&eval_tmp
, eval
);
1592 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1594 if (irt
&& irt
->vnis
)
1595 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1603 * Update and advertise local routes for a VNI. Invoked upon router-id
1604 * change. Note that the processing is done only on the global route table
1605 * using routes that already exist in the per-VNI table.
1607 static int update_advertise_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1609 struct prefix_evpn p
;
1610 struct bgp_node
*rn
, *global_rn
;
1611 struct bgp_info
*ri
, *global_ri
;
1613 afi_t afi
= AFI_L2VPN
;
1614 safi_t safi
= SAFI_EVPN
;
1616 /* Locate type-3 route for VNI in the per-VNI table and use its
1617 * attributes to create and advertise the type-3 route for this VNI
1618 * in the global table.
1620 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1621 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1622 if (!rn
) /* unexpected */
1624 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1625 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
1626 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1628 if (!ri
) /* unexpected */
1632 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1633 (struct prefix
*)&p
, &vpn
->prd
);
1634 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1, 0,
1637 /* Schedule for processing and unlock node. */
1638 bgp_process(bgp
, global_rn
, afi
, safi
);
1639 bgp_unlock_node(global_rn
);
1641 /* Now, walk this VNI's route table and use the route and its attribute
1642 * to create and schedule route in global table.
1644 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1645 rn
= bgp_route_next(rn
)) {
1646 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1648 /* Identify MAC-IP local routes. */
1649 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1652 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1653 if (ri
->peer
== bgp
->peer_self
1654 && ri
->type
== ZEBRA_ROUTE_BGP
1655 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1660 /* Create route in global routing table using this route entry's
1664 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1665 (struct prefix
*)evp
, &vpn
->prd
);
1667 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1,
1670 /* Schedule for processing and unlock node. */
1671 bgp_process(bgp
, global_rn
, afi
, safi
);
1672 bgp_unlock_node(global_rn
);
1679 * Delete (and withdraw) local routes for a VNI - only from the global
1680 * table. Invoked upon router-id change.
1682 static int delete_withdraw_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1685 struct prefix_evpn p
;
1686 struct bgp_node
*global_rn
;
1687 struct bgp_info
*ri
;
1688 afi_t afi
= AFI_L2VPN
;
1689 safi_t safi
= SAFI_EVPN
;
1691 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1692 * for this VNI - from the global table.
1694 ret
= delete_global_type2_routes(bgp
, vpn
);
1698 /* Remove type-3 route for this VNI from global table. */
1699 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1700 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1701 (struct prefix
*)&p
, &vpn
->prd
);
1703 /* Delete route entry in the global EVPN table. */
1704 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
1706 /* Schedule for processing - withdraws to peers happen from
1710 bgp_process(bgp
, global_rn
, afi
, safi
);
1711 bgp_unlock_node(global_rn
);
1718 * Handle router-id change. Update and advertise local routes corresponding
1719 * to this VNI from peers. Note that this is invoked after updating the
1720 * router-id. The routes in the per-VNI table are used to create routes in
1721 * the global table and schedule them.
1723 static void update_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1725 struct bgpevpn
*vpn
;
1727 vpn
= (struct bgpevpn
*)backet
->data
;
1730 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1734 /* Skip VNIs with configured RD. */
1735 if (is_rd_configured(vpn
))
1738 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1739 update_advertise_vni_routes(bgp
, vpn
);
1743 * Handle router-id change. Delete and withdraw local routes corresponding
1744 * to this VNI from peers. Note that this is invoked prior to updating
1745 * the router-id and is done only on the global route table, the routes
1746 * are needed in the per-VNI table to re-advertise with new router id.
1748 static void withdraw_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1750 struct bgpevpn
*vpn
;
1752 vpn
= (struct bgpevpn
*)backet
->data
;
1755 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1759 /* Skip VNIs with configured RD. */
1760 if (is_rd_configured(vpn
))
1763 delete_withdraw_vni_routes(bgp
, vpn
);
1767 * Process received EVPN type-2 route (advertise or withdraw).
1769 static int process_type2_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1770 struct attr
*attr
, u_char
*pfx
, int psize
,
1771 u_int32_t addpath_id
)
1773 struct prefix_rd prd
;
1774 struct prefix_evpn p
;
1777 mpls_label_t
*label_pnt
;
1780 /* Type-2 route should be either 33, 37 or 49 bytes or an
1781 * additional 3 bytes if there is a second label (VNI):
1782 * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1),
1783 * MAC Addr (6), IP len (1), IP (0, 4 or 16),
1784 * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3)
1786 if (psize
!= 33 && psize
!= 37 && psize
!= 49 && psize
!= 36
1787 && psize
!= 40 && psize
!= 52) {
1788 zlog_err("%u:%s - Rx EVPN Type-2 NLRI with invalid length %d",
1789 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1793 /* Make prefix_rd */
1794 prd
.family
= AF_UNSPEC
;
1796 memcpy(&prd
.val
, pfx
, 8);
1799 /* Make EVPN prefix. */
1800 memset(&p
, 0, sizeof(struct prefix_evpn
));
1801 p
.family
= AF_ETHERNET
;
1802 p
.prefixlen
= EVPN_TYPE_2_ROUTE_PREFIXLEN
;
1803 p
.prefix
.route_type
= BGP_EVPN_MAC_IP_ROUTE
;
1805 /* Skip over Ethernet Seg Identifier for now. */
1808 /* Skip over Ethernet Tag for now. */
1811 /* Get the MAC Addr len */
1812 macaddr_len
= *pfx
++;
1814 /* Get the MAC Addr */
1815 if (macaddr_len
== (ETHER_ADDR_LEN
* 8)) {
1816 memcpy(&p
.prefix
.mac
.octet
, pfx
, ETHER_ADDR_LEN
);
1817 pfx
+= ETHER_ADDR_LEN
;
1820 "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d",
1821 peer
->bgp
->vrf_id
, peer
->host
, macaddr_len
);
1827 ipaddr_len
= *pfx
++;
1828 if (ipaddr_len
!= 0 && ipaddr_len
!= IPV4_MAX_BITLEN
1829 && ipaddr_len
!= IPV6_MAX_BITLEN
) {
1831 "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d",
1832 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1837 ipaddr_len
/= 8; /* Convert to bytes. */
1838 p
.prefix
.ip
.ipa_type
= (ipaddr_len
== IPV4_MAX_BYTELEN
)
1841 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, ipaddr_len
);
1845 /* Get the VNI (in MPLS label field). */
1846 /* Note: We ignore the second VNI, if any. */
1847 label_pnt
= (mpls_label_t
*)pfx
;
1849 /* Process the route. */
1851 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1852 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1853 &prd
, label_pnt
, 0, NULL
);
1855 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1856 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1857 &prd
, label_pnt
, NULL
);
1862 * Process received EVPN type-3 route (advertise or withdraw).
1864 static int process_type3_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1865 struct attr
*attr
, u_char
*pfx
, int psize
,
1866 u_int32_t addpath_id
)
1868 struct prefix_rd prd
;
1869 struct prefix_evpn p
;
1873 /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
1874 * IP len (1) and IP (4 or 16).
1876 if (psize
!= 17 && psize
!= 29) {
1877 zlog_err("%u:%s - Rx EVPN Type-3 NLRI with invalid length %d",
1878 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1882 /* Make prefix_rd */
1883 prd
.family
= AF_UNSPEC
;
1885 memcpy(&prd
.val
, pfx
, 8);
1888 /* Make EVPN prefix. */
1889 memset(&p
, 0, sizeof(struct prefix_evpn
));
1890 p
.family
= AF_ETHERNET
;
1891 p
.prefixlen
= EVPN_TYPE_3_ROUTE_PREFIXLEN
;
1892 p
.prefix
.route_type
= BGP_EVPN_IMET_ROUTE
;
1894 /* Skip over Ethernet Tag for now. */
1898 ipaddr_len
= *pfx
++;
1899 if (ipaddr_len
== IPV4_MAX_BITLEN
) {
1900 p
.prefix
.ip
.ipa_type
= IPADDR_V4
;
1901 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, IPV4_MAX_BYTELEN
);
1904 "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
1905 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1909 /* Process the route. */
1911 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1912 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1913 &prd
, NULL
, 0, NULL
);
1915 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1916 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1922 * Process received EVPN type-5 route (advertise or withdraw).
1924 static int process_type5_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1925 struct attr
*attr
, u_char
*pfx
, int psize
,
1926 u_int32_t addpath_id
, int withdraw
)
1928 struct prefix_rd prd
;
1929 struct prefix_evpn p
;
1930 struct bgp_route_evpn evpn
;
1933 mpls_label_t
*label_pnt
;
1936 /* Type-5 route should be 34 or 58 bytes:
1937 * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
1938 * GW (4 or 16) and VNI (3).
1939 * Note that the IP and GW should both be IPv4 or both IPv6.
1941 if (psize
!= 34 && psize
!= 58) {
1942 zlog_err("%u:%s - Rx EVPN Type-5 NLRI with invalid length %d",
1943 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1947 /* Make prefix_rd */
1948 prd
.family
= AF_UNSPEC
;
1950 memcpy(&prd
.val
, pfx
, 8);
1953 /* Make EVPN prefix. */
1954 memset(&p
, 0, sizeof(struct prefix_evpn
));
1955 p
.family
= AF_ETHERNET
;
1956 p
.prefix
.route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
1958 /* Additional information outside of prefix - ESI and GW IP */
1959 memset(&evpn
, 0, sizeof(evpn
));
1962 memcpy(&evpn
.eth_s_id
.val
, pfx
, 10);
1965 /* Fetch Ethernet Tag. */
1966 memcpy(ð_tag
, pfx
, 4);
1967 p
.prefix
.eth_tag
= ntohl(eth_tag
);
1970 /* Fetch IP prefix length. */
1972 if (ippfx_len
> IPV6_MAX_BITLEN
) {
1974 "%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d",
1975 peer
->bgp
->vrf_id
, peer
->host
, ippfx_len
);
1978 p
.prefix
.ip_prefix_length
= ippfx_len
;
1980 /* Determine IPv4 or IPv6 prefix */
1981 /* Since the address and GW are from the same family, this just becomes
1982 * a simple check on the total size.
1985 SET_IPADDR_V4(&p
.prefix
.ip
);
1986 memcpy(&p
.prefix
.ip
.ipaddr_v4
, pfx
, 4);
1988 memcpy(&evpn
.gw_ip
.ipv4
, pfx
, 4);
1990 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
1992 SET_IPADDR_V6(&p
.prefix
.ip
);
1993 memcpy(&p
.prefix
.ip
.ipaddr_v6
, pfx
, 16);
1995 memcpy(&evpn
.gw_ip
.ipv6
, pfx
, 16);
1997 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV6
;
2000 label_pnt
= (mpls_label_t
*)pfx
;
2002 /* Process the route. */
2004 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2005 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2006 &prd
, label_pnt
, 0, &evpn
);
2008 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2009 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2010 &prd
, label_pnt
, &evpn
);
2015 static void evpn_mpattr_encode_type5(struct stream
*s
, struct prefix
*p
,
2016 struct prefix_rd
*prd
, mpls_label_t
*label
,
2021 struct evpn_addr
*p_evpn_p
;
2023 memset(&temp
, 0, 16);
2024 if (p
->family
!= AF_ETHERNET
)
2026 p_evpn_p
= &(p
->u
.prefix_evpn
);
2028 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2031 len
= 32; /* ipv6 */
2032 stream_putc(s
, BGP_EVPN_IP_PREFIX_ROUTE
);
2033 /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
2034 stream_putc(s
, 8 + 10 + 4 + 1 + len
+ 3);
2035 stream_put(s
, prd
->val
, 8);
2037 stream_put(s
, &(attr
->evpn_overlay
.eth_s_id
), 10);
2039 stream_put(s
, &temp
, 10);
2040 stream_putl(s
, p_evpn_p
->eth_tag
);
2041 stream_putc(s
, p_evpn_p
->ip_prefix_length
);
2042 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2043 stream_put_ipv4(s
, p_evpn_p
->ip
.ipaddr_v4
.s_addr
);
2045 stream_put(s
, &p_evpn_p
->ip
.ipaddr_v6
, 16);
2047 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2049 attr
->evpn_overlay
.gw_ip
.ipv4
.s_addr
);
2051 stream_put(s
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), 16);
2053 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2054 stream_put_ipv4(s
, 0);
2056 stream_put(s
, &temp
, 16);
2060 stream_put(s
, label
, 3);
2066 * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled.
2068 static void cleanup_vni_on_disable(struct hash_backet
*backet
, struct bgp
*bgp
)
2070 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2072 /* Remove EVPN routes and schedule for processing. */
2073 delete_routes_for_vni(bgp
, vpn
);
2075 /* Clear "live" flag and see if hash needs to be freed. */
2076 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2077 if (!is_vni_configured(vpn
))
2078 bgp_evpn_free(bgp
, vpn
);
2082 * Free a VNI entry; iterator function called during cleanup.
2084 static void free_vni_entry(struct hash_backet
*backet
, struct bgp
*bgp
)
2086 struct bgpevpn
*vpn
;
2088 vpn
= (struct bgpevpn
*)backet
->data
;
2089 delete_all_vni_routes(bgp
, vpn
);
2090 bgp_evpn_free(bgp
, vpn
);
2099 * Handle change to BGP router id. This is invoked twice by the change
2100 * handler, first before the router id has been changed and then after
2101 * the router id has been changed. The first invocation will result in
2102 * local routes for all VNIs being deleted and withdrawn and the next
2103 * will result in the routes being re-advertised.
2105 void bgp_evpn_handle_router_id_update(struct bgp
*bgp
, int withdraw
)
2108 hash_iterate(bgp
->vnihash
,
2109 (void (*)(struct hash_backet
*,
2110 void *))withdraw_router_id_vni
,
2113 hash_iterate(bgp
->vnihash
,
2114 (void (*)(struct hash_backet
*,
2115 void *))update_router_id_vni
,
2120 * Handle change to export RT - update and advertise local routes.
2122 int bgp_evpn_handle_export_rt_change(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2124 return update_routes_for_vni(bgp
, vpn
);
2128 * Handle change to RD. This is invoked twice by the change handler,
2129 * first before the RD has been changed and then after the RD has
2130 * been changed. The first invocation will result in local routes
2131 * of this VNI being deleted and withdrawn and the next will result
2132 * in the routes being re-advertised.
2134 void bgp_evpn_handle_rd_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2138 delete_withdraw_vni_routes(bgp
, vpn
);
2140 update_advertise_vni_routes(bgp
, vpn
);
2144 * Install routes for this VNI. Invoked upon change to Import RT.
2146 int bgp_evpn_install_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2148 return install_routes_for_vni(bgp
, vpn
);
2152 * Uninstall all routes installed for this VNI. Invoked upon change
2155 int bgp_evpn_uninstall_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2157 return uninstall_routes_for_vni(bgp
, vpn
);
2161 * Function to display "tag" in route as a VNI.
2163 char *bgp_evpn_label2str(mpls_label_t
*label
, char *buf
, int len
)
2167 vni
= label2vni(label
);
2168 snprintf(buf
, len
, "%u", vni
);
2173 * Function to convert evpn route to string.
2174 * NOTE: We don't use prefix2str as the output here is a bit different.
2176 char *bgp_evpn_route2str(struct prefix_evpn
*p
, char *buf
, int len
)
2178 char buf1
[ETHER_ADDR_STRLEN
];
2179 char buf2
[PREFIX2STR_BUFFER
];
2181 if (p
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
) {
2182 snprintf(buf
, len
, "[%d]:[0]:[%d]:[%s]", p
->prefix
.route_type
,
2183 IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BITLEN
2185 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
2186 } else if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
2187 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
2188 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]",
2189 p
->prefix
.route_type
, 8 * ETHER_ADDR_LEN
,
2190 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2195 family
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? AF_INET
2197 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]",
2198 p
->prefix
.route_type
, 8 * ETHER_ADDR_LEN
,
2199 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2201 family
== AF_INET
? IPV4_MAX_BITLEN
2203 inet_ntop(family
, &p
->prefix
.ip
.ip
.addr
, buf2
,
2204 PREFIX2STR_BUFFER
));
2207 /* Currently, this is to cater to other AF_ETHERNET code. */
2214 * Encode EVPN prefix in Update (MP_REACH)
2216 void bgp_evpn_encode_prefix(struct stream
*s
, struct prefix
*p
,
2217 struct prefix_rd
*prd
, mpls_label_t
*label
,
2218 struct attr
*attr
, int addpath_encode
,
2219 u_int32_t addpath_tx_id
)
2221 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
2225 stream_putl(s
, addpath_tx_id
);
2228 stream_putc(s
, evp
->prefix
.route_type
);
2230 switch (evp
->prefix
.route_type
) {
2231 case BGP_EVPN_MAC_IP_ROUTE
:
2232 if (IS_EVPN_PREFIX_IPADDR_V4(evp
))
2233 ipa_len
= IPV4_MAX_BYTELEN
;
2234 else if (IS_EVPN_PREFIX_IPADDR_V6(evp
))
2235 ipa_len
= IPV6_MAX_BYTELEN
;
2236 stream_putc(s
, 33 + ipa_len
); // 1 VNI
2237 stream_put(s
, prd
->val
, 8); /* RD */
2238 stream_put(s
, 0, 10); /* ESI */
2239 stream_putl(s
, 0); /* Ethernet Tag ID */
2240 stream_putc(s
, 8 * ETHER_ADDR_LEN
); /* Mac Addr Len - bits */
2241 stream_put(s
, evp
->prefix
.mac
.octet
, 6); /* Mac Addr */
2242 stream_putc(s
, 8 * ipa_len
); /* IP address Length */
2244 stream_put(s
, &evp
->prefix
.ip
.ip
.addr
,
2246 stream_put(s
, label
,
2247 BGP_LABEL_BYTES
); /* VNI is contained in 'tag' */
2250 case BGP_EVPN_IMET_ROUTE
:
2251 stream_putc(s
, 17); // TODO: length - assumes IPv4 address
2252 stream_put(s
, prd
->val
, 8); /* RD */
2253 stream_putl(s
, 0); /* Ethernet Tag ID */
2254 stream_putc(s
, IPV4_MAX_BITLEN
); /* IP address Length - bits */
2255 /* Originating Router's IP Addr */
2256 stream_put_in_addr(s
, &evp
->prefix
.ip
.ipaddr_v4
);
2259 case BGP_EVPN_IP_PREFIX_ROUTE
:
2260 /* TODO: AddPath support. */
2261 evpn_mpattr_encode_type5(s
, p
, prd
, label
, attr
);
2269 int bgp_nlri_parse_evpn(struct peer
*peer
, struct attr
*attr
,
2270 struct bgp_nlri
*packet
, int withdraw
)
2276 u_int32_t addpath_id
;
2277 int addpath_encoded
;
2283 /* Check peer status. */
2284 if (peer
->status
!= Established
) {
2285 zlog_err("%u:%s - EVPN update received in state %d",
2286 peer
->bgp
->vrf_id
, peer
->host
, peer
->status
);
2290 /* Start processing the NLRI - there may be multiple in the MP_REACH */
2292 lim
= pnt
+ packet
->length
;
2294 safi
= packet
->safi
;
2298 (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
2299 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2300 PEER_CAP_ADDPATH_AF_TX_RCV
));
2302 for (; pnt
< lim
; pnt
+= psize
) {
2303 /* Clear prefix structure. */
2304 memset(&p
, 0, sizeof(struct prefix
));
2306 /* Deal with path-id if AddPath is supported. */
2307 if (addpath_encoded
) {
2308 /* When packet overflow occurs return immediately. */
2309 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
2312 addpath_id
= ntohl(*((uint32_t *)pnt
));
2313 pnt
+= BGP_ADDPATH_ID_LEN
;
2316 /* All EVPN NLRI types start with type and length. */
2321 psize
= rlen
= *pnt
++;
2323 /* When packet overflow occur return immediately. */
2324 if (pnt
+ psize
> lim
)
2328 case BGP_EVPN_MAC_IP_ROUTE
:
2329 if (process_type2_route(peer
, afi
, safi
,
2330 withdraw
? NULL
: attr
, pnt
,
2331 psize
, addpath_id
)) {
2333 "%u:%s - Error in processing EVPN type-2 NLRI size %d",
2334 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2339 case BGP_EVPN_IMET_ROUTE
:
2340 if (process_type3_route(peer
, afi
, safi
,
2341 withdraw
? NULL
: attr
, pnt
,
2342 psize
, addpath_id
)) {
2344 "%u:%s - Error in processing EVPN type-3 NLRI size %d",
2345 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2350 case BGP_EVPN_IP_PREFIX_ROUTE
:
2351 if (process_type5_route(peer
, afi
, safi
, attr
, pnt
,
2352 psize
, addpath_id
, withdraw
)) {
2354 "%u:%s - Error in processing EVPN type-5 NLRI size %d",
2355 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2365 /* Packet length consistency check. */
2374 * Map the RTs (configured or automatically derived) of a VNI to the VNI.
2375 * The mapping will be used during route processing.
2377 void bgp_evpn_map_vni_to_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2380 struct ecommunity_val
*eval
;
2381 struct listnode
*node
, *nnode
;
2382 struct ecommunity
*ecom
;
2384 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2385 for (i
= 0; i
< ecom
->size
; i
++) {
2386 eval
= (struct ecommunity_val
*)(ecom
->val
2388 * ECOMMUNITY_SIZE
));
2389 map_vni_to_rt(bgp
, vpn
, eval
);
2395 * Unmap the RTs (configured or automatically derived) of a VNI from the VNI.
2397 void bgp_evpn_unmap_vni_from_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2400 struct ecommunity_val
*eval
;
2401 struct listnode
*node
, *nnode
;
2402 struct ecommunity
*ecom
;
2404 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2405 for (i
= 0; i
< ecom
->size
; i
++) {
2406 struct irt_node
*irt
;
2407 struct ecommunity_val eval_tmp
;
2409 eval
= (struct ecommunity_val
*)(ecom
->val
2411 * ECOMMUNITY_SIZE
));
2412 /* If using "automatic" RT, we only care about the
2413 * local-admin sub-field.
2414 * This is to facilitate using VNI as the RT for EBGP
2417 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
2418 if (!is_import_rt_configured(vpn
))
2419 mask_ecom_global_admin(&eval_tmp
, eval
);
2421 irt
= lookup_import_rt(bgp
, &eval_tmp
);
2423 unmap_vni_from_rt(bgp
, vpn
, irt
);
2429 * Derive Import RT automatically for VNI and map VNI to RT.
2430 * The mapping will be used during route processing.
2432 void bgp_evpn_derive_auto_rt_import(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2434 form_auto_rt(bgp
, vpn
, vpn
->import_rtl
);
2435 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2438 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2442 * Derive Export RT automatically for VNI.
2444 void bgp_evpn_derive_auto_rt_export(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2446 form_auto_rt(bgp
, vpn
, vpn
->export_rtl
);
2447 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2451 * Derive RD automatically for VNI using passed information - it
2452 * is of the form RouterId:unique-id-for-vni.
2454 void bgp_evpn_derive_auto_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2458 vpn
->prd
.family
= AF_UNSPEC
;
2459 vpn
->prd
.prefixlen
= 64;
2460 sprintf(buf
, "%s:%hu", inet_ntoa(bgp
->router_id
), vpn
->rd_id
);
2461 str2prefix_rd(buf
, &vpn
->prd
);
2462 UNSET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2468 struct bgpevpn
*bgp_evpn_lookup_vni(struct bgp
*bgp
, vni_t vni
)
2470 struct bgpevpn
*vpn
;
2473 memset(&tmp
, 0, sizeof(struct bgpevpn
));
2475 vpn
= hash_lookup(bgp
->vnihash
, &tmp
);
2480 * Create a new vpn - invoked upon configuration or zebra notification.
2482 struct bgpevpn
*bgp_evpn_new(struct bgp
*bgp
, vni_t vni
,
2483 struct in_addr originator_ip
)
2485 struct bgpevpn
*vpn
;
2490 vpn
= XCALLOC(MTYPE_BGP_EVPN
, sizeof(struct bgpevpn
));
2494 /* Set values - RD and RT set to defaults. */
2496 vpn
->originator_ip
= originator_ip
;
2498 /* Initialize route-target import and export lists */
2499 vpn
->import_rtl
= list_new();
2500 vpn
->import_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2501 vpn
->export_rtl
= list_new();
2502 vpn
->export_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2503 bf_assign_index(bgp
->rd_idspace
, vpn
->rd_id
);
2504 derive_rd_rt_for_vni(bgp
, vpn
);
2506 /* Initialize EVPN route table. */
2507 vpn
->route_table
= bgp_table_init(AFI_L2VPN
, SAFI_EVPN
);
2510 if (!hash_get(bgp
->vnihash
, vpn
, hash_alloc_intern
)) {
2511 XFREE(MTYPE_BGP_EVPN
, vpn
);
2514 QOBJ_REG(vpn
, bgpevpn
);
2519 * Free a given VPN - called in multiple scenarios such as zebra
2520 * notification, configuration being deleted, advertise-all-vni disabled etc.
2521 * This just frees appropriate memory, caller should have taken other
2524 void bgp_evpn_free(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2526 bgp_table_unlock(vpn
->route_table
);
2527 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2528 list_delete(vpn
->import_rtl
);
2529 list_delete(vpn
->export_rtl
);
2530 vpn
->import_rtl
= NULL
;
2531 vpn
->export_rtl
= NULL
;
2532 bf_release_index(bgp
->rd_idspace
, vpn
->rd_id
);
2533 hash_release(bgp
->vnihash
, vpn
);
2535 XFREE(MTYPE_BGP_EVPN
, vpn
);
2539 * Import route into matching VNI(s).
2541 int bgp_evpn_import_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2542 struct prefix
*p
, struct bgp_info
*ri
)
2544 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 1);
2548 * Unimport route from matching VNI(s).
2550 int bgp_evpn_unimport_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2551 struct prefix
*p
, struct bgp_info
*ri
)
2553 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 0);
2557 * Handle del of a local MACIP.
2559 int bgp_evpn_local_macip_del(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2562 struct bgpevpn
*vpn
;
2563 struct prefix_evpn p
;
2565 if (!bgp
->vnihash
) {
2566 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2570 /* Lookup VNI hash - should exist. */
2571 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2572 if (!vpn
|| !is_vni_live(vpn
)) {
2573 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP DEL",
2574 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2578 /* Remove EVPN type-2 route and schedule for processing. */
2579 build_evpn_type2_prefix(&p
, mac
, ip
);
2580 delete_evpn_route(bgp
, vpn
, &p
);
2586 * Handle add of a local MACIP.
2588 int bgp_evpn_local_macip_add(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2589 struct ipaddr
*ip
, u_char sticky
)
2591 struct bgpevpn
*vpn
;
2592 struct prefix_evpn p
;
2594 if (!bgp
->vnihash
) {
2595 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2599 /* Lookup VNI hash - should exist. */
2600 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2601 if (!vpn
|| !is_vni_live(vpn
)) {
2602 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP ADD",
2603 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2607 /* Create EVPN type-2 route and schedule for processing. */
2608 build_evpn_type2_prefix(&p
, mac
, ip
);
2609 if (update_evpn_route(bgp
, vpn
, &p
, sticky
)) {
2610 char buf
[ETHER_ADDR_STRLEN
];
2611 char buf2
[INET6_ADDRSTRLEN
];
2614 "%u:Failed to create Type-2 route, VNI %u %sMAC %s IP %s",
2615 bgp
->vrf_id
, vpn
->vni
, sticky
? "sticky" : "",
2616 prefix_mac2str(mac
, buf
, sizeof(buf
)),
2617 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2625 * Handle del of a local VNI.
2627 int bgp_evpn_local_vni_del(struct bgp
*bgp
, vni_t vni
)
2629 struct bgpevpn
*vpn
;
2631 if (!bgp
->vnihash
) {
2632 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2636 /* Locate VNI hash */
2637 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2639 zlog_warn("%u: VNI hash entry for VNI %u not found at DEL",
2644 /* Remove all local EVPN routes and schedule for processing (to
2645 * withdraw from peers).
2647 delete_routes_for_vni(bgp
, vpn
);
2649 /* Clear "live" flag and see if hash needs to be freed. */
2650 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2651 if (!is_vni_configured(vpn
))
2652 bgp_evpn_free(bgp
, vpn
);
2658 * Handle add (or update) of a local VNI. The only VNI change we care
2659 * about is change to local-tunnel-ip.
2661 int bgp_evpn_local_vni_add(struct bgp
*bgp
, vni_t vni
,
2662 struct in_addr originator_ip
)
2664 struct bgpevpn
*vpn
;
2665 struct prefix_evpn p
;
2667 if (!bgp
->vnihash
) {
2668 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2672 /* Lookup VNI. If present and no change, exit. */
2673 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2674 if (vpn
&& is_vni_live(vpn
)) {
2675 if (IPV4_ADDR_SAME(&vpn
->originator_ip
, &originator_ip
))
2676 /* Probably some other param has changed that we don't
2680 /* Local tunnel endpoint IP address has changed */
2681 return handle_tunnel_ip_change(bgp
, vpn
, originator_ip
);
2684 /* Create or update as appropriate. */
2686 vpn
= bgp_evpn_new(bgp
, vni
, originator_ip
);
2689 "%u: Failed to allocate VNI entry for VNI %u - at Add",
2695 /* Mark as "live" */
2696 SET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2698 /* Create EVPN type-3 route and schedule for processing. */
2699 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
2700 if (update_evpn_route(bgp
, vpn
, &p
, 0)) {
2701 zlog_err("%u: Type3 route creation failure for VNI %u",
2706 /* If we have learnt and retained remote routes (VTEPs, MACs) for this
2710 install_routes_for_vni(bgp
, vpn
);
2716 * Cleanup EVPN information on disable - Need to delete and withdraw
2717 * EVPN routes from peers.
2719 void bgp_evpn_cleanup_on_disable(struct bgp
*bgp
)
2723 (void (*)(struct hash_backet
*, void *))cleanup_vni_on_disable
,
2728 * Cleanup EVPN information - invoked at the time of bgpd exit or when the
2729 * BGP instance (default) is being freed.
2731 void bgp_evpn_cleanup(struct bgp
*bgp
)
2736 (void (*)(struct hash_backet
*, void *))free_vni_entry
,
2738 if (bgp
->import_rt_hash
)
2739 hash_free(bgp
->import_rt_hash
);
2740 bgp
->import_rt_hash
= NULL
;
2742 hash_free(bgp
->vnihash
);
2743 bgp
->vnihash
= NULL
;
2744 bf_free(bgp
->rd_idspace
);
2748 * Initialization for EVPN
2751 * hash for RT to VNI
2752 * unique rd id space for auto derivation of RD for VNIs
2754 void bgp_evpn_init(struct bgp
*bgp
)
2757 hash_create(vni_hash_key_make
, vni_hash_cmp
, "BGP VNI Hash");
2758 bgp
->import_rt_hash
=
2759 hash_create(import_rt_hash_key_make
, import_rt_hash_cmp
,
2760 "BGP Import RT Hash");
2761 bf_init(bgp
->rd_idspace
, UINT16_MAX
);
2762 /*assign 0th index in the bitfield, so that we start with id 1*/
2763 bf_assign_zero_index(bgp
->rd_idspace
);