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"
49 #include "bgpd/bgp_nexthop.h"
52 * Definitions and external declarations.
54 extern struct zclient
*zclient
;
56 DEFINE_QOBJ_TYPE(bgpevpn
)
60 * Static function declarations
62 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
63 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
64 struct bgp_info
**ri
);
65 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
);
74 static unsigned int vni_hash_key_make(void *p
)
76 struct bgpevpn
*vpn
= p
;
77 return (jhash_1word(vpn
->vni
, 0));
81 * Comparison function for vni hash
83 static int vni_hash_cmp(const void *p1
, const void *p2
)
85 const struct bgpevpn
*vpn1
= p1
;
86 const struct bgpevpn
*vpn2
= p2
;
92 return (vpn1
->vni
== vpn2
->vni
);
96 * Make import route target hash key.
98 static unsigned int import_rt_hash_key_make(void *p
)
100 struct irt_node
*irt
= p
;
101 char *pnt
= irt
->rt
.val
;
102 unsigned int key
= 0;
118 * Comparison function for import rt hash
120 static int import_rt_hash_cmp(const void *p1
, const void *p2
)
122 const struct irt_node
*irt1
= p1
;
123 const struct irt_node
*irt2
= p2
;
125 if (irt1
== NULL
&& irt2
== NULL
)
128 if (irt1
== NULL
|| irt2
== NULL
)
131 return (memcmp(irt1
->rt
.val
, irt2
->rt
.val
, ECOMMUNITY_SIZE
) == 0);
135 * Create a new import_rt
137 static struct irt_node
*import_rt_new(struct bgp
*bgp
,
138 struct ecommunity_val
*rt
)
140 struct irt_node
*irt
;
145 irt
= XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT
, sizeof(struct irt_node
));
150 irt
->vnis
= list_new();
153 if (!hash_get(bgp
->import_rt_hash
, irt
, hash_alloc_intern
)) {
154 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
162 * Free the import rt node
164 static void import_rt_free(struct bgp
*bgp
, struct irt_node
*irt
)
166 hash_release(bgp
->import_rt_hash
, irt
);
167 XFREE(MTYPE_BGP_EVPN_IMPORT_RT
, irt
);
171 * Function to lookup Import RT node - used to map a RT to set of
172 * VNIs importing routes with that RT.
174 static struct irt_node
*lookup_import_rt(struct bgp
*bgp
,
175 struct ecommunity_val
*rt
)
177 struct irt_node
*irt
;
180 memset(&tmp
, 0, sizeof(struct irt_node
));
181 memcpy(&tmp
.rt
, rt
, ECOMMUNITY_SIZE
);
182 irt
= hash_lookup(bgp
->import_rt_hash
, &tmp
);
187 * Is specified VNI present on the RT's list of "importing" VNIs?
189 static int is_vni_present_in_irt_vnis(struct list
*vnis
, struct bgpevpn
*vpn
)
191 struct listnode
*node
, *nnode
;
192 struct bgpevpn
*tmp_vpn
;
194 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, tmp_vpn
)) {
203 * Compare Route Targets.
205 static int evpn_route_target_cmp(struct ecommunity
*ecom1
,
206 struct ecommunity
*ecom2
)
214 if (!ecom1
&& !ecom2
)
217 if (ecom1
->str
&& !ecom2
->str
)
220 if (!ecom1
->str
&& ecom2
->str
)
223 if (!ecom1
->str
&& !ecom2
->str
)
226 return strcmp(ecom1
->str
, ecom2
->str
);
230 * Mask off global-admin field of specified extended community (RT),
231 * just retain the local-admin field.
233 static inline void mask_ecom_global_admin(struct ecommunity_val
*dst
,
234 struct ecommunity_val
*src
)
240 if (type
== ECOMMUNITY_ENCODE_AS
) {
241 dst
->val
[2] = dst
->val
[3] = 0;
242 } else if (type
== ECOMMUNITY_ENCODE_AS4
243 || type
== ECOMMUNITY_ENCODE_IP
) {
244 dst
->val
[2] = dst
->val
[3] = 0;
245 dst
->val
[4] = dst
->val
[5] = 0;
250 * Map one RT to specified VNI.
252 static void map_vni_to_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
253 struct ecommunity_val
*eval
)
255 struct irt_node
*irt
;
256 struct ecommunity_val eval_tmp
;
258 /* If using "automatic" RT, we only care about the local-admin
260 * This is to facilitate using VNI as the RT for EBGP peering too.
262 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
263 if (!is_import_rt_configured(vpn
))
264 mask_ecom_global_admin(&eval_tmp
, eval
);
266 irt
= lookup_import_rt(bgp
, &eval_tmp
);
267 if (irt
&& irt
->vnis
)
268 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
269 /* Already mapped. */
273 irt
= import_rt_new(bgp
, &eval_tmp
);
277 /* Add VNI to the hash list for this RT. */
278 listnode_add(irt
->vnis
, vpn
);
282 * Unmap specified VNI from specified RT. If there are no other
283 * VNIs for this RT, then the RT hash is deleted.
285 static void unmap_vni_from_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
286 struct irt_node
*irt
)
288 /* Delete VNI from hash list for this RT. */
289 listnode_delete(irt
->vnis
, vpn
);
290 if (!listnode_head(irt
->vnis
)) {
291 list_delete_and_null(&irt
->vnis
);
292 import_rt_free(bgp
, irt
);
297 * Create RT extended community automatically from passed information:
298 * of the form AS:VNI.
299 * NOTE: We use only the lower 16 bits of the AS. This is sufficient as
300 * the need is to get a RT value that will be unique across different
301 * VNIs but the same across routers (in the same AS) for a particular
304 static void form_auto_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
, struct list
*rtl
)
306 struct ecommunity_val eval
;
307 struct ecommunity
*ecomadd
;
309 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
311 ecomadd
= ecommunity_new();
312 ecommunity_add_val(ecomadd
, &eval
);
313 listnode_add_sort(rtl
, ecomadd
);
317 * Derive RD and RT for a VNI automatically. Invoked at the time of
320 static void derive_rd_rt_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
322 bgp_evpn_derive_auto_rd(bgp
, vpn
);
323 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
324 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
328 * Add (update) or delete MACIP from zebra.
330 static int bgp_zebra_send_remote_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
331 struct prefix_evpn
*p
,
332 struct in_addr remote_vtep_ip
, int add
,
337 char buf1
[ETHER_ADDR_STRLEN
];
338 char buf2
[INET6_ADDRSTRLEN
];
339 char buf3
[INET6_ADDRSTRLEN
];
342 if (!zclient
|| zclient
->sock
< 0)
345 /* Don't try to register if Zebra doesn't know of this instance. */
346 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
352 zclient_create_header(s
, add
? ZEBRA_REMOTE_MACIP_ADD
353 : ZEBRA_REMOTE_MACIP_DEL
,
355 stream_putl(s
, vpn
->vni
);
356 stream_put(s
, &p
->prefix
.mac
.octet
, ETH_ALEN
); /* Mac Addr */
357 /* IP address length and IP address, if any. */
358 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
361 ipa_len
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BYTELEN
363 stream_putl(s
, ipa_len
);
364 stream_put(s
, &p
->prefix
.ip
.ip
.addr
, ipa_len
);
366 stream_put_in_addr(s
, &remote_vtep_ip
);
368 /* TX MAC sticky status */
370 stream_putc(s
, sticky
);
372 stream_putw_at(s
, 0, stream_get_endp(s
));
374 if (bgp_debug_zebra(NULL
))
375 zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s",
376 add
? "ADD" : "DEL", vpn
->vni
,
377 sticky
? "sticky " : "",
378 prefix_mac2str(&p
->prefix
.mac
, buf1
, sizeof(buf1
)),
379 ipaddr2str(&p
->prefix
.ip
, buf3
, sizeof(buf3
)),
380 inet_ntop(AF_INET
, &remote_vtep_ip
, buf2
,
383 return zclient_send_message(zclient
);
387 * Add (update) or delete remote VTEP from zebra.
389 static int bgp_zebra_send_remote_vtep(struct bgp
*bgp
, struct bgpevpn
*vpn
,
390 struct prefix_evpn
*p
, int add
)
395 if (!zclient
|| zclient
->sock
< 0)
398 /* Don't try to register if Zebra doesn't know of this instance. */
399 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp
))
405 zclient_create_header(s
, add
? ZEBRA_REMOTE_VTEP_ADD
406 : ZEBRA_REMOTE_VTEP_DEL
,
408 stream_putl(s
, vpn
->vni
);
409 if (IS_EVPN_PREFIX_IPADDR_V4(p
))
410 stream_put_in_addr(s
, &p
->prefix
.ip
.ipaddr_v4
);
411 else if (IS_EVPN_PREFIX_IPADDR_V6(p
)) {
413 "Bad remote IP when trying to %s remote VTEP for VNI %u",
414 add
? "ADD" : "DEL", vpn
->vni
);
418 stream_putw_at(s
, 0, stream_get_endp(s
));
420 if (bgp_debug_zebra(NULL
))
421 zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
422 add
? "ADD" : "DEL", vpn
->vni
,
423 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
425 return zclient_send_message(zclient
);
429 * Build extended communities for EVPN route. RT and ENCAP are
430 * applicable to all routes.
432 static void build_evpn_route_extcomm(struct bgpevpn
*vpn
, struct attr
*attr
)
434 struct ecommunity ecom_encap
;
435 struct ecommunity ecom_sticky
;
436 struct ecommunity_val eval
;
437 struct ecommunity_val eval_sticky
;
438 bgp_encap_types tnl_type
;
439 struct listnode
*node
, *nnode
;
440 struct ecommunity
*ecom
;
444 tnl_type
= BGP_ENCAP_TYPE_VXLAN
;
445 memset(&ecom_encap
, 0, sizeof(ecom_encap
));
446 encode_encap_extcomm(tnl_type
, &eval
);
448 ecom_encap
.val
= (u_int8_t
*)eval
.val
;
451 attr
->ecommunity
= ecommunity_dup(&ecom_encap
);
453 /* Add the export RTs */
454 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
455 attr
->ecommunity
= ecommunity_merge(attr
->ecommunity
, ecom
);
459 memset(&ecom_sticky
, 0, sizeof(ecom_sticky
));
460 encode_mac_mobility_extcomm(1, seqnum
, &eval_sticky
);
461 ecom_sticky
.size
= 1;
462 ecom_sticky
.val
= (u_int8_t
*)eval_sticky
.val
;
464 ecommunity_merge(attr
->ecommunity
, &ecom_sticky
);
467 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
471 * Add MAC mobility extended community to attribute.
473 static void add_mac_mobility_to_attr(u_int32_t seq_num
, struct attr
*attr
)
475 struct ecommunity ecom_tmp
;
476 struct ecommunity_val eval
;
477 u_int8_t
*ecom_val_ptr
;
484 encode_mac_mobility_extcomm(0, seq_num
, &eval
);
486 /* Find current MM ecommunity */
489 if (attr
->ecommunity
) {
490 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
491 pnt
= attr
->ecommunity
->val
+ (i
* 8);
495 if (type
== ECOMMUNITY_ENCODE_EVPN
497 == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
) {
499 (u_int8_t
*)(attr
->ecommunity
->val
506 /* Update the existing MM ecommunity */
508 memcpy(ecom_val_ptr
, eval
.val
, sizeof(char) * ECOMMUNITY_SIZE
);
510 /* Add MM to existing */
512 memset(&ecom_tmp
, 0, sizeof(ecom_tmp
));
514 ecom_tmp
.val
= (u_int8_t
*)eval
.val
;
517 ecommunity_merge(attr
->ecommunity
, &ecom_tmp
);
521 /* Install EVPN route into zebra. */
522 static int evpn_zebra_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
523 struct prefix_evpn
*p
,
524 struct in_addr remote_vtep_ip
, u_char sticky
)
528 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
529 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
532 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 1);
537 /* Uninstall EVPN route from zebra. */
538 static int evpn_zebra_uninstall(struct bgp
*bgp
, struct bgpevpn
*vpn
,
539 struct prefix_evpn
*p
,
540 struct in_addr remote_vtep_ip
)
544 if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
)
545 ret
= bgp_zebra_send_remote_macip(bgp
, vpn
, p
, remote_vtep_ip
,
548 ret
= bgp_zebra_send_remote_vtep(bgp
, vpn
, p
, 0);
554 * Due to MAC mobility, the prior "local" best route has been supplanted
555 * by a "remote" best route. The prior route has to be deleted and withdrawn
558 static void evpn_delete_old_local_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
560 struct bgp_info
*old_local
)
562 struct bgp_node
*global_rn
;
564 afi_t afi
= AFI_L2VPN
;
565 safi_t safi
= SAFI_EVPN
;
567 /* Locate route node in the global EVPN routing table. Note that
568 * this table is a 2-level tree (RD-level + Prefix-level) similar to
571 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
572 (struct prefix
*)&rn
->p
, &vpn
->prd
);
574 /* Delete route entry in the global EVPN table. */
575 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
577 /* Schedule for processing - withdraws to peers happen from
581 bgp_process(bgp
, global_rn
, afi
, safi
);
582 bgp_unlock_node(global_rn
);
585 /* Delete route entry in the VNI route table, caller to remove. */
586 bgp_info_delete(rn
, old_local
);
590 * Calculate the best path for an EVPN route. Install/update best path in zebra,
593 static int evpn_route_select_install(struct bgp
*bgp
, struct bgpevpn
*vpn
,
596 struct bgp_info
*old_select
, *new_select
;
597 struct bgp_info_pair old_and_new
;
598 afi_t afi
= AFI_L2VPN
;
599 safi_t safi
= SAFI_EVPN
;
602 /* Compute the best path. */
603 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
605 old_select
= old_and_new
.old
;
606 new_select
= old_and_new
.new;
608 /* If the best path hasn't changed - see if there is still something to
612 if (old_select
&& old_select
== new_select
613 && old_select
->type
== ZEBRA_ROUTE_BGP
614 && old_select
->sub_type
== BGP_ROUTE_NORMAL
615 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
616 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
617 && !bgp
->addpath_tx_used
[afi
][safi
]) {
618 if (bgp_zebra_has_route_changed(rn
, old_select
))
619 ret
= evpn_zebra_install(bgp
, vpn
,
620 (struct prefix_evpn
*)&rn
->p
,
621 old_select
->attr
->nexthop
,
622 old_select
->attr
->sticky
);
623 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
624 bgp_zebra_clear_route_change_flags(rn
);
628 /* If the user did a "clear" this flag will be set */
629 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
631 /* bestpath has changed; update relevant fields and install or uninstall
632 * into the zebra RIB.
634 if (old_select
|| new_select
)
635 bgp_bump_version(rn
);
638 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
640 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
641 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
642 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
645 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
646 && new_select
->sub_type
== BGP_ROUTE_NORMAL
) {
647 ret
= evpn_zebra_install(bgp
, vpn
, (struct prefix_evpn
*)&rn
->p
,
648 new_select
->attr
->nexthop
,
649 new_select
->attr
->sticky
);
650 /* If an old best existed and it was a "local" route, the only
652 * it would be supplanted is due to MAC mobility procedures. So,
654 * need to do an implicit delete and withdraw that route from
657 if (old_select
&& old_select
->peer
== bgp
->peer_self
658 && old_select
->type
== ZEBRA_ROUTE_BGP
659 && old_select
->sub_type
== BGP_ROUTE_STATIC
)
660 evpn_delete_old_local_route(bgp
, vpn
, rn
, old_select
);
662 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
663 && old_select
->sub_type
== BGP_ROUTE_NORMAL
)
664 ret
= evpn_zebra_uninstall(bgp
, vpn
,
665 (struct prefix_evpn
*)&rn
->p
,
666 old_select
->attr
->nexthop
);
669 /* Clear any route change flags. */
670 bgp_zebra_clear_route_change_flags(rn
);
672 /* Reap old select bgp_info, if it has been removed */
673 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
674 bgp_info_reap(rn
, old_select
);
681 * Return true if the local ri for this rn has sticky set
683 static int evpn_route_is_sticky(struct bgp
*bgp
, struct bgp_node
*rn
)
685 struct bgp_info
*tmp_ri
;
686 struct bgp_info
*local_ri
;
689 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
690 if (tmp_ri
->peer
== bgp
->peer_self
691 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
692 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
699 return local_ri
->attr
->sticky
;
703 * Create or update EVPN route entry. This could be in the VNI route table
704 * or the global route table.
706 static int update_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
707 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
708 struct attr
*attr
, int add
, int vni_table
,
709 struct bgp_info
**ri
, u_char flags
)
711 struct bgp_info
*tmp_ri
;
712 struct bgp_info
*local_ri
, *remote_ri
;
713 struct attr
*attr_new
;
714 mpls_label_t label
= MPLS_INVALID_LABEL
;
715 int route_change
= 1;
720 /* See if this is an update of an existing route, or a new add. Also,
721 * identify if already known from remote, and if so, the one with the
722 * highest sequence number; this is only when adding to the VNI routing
725 local_ri
= remote_ri
= NULL
;
726 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
) {
727 if (tmp_ri
->peer
== bgp
->peer_self
728 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
729 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
732 if (tmp_ri
->type
== ZEBRA_ROUTE_BGP
733 && tmp_ri
->sub_type
== BGP_ROUTE_NORMAL
734 && CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
)) {
737 else if (mac_mobility_seqnum(tmp_ri
->attr
)
738 > mac_mobility_seqnum(remote_ri
->attr
))
744 /* If route doesn't exist already, create a new one, if told to.
745 * Otherwise act based on whether the attributes of the route have
748 if (!local_ri
&& !add
)
752 /* When learnt locally for the first time but already known from
753 * remote, we have to initiate appropriate MAC mobility steps.
755 * is applicable when updating the VNI routing table.
756 * We need to skip mobility steps for g/w macs (local mac on g/w
757 * SVI) advertised in EVPN.
758 * This will ensure that local routes are preferred for g/w macs
760 if (remote_ri
&& !CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_GW
)) {
761 u_int32_t cur_seqnum
;
763 /* Add MM extended community to route. */
764 cur_seqnum
= mac_mobility_seqnum(remote_ri
->attr
);
765 add_mac_mobility_to_attr(cur_seqnum
+ 1, attr
);
768 /* Add (or update) attribute to hash. */
769 attr_new
= bgp_attr_intern(attr
);
771 /* Extract MAC mobility sequence number, if any. */
772 attr_new
->mm_seqnum
=
773 bgp_attr_mac_mobility_seqnum(attr_new
, &sticky
);
774 attr_new
->sticky
= sticky
;
776 /* Create new route with its attribute. */
777 tmp_ri
= info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0,
778 bgp
->peer_self
, attr_new
, rn
);
779 SET_FLAG(tmp_ri
->flags
, BGP_INFO_VALID
);
780 bgp_info_extra_get(tmp_ri
);
782 /* The VNI goes into the 'label' field of the route */
783 vni2label(vpn
->vni
, &label
);
785 memcpy(&tmp_ri
->extra
->label
, &label
, BGP_LABEL_BYTES
);
786 bgp_info_add(rn
, tmp_ri
);
789 if (attrhash_cmp(tmp_ri
->attr
, attr
)
790 && !CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
793 /* The attribute has changed. */
794 /* Add (or update) attribute to hash. */
795 attr_new
= bgp_attr_intern(attr
);
796 bgp_info_set_flag(rn
, tmp_ri
, BGP_INFO_ATTR_CHANGED
);
798 /* Restore route, if needed. */
799 if (CHECK_FLAG(tmp_ri
->flags
, BGP_INFO_REMOVED
))
800 bgp_info_restore(rn
, tmp_ri
);
802 /* Unintern existing, set to new. */
803 bgp_attr_unintern(&tmp_ri
->attr
);
804 tmp_ri
->attr
= attr_new
;
805 tmp_ri
->uptime
= bgp_clock();
809 /* Return back the route entry. */
815 * Create or update EVPN route (of type based on prefix) for specified VNI
816 * and schedule for processing.
818 static int update_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
819 struct prefix_evpn
*p
, u_char flags
)
823 struct attr
*attr_new
;
825 afi_t afi
= AFI_L2VPN
;
826 safi_t safi
= SAFI_EVPN
;
829 memset(&attr
, 0, sizeof(struct attr
));
831 /* Build path-attribute for this route. */
832 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
833 attr
.nexthop
= vpn
->originator_ip
;
834 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
835 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
836 attr
.sticky
= CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_STICKY
) ? 1 : 0;
838 /* Set up RT and ENCAP extended community. */
839 build_evpn_route_extcomm(vpn
, &attr
);
841 /* First, create (or fetch) route node within the VNI. */
842 /* NOTE: There is no RD here. */
843 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
845 /* Create or update route entry. */
846 route_change
= update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
851 /* Perform route selection; this is just to set the flags correctly
852 * as local route in the VNI always wins.
854 evpn_route_select_install(bgp
, vpn
, rn
);
857 /* If this is a new route or some attribute has changed, export the
858 * route to the global table. The route will be advertised to peers
859 * from there. Note that this table is a 2-level tree (RD-level +
860 * Prefix-level) similar to L3VPN routes.
863 struct bgp_info
*global_ri
;
865 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
866 (struct prefix
*)p
, &vpn
->prd
);
867 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, attr_new
, 1, 0,
870 /* Schedule for processing and unlock node. */
871 bgp_process(bgp
, rn
, afi
, safi
);
875 /* Unintern temporary. */
876 aspath_unintern(&attr
.aspath
);
882 * Delete EVPN route entry. This could be in the VNI route table
883 * or the global route table.
885 static void delete_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
886 afi_t afi
, safi_t safi
, struct bgp_node
*rn
,
887 struct bgp_info
**ri
)
889 struct bgp_info
*tmp_ri
;
893 /* Now, find matching route. */
894 for (tmp_ri
= rn
->info
; tmp_ri
; tmp_ri
= tmp_ri
->next
)
895 if (tmp_ri
->peer
== bgp
->peer_self
896 && tmp_ri
->type
== ZEBRA_ROUTE_BGP
897 && tmp_ri
->sub_type
== BGP_ROUTE_STATIC
)
902 /* Mark route for delete. */
904 bgp_info_delete(rn
, tmp_ri
);
908 * Delete EVPN route (of type based on prefix) for specified VNI and
909 * schedule for processing.
911 static int delete_evpn_route(struct bgp
*bgp
, struct bgpevpn
*vpn
,
912 struct prefix_evpn
*p
)
914 struct bgp_node
*rn
, *global_rn
;
916 afi_t afi
= AFI_L2VPN
;
917 safi_t safi
= SAFI_EVPN
;
919 /* First, locate the route node within the VNI. If it doesn't exist,
921 * is nothing further to do.
923 /* NOTE: There is no RD here. */
924 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
928 /* Next, locate route node in the global EVPN routing table. Note that
929 * this table is a 2-level tree (RD-level + Prefix-level) similar to
932 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
933 (struct prefix
*)p
, &vpn
->prd
);
935 /* Delete route entry in the global EVPN table. */
936 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
938 /* Schedule for processing - withdraws to peers happen from
942 bgp_process(bgp
, global_rn
, afi
, safi
);
943 bgp_unlock_node(global_rn
);
946 /* Delete route entry in the VNI route table. This can just be removed.
948 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
950 bgp_info_reap(rn
, ri
);
957 * Update all type-2 (MACIP) local routes for this VNI - these should also
958 * be scheduled for advertise to peers.
960 static int update_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
967 struct attr attr_sticky
;
968 struct attr
*attr_new
;
972 memset(&attr
, 0, sizeof(struct attr
));
973 memset(&attr_sticky
, 0, sizeof(struct attr
));
975 /* Build path-attribute - all type-2 routes for this VNI will share the
976 * same path attribute.
978 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
979 bgp_attr_default_set(&attr_sticky
, BGP_ORIGIN_IGP
);
980 attr
.nexthop
= vpn
->originator_ip
;
981 attr
.mp_nexthop_global_in
= vpn
->originator_ip
;
982 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
983 attr_sticky
.nexthop
= vpn
->originator_ip
;
984 attr_sticky
.mp_nexthop_global_in
= vpn
->originator_ip
;
985 attr_sticky
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
986 attr_sticky
.sticky
= 1;
988 /* Set up RT, ENCAP and sticky MAC extended community. */
989 build_evpn_route_extcomm(vpn
, &attr
);
990 build_evpn_route_extcomm(vpn
, &attr_sticky
);
992 /* Walk this VNI's route table and update local type-2 routes. For any
993 * routes updated, update corresponding entry in the global table too.
995 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
996 rn
= bgp_route_next(rn
)) {
997 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
998 struct bgp_node
*rd_rn
;
999 struct bgp_info
*global_ri
;
1001 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1004 if (evpn_route_is_sticky(bgp
, rn
))
1005 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
,
1006 &attr_sticky
, 0, 1, &ri
, 0);
1008 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &attr
,
1011 /* If a local route exists for this prefix, we need to update
1012 * the global routing table too.
1017 /* Perform route selection; this is just to set the flags
1019 * as local route in the VNI always wins.
1021 evpn_route_select_install(bgp
, vpn
, rn
);
1023 attr_new
= ri
->attr
;
1025 /* Update route in global routing table. */
1026 rd_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1027 (struct prefix
*)evp
, &vpn
->prd
);
1029 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, rd_rn
, attr_new
, 0,
1032 /* Schedule for processing and unlock node. */
1033 bgp_process(bgp
, rd_rn
, afi
, safi
);
1034 bgp_unlock_node(rd_rn
);
1037 /* Unintern temporary. */
1038 aspath_unintern(&attr
.aspath
);
1039 aspath_unintern(&attr_sticky
.aspath
);
1045 * Delete all type-2 (MACIP) local routes for this VNI - only from the
1046 * global routing table. These are also scheduled for withdraw from peers.
1048 static int delete_global_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1052 struct bgp_node
*rdrn
, *rn
;
1053 struct bgp_table
*table
;
1054 struct bgp_info
*ri
;
1059 rdrn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)&vpn
->prd
);
1060 if (rdrn
&& rdrn
->info
) {
1061 table
= (struct bgp_table
*)rdrn
->info
;
1062 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1063 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1065 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1068 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1070 bgp_process(bgp
, rn
, afi
, safi
);
1074 /* Unlock RD node. */
1076 bgp_unlock_node(rdrn
);
1082 * Delete all type-2 (MACIP) local routes for this VNI - from the global
1083 * table as well as the per-VNI route table.
1085 static int delete_all_type2_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1089 struct bgp_node
*rn
;
1090 struct bgp_info
*ri
;
1095 /* First, walk the global route table for this VNI's type-2 local
1097 * EVPN routes are a 2-level table, first get the RD table.
1099 delete_global_type2_routes(bgp
, vpn
);
1101 /* Next, walk this VNI's route table and delete local type-2 routes. */
1102 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1103 rn
= bgp_route_next(rn
)) {
1104 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1106 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1109 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, rn
, &ri
);
1111 /* Route entry in local table gets deleted immediately. */
1113 bgp_info_reap(rn
, ri
);
1120 * Delete all routes in the per-VNI route table.
1122 static int delete_all_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1124 struct bgp_node
*rn
;
1125 struct bgp_info
*ri
, *nextri
;
1127 /* Walk this VNI's route table and delete all routes. */
1128 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1129 rn
= bgp_route_next(rn
)) {
1130 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1132 bgp_info_delete(rn
, ri
);
1133 bgp_info_reap(rn
, ri
);
1141 * Update (and advertise) local routes for a VNI. Invoked upon the VNI
1142 * export RT getting modified or change to tunnel IP. Note that these
1143 * situations need the route in the per-VNI table as well as the global
1144 * table to be updated (as attributes change).
1146 static int update_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1149 struct prefix_evpn p
;
1151 /* Update and advertise the type-3 route (only one) followed by the
1152 * locally learnt type-2 routes (MACIP) - for this VNI.
1154 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1155 ret
= update_evpn_route(bgp
, vpn
, &p
, 0);
1159 return update_all_type2_routes(bgp
, vpn
);
1163 * Delete (and withdraw) local routes for specified VNI from the global
1164 * table and per-VNI table. After this, remove all other routes from
1165 * the per-VNI table. Invoked upon the VNI being deleted or EVPN
1166 * (advertise-all-vni) being disabled.
1168 static int delete_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1171 struct prefix_evpn p
;
1173 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1174 * followed by type-3 routes (only one) - for this VNI.
1176 ret
= delete_all_type2_routes(bgp
, vpn
);
1180 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1181 ret
= delete_evpn_route(bgp
, vpn
, &p
);
1185 /* Delete all routes from the per-VNI table. */
1186 return delete_all_vni_routes(bgp
, vpn
);
1190 * There is a tunnel endpoint IP address change for this VNI,
1191 * need to re-advertise routes with the new nexthop.
1193 static int handle_tunnel_ip_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1194 struct in_addr originator_ip
)
1196 struct prefix_evpn p
;
1198 /* If VNI is not live, we only need to update the originator ip */
1199 if (!is_vni_live(vpn
)) {
1200 vpn
->originator_ip
= originator_ip
;
1204 /* Update the tunnel-ip hash */
1205 bgp_tip_del(bgp
, &vpn
->originator_ip
);
1206 bgp_tip_add(bgp
, &originator_ip
);
1208 /* filter routes as martian nexthop db has changed */
1209 bgp_filter_evpn_routes_upon_martian_nh_change(bgp
);
1211 /* Need to withdraw type-3 route as the originator IP is part
1214 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1215 delete_evpn_route(bgp
, vpn
, &p
);
1217 /* Update the tunnel IP and re-advertise all routes for this VNI. */
1218 vpn
->originator_ip
= originator_ip
;
1219 return update_routes_for_vni(bgp
, vpn
);
1223 * Install route entry into the VNI routing table and invoke route selection.
1225 static int install_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1226 struct prefix_evpn
*p
,
1227 struct bgp_info
*parent_ri
)
1229 struct bgp_node
*rn
;
1230 struct bgp_info
*ri
;
1231 struct attr
*attr_new
;
1234 /* Create (or fetch) route within the VNI. */
1235 /* NOTE: There is no RD here. */
1236 rn
= bgp_node_get(vpn
->route_table
, (struct prefix
*)p
);
1238 /* Check if route entry is already present. */
1239 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1241 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1245 /* Add (or update) attribute to hash. */
1246 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1248 /* Create new route with its attribute. */
1249 ri
= info_make(parent_ri
->type
, parent_ri
->sub_type
, 0,
1250 parent_ri
->peer
, attr_new
, rn
);
1251 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
1252 bgp_info_extra_get(ri
);
1253 ri
->extra
->parent
= parent_ri
;
1254 if (parent_ri
->extra
)
1255 memcpy(&ri
->extra
->label
, &parent_ri
->extra
->label
,
1257 bgp_info_add(rn
, ri
);
1259 if (attrhash_cmp(ri
->attr
, parent_ri
->attr
)
1260 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1261 bgp_unlock_node(rn
);
1264 /* The attribute has changed. */
1265 /* Add (or update) attribute to hash. */
1266 attr_new
= bgp_attr_intern(parent_ri
->attr
);
1268 /* Restore route, if needed. */
1269 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
1270 bgp_info_restore(rn
, ri
);
1272 /* Mark if nexthop has changed. */
1273 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
, &attr_new
->nexthop
))
1274 SET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1276 /* Unintern existing, set to new. */
1277 bgp_attr_unintern(&ri
->attr
);
1278 ri
->attr
= attr_new
;
1279 ri
->uptime
= bgp_clock();
1282 /* Perform route selection and update zebra, if required. */
1283 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1289 * Uninstall route entry from the VNI routing table and send message
1290 * to zebra, if appropriate.
1292 static int uninstall_evpn_route_entry(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1293 struct prefix_evpn
*p
,
1294 struct bgp_info
*parent_ri
)
1296 struct bgp_node
*rn
;
1297 struct bgp_info
*ri
;
1300 /* Locate route within the VNI. */
1301 /* NOTE: There is no RD here. */
1302 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)p
);
1306 /* Find matching route entry. */
1307 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1309 && (struct bgp_info
*)ri
->extra
->parent
== parent_ri
)
1315 /* Mark entry for deletion */
1316 bgp_info_delete(rn
, ri
);
1318 /* Perform route selection and update zebra, if required. */
1319 ret
= evpn_route_select_install(bgp
, vpn
, rn
);
1321 /* Unlock route node. */
1322 bgp_unlock_node(rn
);
1328 * Given a route entry and a VNI, see if this route entry should be
1329 * imported into the VNI i.e., RTs match.
1331 static int is_route_matching_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1332 struct bgp_info
*ri
)
1334 struct attr
*attr
= ri
->attr
;
1335 struct ecommunity
*ecom
;
1339 /* Route should have valid RT to be even considered. */
1340 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1343 ecom
= attr
->ecommunity
;
1344 if (!ecom
|| !ecom
->size
)
1347 /* For each extended community RT, see if it matches this VNI. If any RT
1348 * matches, we're done.
1350 for (i
= 0; i
< ecom
->size
; i
++) {
1352 u_char type
, sub_type
;
1353 struct ecommunity_val
*eval
;
1354 struct ecommunity_val eval_tmp
;
1355 struct irt_node
*irt
;
1357 /* Only deal with RTs */
1358 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1359 eval
= (struct ecommunity_val
*)(ecom
->val
1360 + (i
* ECOMMUNITY_SIZE
));
1363 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1366 /* See if this RT matches specified VNIs import RTs */
1367 irt
= lookup_import_rt(bgp
, eval
);
1368 if (irt
&& irt
->vnis
)
1369 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1372 /* Also check for non-exact match. In this, we mask out the AS
1374 * only check on the local-admin sub-field. This is to
1376 * VNI as the RT for EBGP peering too.
1379 if (type
== ECOMMUNITY_ENCODE_AS
1380 || type
== ECOMMUNITY_ENCODE_AS4
1381 || type
== ECOMMUNITY_ENCODE_IP
) {
1382 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1383 mask_ecom_global_admin(&eval_tmp
, eval
);
1384 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1386 if (irt
&& irt
->vnis
)
1387 if (is_vni_present_in_irt_vnis(irt
->vnis
, vpn
))
1395 * Install or uninstall routes of specified type that are appropriate for this
1398 static int install_uninstall_routes_for_vni(struct bgp
*bgp
,
1399 struct bgpevpn
*vpn
,
1400 bgp_evpn_route_type rtype
,
1405 struct bgp_node
*rd_rn
, *rn
;
1406 struct bgp_table
*table
;
1407 struct bgp_info
*ri
;
1413 /* Walk entire global routing table and evaluate routes which could be
1414 * imported into this VPN. Note that we cannot just look at the routes
1416 * the VNI's RD - remote routes applicable for this VNI could have any
1419 /* EVPN routes are a 2-level table. */
1420 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1421 rd_rn
= bgp_route_next(rd_rn
)) {
1422 table
= (struct bgp_table
*)(rd_rn
->info
);
1426 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1427 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1429 if (evp
->prefix
.route_type
!= rtype
)
1432 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1433 /* Consider "valid" remote routes applicable for
1435 if (!(CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1436 && ri
->type
== ZEBRA_ROUTE_BGP
1437 && ri
->sub_type
== BGP_ROUTE_NORMAL
))
1440 if (is_route_matching_for_vni(bgp
, vpn
, ri
)) {
1442 ret
= install_evpn_route_entry(
1445 ret
= uninstall_evpn_route_entry(
1450 "%u: Failed to %s EVPN %s route in VNI %u",
1454 rtype
== BGP_EVPN_MAC_IP_ROUTE
1469 * Install any existing remote routes applicable for this VNI into its
1470 * routing table. This is invoked when a VNI becomes "live" or its Import
1473 static int install_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1477 /* Install type-3 routes followed by type-2 routes - the ones applicable
1480 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1485 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1490 * Uninstall any existing remote routes for this VNI. One scenario in which
1491 * this is invoked is upon an import RT change.
1493 static int uninstall_routes_for_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1497 /* Uninstall type-2 routes followed by type-3 routes - the ones
1501 ret
= install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_MAC_IP_ROUTE
,
1506 return install_uninstall_routes_for_vni(bgp
, vpn
, BGP_EVPN_IMET_ROUTE
,
1511 * Install or uninstall route in matching VNIs (list).
1513 static int install_uninstall_route_in_vnis(struct bgp
*bgp
, afi_t afi
,
1514 safi_t safi
, struct prefix_evpn
*evp
,
1515 struct bgp_info
*ri
,
1516 struct list
*vnis
, int install
)
1518 struct bgpevpn
*vpn
;
1519 struct listnode
*node
, *nnode
;
1521 for (ALL_LIST_ELEMENTS(vnis
, node
, nnode
, vpn
)) {
1524 if (!is_vni_live(vpn
))
1528 ret
= install_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1530 ret
= uninstall_evpn_route_entry(bgp
, vpn
, evp
, ri
);
1533 zlog_err("%u: Failed to %s EVPN %s route in VNI %u",
1534 bgp
->vrf_id
, install
? "install" : "uninstall",
1535 evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1547 * Install or uninstall route for appropriate VNIs.
1549 static int install_uninstall_evpn_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1550 struct prefix
*p
, struct bgp_info
*ri
,
1553 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
1554 struct attr
*attr
= ri
->attr
;
1555 struct ecommunity
*ecom
;
1560 /* Only type-2 and type-3 routes go into a L2 VNI. */
1561 if (!(evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
1562 || evp
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
))
1565 /* If we don't have Route Target, nothing much to do. */
1566 if (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)))
1569 ecom
= attr
->ecommunity
;
1570 if (!ecom
|| !ecom
->size
)
1573 /* For each extended community RT, see which VNIs match and import
1574 * the route into matching VNIs.
1576 for (i
= 0; i
< ecom
->size
; i
++) {
1578 u_char type
, sub_type
;
1579 struct ecommunity_val
*eval
;
1580 struct ecommunity_val eval_tmp
;
1581 struct irt_node
*irt
;
1583 /* Only deal with RTs */
1584 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
1585 eval
= (struct ecommunity_val
*)(ecom
->val
1586 + (i
* ECOMMUNITY_SIZE
));
1589 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
1592 /* Are we interested in this RT? */
1593 irt
= lookup_import_rt(bgp
, eval
);
1594 if (irt
&& irt
->vnis
)
1595 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1598 /* Also check for non-exact match. In this, we mask out the AS
1600 * only check on the local-admin sub-field. This is to
1602 * VNI as the RT for EBGP peering too.
1605 if (type
== ECOMMUNITY_ENCODE_AS
1606 || type
== ECOMMUNITY_ENCODE_AS4
1607 || type
== ECOMMUNITY_ENCODE_IP
) {
1608 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
1609 mask_ecom_global_admin(&eval_tmp
, eval
);
1610 irt
= lookup_import_rt(bgp
, &eval_tmp
);
1612 if (irt
&& irt
->vnis
)
1613 install_uninstall_route_in_vnis(bgp
, afi
, safi
, evp
, ri
,
1621 * Update and advertise local routes for a VNI. Invoked upon router-id
1622 * change. Note that the processing is done only on the global route table
1623 * using routes that already exist in the per-VNI table.
1625 static int update_advertise_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1627 struct prefix_evpn p
;
1628 struct bgp_node
*rn
, *global_rn
;
1629 struct bgp_info
*ri
, *global_ri
;
1631 afi_t afi
= AFI_L2VPN
;
1632 safi_t safi
= SAFI_EVPN
;
1634 /* Locate type-3 route for VNI in the per-VNI table and use its
1635 * attributes to create and advertise the type-3 route for this VNI
1636 * in the global table.
1638 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1639 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1640 if (!rn
) /* unexpected */
1642 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1643 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
1644 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1646 if (!ri
) /* unexpected */
1650 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1651 (struct prefix
*)&p
, &vpn
->prd
);
1652 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1, 0, &ri
,
1655 /* Schedule for processing and unlock node. */
1656 bgp_process(bgp
, global_rn
, afi
, safi
);
1657 bgp_unlock_node(global_rn
);
1659 /* Now, walk this VNI's route table and use the route and its attribute
1660 * to create and schedule route in global table.
1662 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
1663 rn
= bgp_route_next(rn
)) {
1664 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1666 /* Identify MAC-IP local routes. */
1667 if (evp
->prefix
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
1670 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1671 if (ri
->peer
== bgp
->peer_self
1672 && ri
->type
== ZEBRA_ROUTE_BGP
1673 && ri
->sub_type
== BGP_ROUTE_STATIC
)
1678 /* Create route in global routing table using this route entry's
1682 global_rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
,
1683 (struct prefix
*)evp
, &vpn
->prd
);
1685 update_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, attr
, 1,
1688 /* Schedule for processing and unlock node. */
1689 bgp_process(bgp
, global_rn
, afi
, safi
);
1690 bgp_unlock_node(global_rn
);
1697 * Delete (and withdraw) local routes for a VNI - only from the global
1698 * table. Invoked upon router-id change.
1700 static int delete_withdraw_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1703 struct prefix_evpn p
;
1704 struct bgp_node
*global_rn
;
1705 struct bgp_info
*ri
;
1706 afi_t afi
= AFI_L2VPN
;
1707 safi_t safi
= SAFI_EVPN
;
1709 /* Delete and withdraw locally learnt type-2 routes (MACIP)
1710 * for this VNI - from the global table.
1712 ret
= delete_global_type2_routes(bgp
, vpn
);
1716 /* Remove type-3 route for this VNI from global table. */
1717 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
1718 global_rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1719 (struct prefix
*)&p
, &vpn
->prd
);
1721 /* Delete route entry in the global EVPN table. */
1722 delete_evpn_route_entry(bgp
, vpn
, afi
, safi
, global_rn
, &ri
);
1724 /* Schedule for processing - withdraws to peers happen from
1728 bgp_process(bgp
, global_rn
, afi
, safi
);
1729 bgp_unlock_node(global_rn
);
1736 * Handle router-id change. Update and advertise local routes corresponding
1737 * to this VNI from peers. Note that this is invoked after updating the
1738 * router-id. The routes in the per-VNI table are used to create routes in
1739 * the global table and schedule them.
1741 static void update_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1743 struct bgpevpn
*vpn
;
1745 vpn
= (struct bgpevpn
*)backet
->data
;
1748 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1752 /* Skip VNIs with configured RD. */
1753 if (is_rd_configured(vpn
))
1756 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1757 update_advertise_vni_routes(bgp
, vpn
);
1761 * Handle router-id change. Delete and withdraw local routes corresponding
1762 * to this VNI from peers. Note that this is invoked prior to updating
1763 * the router-id and is done only on the global route table, the routes
1764 * are needed in the per-VNI table to re-advertise with new router id.
1766 static void withdraw_router_id_vni(struct hash_backet
*backet
, struct bgp
*bgp
)
1768 struct bgpevpn
*vpn
;
1770 vpn
= (struct bgpevpn
*)backet
->data
;
1773 zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__
);
1777 /* Skip VNIs with configured RD. */
1778 if (is_rd_configured(vpn
))
1781 delete_withdraw_vni_routes(bgp
, vpn
);
1785 * Process received EVPN type-2 route (advertise or withdraw).
1787 static int process_type2_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1788 struct attr
*attr
, u_char
*pfx
, int psize
,
1789 u_int32_t addpath_id
)
1791 struct prefix_rd prd
;
1792 struct prefix_evpn p
;
1795 mpls_label_t
*label_pnt
;
1798 /* Type-2 route should be either 33, 37 or 49 bytes or an
1799 * additional 3 bytes if there is a second label (VNI):
1800 * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1),
1801 * MAC Addr (6), IP len (1), IP (0, 4 or 16),
1802 * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3)
1804 if (psize
!= 33 && psize
!= 37 && psize
!= 49 && psize
!= 36
1805 && psize
!= 40 && psize
!= 52) {
1806 zlog_err("%u:%s - Rx EVPN Type-2 NLRI with invalid length %d",
1807 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1811 /* Make prefix_rd */
1812 prd
.family
= AF_UNSPEC
;
1814 memcpy(&prd
.val
, pfx
, 8);
1817 /* Make EVPN prefix. */
1818 memset(&p
, 0, sizeof(struct prefix_evpn
));
1820 p
.prefixlen
= EVPN_TYPE_2_ROUTE_PREFIXLEN
;
1821 p
.prefix
.route_type
= BGP_EVPN_MAC_IP_ROUTE
;
1823 /* Skip over Ethernet Seg Identifier for now. */
1826 /* Skip over Ethernet Tag for now. */
1829 /* Get the MAC Addr len */
1830 macaddr_len
= *pfx
++;
1832 /* Get the MAC Addr */
1833 if (macaddr_len
== (ETH_ALEN
* 8)) {
1834 memcpy(&p
.prefix
.mac
.octet
, pfx
, ETH_ALEN
);
1838 "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d",
1839 peer
->bgp
->vrf_id
, peer
->host
, macaddr_len
);
1845 ipaddr_len
= *pfx
++;
1846 if (ipaddr_len
!= 0 && ipaddr_len
!= IPV4_MAX_BITLEN
1847 && ipaddr_len
!= IPV6_MAX_BITLEN
) {
1849 "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d",
1850 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1855 ipaddr_len
/= 8; /* Convert to bytes. */
1856 p
.prefix
.ip
.ipa_type
= (ipaddr_len
== IPV4_MAX_BYTELEN
)
1859 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, ipaddr_len
);
1863 /* Get the VNI (in MPLS label field). */
1864 /* Note: We ignore the second VNI, if any. */
1865 label_pnt
= (mpls_label_t
*)pfx
;
1867 /* Process the route. */
1869 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1870 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1871 &prd
, label_pnt
, 0, NULL
);
1873 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1874 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1875 &prd
, label_pnt
, NULL
);
1880 * Process received EVPN type-3 route (advertise or withdraw).
1882 static int process_type3_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1883 struct attr
*attr
, u_char
*pfx
, int psize
,
1884 u_int32_t addpath_id
)
1886 struct prefix_rd prd
;
1887 struct prefix_evpn p
;
1891 /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
1892 * IP len (1) and IP (4 or 16).
1894 if (psize
!= 17 && psize
!= 29) {
1895 zlog_err("%u:%s - Rx EVPN Type-3 NLRI with invalid length %d",
1896 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1900 /* Make prefix_rd */
1901 prd
.family
= AF_UNSPEC
;
1903 memcpy(&prd
.val
, pfx
, 8);
1906 /* Make EVPN prefix. */
1907 memset(&p
, 0, sizeof(struct prefix_evpn
));
1909 p
.prefixlen
= EVPN_TYPE_3_ROUTE_PREFIXLEN
;
1910 p
.prefix
.route_type
= BGP_EVPN_IMET_ROUTE
;
1912 /* Skip over Ethernet Tag for now. */
1916 ipaddr_len
= *pfx
++;
1917 if (ipaddr_len
== IPV4_MAX_BITLEN
) {
1918 p
.prefix
.ip
.ipa_type
= IPADDR_V4
;
1919 memcpy(&p
.prefix
.ip
.ip
.addr
, pfx
, IPV4_MAX_BYTELEN
);
1922 "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
1923 peer
->bgp
->vrf_id
, peer
->host
, ipaddr_len
);
1927 /* Process the route. */
1929 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1930 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1931 &prd
, NULL
, 0, NULL
);
1933 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
1934 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
1940 * Process received EVPN type-5 route (advertise or withdraw).
1942 static int process_type5_route(struct peer
*peer
, afi_t afi
, safi_t safi
,
1943 struct attr
*attr
, u_char
*pfx
, int psize
,
1944 u_int32_t addpath_id
, int withdraw
)
1946 struct prefix_rd prd
;
1947 struct prefix_evpn p
;
1948 struct bgp_route_evpn evpn
;
1951 mpls_label_t
*label_pnt
;
1954 /* Type-5 route should be 34 or 58 bytes:
1955 * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
1956 * GW (4 or 16) and VNI (3).
1957 * Note that the IP and GW should both be IPv4 or both IPv6.
1959 if (psize
!= 34 && psize
!= 58) {
1960 zlog_err("%u:%s - Rx EVPN Type-5 NLRI with invalid length %d",
1961 peer
->bgp
->vrf_id
, peer
->host
, psize
);
1965 /* Make prefix_rd */
1966 prd
.family
= AF_UNSPEC
;
1968 memcpy(&prd
.val
, pfx
, 8);
1971 /* Make EVPN prefix. */
1972 memset(&p
, 0, sizeof(struct prefix_evpn
));
1974 p
.prefix
.route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
1976 /* Additional information outside of prefix - ESI and GW IP */
1977 memset(&evpn
, 0, sizeof(evpn
));
1980 memcpy(&evpn
.eth_s_id
.val
, pfx
, 10);
1983 /* Fetch Ethernet Tag. */
1984 memcpy(ð_tag
, pfx
, 4);
1985 p
.prefix
.eth_tag
= ntohl(eth_tag
);
1988 /* Fetch IP prefix length. */
1990 if (ippfx_len
> IPV6_MAX_BITLEN
) {
1992 "%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d",
1993 peer
->bgp
->vrf_id
, peer
->host
, ippfx_len
);
1996 p
.prefix
.ip_prefix_length
= ippfx_len
;
1998 /* Determine IPv4 or IPv6 prefix */
1999 /* Since the address and GW are from the same family, this just becomes
2000 * a simple check on the total size.
2003 SET_IPADDR_V4(&p
.prefix
.ip
);
2004 memcpy(&p
.prefix
.ip
.ipaddr_v4
, pfx
, 4);
2006 memcpy(&evpn
.gw_ip
.ipv4
, pfx
, 4);
2008 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
2010 SET_IPADDR_V6(&p
.prefix
.ip
);
2011 memcpy(&p
.prefix
.ip
.ipaddr_v6
, pfx
, 16);
2013 memcpy(&evpn
.gw_ip
.ipv6
, pfx
, 16);
2015 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV6
;
2018 label_pnt
= (mpls_label_t
*)pfx
;
2020 /* Process the route. */
2022 ret
= bgp_update(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2023 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2024 &prd
, label_pnt
, 0, &evpn
);
2026 ret
= bgp_withdraw(peer
, (struct prefix
*)&p
, addpath_id
, attr
,
2027 afi
, safi
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
2028 &prd
, label_pnt
, &evpn
);
2033 static void evpn_mpattr_encode_type5(struct stream
*s
, struct prefix
*p
,
2034 struct prefix_rd
*prd
, mpls_label_t
*label
,
2039 struct evpn_addr
*p_evpn_p
;
2041 memset(&temp
, 0, 16);
2042 if (p
->family
!= AF_EVPN
)
2044 p_evpn_p
= &(p
->u
.prefix_evpn
);
2046 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2049 len
= 32; /* ipv6 */
2050 /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
2051 stream_putc(s
, 8 + 10 + 4 + 1 + len
+ 3);
2052 stream_put(s
, prd
->val
, 8);
2054 stream_put(s
, &(attr
->evpn_overlay
.eth_s_id
), 10);
2056 stream_put(s
, &temp
, 10);
2057 stream_putl(s
, p_evpn_p
->eth_tag
);
2058 stream_putc(s
, p_evpn_p
->ip_prefix_length
);
2059 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2060 stream_put_ipv4(s
, p_evpn_p
->ip
.ipaddr_v4
.s_addr
);
2062 stream_put(s
, &p_evpn_p
->ip
.ipaddr_v6
, 16);
2064 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2066 attr
->evpn_overlay
.gw_ip
.ipv4
.s_addr
);
2068 stream_put(s
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), 16);
2070 if (IS_IPADDR_V4(&p_evpn_p
->ip
))
2071 stream_put_ipv4(s
, 0);
2073 stream_put(s
, &temp
, 16);
2077 stream_put(s
, label
, 3);
2083 * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled.
2085 static void cleanup_vni_on_disable(struct hash_backet
*backet
, struct bgp
*bgp
)
2087 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2089 /* Remove EVPN routes and schedule for processing. */
2090 delete_routes_for_vni(bgp
, vpn
);
2092 /* Clear "live" flag and see if hash needs to be freed. */
2093 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2094 if (!is_vni_configured(vpn
))
2095 bgp_evpn_free(bgp
, vpn
);
2099 * Free a VNI entry; iterator function called during cleanup.
2101 static void free_vni_entry(struct hash_backet
*backet
, struct bgp
*bgp
)
2103 struct bgpevpn
*vpn
;
2105 vpn
= (struct bgpevpn
*)backet
->data
;
2106 delete_all_vni_routes(bgp
, vpn
);
2107 bgp_evpn_free(bgp
, vpn
);
2116 * Handle change to BGP router id. This is invoked twice by the change
2117 * handler, first before the router id has been changed and then after
2118 * the router id has been changed. The first invocation will result in
2119 * local routes for all VNIs being deleted and withdrawn and the next
2120 * will result in the routes being re-advertised.
2122 void bgp_evpn_handle_router_id_update(struct bgp
*bgp
, int withdraw
)
2125 hash_iterate(bgp
->vnihash
,
2126 (void (*)(struct hash_backet
*,
2127 void *))withdraw_router_id_vni
,
2130 hash_iterate(bgp
->vnihash
,
2131 (void (*)(struct hash_backet
*,
2132 void *))update_router_id_vni
,
2137 * Handle change to export RT - update and advertise local routes.
2139 int bgp_evpn_handle_export_rt_change(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2141 return update_routes_for_vni(bgp
, vpn
);
2145 * Handle change to RD. This is invoked twice by the change handler,
2146 * first before the RD has been changed and then after the RD has
2147 * been changed. The first invocation will result in local routes
2148 * of this VNI being deleted and withdrawn and the next will result
2149 * in the routes being re-advertised.
2151 void bgp_evpn_handle_rd_change(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2155 delete_withdraw_vni_routes(bgp
, vpn
);
2157 update_advertise_vni_routes(bgp
, vpn
);
2161 * Install routes for this VNI. Invoked upon change to Import RT.
2163 int bgp_evpn_install_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2165 return install_routes_for_vni(bgp
, vpn
);
2169 * Uninstall all routes installed for this VNI. Invoked upon change
2172 int bgp_evpn_uninstall_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2174 return uninstall_routes_for_vni(bgp
, vpn
);
2178 * Function to display "tag" in route as a VNI.
2180 char *bgp_evpn_label2str(mpls_label_t
*label
, char *buf
, int len
)
2184 vni
= label2vni(label
);
2185 snprintf(buf
, len
, "%u", vni
);
2190 * Function to convert evpn route to json format.
2191 * NOTE: We don't use prefix2str as the output here is a bit different.
2193 void bgp_evpn_route2json(struct prefix_evpn
*p
, json_object
*json
)
2195 char buf1
[ETHER_ADDR_STRLEN
];
2196 char buf2
[PREFIX2STR_BUFFER
];
2201 if (p
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
) {
2202 json_object_int_add(json
, "routeType", p
->prefix
.route_type
);
2203 json_object_int_add(json
, "ethTag", 0);
2204 json_object_int_add(json
, "ipLen",
2205 IS_EVPN_PREFIX_IPADDR_V4(p
)
2208 json_object_string_add(json
, "ip",
2209 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
2210 } else if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
2211 if (IS_EVPN_PREFIX_IPADDR_NONE(p
)) {
2212 json_object_int_add(json
, "routeType",
2213 p
->prefix
.route_type
);
2214 json_object_int_add(
2216 0); /* TODO: we don't support esi yet */
2217 json_object_int_add(json
, "ethTag", 0);
2218 json_object_int_add(json
, "macLen", 8 * ETH_ALEN
);
2219 json_object_string_add(json
, "mac",
2220 prefix_mac2str(&p
->prefix
.mac
,
2226 family
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? AF_INET
2229 json_object_int_add(json
, "routeType",
2230 p
->prefix
.route_type
);
2231 json_object_int_add(
2233 0); /* TODO: we don't support esi yet */
2234 json_object_int_add(json
, "ethTag", 0);
2235 json_object_int_add(json
, "macLen", 8 * ETH_ALEN
);
2236 json_object_string_add(json
, "mac",
2237 prefix_mac2str(&p
->prefix
.mac
,
2240 json_object_int_add(json
, "ipLen",
2241 IS_EVPN_PREFIX_IPADDR_V4(p
)
2244 json_object_string_add(
2246 inet_ntop(family
, &p
->prefix
.ip
.ip
.addr
, buf2
,
2247 PREFIX2STR_BUFFER
));
2250 /* Currently, this is to cater to other AF_ETHERNET code. */
2255 * Function to convert evpn route to string.
2256 * NOTE: We don't use prefix2str as the output here is a bit different.
2258 char *bgp_evpn_route2str(struct prefix_evpn
*p
, char *buf
, int len
)
2260 char buf1
[ETHER_ADDR_STRLEN
];
2261 char buf2
[PREFIX2STR_BUFFER
];
2263 if (p
->prefix
.route_type
== BGP_EVPN_IMET_ROUTE
) {
2264 snprintf(buf
, len
, "[%d]:[0]:[%d]:[%s]", p
->prefix
.route_type
,
2265 IS_EVPN_PREFIX_IPADDR_V4(p
) ? IPV4_MAX_BITLEN
2267 inet_ntoa(p
->prefix
.ip
.ipaddr_v4
));
2268 } else if (p
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
2269 if (IS_EVPN_PREFIX_IPADDR_NONE(p
))
2270 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]",
2271 p
->prefix
.route_type
, 8 * ETH_ALEN
,
2272 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2277 family
= IS_EVPN_PREFIX_IPADDR_V4(p
) ? AF_INET
2279 snprintf(buf
, len
, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]",
2280 p
->prefix
.route_type
, 8 * ETH_ALEN
,
2281 prefix_mac2str(&p
->prefix
.mac
, buf1
,
2283 family
== AF_INET
? IPV4_MAX_BITLEN
2285 inet_ntop(family
, &p
->prefix
.ip
.ip
.addr
, buf2
,
2286 PREFIX2STR_BUFFER
));
2289 /* For EVPN route types not supported yet. */
2290 snprintf(buf
, len
, "(unsupported route type %d)",
2291 p
->prefix
.route_type
);
2298 * Encode EVPN prefix in Update (MP_REACH)
2300 void bgp_evpn_encode_prefix(struct stream
*s
, struct prefix
*p
,
2301 struct prefix_rd
*prd
, mpls_label_t
*label
,
2302 struct attr
*attr
, int addpath_encode
,
2303 u_int32_t addpath_tx_id
)
2305 struct prefix_evpn
*evp
= (struct prefix_evpn
*)p
;
2309 stream_putl(s
, addpath_tx_id
);
2312 stream_putc(s
, evp
->prefix
.route_type
);
2314 switch (evp
->prefix
.route_type
) {
2315 case BGP_EVPN_MAC_IP_ROUTE
:
2316 if (IS_EVPN_PREFIX_IPADDR_V4(evp
))
2317 ipa_len
= IPV4_MAX_BYTELEN
;
2318 else if (IS_EVPN_PREFIX_IPADDR_V6(evp
))
2319 ipa_len
= IPV6_MAX_BYTELEN
;
2320 stream_putc(s
, 33 + ipa_len
); // 1 VNI
2321 stream_put(s
, prd
->val
, 8); /* RD */
2322 stream_put(s
, 0, 10); /* ESI */
2323 stream_putl(s
, 0); /* Ethernet Tag ID */
2324 stream_putc(s
, 8 * ETH_ALEN
); /* Mac Addr Len - bits */
2325 stream_put(s
, evp
->prefix
.mac
.octet
, 6); /* Mac Addr */
2326 stream_putc(s
, 8 * ipa_len
); /* IP address Length */
2328 stream_put(s
, &evp
->prefix
.ip
.ip
.addr
,
2330 stream_put(s
, label
,
2331 BGP_LABEL_BYTES
); /* VNI is contained in 'tag' */
2334 case BGP_EVPN_IMET_ROUTE
:
2335 stream_putc(s
, 17); // TODO: length - assumes IPv4 address
2336 stream_put(s
, prd
->val
, 8); /* RD */
2337 stream_putl(s
, 0); /* Ethernet Tag ID */
2338 stream_putc(s
, IPV4_MAX_BITLEN
); /* IP address Length - bits */
2339 /* Originating Router's IP Addr */
2340 stream_put_in_addr(s
, &evp
->prefix
.ip
.ipaddr_v4
);
2343 case BGP_EVPN_IP_PREFIX_ROUTE
:
2344 /* TODO: AddPath support. */
2345 evpn_mpattr_encode_type5(s
, p
, prd
, label
, attr
);
2353 int bgp_nlri_parse_evpn(struct peer
*peer
, struct attr
*attr
,
2354 struct bgp_nlri
*packet
, int withdraw
)
2360 u_int32_t addpath_id
;
2361 int addpath_encoded
;
2367 /* Check peer status. */
2368 if (peer
->status
!= Established
) {
2369 zlog_err("%u:%s - EVPN update received in state %d",
2370 peer
->bgp
->vrf_id
, peer
->host
, peer
->status
);
2374 /* Start processing the NLRI - there may be multiple in the MP_REACH */
2376 lim
= pnt
+ packet
->length
;
2378 safi
= packet
->safi
;
2382 (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
2383 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
2384 PEER_CAP_ADDPATH_AF_TX_RCV
));
2386 for (; pnt
< lim
; pnt
+= psize
) {
2387 /* Clear prefix structure. */
2388 memset(&p
, 0, sizeof(struct prefix
));
2390 /* Deal with path-id if AddPath is supported. */
2391 if (addpath_encoded
) {
2392 /* When packet overflow occurs return immediately. */
2393 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
2396 addpath_id
= ntohl(*((uint32_t *)pnt
));
2397 pnt
+= BGP_ADDPATH_ID_LEN
;
2400 /* All EVPN NLRI types start with type and length. */
2405 psize
= rlen
= *pnt
++;
2407 /* When packet overflow occur return immediately. */
2408 if (pnt
+ psize
> lim
)
2412 case BGP_EVPN_MAC_IP_ROUTE
:
2413 if (process_type2_route(peer
, afi
, safi
,
2414 withdraw
? NULL
: attr
, pnt
,
2415 psize
, addpath_id
)) {
2417 "%u:%s - Error in processing EVPN type-2 NLRI size %d",
2418 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2423 case BGP_EVPN_IMET_ROUTE
:
2424 if (process_type3_route(peer
, afi
, safi
,
2425 withdraw
? NULL
: attr
, pnt
,
2426 psize
, addpath_id
)) {
2428 "%u:%s - Error in processing EVPN type-3 NLRI size %d",
2429 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2434 case BGP_EVPN_IP_PREFIX_ROUTE
:
2435 if (process_type5_route(peer
, afi
, safi
, attr
, pnt
,
2436 psize
, addpath_id
, withdraw
)) {
2438 "%u:%s - Error in processing EVPN type-5 NLRI size %d",
2439 peer
->bgp
->vrf_id
, peer
->host
, psize
);
2449 /* Packet length consistency check. */
2458 * Map the RTs (configured or automatically derived) of a VNI to the VNI.
2459 * The mapping will be used during route processing.
2461 void bgp_evpn_map_vni_to_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2464 struct ecommunity_val
*eval
;
2465 struct listnode
*node
, *nnode
;
2466 struct ecommunity
*ecom
;
2468 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2469 for (i
= 0; i
< ecom
->size
; i
++) {
2470 eval
= (struct ecommunity_val
*)(ecom
->val
2472 * ECOMMUNITY_SIZE
));
2473 map_vni_to_rt(bgp
, vpn
, eval
);
2479 * Unmap the RTs (configured or automatically derived) of a VNI from the VNI.
2481 void bgp_evpn_unmap_vni_from_its_rts(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2484 struct ecommunity_val
*eval
;
2485 struct listnode
*node
, *nnode
;
2486 struct ecommunity
*ecom
;
2488 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2489 for (i
= 0; i
< ecom
->size
; i
++) {
2490 struct irt_node
*irt
;
2491 struct ecommunity_val eval_tmp
;
2493 eval
= (struct ecommunity_val
*)(ecom
->val
2495 * ECOMMUNITY_SIZE
));
2496 /* If using "automatic" RT, we only care about the
2497 * local-admin sub-field.
2498 * This is to facilitate using VNI as the RT for EBGP
2501 memcpy(&eval_tmp
, eval
, ECOMMUNITY_SIZE
);
2502 if (!is_import_rt_configured(vpn
))
2503 mask_ecom_global_admin(&eval_tmp
, eval
);
2505 irt
= lookup_import_rt(bgp
, &eval_tmp
);
2507 unmap_vni_from_rt(bgp
, vpn
, irt
);
2513 * Derive Import RT automatically for VNI and map VNI to RT.
2514 * The mapping will be used during route processing.
2516 void bgp_evpn_derive_auto_rt_import(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2518 form_auto_rt(bgp
, vpn
, vpn
->import_rtl
);
2519 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2522 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2526 * Derive Export RT automatically for VNI.
2528 void bgp_evpn_derive_auto_rt_export(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2530 form_auto_rt(bgp
, vpn
, vpn
->export_rtl
);
2531 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2535 * Derive RD automatically for VNI using passed information - it
2536 * is of the form RouterId:unique-id-for-vni.
2538 void bgp_evpn_derive_auto_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2542 vpn
->prd
.family
= AF_UNSPEC
;
2543 vpn
->prd
.prefixlen
= 64;
2544 sprintf(buf
, "%s:%hu", inet_ntoa(bgp
->router_id
), vpn
->rd_id
);
2545 str2prefix_rd(buf
, &vpn
->prd
);
2546 UNSET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2552 struct bgpevpn
*bgp_evpn_lookup_vni(struct bgp
*bgp
, vni_t vni
)
2554 struct bgpevpn
*vpn
;
2557 memset(&tmp
, 0, sizeof(struct bgpevpn
));
2559 vpn
= hash_lookup(bgp
->vnihash
, &tmp
);
2564 * Create a new vpn - invoked upon configuration or zebra notification.
2566 struct bgpevpn
*bgp_evpn_new(struct bgp
*bgp
, vni_t vni
,
2567 struct in_addr originator_ip
)
2569 struct bgpevpn
*vpn
;
2574 vpn
= XCALLOC(MTYPE_BGP_EVPN
, sizeof(struct bgpevpn
));
2578 /* Set values - RD and RT set to defaults. */
2580 vpn
->originator_ip
= originator_ip
;
2582 /* Initialize route-target import and export lists */
2583 vpn
->import_rtl
= list_new();
2584 vpn
->import_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2585 vpn
->export_rtl
= list_new();
2586 vpn
->export_rtl
->cmp
= (int (*)(void *, void *))evpn_route_target_cmp
;
2587 bf_assign_index(bgp
->rd_idspace
, vpn
->rd_id
);
2588 derive_rd_rt_for_vni(bgp
, vpn
);
2590 /* Initialize EVPN route table. */
2591 vpn
->route_table
= bgp_table_init(AFI_L2VPN
, SAFI_EVPN
);
2594 if (!hash_get(bgp
->vnihash
, vpn
, hash_alloc_intern
)) {
2595 XFREE(MTYPE_BGP_EVPN
, vpn
);
2598 QOBJ_REG(vpn
, bgpevpn
);
2603 * Free a given VPN - called in multiple scenarios such as zebra
2604 * notification, configuration being deleted, advertise-all-vni disabled etc.
2605 * This just frees appropriate memory, caller should have taken other
2608 void bgp_evpn_free(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2610 bgp_table_unlock(vpn
->route_table
);
2611 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2612 list_delete_and_null(&vpn
->import_rtl
);
2613 list_delete_and_null(&vpn
->export_rtl
);
2614 bf_release_index(bgp
->rd_idspace
, vpn
->rd_id
);
2615 hash_release(bgp
->vnihash
, vpn
);
2617 XFREE(MTYPE_BGP_EVPN
, vpn
);
2621 * Import route into matching VNI(s).
2623 int bgp_evpn_import_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2624 struct prefix
*p
, struct bgp_info
*ri
)
2626 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 1);
2630 * Unimport route from matching VNI(s).
2632 int bgp_evpn_unimport_route(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2633 struct prefix
*p
, struct bgp_info
*ri
)
2635 return install_uninstall_evpn_route(bgp
, afi
, safi
, p
, ri
, 0);
2638 /* filter routes which have martian next hops */
2639 int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp
*bgp
)
2643 struct bgp_node
*rd_rn
, *rn
;
2644 struct bgp_table
*table
;
2645 struct bgp_info
*ri
;
2650 /* Walk entire global routing table and evaluate routes which could be
2651 * imported into this VPN. Note that we cannot just look at the routes
2652 * for the VNI's RD -
2653 * remote routes applicable for this VNI could have any RD.
2655 /* EVPN routes are a 2-level table. */
2656 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2657 rd_rn
= bgp_route_next(rd_rn
)) {
2658 table
= (struct bgp_table
*)(rd_rn
->info
);
2662 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2664 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2666 /* Consider "valid" remote routes applicable for
2668 if (!(ri
->type
== ZEBRA_ROUTE_BGP
2669 && ri
->sub_type
== BGP_ROUTE_NORMAL
))
2672 if (bgp_nexthop_self(bgp
, ri
->attr
->nexthop
)) {
2674 char attr_str
[BUFSIZ
];
2675 char pbuf
[PREFIX_STRLEN
];
2677 bgp_dump_attr(ri
->attr
, attr_str
,
2680 if (bgp_debug_update(ri
->peer
, &rn
->p
,
2683 "%u: prefix %s with attr %s - DENIED due to martian or self nexthop",
2690 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2693 bgp_rib_remove(rn
, ri
, ri
->peer
, afi
,
2704 * Handle del of a local MACIP.
2706 int bgp_evpn_local_macip_del(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2709 struct bgpevpn
*vpn
;
2710 struct prefix_evpn p
;
2712 if (!bgp
->vnihash
) {
2713 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2717 /* Lookup VNI hash - should exist. */
2718 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2719 if (!vpn
|| !is_vni_live(vpn
)) {
2720 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP DEL",
2721 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2725 /* Remove EVPN type-2 route and schedule for processing. */
2726 build_evpn_type2_prefix(&p
, mac
, ip
);
2727 delete_evpn_route(bgp
, vpn
, &p
);
2733 * Handle add of a local MACIP.
2735 int bgp_evpn_local_macip_add(struct bgp
*bgp
, vni_t vni
, struct ethaddr
*mac
,
2736 struct ipaddr
*ip
, u_char flags
)
2738 struct bgpevpn
*vpn
;
2739 struct prefix_evpn p
;
2741 if (!bgp
->vnihash
) {
2742 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2746 /* Lookup VNI hash - should exist. */
2747 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2748 if (!vpn
|| !is_vni_live(vpn
)) {
2749 zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP ADD",
2750 bgp
->vrf_id
, vni
, vpn
? "not live" : "not found");
2754 /* Create EVPN type-2 route and schedule for processing. */
2755 build_evpn_type2_prefix(&p
, mac
, ip
);
2756 if (update_evpn_route(bgp
, vpn
, &p
, flags
)) {
2757 char buf
[ETHER_ADDR_STRLEN
];
2758 char buf2
[INET6_ADDRSTRLEN
];
2761 "%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s",
2762 bgp
->vrf_id
, vpn
->vni
,
2763 CHECK_FLAG(flags
, ZEBRA_MAC_TYPE_STICKY
) ? "sticky gateway"
2765 prefix_mac2str(mac
, buf
, sizeof(buf
)),
2766 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2774 * Handle del of a local VNI.
2776 int bgp_evpn_local_vni_del(struct bgp
*bgp
, vni_t vni
)
2778 struct bgpevpn
*vpn
;
2780 if (!bgp
->vnihash
) {
2781 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2785 /* Locate VNI hash */
2786 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2788 zlog_warn("%u: VNI hash entry for VNI %u not found at DEL",
2793 /* Remove all local EVPN routes and schedule for processing (to
2794 * withdraw from peers).
2796 delete_routes_for_vni(bgp
, vpn
);
2799 * tunnel is no longer active, del tunnel ip address from tip_hash
2801 bgp_tip_del(bgp
, &vpn
->originator_ip
);
2803 /* Clear "live" flag and see if hash needs to be freed. */
2804 UNSET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2805 if (!is_vni_configured(vpn
))
2806 bgp_evpn_free(bgp
, vpn
);
2812 * Handle add (or update) of a local VNI. The only VNI change we care
2813 * about is change to local-tunnel-ip.
2815 int bgp_evpn_local_vni_add(struct bgp
*bgp
, vni_t vni
,
2816 struct in_addr originator_ip
)
2818 struct bgpevpn
*vpn
;
2819 struct prefix_evpn p
;
2821 if (!bgp
->vnihash
) {
2822 zlog_err("%u: VNI hash not created", bgp
->vrf_id
);
2826 /* Lookup VNI. If present and no change, exit. */
2827 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2829 if (is_vni_live(vpn
)
2830 && IPV4_ADDR_SAME(&vpn
->originator_ip
, &originator_ip
))
2831 /* Probably some other param has changed that we don't
2835 /* Local tunnel endpoint IP address has changed */
2836 handle_tunnel_ip_change(bgp
, vpn
, originator_ip
);
2839 /* Create or update as appropriate. */
2841 vpn
= bgp_evpn_new(bgp
, vni
, originator_ip
);
2844 "%u: Failed to allocate VNI entry for VNI %u - at Add",
2850 /* if the VNI is live already, there is nothing more to do */
2851 if (is_vni_live(vpn
))
2854 /* Mark as "live" */
2855 SET_FLAG(vpn
->flags
, VNI_FLAG_LIVE
);
2857 /* tunnel is now active, add tunnel-ip to db */
2858 bgp_tip_add(bgp
, &originator_ip
);
2860 /* filter routes as nexthop database has changed */
2861 bgp_filter_evpn_routes_upon_martian_nh_change(bgp
);
2863 /* Create EVPN type-3 route and schedule for processing. */
2864 build_evpn_type3_prefix(&p
, vpn
->originator_ip
);
2865 if (update_evpn_route(bgp
, vpn
, &p
, 0)) {
2866 zlog_err("%u: Type3 route creation failure for VNI %u",
2871 /* If we have learnt and retained remote routes (VTEPs, MACs) for this
2875 install_routes_for_vni(bgp
, vpn
);
2877 /* If we are advertising gateway mac-ip
2878 It needs to be conveyed again to zebra */
2879 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
, vpn
->vni
);
2885 * Cleanup EVPN information on disable - Need to delete and withdraw
2886 * EVPN routes from peers.
2888 void bgp_evpn_cleanup_on_disable(struct bgp
*bgp
)
2890 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2891 void *))cleanup_vni_on_disable
,
2896 * Cleanup EVPN information - invoked at the time of bgpd exit or when the
2897 * BGP instance (default) is being freed.
2899 void bgp_evpn_cleanup(struct bgp
*bgp
)
2902 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2903 void *))free_vni_entry
,
2905 if (bgp
->import_rt_hash
)
2906 hash_free(bgp
->import_rt_hash
);
2907 bgp
->import_rt_hash
= NULL
;
2909 hash_free(bgp
->vnihash
);
2910 bgp
->vnihash
= NULL
;
2911 bf_free(bgp
->rd_idspace
);
2915 * Initialization for EVPN
2918 * hash for RT to VNI
2919 * unique rd id space for auto derivation of RD for VNIs
2921 void bgp_evpn_init(struct bgp
*bgp
)
2924 hash_create(vni_hash_key_make
, vni_hash_cmp
, "BGP VNI Hash");
2925 bgp
->import_rt_hash
=
2926 hash_create(import_rt_hash_key_make
, import_rt_hash_cmp
,
2927 "BGP Import RT Hash");
2928 bf_init(bgp
->rd_idspace
, UINT16_MAX
);
2929 /*assign 0th index in the bitfield, so that we start with id 1*/
2930 bf_assign_zero_index(bgp
->rd_idspace
);