back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_evpn.c (source / functions) Hit Total Coverage
Test: test_bgp_rmap_extcommunity_none.py::TestBGPExtCommunity Lines: 55 3048 1.8 %
Date: 2023-02-24 18:37:31 Functions: 6 205 2.9 %

          Line data    Source code
       1             : /* Ethernet-VPN Packet and vty Processing File
       2             :  * Copyright (C) 2016 6WIND
       3             :  * Copyright (C) 2017 Cumulus Networks, Inc.
       4             :  *
       5             :  * This file is part of FRR.
       6             :  *
       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
      10             :  * later version.
      11             :  *
      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.
      16             :  *
      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
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "command.h"
      25             : #include "filter.h"
      26             : #include "prefix.h"
      27             : #include "log.h"
      28             : #include "memory.h"
      29             : #include "stream.h"
      30             : #include "hash.h"
      31             : #include "jhash.h"
      32             : #include "zclient.h"
      33             : 
      34             : #include "lib/printfrr.h"
      35             : 
      36             : #include "bgpd/bgp_attr_evpn.h"
      37             : #include "bgpd/bgpd.h"
      38             : #include "bgpd/bgp_table.h"
      39             : #include "bgpd/bgp_route.h"
      40             : #include "bgpd/bgp_attr.h"
      41             : #include "bgpd/bgp_mplsvpn.h"
      42             : #include "bgpd/bgp_label.h"
      43             : #include "bgpd/bgp_evpn.h"
      44             : #include "bgpd/bgp_evpn_private.h"
      45             : #include "bgpd/bgp_evpn_mh.h"
      46             : #include "bgpd/bgp_ecommunity.h"
      47             : #include "bgpd/bgp_encap_types.h"
      48             : #include "bgpd/bgp_debug.h"
      49             : #include "bgpd/bgp_errors.h"
      50             : #include "bgpd/bgp_aspath.h"
      51             : #include "bgpd/bgp_zebra.h"
      52             : #include "bgpd/bgp_nexthop.h"
      53             : #include "bgpd/bgp_addpath.h"
      54             : #include "bgpd/bgp_mac.h"
      55             : #include "bgpd/bgp_vty.h"
      56             : #include "bgpd/bgp_nht.h"
      57             : #include "bgpd/bgp_trace.h"
      58             : 
      59             : /*
      60             :  * Definitions and external declarations.
      61             :  */
      62             : DEFINE_QOBJ_TYPE(bgpevpn);
      63             : DEFINE_QOBJ_TYPE(bgp_evpn_es);
      64             : 
      65           6 : DEFINE_MTYPE_STATIC(BGPD, VRF_ROUTE_TARGET, "L3 Route Target");
      66             : 
      67             : /*
      68             :  * Static function declarations
      69             :  */
      70             : static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *evpn);
      71             : static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *evpn);
      72             : static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn,
      73             :                                         struct bgp_path_info *pi);
      74             : static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn,
      75             :                                         struct bgp_path_info *pi);
      76             : static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn,
      77             :                                             void (*func)(struct hash_bucket *,
      78             :                                                          void *),
      79             :                                             void *arg);
      80             : static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn);
      81             : static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp,
      82             :                                               struct bgpevpn *vpn);
      83             : static unsigned int vni_svi_hash_key_make(const void *p);
      84             : static bool vni_svi_hash_cmp(const void *p1, const void *p2);
      85             : static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn,
      86             :                                                 struct ipaddr *addr,
      87             :                                                 bool resolve);
      88             : static void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket,
      89             :                                                  void *args);
      90             : static void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket,
      91             :                                                    void *args);
      92             : static struct in_addr zero_vtep_ip;
      93             : 
      94             : /*
      95             :  * Private functions.
      96             :  */
      97             : 
      98             : /*
      99             :  * Make vni hash key.
     100             :  */
     101           0 : static unsigned int vni_hash_key_make(const void *p)
     102             : {
     103           0 :         const struct bgpevpn *vpn = p;
     104           0 :         return (jhash_1word(vpn->vni, 0));
     105             : }
     106             : 
     107             : /*
     108             :  * Comparison function for vni hash
     109             :  */
     110           0 : static bool vni_hash_cmp(const void *p1, const void *p2)
     111             : {
     112           0 :         const struct bgpevpn *vpn1 = p1;
     113           0 :         const struct bgpevpn *vpn2 = p2;
     114             : 
     115           0 :         return vpn1->vni == vpn2->vni;
     116             : }
     117             : 
     118           0 : int vni_list_cmp(void *p1, void *p2)
     119             : {
     120           0 :         const struct bgpevpn *vpn1 = p1;
     121           0 :         const struct bgpevpn *vpn2 = p2;
     122             : 
     123           0 :         return vpn1->vni - vpn2->vni;
     124             : }
     125             : 
     126             : /*
     127             :  * Make vrf import route target hash key.
     128             :  */
     129           0 : static unsigned int vrf_import_rt_hash_key_make(const void *p)
     130             : {
     131           0 :         const struct vrf_irt_node *irt = p;
     132           0 :         const char *pnt = irt->rt.val;
     133             : 
     134           0 :         return jhash(pnt, 8, 0x5abc1234);
     135             : }
     136             : 
     137             : /*
     138             :  * Comparison function for vrf import rt hash
     139             :  */
     140           0 : static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2)
     141             : {
     142           0 :         const struct vrf_irt_node *irt1 = p1;
     143           0 :         const struct vrf_irt_node *irt2 = p2;
     144             : 
     145           0 :         return (memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0);
     146             : }
     147             : 
     148             : /*
     149             :  * Create a new vrf import_rt in evpn instance
     150             :  */
     151           0 : static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt)
     152             : {
     153           0 :         struct bgp *bgp_evpn = NULL;
     154           0 :         struct vrf_irt_node *irt;
     155             : 
     156           0 :         bgp_evpn = bgp_get_evpn();
     157           0 :         if (!bgp_evpn) {
     158           0 :                 flog_err(EC_BGP_NO_DFLT,
     159             :                          "vrf import rt new - evpn instance not created yet");
     160           0 :                 return NULL;
     161             :         }
     162             : 
     163           0 :         irt = XCALLOC(MTYPE_BGP_EVPN_VRF_IMPORT_RT,
     164             :                       sizeof(struct vrf_irt_node));
     165             : 
     166           0 :         irt->rt = *rt;
     167           0 :         irt->vrfs = list_new();
     168             : 
     169             :         /* Add to hash */
     170           0 :         (void)hash_get(bgp_evpn->vrf_import_rt_hash, irt, hash_alloc_intern);
     171             : 
     172           0 :         return irt;
     173             : }
     174             : 
     175             : /*
     176             :  * Free the vrf import rt node
     177             :  */
     178           0 : static void vrf_import_rt_free(struct vrf_irt_node *irt)
     179             : {
     180           0 :         struct bgp *bgp_evpn = NULL;
     181             : 
     182           0 :         bgp_evpn = bgp_get_evpn();
     183           0 :         if (!bgp_evpn) {
     184           0 :                 flog_err(EC_BGP_NO_DFLT,
     185             :                          "vrf import rt free - evpn instance not created yet");
     186           0 :                 return;
     187             :         }
     188             : 
     189           0 :         hash_release(bgp_evpn->vrf_import_rt_hash, irt);
     190           0 :         list_delete(&irt->vrfs);
     191           0 :         XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
     192             : }
     193             : 
     194           0 : static void hash_vrf_import_rt_free(struct vrf_irt_node *irt)
     195             : {
     196           0 :         XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
     197           0 : }
     198             : 
     199             : /*
     200             :  * Function to lookup Import RT node - used to map a RT to set of
     201             :  * VNIs importing routes with that RT.
     202             :  */
     203           0 : static struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt)
     204             : {
     205           0 :         struct bgp *bgp_evpn = NULL;
     206           0 :         struct vrf_irt_node *irt;
     207           0 :         struct vrf_irt_node tmp;
     208             : 
     209           0 :         bgp_evpn = bgp_get_evpn();
     210           0 :         if (!bgp_evpn) {
     211           0 :                 flog_err(
     212             :                         EC_BGP_NO_DFLT,
     213             :                         "vrf import rt lookup - evpn instance not created yet");
     214           0 :                 return NULL;
     215             :         }
     216             : 
     217           0 :         memset(&tmp, 0, sizeof(tmp));
     218           0 :         memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE);
     219           0 :         irt = hash_lookup(bgp_evpn->vrf_import_rt_hash, &tmp);
     220           0 :         return irt;
     221             : }
     222             : 
     223             : /*
     224             :  * Is specified VRF present on the RT's list of "importing" VRFs?
     225             :  */
     226           0 : static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf)
     227             : {
     228           0 :         struct listnode *node = NULL, *nnode = NULL;
     229           0 :         struct bgp *tmp_bgp_vrf = NULL;
     230             : 
     231           0 :         for (ALL_LIST_ELEMENTS(vrfs, node, nnode, tmp_bgp_vrf)) {
     232           0 :                 if (tmp_bgp_vrf == bgp_vrf)
     233             :                         return 1;
     234             :         }
     235             :         return 0;
     236             : }
     237             : 
     238             : /*
     239             :  * Make import route target hash key.
     240             :  */
     241           0 : static unsigned int import_rt_hash_key_make(const void *p)
     242             : {
     243           0 :         const struct irt_node *irt = p;
     244           0 :         const char *pnt = irt->rt.val;
     245             : 
     246           0 :         return jhash(pnt, 8, 0xdeadbeef);
     247             : }
     248             : 
     249             : /*
     250             :  * Comparison function for import rt hash
     251             :  */
     252           0 : static bool import_rt_hash_cmp(const void *p1, const void *p2)
     253             : {
     254           0 :         const struct irt_node *irt1 = p1;
     255           0 :         const struct irt_node *irt2 = p2;
     256             : 
     257           0 :         return (memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0);
     258             : }
     259             : 
     260             : /*
     261             :  * Create a new import_rt
     262             :  */
     263           0 : static struct irt_node *import_rt_new(struct bgp *bgp,
     264             :                                       struct ecommunity_val *rt)
     265             : {
     266           0 :         struct irt_node *irt;
     267             : 
     268           0 :         irt = XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT, sizeof(struct irt_node));
     269             : 
     270           0 :         irt->rt = *rt;
     271           0 :         irt->vnis = list_new();
     272             : 
     273             :         /* Add to hash */
     274           0 :         (void)hash_get(bgp->import_rt_hash, irt, hash_alloc_intern);
     275             : 
     276           0 :         return irt;
     277             : }
     278             : 
     279             : /*
     280             :  * Free the import rt node
     281             :  */
     282           0 : static void import_rt_free(struct bgp *bgp, struct irt_node *irt)
     283             : {
     284           0 :         hash_release(bgp->import_rt_hash, irt);
     285           0 :         list_delete(&irt->vnis);
     286           0 :         XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt);
     287           0 : }
     288             : 
     289           0 : static void hash_import_rt_free(struct irt_node *irt)
     290             : {
     291           0 :         XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt);
     292           0 : }
     293             : 
     294             : /*
     295             :  * Function to lookup Import RT node - used to map a RT to set of
     296             :  * VNIs importing routes with that RT.
     297             :  */
     298           0 : static struct irt_node *lookup_import_rt(struct bgp *bgp,
     299             :                                          struct ecommunity_val *rt)
     300             : {
     301           0 :         struct irt_node *irt;
     302           0 :         struct irt_node tmp;
     303             : 
     304           0 :         memset(&tmp, 0, sizeof(tmp));
     305           0 :         memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE);
     306           0 :         irt = hash_lookup(bgp->import_rt_hash, &tmp);
     307           0 :         return irt;
     308             : }
     309             : 
     310             : /*
     311             :  * Is specified VNI present on the RT's list of "importing" VNIs?
     312             :  */
     313           0 : static int is_vni_present_in_irt_vnis(struct list *vnis, struct bgpevpn *vpn)
     314             : {
     315           0 :         struct listnode *node, *nnode;
     316           0 :         struct bgpevpn *tmp_vpn;
     317             : 
     318           0 :         for (ALL_LIST_ELEMENTS(vnis, node, nnode, tmp_vpn)) {
     319           0 :                 if (tmp_vpn == vpn)
     320             :                         return 1;
     321             :         }
     322             : 
     323             :         return 0;
     324             : }
     325             : 
     326             : /*
     327             :  * Compare Route Targets.
     328             :  */
     329           0 : int bgp_evpn_route_target_cmp(struct ecommunity *ecom1,
     330             :                               struct ecommunity *ecom2)
     331             : {
     332           0 :         if (ecom1 && !ecom2)
     333             :                 return -1;
     334             : 
     335           0 :         if (!ecom1 && ecom2)
     336             :                 return 1;
     337             : 
     338           0 :         if (!ecom1 && !ecom2)
     339             :                 return 0;
     340             : 
     341           0 :         if (ecom1->str && !ecom2->str)
     342             :                 return -1;
     343             : 
     344           0 :         if (!ecom1->str && ecom2->str)
     345             :                 return 1;
     346             : 
     347           0 :         if (!ecom1->str && !ecom2->str)
     348             :                 return 0;
     349             : 
     350           0 :         return strcmp(ecom1->str, ecom2->str);
     351             : }
     352             : 
     353             : /*
     354             :  * Compare L3 Route Targets.
     355             :  */
     356           0 : static int evpn_vrf_route_target_cmp(struct vrf_route_target *rt1,
     357             :                                      struct vrf_route_target *rt2)
     358             : {
     359           0 :         return bgp_evpn_route_target_cmp(rt1->ecom, rt2->ecom);
     360             : }
     361             : 
     362           0 : void bgp_evpn_xxport_delete_ecomm(void *val)
     363             : {
     364           0 :         struct ecommunity *ecomm = val;
     365           0 :         ecommunity_free(&ecomm);
     366           0 : }
     367             : 
     368             : /*
     369             :  * Delete l3 Route Target.
     370             :  */
     371           0 : static void evpn_vrf_rt_del(void *val)
     372             : {
     373           0 :         struct vrf_route_target *l3rt = val;
     374             : 
     375           0 :         ecommunity_free(&l3rt->ecom);
     376             : 
     377           0 :         XFREE(MTYPE_VRF_ROUTE_TARGET, l3rt);
     378           0 : }
     379             : 
     380             : /*
     381             :  * Allocate a new l3 Route Target.
     382             :  */
     383           0 : static struct vrf_route_target *evpn_vrf_rt_new(struct ecommunity *ecom)
     384             : {
     385           0 :         struct vrf_route_target *l3rt;
     386             : 
     387           0 :         l3rt = XCALLOC(MTYPE_VRF_ROUTE_TARGET, sizeof(struct vrf_route_target));
     388             : 
     389           0 :         l3rt->ecom = ecom;
     390             : 
     391           0 :         return l3rt;
     392             : }
     393             : 
     394             : /*
     395             :  * Mask off global-admin field of specified extended community (RT),
     396             :  * just retain the local-admin field.
     397             :  */
     398           0 : static inline void mask_ecom_global_admin(struct ecommunity_val *dst,
     399             :                                           const struct ecommunity_val *src)
     400             : {
     401           0 :         uint8_t type;
     402             : 
     403           0 :         type = src->val[0];
     404           0 :         dst->val[0] = 0;
     405           0 :         if (type == ECOMMUNITY_ENCODE_AS) {
     406           0 :                 dst->val[2] = dst->val[3] = 0;
     407           0 :         } else if (type == ECOMMUNITY_ENCODE_AS4
     408           0 :                    || type == ECOMMUNITY_ENCODE_IP) {
     409           0 :                 dst->val[2] = dst->val[3] = 0;
     410           0 :                 dst->val[4] = dst->val[5] = 0;
     411             :         }
     412             : }
     413             : 
     414             : /*
     415             :  * Converts the RT to Ecommunity Value and adjusts masking based
     416             :  * on flags set for RT.
     417             :  */
     418           0 : static void vrf_rt2ecom_val(struct ecommunity_val *to_eval,
     419             :                             const struct vrf_route_target *l3rt, int iter)
     420             : {
     421           0 :         const struct ecommunity_val *eval;
     422             : 
     423           0 :         eval = (const struct ecommunity_val *)(l3rt->ecom->val +
     424           0 :                                                (iter * ECOMMUNITY_SIZE));
     425             :         /* If using "automatic" or "wildcard *" RT,
     426             :          * we only care about the local-admin sub-field.
     427             :          * This is to facilitate using L3VNI(VRF-VNI)
     428             :          * as the RT for EBGP peering too and simplify
     429             :          * configurations by allowing any ASN via '*'.
     430             :          */
     431           0 :         memcpy(to_eval, eval, ECOMMUNITY_SIZE);
     432             : 
     433           0 :         if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO) ||
     434             :             CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD))
     435           0 :                 mask_ecom_global_admin(to_eval, eval);
     436           0 : }
     437             : 
     438             : /*
     439             :  * Map one RT to specified VRF.
     440             :  * bgp_vrf = BGP vrf instance
     441             :  */
     442           0 : static void map_vrf_to_rt(struct bgp *bgp_vrf, struct vrf_route_target *l3rt)
     443             : {
     444           0 :         uint32_t i = 0;
     445             : 
     446           0 :         for (i = 0; i < l3rt->ecom->size; i++) {
     447           0 :                 struct vrf_irt_node *irt = NULL;
     448           0 :                 struct ecommunity_val eval_tmp;
     449             : 
     450             :                 /* Adjust masking for value */
     451           0 :                 vrf_rt2ecom_val(&eval_tmp, l3rt, i);
     452             : 
     453           0 :                 irt = lookup_vrf_import_rt(&eval_tmp);
     454             : 
     455           0 :                 if (irt && is_vrf_present_in_irt_vrfs(irt->vrfs, bgp_vrf))
     456           0 :                         return; /* Already mapped. */
     457             : 
     458           0 :                 if (!irt)
     459           0 :                         irt = vrf_import_rt_new(&eval_tmp);
     460             : 
     461             :                 /* Add VRF to the list for this RT. */
     462           0 :                 listnode_add(irt->vrfs, bgp_vrf);
     463             :         }
     464             : }
     465             : 
     466             : /*
     467             :  * Unmap specified VRF from specified RT. If there are no other
     468             :  * VRFs for this RT, then the RT hash is deleted.
     469             :  * bgp_vrf: BGP VRF specific instance
     470             :  */
     471           0 : static void unmap_vrf_from_rt(struct bgp *bgp_vrf,
     472             :                               struct vrf_route_target *l3rt)
     473             : {
     474           0 :         uint32_t i;
     475             : 
     476           0 :         for (i = 0; i < l3rt->ecom->size; i++) {
     477           0 :                 struct vrf_irt_node *irt;
     478           0 :                 struct ecommunity_val eval_tmp;
     479             : 
     480             :                 /* Adjust masking for value */
     481           0 :                 vrf_rt2ecom_val(&eval_tmp, l3rt, i);
     482             : 
     483           0 :                 irt = lookup_vrf_import_rt(&eval_tmp);
     484             : 
     485           0 :                 if (!irt)
     486           0 :                         return; /* Not mapped */
     487             : 
     488             :                 /* Delete VRF from list for this RT. */
     489           0 :                 listnode_delete(irt->vrfs, bgp_vrf);
     490             : 
     491           0 :                 if (!listnode_head(irt->vrfs))
     492           0 :                         vrf_import_rt_free(irt);
     493             :         }
     494             : }
     495             : 
     496             : /*
     497             :  * Map one RT to specified VNI.
     498             :  */
     499           0 : static void map_vni_to_rt(struct bgp *bgp, struct bgpevpn *vpn,
     500             :                           struct ecommunity_val *eval)
     501             : {
     502           0 :         struct irt_node *irt;
     503           0 :         struct ecommunity_val eval_tmp;
     504             : 
     505             :         /* If using "automatic" RT, we only care about the local-admin
     506             :          * sub-field.
     507             :          * This is to facilitate using VNI as the RT for EBGP peering too.
     508             :          */
     509           0 :         memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE);
     510           0 :         if (!is_import_rt_configured(vpn))
     511           0 :                 mask_ecom_global_admin(&eval_tmp, eval);
     512             : 
     513           0 :         irt = lookup_import_rt(bgp, &eval_tmp);
     514           0 :         if (irt)
     515           0 :                 if (is_vni_present_in_irt_vnis(irt->vnis, vpn))
     516             :                         /* Already mapped. */
     517           0 :                         return;
     518             : 
     519           0 :         if (!irt)
     520           0 :                 irt = import_rt_new(bgp, &eval_tmp);
     521             : 
     522             :         /* Add VNI to the hash list for this RT. */
     523           0 :         listnode_add(irt->vnis, vpn);
     524             : }
     525             : 
     526             : /*
     527             :  * Unmap specified VNI from specified RT. If there are no other
     528             :  * VNIs for this RT, then the RT hash is deleted.
     529             :  */
     530           0 : static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn,
     531             :                               struct irt_node *irt)
     532             : {
     533             :         /* Delete VNI from hash list for this RT. */
     534           0 :         listnode_delete(irt->vnis, vpn);
     535           0 :         if (!listnode_head(irt->vnis)) {
     536           0 :                 import_rt_free(bgp, irt);
     537             :         }
     538           0 : }
     539             : 
     540           0 : static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn,
     541             :                                       const struct prefix_evpn *p,
     542             :                                       struct attr *attr, uint8_t flags)
     543             : {
     544           0 :         struct bgp *bgp_vrf = vpn->bgp_vrf;
     545             : 
     546           0 :         memset(&attr->rmac, 0, sizeof(struct ethaddr));
     547           0 :         if (!bgp_vrf)
     548             :                 return;
     549             : 
     550           0 :         if (p->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
     551             :                 return;
     552             : 
     553             :         /* Copy sys (pip) RMAC and PIP IP as nexthop
     554             :          * in case of route is self MAC-IP,
     555             :          * advertise-pip and advertise-svi-ip features
     556             :          * are enabled.
     557             :          * Otherwise, for all host MAC-IP route's
     558             :          * copy anycast RMAC.
     559             :          */
     560           0 :         if (CHECK_FLAG(flags, BGP_EVPN_MACIP_TYPE_SVI_IP)
     561           0 :             && bgp_vrf->evpn_info->advertise_pip &&
     562           0 :             bgp_vrf->evpn_info->is_anycast_mac) {
     563             :                 /* copy sys rmac */
     564           0 :                 memcpy(&attr->rmac, &bgp_vrf->evpn_info->pip_rmac,
     565             :                        ETH_ALEN);
     566           0 :                 attr->nexthop = bgp_vrf->evpn_info->pip_ip;
     567           0 :                 attr->mp_nexthop_global_in =
     568             :                         bgp_vrf->evpn_info->pip_ip;
     569             :         } else
     570           0 :                 memcpy(&attr->rmac, &bgp_vrf->rmac, ETH_ALEN);
     571             : }
     572             : 
     573             : /*
     574             :  * Create RT extended community automatically from passed information:
     575             :  * of the form AS:VNI.
     576             :  * NOTE: We use only the lower 16 bits of the AS. This is sufficient as
     577             :  * the need is to get a RT value that will be unique across different
     578             :  * VNIs but the same across routers (in the same AS) for a particular
     579             :  * VNI.
     580             :  */
     581           0 : static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl,
     582             :                          bool is_l3)
     583             : {
     584           0 :         struct ecommunity_val eval;
     585           0 :         struct ecommunity *ecomadd;
     586           0 :         struct ecommunity *ecom;
     587           0 :         struct vrf_route_target *l3rt;
     588           0 :         struct vrf_route_target *newrt;
     589           0 :         bool ecom_found = false;
     590           0 :         struct listnode *node;
     591             : 
     592           0 :         if (bgp->advertise_autort_rfc8365)
     593           0 :                 vni |= EVPN_AUTORT_VXLAN;
     594           0 :         encode_route_target_as((bgp->as & 0xFFFF), vni, &eval);
     595             : 
     596           0 :         ecomadd = ecommunity_new();
     597           0 :         ecommunity_add_val(ecomadd, &eval, false, false);
     598             : 
     599           0 :         if (is_l3) {
     600           0 :                 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt))
     601           0 :                         if (ecommunity_cmp(ecomadd, l3rt->ecom)) {
     602             :                                 ecom_found = true;
     603             :                                 break;
     604             :                         }
     605             :         } else {
     606           0 :                 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom))
     607           0 :                         if (ecommunity_cmp(ecomadd, ecom)) {
     608             :                                 ecom_found = true;
     609             :                                 break;
     610             :                         }
     611             :         }
     612             : 
     613           0 :         if (!ecom_found) {
     614           0 :                 if (is_l3) {
     615           0 :                         newrt = evpn_vrf_rt_new(ecomadd);
     616             :                         /* Label it as autoderived */
     617           0 :                         SET_FLAG(newrt->flags, BGP_VRF_RT_AUTO);
     618           0 :                         listnode_add_sort(rtl, newrt);
     619             :                 } else
     620           0 :                         listnode_add_sort(rtl, ecomadd);
     621             :         } else
     622           0 :                 ecommunity_free(&ecomadd);
     623           0 : }
     624             : 
     625             : /*
     626             :  * Derive RD and RT for a VNI automatically. Invoked at the time of
     627             :  * creation of a VNI.
     628             :  */
     629           0 : static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
     630             : {
     631           0 :         bgp_evpn_derive_auto_rd(bgp, vpn);
     632           0 :         bgp_evpn_derive_auto_rt_import(bgp, vpn);
     633           0 :         bgp_evpn_derive_auto_rt_export(bgp, vpn);
     634           0 : }
     635             : 
     636             : /*
     637             :  * Convert nexthop (remote VTEP IP) into an IPv6 address.
     638             :  */
     639           0 : static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
     640             : {
     641           0 :         if (BGP_ATTR_NEXTHOP_AFI_IP6(attr))
     642             :                 return;
     643           0 :         ipv4_to_ipv4_mapped_ipv6(&attr->mp_nexthop_global, attr->nexthop);
     644           0 :         attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
     645             : }
     646             : 
     647             : /*
     648             :  * Wrapper for node get in global table.
     649             :  */
     650           0 : struct bgp_dest *bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi,
     651             :                                           safi_t safi,
     652             :                                           const struct prefix_evpn *evp,
     653             :                                           struct prefix_rd *prd,
     654             :                                           const struct bgp_path_info *local_pi)
     655             : {
     656           0 :         struct prefix_evpn global_p;
     657             : 
     658           0 :         if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
     659             :                 /* prefix in the global table doesn't include the VTEP-IP so
     660             :                  * we need to create a different copy of the prefix
     661             :                  */
     662           0 :                 evpn_type1_prefix_global_copy(&global_p, evp);
     663           0 :                 evp = &global_p;
     664           0 :         } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
     665             :                    local_pi) {
     666             :                 /*
     667             :                  * prefix in the global table needs MAC/IP, ensure they are
     668             :                  * present, using one's from local table's path_info.
     669             :                  */
     670           0 :                 if (is_evpn_prefix_ipaddr_none(evp)) {
     671             :                         /* VNI MAC -> Global */
     672           0 :                         evpn_type2_prefix_global_copy(
     673             :                                 &global_p, evp, NULL /* mac */,
     674           0 :                                 evpn_type2_path_info_get_ip(local_pi));
     675             :                 } else {
     676             :                         /* VNI IP -> Global */
     677           0 :                         evpn_type2_prefix_global_copy(
     678             :                                 &global_p, evp,
     679           0 :                                 evpn_type2_path_info_get_mac(local_pi),
     680             :                                 NULL /* ip */);
     681             :                 }
     682             : 
     683             :                 evp = &global_p;
     684             :         }
     685           0 :         return bgp_afi_node_get(table, afi, safi, (struct prefix *)evp, prd);
     686             : }
     687             : 
     688             : /*
     689             :  * Wrapper for node lookup in global table.
     690             :  */
     691             : struct bgp_dest *
     692           0 : bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
     693             :                             const struct prefix_evpn *evp,
     694             :                             struct prefix_rd *prd,
     695             :                             const struct bgp_path_info *local_pi)
     696             : {
     697           0 :         struct prefix_evpn global_p;
     698             : 
     699           0 :         if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
     700             :                 /* prefix in the global table doesn't include the VTEP-IP so
     701             :                  * we need to create a different copy of the prefix
     702             :                  */
     703           0 :                 evpn_type1_prefix_global_copy(&global_p, evp);
     704           0 :                 evp = &global_p;
     705           0 :         } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
     706             :                    local_pi) {
     707             :                 /*
     708             :                  * prefix in the global table needs MAC/IP, ensure they are
     709             :                  * present, using one's from local table's path_info.
     710             :                  */
     711           0 :                 if (is_evpn_prefix_ipaddr_none(evp)) {
     712             :                         /* VNI MAC -> Global */
     713           0 :                         evpn_type2_prefix_global_copy(
     714             :                                 &global_p, evp, NULL /* mac */,
     715           0 :                                 evpn_type2_path_info_get_ip(local_pi));
     716             :                 } else {
     717             :                         /* VNI IP -> Global */
     718           0 :                         evpn_type2_prefix_global_copy(
     719             :                                 &global_p, evp,
     720           0 :                                 evpn_type2_path_info_get_mac(local_pi),
     721             :                                 NULL /* ip */);
     722             :                 }
     723             : 
     724             :                 evp = &global_p;
     725             :         }
     726           0 :         return bgp_afi_node_lookup(table, afi, safi, (struct prefix *)evp, prd);
     727             : }
     728             : 
     729             : /*
     730             :  * Wrapper for node get in VNI IP table.
     731             :  */
     732           0 : struct bgp_dest *bgp_evpn_vni_ip_node_get(struct bgp_table *const table,
     733             :                                           const struct prefix_evpn *evp,
     734             :                                           const struct bgp_path_info *parent_pi)
     735             : {
     736           0 :         struct prefix_evpn vni_p;
     737             : 
     738           0 :         if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE && parent_pi) {
     739             :                 /* prefix in the global table doesn't include the VTEP-IP so
     740             :                  * we need to create a different copy for the VNI
     741             :                  */
     742           0 :                 evpn_type1_prefix_vni_ip_copy(&vni_p, evp,
     743           0 :                                               parent_pi->attr->nexthop);
     744           0 :                 evp = &vni_p;
     745           0 :         } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
     746             :                 /* Only MAC-IP should go into this table, not mac-only */
     747           0 :                 assert(is_evpn_prefix_ipaddr_none(evp) == false);
     748             : 
     749             :                 /*
     750             :                  * prefix in the vni IP table doesn't include MAC so
     751             :                  * we need to create a different copy of the prefix.
     752             :                  */
     753           0 :                 evpn_type2_prefix_vni_ip_copy(&vni_p, evp);
     754           0 :                 evp = &vni_p;
     755             :         }
     756           0 :         return bgp_node_get(table, (struct prefix *)evp);
     757             : }
     758             : 
     759             : /*
     760             :  * Wrapper for node lookup in VNI IP table.
     761             :  */
     762             : struct bgp_dest *
     763           0 : bgp_evpn_vni_ip_node_lookup(const struct bgp_table *const table,
     764             :                             const struct prefix_evpn *evp,
     765             :                             const struct bgp_path_info *parent_pi)
     766             : {
     767           0 :         struct prefix_evpn vni_p;
     768             : 
     769           0 :         if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE && parent_pi) {
     770             :                 /* prefix in the global table doesn't include the VTEP-IP so
     771             :                  * we need to create a different copy for the VNI
     772             :                  */
     773           0 :                 evpn_type1_prefix_vni_ip_copy(&vni_p, evp,
     774           0 :                                               parent_pi->attr->nexthop);
     775           0 :                 evp = &vni_p;
     776           0 :         } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
     777             :                 /* Only MAC-IP should go into this table, not mac-only */
     778           0 :                 assert(is_evpn_prefix_ipaddr_none(evp) == false);
     779             : 
     780             :                 /*
     781             :                  * prefix in the vni IP table doesn't include MAC so
     782             :                  * we need to create a different copy of the prefix.
     783             :                  */
     784           0 :                 evpn_type2_prefix_vni_ip_copy(&vni_p, evp);
     785           0 :                 evp = &vni_p;
     786             :         }
     787           0 :         return bgp_node_lookup(table, (struct prefix *)evp);
     788             : }
     789             : 
     790             : /*
     791             :  * Wrapper for node get in VNI MAC table.
     792             :  */
     793             : struct bgp_dest *
     794           0 : bgp_evpn_vni_mac_node_get(struct bgp_table *const table,
     795             :                           const struct prefix_evpn *evp,
     796             :                           const struct bgp_path_info *parent_pi)
     797             : {
     798           0 :         struct prefix_evpn vni_p;
     799             : 
     800             :         /* Only type-2 should ever go into this table */
     801           0 :         assert(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE);
     802             : 
     803             :         /*
     804             :          * prefix in the vni MAC table doesn't include IP so
     805             :          * we need to create a different copy of the prefix.
     806             :          */
     807           0 :         evpn_type2_prefix_vni_mac_copy(&vni_p, evp);
     808           0 :         evp = &vni_p;
     809           0 :         return bgp_node_get(table, (struct prefix *)evp);
     810             : }
     811             : 
     812             : /*
     813             :  * Wrapper for node lookup in VNI MAC table.
     814             :  */
     815             : struct bgp_dest *
     816           0 : bgp_evpn_vni_mac_node_lookup(const struct bgp_table *const table,
     817             :                              const struct prefix_evpn *evp,
     818             :                              const struct bgp_path_info *parent_pi)
     819             : {
     820           0 :         struct prefix_evpn vni_p;
     821             : 
     822             :         /* Only type-2 should ever go into this table */
     823           0 :         assert(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE);
     824             : 
     825             :         /*
     826             :          * prefix in the vni MAC table doesn't include IP so
     827             :          * we need to create a different copy of the prefix.
     828             :          */
     829           0 :         evpn_type2_prefix_vni_mac_copy(&vni_p, evp);
     830           0 :         evp = &vni_p;
     831           0 :         return bgp_node_lookup(table, (struct prefix *)evp);
     832             : }
     833             : 
     834             : /*
     835             :  * Wrapper for node get in both VNI tables.
     836             :  */
     837           0 : struct bgp_dest *bgp_evpn_vni_node_get(struct bgpevpn *vpn,
     838             :                                        const struct prefix_evpn *p,
     839             :                                        const struct bgp_path_info *parent_pi)
     840             : {
     841           0 :         if ((p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) &&
     842           0 :             (is_evpn_prefix_ipaddr_none(p) == true))
     843           0 :                 return bgp_evpn_vni_mac_node_get(vpn->mac_table, p, parent_pi);
     844             : 
     845           0 :         return bgp_evpn_vni_ip_node_get(vpn->ip_table, p, parent_pi);
     846             : }
     847             : 
     848             : /*
     849             :  * Wrapper for node lookup in both VNI tables.
     850             :  */
     851           0 : struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn,
     852             :                                           const struct prefix_evpn *p,
     853             :                                           const struct bgp_path_info *parent_pi)
     854             : {
     855           0 :         if ((p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) &&
     856           0 :             (is_evpn_prefix_ipaddr_none(p) == true))
     857           0 :                 return bgp_evpn_vni_mac_node_lookup(vpn->mac_table, p,
     858             :                                                     parent_pi);
     859             : 
     860           0 :         return bgp_evpn_vni_ip_node_lookup(vpn->ip_table, p, parent_pi);
     861             : }
     862             : 
     863             : /*
     864             :  * Add (update) or delete MACIP from zebra.
     865             :  */
     866           0 : static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
     867             :                                        const struct prefix_evpn *p,
     868             :                                        const struct ethaddr *mac,
     869             :                                        struct in_addr remote_vtep_ip, int add,
     870             :                                        uint8_t flags, uint32_t seq, esi_t *esi)
     871             : {
     872           0 :         struct stream *s;
     873           0 :         uint16_t ipa_len;
     874           0 :         static struct in_addr zero_remote_vtep_ip;
     875           0 :         bool esi_valid;
     876             : 
     877             :         /* Check socket. */
     878           0 :         if (!zclient || zclient->sock < 0)
     879             :                 return 0;
     880             : 
     881             :         /* Don't try to register if Zebra doesn't know of this instance. */
     882           0 :         if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
     883           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
     884           0 :                         zlog_debug(
     885             :                                 "%s: No zebra instance to talk to, not installing remote macip",
     886             :                                 __func__);
     887           0 :                 return 0;
     888             :         }
     889             : 
     890           0 :         if (!esi)
     891           0 :                 esi = zero_esi;
     892           0 :         s = zclient->obuf;
     893           0 :         stream_reset(s);
     894             : 
     895           0 :         zclient_create_header(
     896             :                 s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
     897             :                 bgp->vrf_id);
     898           0 :         stream_putl(s, vpn->vni);
     899             : 
     900           0 :         if (mac) /* Mac Addr */
     901           0 :                 stream_put(s, &mac->octet, ETH_ALEN);
     902             :         else
     903           0 :                 stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN);
     904             : 
     905             :         /* IP address length and IP address, if any. */
     906           0 :         if (is_evpn_prefix_ipaddr_none(p))
     907           0 :                 stream_putw(s, 0);
     908             :         else {
     909           0 :                 ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN
     910             :                                                       : IPV6_MAX_BYTELEN;
     911           0 :                 stream_putw(s, ipa_len);
     912           0 :                 stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len);
     913             :         }
     914             :         /* If the ESI is valid that becomes the nexthop; tape out the
     915             :          * VTEP-IP for that case
     916             :          */
     917           0 :         if (bgp_evpn_is_esi_valid(esi)) {
     918           0 :                 esi_valid = true;
     919           0 :                 stream_put_in_addr(s, &zero_remote_vtep_ip);
     920             :         } else {
     921           0 :                 esi_valid = false;
     922           0 :                 stream_put_in_addr(s, &remote_vtep_ip);
     923             :         }
     924             : 
     925             :         /* TX flags - MAC sticky status and/or gateway mac */
     926             :         /* Also TX the sequence number of the best route. */
     927           0 :         if (add) {
     928           0 :                 stream_putc(s, flags);
     929           0 :                 stream_putl(s, seq);
     930           0 :                 stream_put(s, esi, sizeof(esi_t));
     931             :         }
     932             : 
     933           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     934             : 
     935           0 :         if (bgp_debug_zebra(NULL)) {
     936           0 :                 char esi_buf[ESI_STR_LEN];
     937             : 
     938           0 :                 if (esi_valid)
     939           0 :                         esi_to_str(esi, esi_buf, sizeof(esi_buf));
     940             :                 else
     941           0 :                         snprintf(esi_buf, sizeof(esi_buf), "-");
     942           0 :                 zlog_debug(
     943             :                         "Tx %s MACIP, VNI %u MAC %pEA IP %pIA flags 0x%x seq %u remote VTEP %pI4 esi %s",
     944             :                         add ? "ADD" : "DEL", vpn->vni,
     945             :                         (mac ? mac : &p->prefix.macip_addr.mac),
     946             :                         &p->prefix.macip_addr.ip, flags, seq, &remote_vtep_ip,
     947             :                         esi_buf);
     948             :         }
     949             : 
     950           0 :         frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip,
     951             :                  esi);
     952             : 
     953           0 :         return zclient_send_message(zclient);
     954             : }
     955             : 
     956             : /*
     957             :  * Add (update) or delete remote VTEP from zebra.
     958             :  */
     959           0 : static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
     960             :                                       const struct prefix_evpn *p,
     961             :                                       int flood_control, int add)
     962             : {
     963           0 :         struct stream *s;
     964             : 
     965             :         /* Check socket. */
     966           0 :         if (!zclient || zclient->sock < 0)
     967             :                 return 0;
     968             : 
     969             :         /* Don't try to register if Zebra doesn't know of this instance. */
     970           0 :         if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
     971           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
     972           0 :                         zlog_debug(
     973             :                                 "%s: No zebra instance to talk to, not installing remote vtep",
     974             :                                 __func__);
     975           0 :                 return 0;
     976             :         }
     977             : 
     978           0 :         s = zclient->obuf;
     979           0 :         stream_reset(s);
     980             : 
     981           0 :         zclient_create_header(
     982             :                 s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
     983             :                 bgp->vrf_id);
     984           0 :         stream_putl(s, vpn->vni);
     985           0 :         if (is_evpn_prefix_ipaddr_v4(p))
     986           0 :                 stream_put_in_addr(s, &p->prefix.imet_addr.ip.ipaddr_v4);
     987           0 :         else if (is_evpn_prefix_ipaddr_v6(p)) {
     988           0 :                 flog_err(
     989             :                         EC_BGP_VTEP_INVALID,
     990             :                         "Bad remote IP when trying to %s remote VTEP for VNI %u",
     991             :                         add ? "ADD" : "DEL", vpn->vni);
     992           0 :                 return -1;
     993             :         }
     994           0 :         stream_putl(s, flood_control);
     995             : 
     996           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     997             : 
     998           0 :         if (bgp_debug_zebra(NULL))
     999           0 :                 zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %pI4",
    1000             :                            add ? "ADD" : "DEL", vpn->vni,
    1001             :                            &p->prefix.imet_addr.ip.ipaddr_v4);
    1002             : 
    1003           0 :         frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
    1004             : 
    1005           0 :         return zclient_send_message(zclient);
    1006             : }
    1007             : 
    1008             : /*
    1009             :  * Build extended communities for EVPN prefix route.
    1010             :  */
    1011           0 : static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf,
    1012             :                                            struct attr *attr)
    1013             : {
    1014           0 :         struct ecommunity ecom_encap;
    1015           0 :         struct ecommunity_val eval;
    1016           0 :         struct ecommunity_val eval_rmac;
    1017           0 :         bgp_encap_types tnl_type;
    1018           0 :         struct listnode *node, *nnode;
    1019           0 :         struct vrf_route_target *l3rt;
    1020           0 :         struct ecommunity *old_ecom;
    1021           0 :         struct ecommunity *ecom;
    1022           0 :         struct list *vrf_export_rtl = NULL;
    1023             : 
    1024             :         /* Encap */
    1025           0 :         tnl_type = BGP_ENCAP_TYPE_VXLAN;
    1026           0 :         memset(&ecom_encap, 0, sizeof(ecom_encap));
    1027           0 :         encode_encap_extcomm(tnl_type, &eval);
    1028           0 :         ecom_encap.size = 1;
    1029           0 :         ecom_encap.unit_size = ECOMMUNITY_SIZE;
    1030           0 :         ecom_encap.val = (uint8_t *)eval.val;
    1031             : 
    1032             :         /* Add Encap */
    1033           0 :         if (bgp_attr_get_ecommunity(attr)) {
    1034           0 :                 old_ecom = bgp_attr_get_ecommunity(attr);
    1035           0 :                 ecom = ecommunity_merge(ecommunity_dup(old_ecom), &ecom_encap);
    1036           0 :                 if (!old_ecom->refcnt)
    1037           0 :                         ecommunity_free(&old_ecom);
    1038             :         } else
    1039           0 :                 ecom = ecommunity_dup(&ecom_encap);
    1040           0 :         bgp_attr_set_ecommunity(attr, ecom);
    1041           0 :         attr->encap_tunneltype = tnl_type;
    1042             : 
    1043             :         /* Add the export RTs for L3VNI/VRF */
    1044           0 :         vrf_export_rtl = bgp_vrf->vrf_export_rtl;
    1045           0 :         for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode, l3rt))
    1046           0 :                 bgp_attr_set_ecommunity(
    1047             :                         attr, ecommunity_merge(bgp_attr_get_ecommunity(attr),
    1048             :                                                l3rt->ecom));
    1049             : 
    1050             :         /* add the router mac extended community */
    1051           0 :         if (!is_zero_mac(&attr->rmac)) {
    1052           0 :                 encode_rmac_extcomm(&eval_rmac, &attr->rmac);
    1053           0 :                 ecommunity_add_val(bgp_attr_get_ecommunity(attr), &eval_rmac,
    1054             :                                    true, true);
    1055             :         }
    1056           0 : }
    1057             : 
    1058             : /*
    1059             :  * Build extended communities for EVPN route.
    1060             :  * This function is applicable for type-2 and type-3 routes. The layer-2 RT
    1061             :  * and ENCAP extended communities are applicable for all routes.
    1062             :  * The default gateway extended community and MAC mobility (sticky) extended
    1063             :  * community are added as needed based on passed settings - only for type-2
    1064             :  * routes. Likewise, the layer-3 RT and Router MAC extended communities are
    1065             :  * added, if present, based on passed settings - only for non-link-local
    1066             :  * type-2 routes.
    1067             :  */
    1068           0 : static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
    1069             :                                      int add_l3_ecomm)
    1070             : {
    1071           0 :         struct ecommunity ecom_encap;
    1072           0 :         struct ecommunity ecom_sticky;
    1073           0 :         struct ecommunity ecom_default_gw;
    1074           0 :         struct ecommunity ecom_na;
    1075           0 :         struct ecommunity_val eval;
    1076           0 :         struct ecommunity_val eval_sticky;
    1077           0 :         struct ecommunity_val eval_default_gw;
    1078           0 :         struct ecommunity_val eval_rmac;
    1079           0 :         struct ecommunity_val eval_na;
    1080           0 :         bool proxy;
    1081             : 
    1082           0 :         bgp_encap_types tnl_type;
    1083           0 :         struct listnode *node, *nnode;
    1084           0 :         struct ecommunity *ecom;
    1085           0 :         struct vrf_route_target *l3rt;
    1086           0 :         uint32_t seqnum;
    1087           0 :         struct list *vrf_export_rtl = NULL;
    1088             : 
    1089             :         /* Encap */
    1090           0 :         tnl_type = BGP_ENCAP_TYPE_VXLAN;
    1091           0 :         memset(&ecom_encap, 0, sizeof(ecom_encap));
    1092           0 :         encode_encap_extcomm(tnl_type, &eval);
    1093           0 :         ecom_encap.size = 1;
    1094           0 :         ecom_encap.unit_size = ECOMMUNITY_SIZE;
    1095           0 :         ecom_encap.val = (uint8_t *)eval.val;
    1096             : 
    1097             :         /* Add Encap */
    1098           0 :         bgp_attr_set_ecommunity(attr, ecommunity_dup(&ecom_encap));
    1099           0 :         attr->encap_tunneltype = tnl_type;
    1100             : 
    1101             :         /* Add the export RTs for L2VNI */
    1102           0 :         for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
    1103           0 :                 bgp_attr_set_ecommunity(
    1104             :                         attr,
    1105             :                         ecommunity_merge(bgp_attr_get_ecommunity(attr), ecom));
    1106             : 
    1107             :         /* Add the export RTs for L3VNI if told to - caller determines
    1108             :          * when this should be done.
    1109             :          */
    1110           0 :         if (add_l3_ecomm) {
    1111           0 :                 vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn);
    1112           0 :                 if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) {
    1113           0 :                         for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode,
    1114             :                                                l3rt))
    1115           0 :                                 bgp_attr_set_ecommunity(
    1116             :                                         attr,
    1117             :                                         ecommunity_merge(
    1118             :                                                 bgp_attr_get_ecommunity(attr),
    1119             :                                                 l3rt->ecom));
    1120             :                 }
    1121             :         }
    1122             : 
    1123             :         /* Add MAC mobility (sticky) if needed. */
    1124           0 :         if (attr->sticky) {
    1125           0 :                 seqnum = 0;
    1126           0 :                 memset(&ecom_sticky, 0, sizeof(ecom_sticky));
    1127           0 :                 encode_mac_mobility_extcomm(1, seqnum, &eval_sticky);
    1128           0 :                 ecom_sticky.size = 1;
    1129           0 :                 ecom_sticky.unit_size = ECOMMUNITY_SIZE;
    1130           0 :                 ecom_sticky.val = (uint8_t *)eval_sticky.val;
    1131           0 :                 bgp_attr_set_ecommunity(
    1132             :                         attr, ecommunity_merge(bgp_attr_get_ecommunity(attr),
    1133             :                                                &ecom_sticky));
    1134             :         }
    1135             : 
    1136             :         /* Add RMAC, if told to. */
    1137           0 :         if (add_l3_ecomm) {
    1138           0 :                 encode_rmac_extcomm(&eval_rmac, &attr->rmac);
    1139           0 :                 ecommunity_add_val(bgp_attr_get_ecommunity(attr), &eval_rmac,
    1140             :                                    true, true);
    1141             :         }
    1142             : 
    1143             :         /* Add default gateway, if needed. */
    1144           0 :         if (attr->default_gw) {
    1145           0 :                 memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
    1146           0 :                 encode_default_gw_extcomm(&eval_default_gw);
    1147           0 :                 ecom_default_gw.size = 1;
    1148           0 :                 ecom_default_gw.unit_size = ECOMMUNITY_SIZE;
    1149           0 :                 ecom_default_gw.val = (uint8_t *)eval_default_gw.val;
    1150           0 :                 bgp_attr_set_ecommunity(
    1151             :                         attr, ecommunity_merge(bgp_attr_get_ecommunity(attr),
    1152             :                                                &ecom_default_gw));
    1153             :         }
    1154             : 
    1155           0 :         proxy = !!(attr->es_flags & ATTR_ES_PROXY_ADVERT);
    1156           0 :         if (attr->router_flag || proxy) {
    1157           0 :                 memset(&ecom_na, 0, sizeof(ecom_na));
    1158           0 :                 encode_na_flag_extcomm(&eval_na, attr->router_flag, proxy);
    1159           0 :                 ecom_na.size = 1;
    1160           0 :                 ecom_na.unit_size = ECOMMUNITY_SIZE;
    1161           0 :                 ecom_na.val = (uint8_t *)eval_na.val;
    1162           0 :                 bgp_attr_set_ecommunity(
    1163             :                         attr, ecommunity_merge(bgp_attr_get_ecommunity(attr),
    1164             :                                                &ecom_na));
    1165             :         }
    1166           0 : }
    1167             : 
    1168             : /*
    1169             :  * Add MAC mobility extended community to attribute.
    1170             :  */
    1171           0 : static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
    1172             : {
    1173           0 :         struct ecommunity ecom_tmp;
    1174           0 :         struct ecommunity_val eval;
    1175           0 :         uint8_t *ecom_val_ptr;
    1176           0 :         uint32_t i;
    1177           0 :         uint8_t *pnt;
    1178           0 :         int type = 0;
    1179           0 :         int sub_type = 0;
    1180           0 :         struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
    1181             : 
    1182             :         /* Build MM */
    1183           0 :         encode_mac_mobility_extcomm(0, seq_num, &eval);
    1184             : 
    1185             :         /* Find current MM ecommunity */
    1186           0 :         ecom_val_ptr = NULL;
    1187             : 
    1188           0 :         if (ecomm) {
    1189           0 :                 for (i = 0; i < ecomm->size; i++) {
    1190           0 :                         pnt = ecomm->val + (i * ecomm->unit_size);
    1191           0 :                         type = *pnt++;
    1192           0 :                         sub_type = *pnt++;
    1193             : 
    1194           0 :                         if (type == ECOMMUNITY_ENCODE_EVPN
    1195           0 :                             && sub_type
    1196           0 :                                        == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) {
    1197             :                                 ecom_val_ptr =
    1198             :                                         (ecomm->val + (i * ecomm->unit_size));
    1199             :                                 break;
    1200             :                         }
    1201             :                 }
    1202             :         }
    1203             : 
    1204             :         /* Update the existing MM ecommunity */
    1205           0 :         if (ecom_val_ptr) {
    1206           0 :                 memcpy(ecom_val_ptr, eval.val, sizeof(char) * ecomm->unit_size);
    1207             :         }
    1208             :         /* Add MM to existing */
    1209             :         else {
    1210           0 :                 memset(&ecom_tmp, 0, sizeof(ecom_tmp));
    1211           0 :                 ecom_tmp.size = 1;
    1212           0 :                 ecom_tmp.unit_size = ECOMMUNITY_SIZE;
    1213           0 :                 ecom_tmp.val = (uint8_t *)eval.val;
    1214             : 
    1215           0 :                 if (ecomm)
    1216           0 :                         bgp_attr_set_ecommunity(
    1217             :                                 attr, ecommunity_merge(ecomm, &ecom_tmp));
    1218             :                 else
    1219           0 :                         bgp_attr_set_ecommunity(attr,
    1220             :                                                 ecommunity_dup(&ecom_tmp));
    1221             :         }
    1222           0 : }
    1223             : 
    1224             : /* Install EVPN route into zebra. */
    1225           0 : static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
    1226             :                               const struct prefix_evpn *p,
    1227             :                               struct bgp_path_info *pi)
    1228             : {
    1229           0 :         int ret;
    1230           0 :         uint8_t flags;
    1231           0 :         int flood_control = VXLAN_FLOOD_DISABLED;
    1232           0 :         uint32_t seq;
    1233             : 
    1234           0 :         if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    1235           0 :                 flags = 0;
    1236             : 
    1237           0 :                 if (pi->sub_type == BGP_ROUTE_IMPORTED) {
    1238           0 :                         if (pi->attr->sticky)
    1239           0 :                                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
    1240           0 :                         if (pi->attr->default_gw)
    1241           0 :                                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
    1242           0 :                         if (is_evpn_prefix_ipaddr_v6(p) &&
    1243           0 :                                         pi->attr->router_flag)
    1244           0 :                                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
    1245             : 
    1246           0 :                         seq = mac_mobility_seqnum(pi->attr);
    1247             :                         /* if local ES notify zebra that this is a sync path */
    1248           0 :                         if (bgp_evpn_attr_is_local_es(pi->attr)) {
    1249           0 :                                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH);
    1250           0 :                                 if (bgp_evpn_attr_is_proxy(pi->attr))
    1251           0 :                                         SET_FLAG(flags,
    1252             :                                                 ZEBRA_MACIP_TYPE_PROXY_ADVERT);
    1253             :                         }
    1254             :                 } else {
    1255           0 :                         if (!bgp_evpn_attr_is_sync(pi->attr))
    1256             :                                 return 0;
    1257             : 
    1258             :                         /* if a local path is being turned around and sent
    1259             :                          * to zebra it is because it is a sync path on
    1260             :                          * a local ES
    1261             :                          */
    1262           0 :                         SET_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH);
    1263             :                         /* supply the highest peer seq number to zebra
    1264             :                          * for MM seq syncing
    1265             :                          */
    1266           0 :                         seq = bgp_evpn_attr_get_sync_seq(pi->attr);
    1267             :                         /* if any of the paths from the peer have the ROUTER
    1268             :                          * flag set install the local entry as a router entry
    1269             :                          */
    1270           0 :                         if (is_evpn_prefix_ipaddr_v6(p) &&
    1271           0 :                                         (pi->attr->es_flags &
    1272             :                                          ATTR_ES_PEER_ROUTER))
    1273           0 :                                 SET_FLAG(flags,
    1274             :                                                 ZEBRA_MACIP_TYPE_ROUTER_FLAG);
    1275             : 
    1276           0 :                         if (!(pi->attr->es_flags & ATTR_ES_PEER_ACTIVE))
    1277           0 :                                 SET_FLAG(flags,
    1278             :                                                 ZEBRA_MACIP_TYPE_PROXY_ADVERT);
    1279             :                 }
    1280             : 
    1281           0 :                 ret = bgp_zebra_send_remote_macip(
    1282             :                         bgp, vpn, p,
    1283           0 :                         (is_evpn_prefix_ipaddr_none(p)
    1284             :                                  ? NULL /* MAC update */
    1285           0 :                                  : evpn_type2_path_info_get_mac(
    1286             :                                            pi) /* MAC-IP update */),
    1287             :                         pi->attr->nexthop, 1, flags, seq,
    1288             :                         bgp_evpn_attr_get_esi(pi->attr));
    1289           0 :         } else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE) {
    1290           0 :                 ret = bgp_evpn_remote_es_evi_add(bgp, vpn, p);
    1291             :         } else {
    1292           0 :                 switch (bgp_attr_get_pmsi_tnl_type(pi->attr)) {
    1293           0 :                 case PMSI_TNLTYPE_INGR_REPL:
    1294           0 :                         flood_control = VXLAN_FLOOD_HEAD_END_REPL;
    1295           0 :                         break;
    1296             : 
    1297           0 :                 case PMSI_TNLTYPE_PIM_SM:
    1298           0 :                         flood_control = VXLAN_FLOOD_PIM_SM;
    1299           0 :                         break;
    1300             : 
    1301             :                 case PMSI_TNLTYPE_NO_INFO:
    1302             :                 case PMSI_TNLTYPE_RSVP_TE_P2MP:
    1303             :                 case PMSI_TNLTYPE_MLDP_P2MP:
    1304             :                 case PMSI_TNLTYPE_PIM_SSM:
    1305             :                 case PMSI_TNLTYPE_PIM_BIDIR:
    1306             :                 case PMSI_TNLTYPE_MLDP_MP2MP:
    1307             :                         flood_control = VXLAN_FLOOD_DISABLED;
    1308             :                         break;
    1309             :                 }
    1310           0 :                 ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1);
    1311             :         }
    1312             : 
    1313             :         return ret;
    1314             : }
    1315             : 
    1316             : /* Uninstall EVPN route from zebra. */
    1317           0 : static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
    1318             :                                 const struct prefix_evpn *p,
    1319             :                                 struct bgp_path_info *pi, bool is_sync)
    1320             : {
    1321           0 :         int ret;
    1322             : 
    1323           0 :         if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
    1324           0 :                 ret = bgp_zebra_send_remote_macip(
    1325             :                         bgp, vpn, p,
    1326           0 :                         (is_evpn_prefix_ipaddr_none(p)
    1327             :                                  ? NULL /* MAC update */
    1328           0 :                                  : evpn_type2_path_info_get_mac(
    1329             :                                            pi) /* MAC-IP update */),
    1330           0 :                         (is_sync ? zero_vtep_ip : pi->attr->nexthop), 0, 0, 0,
    1331             :                         NULL);
    1332           0 :         else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE)
    1333           0 :                 ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p);
    1334             :         else
    1335           0 :                 ret = bgp_zebra_send_remote_vtep(bgp, vpn, p,
    1336             :                                         VXLAN_FLOOD_DISABLED, 0);
    1337             : 
    1338           0 :         return ret;
    1339             : }
    1340             : 
    1341             : /*
    1342             :  * Due to MAC mobility, the prior "local" best route has been supplanted
    1343             :  * by a "remote" best route. The prior route has to be deleted and withdrawn
    1344             :  * from peers.
    1345             :  */
    1346           0 : static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
    1347             :                                         struct bgp_dest *dest,
    1348             :                                         struct bgp_path_info *old_local,
    1349             :                                         struct bgp_path_info *new_select)
    1350             : {
    1351           0 :         struct bgp_dest *global_dest;
    1352           0 :         struct bgp_path_info *pi;
    1353           0 :         afi_t afi = AFI_L2VPN;
    1354           0 :         safi_t safi = SAFI_EVPN;
    1355             : 
    1356           0 :         if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) {
    1357           0 :                 char esi_buf[ESI_STR_LEN];
    1358           0 :                 char esi_buf2[ESI_STR_LEN];
    1359           0 :                 struct prefix_evpn *evp =
    1360           0 :                         (struct prefix_evpn *)bgp_dest_get_prefix(dest);
    1361             : 
    1362           0 :                 zlog_debug("local path deleted %pFX es %s; new-path-es %s", evp,
    1363             :                            esi_to_str(&old_local->attr->esi, esi_buf,
    1364             :                                       sizeof(esi_buf)),
    1365             :                            new_select ? esi_to_str(&new_select->attr->esi,
    1366             :                                                    esi_buf2, sizeof(esi_buf2))
    1367             :                                       : "");
    1368             :         }
    1369             : 
    1370             :         /* Locate route node in the global EVPN routing table. Note that
    1371             :          * this table is a 2-level tree (RD-level + Prefix-level) similar to
    1372             :          * L3VPN routes.
    1373             :          */
    1374           0 :         global_dest = bgp_evpn_global_node_lookup(
    1375             :                 bgp->rib[afi][safi], afi, safi,
    1376           0 :                 (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
    1377             :                 &vpn->prd, old_local);
    1378           0 :         if (global_dest) {
    1379             :                 /* Delete route entry in the global EVPN table. */
    1380           0 :                 delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
    1381             : 
    1382             :                 /* Schedule for processing - withdraws to peers happen from
    1383             :                  * this table.
    1384             :                  */
    1385           0 :                 if (pi)
    1386           0 :                         bgp_process(bgp, global_dest, afi, safi);
    1387           0 :                 bgp_dest_unlock_node(global_dest);
    1388             :         }
    1389             : 
    1390             :         /* Delete route entry in the VNI route table, caller to remove. */
    1391           0 :         bgp_path_info_delete(dest, old_local);
    1392           0 : }
    1393             : 
    1394             : /*
    1395             :  * Calculate the best path for an EVPN route. Install/update best path in zebra,
    1396             :  * if appropriate.
    1397             :  * Note: vpn is NULL for local EAD-ES routes.
    1398             :  */
    1399           0 : int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
    1400             :                                      struct bgp_dest *dest)
    1401             : {
    1402           0 :         struct bgp_path_info *old_select, *new_select;
    1403           0 :         struct bgp_path_info_pair old_and_new;
    1404           0 :         afi_t afi = AFI_L2VPN;
    1405           0 :         safi_t safi = SAFI_EVPN;
    1406           0 :         int ret = 0;
    1407             : 
    1408             :         /* Compute the best path. */
    1409           0 :         bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
    1410             :                            afi, safi);
    1411           0 :         old_select = old_and_new.old;
    1412           0 :         new_select = old_and_new.new;
    1413             : 
    1414             :         /* If the best path hasn't changed - see if there is still something to
    1415             :          * update to zebra RIB.
    1416             :          * Remote routes and SYNC route (i.e. local routes with
    1417             :          * SYNCED_FROM_PEER flag) need to updated to zebra on any attr
    1418             :          * change.
    1419             :          */
    1420           0 :         if (old_select && old_select == new_select
    1421           0 :             && old_select->type == ZEBRA_ROUTE_BGP
    1422           0 :             && (old_select->sub_type == BGP_ROUTE_IMPORTED ||
    1423           0 :                         bgp_evpn_attr_is_sync(old_select->attr))
    1424           0 :             && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
    1425           0 :             && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
    1426           0 :             && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
    1427           0 :                 if (bgp_zebra_has_route_changed(old_select))
    1428           0 :                         ret = evpn_zebra_install(
    1429             :                                 bgp, vpn,
    1430           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    1431             :                                         dest),
    1432             :                                 old_select);
    1433           0 :                 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
    1434           0 :                 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
    1435           0 :                 bgp_zebra_clear_route_change_flags(dest);
    1436           0 :                 return ret;
    1437             :         }
    1438             : 
    1439             :         /* If the user did a "clear" this flag will be set */
    1440           0 :         UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
    1441             : 
    1442             :         /* bestpath has changed; update relevant fields and install or uninstall
    1443             :          * into the zebra RIB.
    1444             :          */
    1445           0 :         if (old_select || new_select)
    1446           0 :                 bgp_bump_version(dest);
    1447             : 
    1448           0 :         if (old_select)
    1449           0 :                 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
    1450           0 :         if (new_select) {
    1451           0 :                 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
    1452           0 :                 bgp_path_info_unset_flag(dest, new_select,
    1453             :                                          BGP_PATH_ATTR_CHANGED);
    1454           0 :                 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
    1455           0 :                 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
    1456             :         }
    1457             : 
    1458             :         /* a local entry with the SYNC flag also results in a MAC-IP update
    1459             :          * to zebra
    1460             :          */
    1461           0 :         if (new_select && new_select->type == ZEBRA_ROUTE_BGP
    1462           0 :             && (new_select->sub_type == BGP_ROUTE_IMPORTED ||
    1463           0 :                         bgp_evpn_attr_is_sync(new_select->attr))) {
    1464           0 :                 ret = evpn_zebra_install(
    1465             :                         bgp, vpn,
    1466           0 :                         (struct prefix_evpn *)bgp_dest_get_prefix(dest),
    1467             :                         new_select);
    1468             : 
    1469             :                 /* If an old best existed and it was a "local" route, the only
    1470             :                  * reason
    1471             :                  * it would be supplanted is due to MAC mobility procedures. So,
    1472             :                  * we
    1473             :                  * need to do an implicit delete and withdraw that route from
    1474             :                  * peers.
    1475             :                  */
    1476           0 :                 if (new_select->sub_type == BGP_ROUTE_IMPORTED &&
    1477           0 :                                 old_select && old_select->peer == bgp->peer_self
    1478             :                                 && old_select->type == ZEBRA_ROUTE_BGP
    1479           0 :                                 && old_select->sub_type == BGP_ROUTE_STATIC
    1480           0 :                                 && vpn)
    1481           0 :                         evpn_delete_old_local_route(bgp, vpn, dest,
    1482             :                                         old_select, new_select);
    1483             :         } else {
    1484           0 :                 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
    1485           0 :                     && old_select->sub_type == BGP_ROUTE_IMPORTED)
    1486           0 :                         ret = evpn_zebra_uninstall(
    1487             :                                 bgp, vpn,
    1488           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    1489             :                                         dest),
    1490             :                                 old_select, false);
    1491             :         }
    1492             : 
    1493             :         /* Clear any route change flags. */
    1494           0 :         bgp_zebra_clear_route_change_flags(dest);
    1495             : 
    1496             :         /* Reap old select bgp_path_info, if it has been removed */
    1497           0 :         if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
    1498           0 :                 bgp_path_info_reap(dest, old_select);
    1499             : 
    1500             :         return ret;
    1501             : }
    1502             : 
    1503           0 : static struct bgp_path_info *bgp_evpn_route_get_local_path(
    1504             :                 struct bgp *bgp, struct bgp_dest *dest)
    1505             : {
    1506           0 :         struct bgp_path_info *tmp_pi;
    1507           0 :         struct bgp_path_info *local_pi = NULL;
    1508             : 
    1509           0 :         for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
    1510           0 :                         tmp_pi = tmp_pi->next) {
    1511           0 :                 if (bgp_evpn_is_path_local(bgp, tmp_pi)) {
    1512             :                         local_pi = tmp_pi;
    1513             :                         break;
    1514             :                 }
    1515             :         }
    1516             : 
    1517           0 :         return local_pi;
    1518             : }
    1519             : 
    1520           0 : static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
    1521             :                                          struct bgp *bgp_vrf, afi_t afi,
    1522             :                                          safi_t safi, struct bgp_dest *dest,
    1523             :                                          struct attr *attr, int *route_changed)
    1524             : {
    1525           0 :         struct attr *attr_new = NULL;
    1526           0 :         struct bgp_path_info *pi = NULL;
    1527           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
    1528           0 :         struct bgp_path_info *local_pi = NULL;
    1529           0 :         struct bgp_path_info *tmp_pi = NULL;
    1530             : 
    1531           0 :         *route_changed = 0;
    1532             :         /* locate the local route entry if any */
    1533           0 :         for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
    1534           0 :              tmp_pi = tmp_pi->next) {
    1535           0 :                 if (tmp_pi->peer == bgp_evpn->peer_self
    1536             :                     && tmp_pi->type == ZEBRA_ROUTE_BGP
    1537           0 :                     && tmp_pi->sub_type == BGP_ROUTE_STATIC)
    1538           0 :                         local_pi = tmp_pi;
    1539             :         }
    1540             : 
    1541             :         /*
    1542             :          * create a new route entry if one doesn't exist.
    1543             :          * Otherwise see if route attr has changed
    1544             :          */
    1545           0 :         if (!local_pi) {
    1546             : 
    1547             :                 /* route has changed as this is the first entry */
    1548           0 :                 *route_changed = 1;
    1549             : 
    1550             :                 /* Add (or update) attribute to hash. */
    1551           0 :                 attr_new = bgp_attr_intern(attr);
    1552             : 
    1553             :                 /* create the route info from attribute */
    1554           0 :                 pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
    1555             :                                bgp_evpn->peer_self, attr_new, dest);
    1556           0 :                 SET_FLAG(pi->flags, BGP_PATH_VALID);
    1557             : 
    1558             :                 /* Type-5 routes advertise the L3-VNI */
    1559           0 :                 bgp_path_info_extra_get(pi);
    1560           0 :                 vni2label(bgp_vrf->l3vni, &label);
    1561           0 :                 memcpy(&pi->extra->label, &label, sizeof(label));
    1562           0 :                 pi->extra->num_labels = 1;
    1563             : 
    1564             :                 /* add the route entry to route node*/
    1565           0 :                 bgp_path_info_add(dest, pi);
    1566             :         } else {
    1567             : 
    1568           0 :                 tmp_pi = local_pi;
    1569           0 :                 if (!attrhash_cmp(tmp_pi->attr, attr)) {
    1570             : 
    1571             :                         /* attribute changed */
    1572           0 :                         *route_changed = 1;
    1573             : 
    1574             :                         /* The attribute has changed. */
    1575             :                         /* Add (or update) attribute to hash. */
    1576           0 :                         attr_new = bgp_attr_intern(attr);
    1577           0 :                         bgp_path_info_set_flag(dest, tmp_pi,
    1578             :                                                BGP_PATH_ATTR_CHANGED);
    1579             : 
    1580             :                         /* Restore route, if needed. */
    1581           0 :                         if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
    1582           0 :                                 bgp_path_info_restore(dest, tmp_pi);
    1583             : 
    1584             :                         /* Unintern existing, set to new. */
    1585           0 :                         bgp_attr_unintern(&tmp_pi->attr);
    1586           0 :                         tmp_pi->attr = attr_new;
    1587           0 :                         tmp_pi->uptime = monotime(NULL);
    1588             :                 }
    1589             :         }
    1590           0 :         return 0;
    1591             : }
    1592             : 
    1593             : /* update evpn type-5 route entry */
    1594           0 : static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
    1595             :                                    struct attr *src_attr, afi_t src_afi,
    1596             :                                    safi_t src_safi)
    1597             : {
    1598           0 :         afi_t afi = AFI_L2VPN;
    1599           0 :         safi_t safi = SAFI_EVPN;
    1600           0 :         struct attr attr;
    1601           0 :         struct bgp_dest *dest = NULL;
    1602           0 :         struct bgp *bgp_evpn = NULL;
    1603           0 :         int route_changed = 0;
    1604             : 
    1605           0 :         bgp_evpn = bgp_get_evpn();
    1606           0 :         if (!bgp_evpn)
    1607             :                 return 0;
    1608             : 
    1609             :         /* Build path attribute for this route - use the source attr, if
    1610             :          * present, else treat as locally originated.
    1611             :          */
    1612           0 :         if (src_attr)
    1613           0 :                 attr = *src_attr;
    1614             :         else {
    1615           0 :                 memset(&attr, 0, sizeof(attr));
    1616           0 :                 bgp_attr_default_set(&attr, bgp_vrf, BGP_ORIGIN_IGP);
    1617             :         }
    1618             : 
    1619             :         /* Advertise Primary IP (PIP) is enabled, send individual
    1620             :          * IP (default instance router-id) as nexthop.
    1621             :          * PIP is disabled or vrr interface is not present
    1622             :          * use anycast-IP as nexthop and anycast RMAC.
    1623             :          */
    1624           0 :         if (!bgp_vrf->evpn_info->advertise_pip ||
    1625           0 :             (!bgp_vrf->evpn_info->is_anycast_mac)) {
    1626           0 :                 attr.nexthop = bgp_vrf->originator_ip;
    1627           0 :                 attr.mp_nexthop_global_in = bgp_vrf->originator_ip;
    1628           0 :                 memcpy(&attr.rmac, &bgp_vrf->rmac, ETH_ALEN);
    1629             :         } else {
    1630             :                 /* copy sys rmac */
    1631           0 :                 memcpy(&attr.rmac, &bgp_vrf->evpn_info->pip_rmac, ETH_ALEN);
    1632           0 :                 if (bgp_vrf->evpn_info->pip_ip.s_addr != INADDR_ANY) {
    1633           0 :                         attr.nexthop = bgp_vrf->evpn_info->pip_ip;
    1634           0 :                         attr.mp_nexthop_global_in = bgp_vrf->evpn_info->pip_ip;
    1635           0 :                 } else if (bgp_vrf->evpn_info->pip_ip.s_addr == INADDR_ANY)
    1636           0 :                         if (bgp_debug_zebra(NULL))
    1637           0 :                                 zlog_debug(
    1638             :                                         "VRF %s evp %pFX advertise-pip primary ip is not configured",
    1639             :                                         vrf_id_to_name(bgp_vrf->vrf_id), evp);
    1640             :         }
    1641             : 
    1642           0 :         if (bgp_debug_zebra(NULL))
    1643           0 :                 zlog_debug(
    1644             :                         "VRF %s type-5 route evp %pFX RMAC %pEA nexthop %pI4",
    1645             :                         vrf_id_to_name(bgp_vrf->vrf_id), evp, &attr.rmac,
    1646             :                         &attr.nexthop);
    1647             : 
    1648           0 :         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    1649             : 
    1650           0 :         if (src_afi == AFI_IP6 &&
    1651           0 :             CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    1652             :                        BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
    1653           0 :                 if (src_attr &&
    1654           0 :                     !IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) {
    1655           0 :                         attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
    1656           0 :                         SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
    1657           0 :                         memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
    1658             :                                &src_attr->mp_nexthop_global,
    1659             :                                sizeof(struct in6_addr));
    1660             :                 }
    1661           0 :         } else if (src_afi == AFI_IP &&
    1662           0 :                    CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    1663             :                               BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
    1664           0 :                 if (src_attr && src_attr->nexthop.s_addr != 0) {
    1665           0 :                         attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
    1666           0 :                         SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
    1667           0 :                         memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
    1668             :                                &src_attr->nexthop, sizeof(struct in_addr));
    1669             :                 }
    1670             :         }
    1671             : 
    1672             :         /* Setup RT and encap extended community */
    1673           0 :         build_evpn_type5_route_extcomm(bgp_vrf, &attr);
    1674             : 
    1675             :         /* get the route node in global table */
    1676           0 :         dest = bgp_evpn_global_node_get(bgp_evpn->rib[afi][safi], afi, safi,
    1677             :                                         evp, &bgp_vrf->vrf_prd, NULL);
    1678           0 :         assert(dest);
    1679             : 
    1680             :         /* create or update the route entry within the route node */
    1681           0 :         update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, dest, &attr,
    1682             :                                       &route_changed);
    1683             : 
    1684             :         /* schedule for processing and unlock node */
    1685           0 :         if (route_changed) {
    1686           0 :                 bgp_process(bgp_evpn, dest, afi, safi);
    1687           0 :                 bgp_dest_unlock_node(dest);
    1688             :         }
    1689             : 
    1690             :         /* uninten temporary */
    1691           0 :         if (!src_attr)
    1692           0 :                 aspath_unintern(&attr.aspath);
    1693             :         return 0;
    1694             : }
    1695             : 
    1696           0 : static void bgp_evpn_get_sync_info(struct bgp *bgp, esi_t *esi,
    1697             :                                    struct bgp_dest *dest, uint32_t loc_seq,
    1698             :                                    uint32_t *max_sync_seq, bool *active_on_peer,
    1699             :                                    bool *peer_router, bool *proxy_from_peer,
    1700             :                                    const struct ethaddr *mac)
    1701             : {
    1702           0 :         struct bgp_path_info *tmp_pi;
    1703           0 :         struct bgp_path_info *second_best_path = NULL;
    1704           0 :         uint32_t tmp_mm_seq = 0;
    1705           0 :         esi_t *tmp_esi;
    1706           0 :         int paths_eq;
    1707           0 :         struct ethaddr *tmp_mac;
    1708           0 :         bool mac_cmp = false;
    1709           0 :         struct prefix_evpn *evp = (struct prefix_evpn *)&dest->p;
    1710             : 
    1711             : 
    1712             :         /* mac comparison is not needed for MAC-only routes */
    1713           0 :         if (mac && !is_evpn_prefix_ipaddr_none(evp))
    1714           0 :                 mac_cmp = true;
    1715             : 
    1716             :         /* find the best non-local path. a local path can only be present
    1717             :          * as best path
    1718             :          */
    1719           0 :         for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
    1720           0 :              tmp_pi = tmp_pi->next) {
    1721           0 :                 if (tmp_pi->sub_type != BGP_ROUTE_IMPORTED ||
    1722           0 :                         !CHECK_FLAG(tmp_pi->flags, BGP_PATH_VALID))
    1723           0 :                         continue;
    1724             : 
    1725             :                 /* ignore paths that have a different mac */
    1726           0 :                 if (mac_cmp) {
    1727           0 :                         tmp_mac = evpn_type2_path_info_get_mac(tmp_pi);
    1728           0 :                         if (memcmp(mac, tmp_mac, sizeof(*mac)))
    1729           0 :                                 continue;
    1730             :                 }
    1731             : 
    1732           0 :                 if (bgp_evpn_path_info_cmp(bgp, tmp_pi,
    1733             :                                 second_best_path, &paths_eq))
    1734           0 :                         second_best_path = tmp_pi;
    1735             :         }
    1736             : 
    1737           0 :         if (!second_best_path)
    1738           0 :                 return;
    1739             : 
    1740           0 :         tmp_esi = bgp_evpn_attr_get_esi(second_best_path->attr);
    1741             :         /* if this has the same ES desination as the local path
    1742             :          * it is a sync path
    1743             :          */
    1744           0 :         if (!memcmp(esi, tmp_esi, sizeof(esi_t))) {
    1745           0 :                 tmp_mm_seq = mac_mobility_seqnum(second_best_path->attr);
    1746           0 :                 if (tmp_mm_seq < loc_seq)
    1747             :                         return;
    1748             : 
    1749             :                 /* we have a non-proxy path from the ES peer.  */
    1750           0 :                 if (second_best_path->attr->es_flags &
    1751             :                                         ATTR_ES_PROXY_ADVERT) {
    1752           0 :                         *proxy_from_peer = true;
    1753             :                 } else {
    1754           0 :                         *active_on_peer = true;
    1755             :                 }
    1756             : 
    1757           0 :                 if (second_best_path->attr->router_flag)
    1758           0 :                         *peer_router = true;
    1759             : 
    1760             :                 /* we use both proxy and non-proxy imports to
    1761             :                  * determine the max sync sequence
    1762             :                  */
    1763           0 :                 if (tmp_mm_seq > *max_sync_seq)
    1764           0 :                         *max_sync_seq = tmp_mm_seq;
    1765             :         }
    1766             : }
    1767             : 
    1768             : /* Bubble up sync-info from all paths (non-best) to the local-path.
    1769             :  * This is need for MM sequence number syncing and proxy advertisement.
    1770             :  * Note: The local path can only exist as a best path in the
    1771             :  * VPN route table. It will take precedence over all sync paths.
    1772             :  */
    1773           0 : static void update_evpn_route_entry_sync_info(struct bgp *bgp,
    1774             :                                               struct bgp_dest *dest,
    1775             :                                               struct attr *attr,
    1776             :                                               uint32_t loc_seq, bool setup_sync,
    1777             :                                               const struct ethaddr *mac)
    1778             : {
    1779           0 :         esi_t *esi;
    1780           0 :         struct prefix_evpn *evp =
    1781           0 :                 (struct prefix_evpn *)bgp_dest_get_prefix(dest);
    1782             : 
    1783           0 :         if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    1784             :                 return;
    1785             : 
    1786           0 :         esi = bgp_evpn_attr_get_esi(attr);
    1787           0 :         if (bgp_evpn_is_esi_valid(esi)) {
    1788           0 :                 if (setup_sync) {
    1789           0 :                         uint32_t max_sync_seq = 0;
    1790           0 :                         bool active_on_peer = false;
    1791           0 :                         bool peer_router = false;
    1792           0 :                         bool proxy_from_peer = false;
    1793             : 
    1794           0 :                         bgp_evpn_get_sync_info(bgp, esi, dest, loc_seq,
    1795             :                                                &max_sync_seq, &active_on_peer,
    1796             :                                                &peer_router, &proxy_from_peer,
    1797             :                                                mac);
    1798           0 :                         attr->mm_sync_seqnum = max_sync_seq;
    1799           0 :                         if (active_on_peer)
    1800           0 :                                 attr->es_flags |= ATTR_ES_PEER_ACTIVE;
    1801             :                         else
    1802           0 :                                 attr->es_flags &= ~ATTR_ES_PEER_ACTIVE;
    1803           0 :                         if (proxy_from_peer)
    1804           0 :                                 attr->es_flags |= ATTR_ES_PEER_PROXY;
    1805             :                         else
    1806           0 :                                 attr->es_flags &= ~ATTR_ES_PEER_PROXY;
    1807           0 :                         if (peer_router)
    1808           0 :                                 attr->es_flags |= ATTR_ES_PEER_ROUTER;
    1809             :                         else
    1810           0 :                                 attr->es_flags &= ~ATTR_ES_PEER_ROUTER;
    1811             : 
    1812           0 :                         if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) {
    1813           0 :                                 char esi_buf[ESI_STR_LEN];
    1814             : 
    1815           0 :                                 zlog_debug(
    1816             :                                         "setup sync info for %pFX es %s max_seq %d %s%s%s",
    1817             :                                         evp,
    1818             :                                         esi_to_str(esi, esi_buf,
    1819             :                                                    sizeof(esi_buf)),
    1820             :                                         max_sync_seq,
    1821             :                                         (attr->es_flags & ATTR_ES_PEER_ACTIVE)
    1822             :                                                 ? "peer-active "
    1823             :                                                 : "",
    1824             :                                         (attr->es_flags & ATTR_ES_PEER_PROXY)
    1825             :                                                 ? "peer-proxy "
    1826             :                                                 : "",
    1827             :                                         (attr->es_flags & ATTR_ES_PEER_ROUTER)
    1828             :                                                 ? "peer-router "
    1829             :                                                 : "");
    1830             :                         }
    1831             :                 }
    1832             :         } else {
    1833           0 :                 attr->mm_sync_seqnum = 0;
    1834           0 :                 attr->es_flags &= ~ATTR_ES_PEER_ACTIVE;
    1835           0 :                 attr->es_flags &= ~ATTR_ES_PEER_PROXY;
    1836             :         }
    1837             : }
    1838             : 
    1839             : /*
    1840             :  * Create or update EVPN route entry. This could be in the VNI route tables
    1841             :  * or the global route table.
    1842             :  */
    1843           0 : static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
    1844             :                                    afi_t afi, safi_t safi,
    1845             :                                    struct bgp_dest *dest, struct attr *attr,
    1846             :                                    const struct ethaddr *mac,
    1847             :                                    const struct ipaddr *ip, int add,
    1848             :                                    struct bgp_path_info **pi, uint8_t flags,
    1849             :                                    uint32_t seq, bool vpn_rt, bool *old_is_sync)
    1850             : {
    1851           0 :         struct bgp_path_info *tmp_pi;
    1852           0 :         struct bgp_path_info *local_pi;
    1853           0 :         struct attr *attr_new;
    1854           0 :         mpls_label_t label[BGP_MAX_LABELS];
    1855           0 :         uint32_t num_labels = 1;
    1856           0 :         int route_change = 1;
    1857           0 :         uint8_t sticky = 0;
    1858           0 :         const struct prefix_evpn *evp;
    1859             : 
    1860           0 :         *pi = NULL;
    1861           0 :         evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    1862           0 :         memset(&label, 0, sizeof(label));
    1863             : 
    1864             :         /* See if this is an update of an existing route, or a new add. */
    1865           0 :         local_pi = bgp_evpn_route_get_local_path(bgp, dest);
    1866             : 
    1867             :         /* If route doesn't exist already, create a new one, if told to.
    1868             :          * Otherwise act based on whether the attributes of the route have
    1869             :          * changed or not.
    1870             :          */
    1871           0 :         if (!local_pi && !add)
    1872             :                 return 0;
    1873             : 
    1874           0 :         if (old_is_sync && local_pi)
    1875           0 :                 *old_is_sync = bgp_evpn_attr_is_sync(local_pi->attr);
    1876             : 
    1877             :         /* if a local path is being added with a non-zero esi look
    1878             :          * for SYNC paths from ES peers and bubble up the sync-info
    1879             :          */
    1880           0 :         update_evpn_route_entry_sync_info(bgp, dest, attr, seq, vpn_rt, mac);
    1881             : 
    1882             :         /* For non-GW MACs, update MAC mobility seq number, if needed. */
    1883           0 :         if (seq && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW))
    1884           0 :                 add_mac_mobility_to_attr(seq, attr);
    1885             : 
    1886           0 :         if (!local_pi) {
    1887             :                 /* Add (or update) attribute to hash. */
    1888           0 :                 attr_new = bgp_attr_intern(attr);
    1889             : 
    1890             :                 /* Extract MAC mobility sequence number, if any. */
    1891           0 :                 attr_new->mm_seqnum =
    1892           0 :                         bgp_attr_mac_mobility_seqnum(attr_new, &sticky);
    1893           0 :                 attr_new->sticky = sticky;
    1894             : 
    1895             :                 /* Create new route with its attribute. */
    1896           0 :                 tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
    1897             :                                    bgp->peer_self, attr_new, dest);
    1898           0 :                 SET_FLAG(tmp_pi->flags, BGP_PATH_VALID);
    1899           0 :                 bgp_path_info_extra_get(tmp_pi);
    1900             : 
    1901             :                 /* The VNI goes into the 'label' field of the route */
    1902           0 :                 vni2label(vpn->vni, &label[0]);
    1903             : 
    1904             :                 /* Type-2 routes may carry a second VNI - the L3-VNI.
    1905             :                  * Only attach second label if we are advertising two labels for
    1906             :                  * type-2 routes.
    1907             :                  */
    1908           0 :                 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    1909           0 :                     && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) {
    1910           0 :                         vni_t l3vni;
    1911             : 
    1912           0 :                         l3vni = bgpevpn_get_l3vni(vpn);
    1913           0 :                         if (l3vni) {
    1914           0 :                                 vni2label(l3vni, &label[1]);
    1915           0 :                                 num_labels++;
    1916             :                         }
    1917             :                 }
    1918             : 
    1919           0 :                 memcpy(&tmp_pi->extra->label, label, sizeof(label));
    1920           0 :                 tmp_pi->extra->num_labels = num_labels;
    1921             : 
    1922           0 :                 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    1923           0 :                         if (mac)
    1924           0 :                                 evpn_type2_path_info_set_mac(tmp_pi, *mac);
    1925           0 :                         else if (ip)
    1926           0 :                                 evpn_type2_path_info_set_ip(tmp_pi, *ip);
    1927             :                 }
    1928             : 
    1929             :                 /* Mark route as self type-2 route */
    1930           0 :                 if (flags && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
    1931           0 :                         tmp_pi->extra->af_flags = BGP_EVPN_MACIP_TYPE_SVI_IP;
    1932           0 :                 bgp_path_info_add(dest, tmp_pi);
    1933             :         } else {
    1934           0 :                 tmp_pi = local_pi;
    1935           0 :                 if (attrhash_cmp(tmp_pi->attr, attr)
    1936           0 :                     && !CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
    1937             :                         route_change = 0;
    1938             :                 else {
    1939             :                         /*
    1940             :                          * The attributes have changed, type-2 routes needs to
    1941             :                          * be advertised with right labels.
    1942             :                          */
    1943           0 :                         vni2label(vpn->vni, &label[0]);
    1944           0 :                         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    1945           0 :                             && CHECK_FLAG(vpn->flags,
    1946             :                                           VNI_FLAG_USE_TWO_LABELS)) {
    1947           0 :                                 vni_t l3vni;
    1948             : 
    1949           0 :                                 l3vni = bgpevpn_get_l3vni(vpn);
    1950           0 :                                 if (l3vni) {
    1951           0 :                                         vni2label(l3vni, &label[1]);
    1952           0 :                                         num_labels++;
    1953             :                                 }
    1954             :                         }
    1955           0 :                         memcpy(&tmp_pi->extra->label, label, sizeof(label));
    1956           0 :                         tmp_pi->extra->num_labels = num_labels;
    1957             : 
    1958           0 :                         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    1959           0 :                                 if (mac)
    1960           0 :                                         evpn_type2_path_info_set_mac(tmp_pi,
    1961             :                                                                      *mac);
    1962           0 :                                 else if (ip)
    1963           0 :                                         evpn_type2_path_info_set_ip(tmp_pi,
    1964             :                                                                     *ip);
    1965             :                         }
    1966             : 
    1967             :                         /* The attribute has changed. */
    1968             :                         /* Add (or update) attribute to hash. */
    1969           0 :                         attr_new = bgp_attr_intern(attr);
    1970           0 :                         bgp_path_info_set_flag(dest, tmp_pi,
    1971             :                                                BGP_PATH_ATTR_CHANGED);
    1972             : 
    1973             :                         /* Extract MAC mobility sequence number, if any. */
    1974           0 :                         attr_new->mm_seqnum =
    1975           0 :                                 bgp_attr_mac_mobility_seqnum(attr_new, &sticky);
    1976           0 :                         attr_new->sticky = sticky;
    1977             : 
    1978             :                         /* Restore route, if needed. */
    1979           0 :                         if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
    1980           0 :                                 bgp_path_info_restore(dest, tmp_pi);
    1981             : 
    1982             :                         /* Unintern existing, set to new. */
    1983           0 :                         bgp_attr_unintern(&tmp_pi->attr);
    1984           0 :                         tmp_pi->attr = attr_new;
    1985           0 :                         tmp_pi->uptime = monotime(NULL);
    1986             :                 }
    1987             :         }
    1988             : 
    1989             :         /* local MAC-IP routes in the VNI table are linked to
    1990             :          * the destination ES
    1991             :          */
    1992           0 :         if (route_change && vpn_rt
    1993           0 :             && (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE))
    1994           0 :                 bgp_evpn_path_es_link(tmp_pi, vpn->vni,
    1995             :                                       bgp_evpn_attr_get_esi(tmp_pi->attr));
    1996             : 
    1997             :         /* Return back the route entry. */
    1998           0 :         *pi = tmp_pi;
    1999           0 :         return route_change;
    2000             : }
    2001             : 
    2002           0 : static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
    2003             :                                             struct bgpevpn *vpn,
    2004             :                                             struct bgp_dest *dest)
    2005             : {
    2006           0 :         struct bgp_path_info *tmp_ri;
    2007           0 :         struct bgp_path_info *curr_select = NULL;
    2008             : 
    2009           0 :         for (tmp_ri = bgp_dest_get_bgp_path_info(dest); tmp_ri;
    2010           0 :              tmp_ri = tmp_ri->next) {
    2011           0 :                 if (CHECK_FLAG(tmp_ri->flags, BGP_PATH_SELECTED)) {
    2012             :                         curr_select = tmp_ri;
    2013             :                         break;
    2014             :                 }
    2015             :         }
    2016             : 
    2017           0 :         if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
    2018           0 :                         && (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
    2019           0 :                                 bgp_evpn_attr_is_sync(curr_select->attr)))
    2020           0 :                 evpn_zebra_install(bgp, vpn,
    2021           0 :                    (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
    2022             :                    curr_select);
    2023           0 : }
    2024             : 
    2025             : /*
    2026             :  * If the local route was not selected evict it and tell zebra to re-add
    2027             :  * the best remote dest.
    2028             :  *
    2029             :  * Typically a local path added by zebra is expected to be selected as
    2030             :  * best. In which case when a remote path wins as best (later)
    2031             :  * evpn_route_select_install itself evicts the older-local-best path.
    2032             :  *
    2033             :  * However if bgp's add and zebra's add cross paths (race condition) it
    2034             :  * is possible that the local path is no longer the "older" best path.
    2035             :  * It is a path that was never designated as best and hence requires
    2036             :  * additional handling to prevent bgp from injecting and holding on to a
    2037             :  * non-best local path.
    2038             :  */
    2039           0 : static void evpn_cleanup_local_non_best_route(struct bgp *bgp,
    2040             :                                               struct bgpevpn *vpn,
    2041             :                                               struct bgp_dest *dest,
    2042             :                                               struct bgp_path_info *local_pi)
    2043             : {
    2044             :         /* local path was not picked as the winner; kick it out */
    2045           0 :         if (bgp_debug_zebra(NULL))
    2046           0 :                 zlog_debug("evicting local evpn prefix %pBD as remote won",
    2047             :                            dest);
    2048             : 
    2049           0 :         evpn_delete_old_local_route(bgp, vpn, dest, local_pi, NULL);
    2050           0 :         bgp_path_info_reap(dest, local_pi);
    2051             : 
    2052             :         /* tell zebra to re-add the best remote path */
    2053           0 :         evpn_zebra_reinstall_best_route(bgp, vpn, dest);
    2054           0 : }
    2055             : 
    2056           0 : static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn,
    2057             :                                                   const struct prefix_evpn *p,
    2058             :                                                   esi_t *esi)
    2059             : {
    2060           0 :         return p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    2061           0 :                && (is_evpn_prefix_ipaddr_v4(p)
    2062           0 :                    || (is_evpn_prefix_ipaddr_v6(p)
    2063           0 :                        && !IN6_IS_ADDR_LINKLOCAL(
    2064             :                                &p->prefix.macip_addr.ip.ipaddr_v6)))
    2065           0 :                && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)
    2066           0 :                && bgpevpn_get_l3vni(vpn) && bgp_evpn_es_add_l3_ecomm_ok(esi);
    2067             : }
    2068             : 
    2069             : /*
    2070             :  * Create or update EVPN route (of type based on prefix) for specified VNI
    2071             :  * and schedule for processing.
    2072             :  */
    2073           0 : static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
    2074             :                              struct prefix_evpn *p, uint8_t flags,
    2075             :                              uint32_t seq, esi_t *esi)
    2076             : {
    2077           0 :         struct bgp_dest *dest;
    2078           0 :         struct attr attr;
    2079           0 :         struct attr *attr_new;
    2080           0 :         int add_l3_ecomm = 0;
    2081           0 :         struct bgp_path_info *pi;
    2082           0 :         afi_t afi = AFI_L2VPN;
    2083           0 :         safi_t safi = SAFI_EVPN;
    2084           0 :         int route_change;
    2085           0 :         bool old_is_sync = false;
    2086           0 :         bool mac_only = false;
    2087             : 
    2088           0 :         memset(&attr, 0, sizeof(attr));
    2089             : 
    2090             :         /* Build path-attribute for this route. */
    2091           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
    2092           0 :         attr.nexthop = vpn->originator_ip;
    2093           0 :         attr.mp_nexthop_global_in = vpn->originator_ip;
    2094           0 :         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    2095           0 :         attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
    2096           0 :         attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
    2097           0 :         attr.router_flag = CHECK_FLAG(flags,
    2098           0 :                                       ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0;
    2099           0 :         if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
    2100           0 :                 attr.es_flags |= ATTR_ES_PROXY_ADVERT;
    2101             : 
    2102           0 :         if (esi && bgp_evpn_is_esi_valid(esi)) {
    2103           0 :                 memcpy(&attr.esi, esi, sizeof(esi_t));
    2104           0 :                 attr.es_flags |= ATTR_ES_IS_LOCAL;
    2105             :         }
    2106             : 
    2107             :         /* PMSI is only needed for type-3 routes */
    2108           0 :         if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
    2109           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
    2110           0 :                 bgp_attr_set_pmsi_tnl_type(&attr, PMSI_TNLTYPE_INGR_REPL);
    2111             :         }
    2112             : 
    2113             :         /* router mac is only needed for type-2 routes here. */
    2114           0 :         if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    2115           0 :                 uint8_t af_flags = 0;
    2116             : 
    2117           0 :                 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
    2118           0 :                         SET_FLAG(af_flags, BGP_EVPN_MACIP_TYPE_SVI_IP);
    2119             : 
    2120           0 :                 bgp_evpn_get_rmac_nexthop(vpn, p, &attr, af_flags);
    2121             :         }
    2122             : 
    2123           0 :         if (bgp_debug_zebra(NULL)) {
    2124           0 :                 char buf3[ESI_STR_LEN];
    2125             : 
    2126           0 :                 zlog_debug(
    2127             :                         "VRF %s vni %u type-%u route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
    2128             :                         vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
    2129             :                                      : "None",
    2130             :                         vpn->vni, p->prefix.route_type, p, &attr.rmac,
    2131             :                         &attr.mp_nexthop_global_in,
    2132             :                         esi_to_str(esi, buf3, sizeof(buf3)));
    2133             :         }
    2134             : 
    2135           0 :         vni2label(vpn->vni, &(attr.label));
    2136             : 
    2137             :         /* Include L3 VNI related RTs and RMAC for type-2 routes, if they're
    2138             :          * IPv4 or IPv6 global addresses and we're advertising L3VNI with
    2139             :          * these routes.
    2140             :          */
    2141           0 :         add_l3_ecomm = bgp_evpn_route_add_l3_ecomm_ok(
    2142           0 :                 vpn, p, (attr.es_flags & ATTR_ES_IS_LOCAL) ? &attr.esi : NULL);
    2143             : 
    2144             :         /* Set up extended community. */
    2145           0 :         build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
    2146             : 
    2147             :         /* First, create (or fetch) route node within the VNI.
    2148             :          * NOTE: There is no RD here.
    2149             :          */
    2150           0 :         dest = bgp_evpn_vni_node_get(vpn, p, NULL);
    2151             : 
    2152           0 :         if ((p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) &&
    2153           0 :             (is_evpn_prefix_ipaddr_none(p) == true))
    2154             :                 mac_only = true;
    2155             : 
    2156             :         /* Create or update route entry. */
    2157           0 :         route_change = update_evpn_route_entry(
    2158             :                 bgp, vpn, afi, safi, dest, &attr,
    2159             :                 (mac_only ? NULL : &p->prefix.macip_addr.mac), NULL /* ip */, 1,
    2160             :                 &pi, flags, seq, true /* setup_sync */, &old_is_sync);
    2161           0 :         assert(pi);
    2162           0 :         attr_new = pi->attr;
    2163             : 
    2164             :         /* lock ri to prevent freeing in evpn_route_select_install */
    2165           0 :         bgp_path_info_lock(pi);
    2166             : 
    2167             :        /* Perform route selection. Normally, the local route in the
    2168             :         * VNI is expected to win and be the best route. However, if
    2169             :         * there is a race condition where a host moved from local to
    2170             :         * remote and the remote route was received in BGP just prior
    2171             :         * to the local MACIP notification from zebra, the remote
    2172             :         * route would win, and we should evict the defunct local route
    2173             :         * and (re)install the remote route into zebra.
    2174             :         */
    2175           0 :         evpn_route_select_install(bgp, vpn, dest);
    2176             :         /*
    2177             :          * If the new local route was not selected evict it and tell zebra
    2178             :          * to re-add the best remote dest. BGP doesn't retain non-best local
    2179             :          * routes.
    2180             :          */
    2181           0 :         if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    2182             :                 route_change = 0;
    2183             :         } else {
    2184           0 :                 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
    2185           0 :                         route_change = 0;
    2186           0 :                         evpn_cleanup_local_non_best_route(bgp, vpn, dest, pi);
    2187             :                 } else {
    2188           0 :                         bool new_is_sync;
    2189             : 
    2190             :                         /* If the local path already existed and is still the
    2191             :                          * best path we need to also check if it transitioned
    2192             :                          * from being a sync path to a non-sync path. If it
    2193             :                          * it did we need to notify zebra that the sync-path
    2194             :                          * has been removed.
    2195             :                          */
    2196           0 :                         new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
    2197           0 :                         if (!new_is_sync && old_is_sync)
    2198           0 :                                 evpn_zebra_uninstall(bgp, vpn, p, pi, true);
    2199             :                 }
    2200             :         }
    2201           0 :         bgp_path_info_unlock(pi);
    2202             : 
    2203           0 :         bgp_dest_unlock_node(dest);
    2204             : 
    2205             :         /* If this is a new route or some attribute has changed, export the
    2206             :          * route to the global table. The route will be advertised to peers
    2207             :          * from there. Note that this table is a 2-level tree (RD-level +
    2208             :          * Prefix-level) similar to L3VPN routes.
    2209             :          */
    2210           0 :         if (route_change) {
    2211           0 :                 struct bgp_path_info *global_pi;
    2212             : 
    2213           0 :                 dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
    2214             :                                                 p, &vpn->prd, NULL);
    2215           0 :                 update_evpn_route_entry(
    2216             :                         bgp, vpn, afi, safi, dest, attr_new, NULL /* mac */,
    2217             :                         NULL /* ip */, 1, &global_pi, flags, seq,
    2218             :                         false /* setup_sync */, NULL /* old_is_sync */);
    2219             : 
    2220             :                 /* Schedule for processing and unlock node. */
    2221           0 :                 bgp_process(bgp, dest, afi, safi);
    2222           0 :                 bgp_dest_unlock_node(dest);
    2223             :         }
    2224             : 
    2225             :         /* Unintern temporary. */
    2226           0 :         aspath_unintern(&attr.aspath);
    2227             : 
    2228           0 :         return 0;
    2229             : }
    2230             : 
    2231             : /*
    2232             :  * Delete EVPN route entry.
    2233             :  * The entry can be in ESI/VNI table or the global table.
    2234             :  */
    2235           0 : void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
    2236             :                                     struct bgp_dest *dest,
    2237             :                                     struct bgp_path_info **pi)
    2238             : {
    2239           0 :         struct bgp_path_info *tmp_pi;
    2240             : 
    2241           0 :         *pi = NULL;
    2242             : 
    2243             :         /* Now, find matching route. */
    2244           0 :         for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
    2245           0 :              tmp_pi = tmp_pi->next)
    2246           0 :                 if (tmp_pi->peer == bgp->peer_self
    2247             :                     && tmp_pi->type == ZEBRA_ROUTE_BGP
    2248           0 :                     && tmp_pi->sub_type == BGP_ROUTE_STATIC)
    2249             :                         break;
    2250             : 
    2251           0 :         *pi = tmp_pi;
    2252             : 
    2253             :         /* Mark route for delete. */
    2254           0 :         if (tmp_pi)
    2255           0 :                 bgp_path_info_delete(dest, tmp_pi);
    2256           0 : }
    2257             : 
    2258             : /* Delete EVPN type5 route */
    2259           0 : static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
    2260             : {
    2261           0 :         afi_t afi = AFI_L2VPN;
    2262           0 :         safi_t safi = SAFI_EVPN;
    2263           0 :         struct bgp_dest *dest = NULL;
    2264           0 :         struct bgp_path_info *pi = NULL;
    2265           0 :         struct bgp *bgp_evpn = NULL; /* evpn bgp instance */
    2266             : 
    2267           0 :         bgp_evpn = bgp_get_evpn();
    2268           0 :         if (!bgp_evpn)
    2269             :                 return 0;
    2270             : 
    2271             :         /* locate the global route entry for this type-5 prefix */
    2272           0 :         dest = bgp_evpn_global_node_lookup(bgp_evpn->rib[afi][safi], afi, safi,
    2273             :                                            evp, &bgp_vrf->vrf_prd, NULL);
    2274           0 :         if (!dest)
    2275             :                 return 0;
    2276             : 
    2277           0 :         delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi);
    2278           0 :         if (pi)
    2279           0 :                 bgp_process(bgp_evpn, dest, afi, safi);
    2280           0 :         bgp_dest_unlock_node(dest);
    2281           0 :         return 0;
    2282             : }
    2283             : 
    2284             : /*
    2285             :  * Delete EVPN route (of type based on prefix) for specified VNI and
    2286             :  * schedule for processing.
    2287             :  */
    2288           0 : static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
    2289             :                              struct prefix_evpn *p)
    2290             : {
    2291           0 :         struct bgp_dest *dest, *global_dest;
    2292           0 :         struct bgp_path_info *pi;
    2293           0 :         afi_t afi = AFI_L2VPN;
    2294           0 :         safi_t safi = SAFI_EVPN;
    2295             : 
    2296             :         /* First, locate the route node within the VNI. If it doesn't exist,
    2297             :          * there
    2298             :          * is nothing further to do.
    2299             :          * NOTE: There is no RD here.
    2300             :          */
    2301           0 :         dest = bgp_evpn_vni_node_lookup(vpn, p, NULL);
    2302           0 :         if (!dest)
    2303             :                 return 0;
    2304             : 
    2305             :         /* Next, locate route node in the global EVPN routing table. Note that
    2306             :          * this table is a 2-level tree (RD-level + Prefix-level) similar to
    2307             :          * L3VPN routes.
    2308             :          */
    2309           0 :         global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
    2310             :                                                   safi, p, &vpn->prd, NULL);
    2311           0 :         if (global_dest) {
    2312             :                 /* Delete route entry in the global EVPN table. */
    2313           0 :                 delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
    2314             : 
    2315             :                 /* Schedule for processing - withdraws to peers happen from
    2316             :                  * this table.
    2317             :                  */
    2318           0 :                 if (pi)
    2319           0 :                         bgp_process(bgp, global_dest, afi, safi);
    2320           0 :                 bgp_dest_unlock_node(global_dest);
    2321             :         }
    2322             : 
    2323             :         /* Delete route entry in the VNI route table. This can just be removed.
    2324             :          */
    2325           0 :         delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
    2326           0 :         if (pi) {
    2327           0 :                 bgp_path_info_reap(dest, pi);
    2328           0 :                 evpn_route_select_install(bgp, vpn, dest);
    2329             :         }
    2330           0 :         bgp_dest_unlock_node(dest);
    2331             : 
    2332           0 :         return 0;
    2333             : }
    2334             : 
    2335           0 : void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
    2336             :                                        struct bgp_dest *dest,
    2337             :                                        struct bgp_path_info *local_pi,
    2338             :                                        const char *caller)
    2339             : {
    2340           0 :         afi_t afi = AFI_L2VPN;
    2341           0 :         safi_t safi = SAFI_EVPN;
    2342           0 :         struct bgp_path_info *pi;
    2343           0 :         struct attr attr;
    2344           0 :         struct attr *attr_new;
    2345           0 :         uint32_t seq;
    2346           0 :         int add_l3_ecomm = 0;
    2347           0 :         struct bgp_dest *global_dest;
    2348           0 :         struct bgp_path_info *global_pi;
    2349           0 :         struct prefix_evpn evp;
    2350           0 :         int route_change;
    2351           0 :         bool old_is_sync = false;
    2352             : 
    2353           0 :         if (CHECK_FLAG(local_pi->flags, BGP_PATH_REMOVED))
    2354           0 :                 return;
    2355             : 
    2356             :         /*
    2357             :          * VNI table MAC-IP prefixes don't have MAC so make sure it's set from
    2358             :          * path info here.
    2359             :          */
    2360           0 :         if (is_evpn_prefix_ipaddr_none((struct prefix_evpn *)&dest->p)) {
    2361             :                 /* VNI MAC -> Global */
    2362           0 :                 evpn_type2_prefix_global_copy(
    2363           0 :                         &evp, (struct prefix_evpn *)&dest->p, NULL /* mac */,
    2364           0 :                         evpn_type2_path_info_get_ip(local_pi));
    2365             :         } else {
    2366             :                 /* VNI IP -> Global */
    2367           0 :                 evpn_type2_prefix_global_copy(
    2368           0 :                         &evp, (struct prefix_evpn *)&dest->p,
    2369           0 :                         evpn_type2_path_info_get_mac(local_pi), NULL /* ip */);
    2370             :         }
    2371             : 
    2372             :         /*
    2373             :          * Build attribute per local route as the MAC mobility and
    2374             :          * some other values could differ for different routes. The
    2375             :          * attributes will be shared in the hash table.
    2376             :          */
    2377           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
    2378           0 :         attr.nexthop = vpn->originator_ip;
    2379           0 :         attr.mp_nexthop_global_in = vpn->originator_ip;
    2380           0 :         attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    2381           0 :         attr.sticky = (local_pi->attr->sticky) ? 1 : 0;
    2382           0 :         attr.router_flag = (local_pi->attr->router_flag) ? 1 : 0;
    2383           0 :         attr.es_flags = local_pi->attr->es_flags;
    2384           0 :         if (local_pi->attr->default_gw) {
    2385           0 :                 attr.default_gw = 1;
    2386           0 :                 if (is_evpn_prefix_ipaddr_v6(&evp))
    2387           0 :                         attr.router_flag = 1;
    2388             :         }
    2389           0 :         memcpy(&attr.esi, &local_pi->attr->esi, sizeof(esi_t));
    2390           0 :         bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr, local_pi->extra->af_flags);
    2391           0 :         vni2label(vpn->vni, &(attr.label));
    2392             :         /* Add L3 VNI RTs and RMAC for non IPv6 link-local if
    2393             :          * using L3 VNI for type-2 routes also.
    2394             :          */
    2395           0 :         add_l3_ecomm = bgp_evpn_route_add_l3_ecomm_ok(
    2396             :                 vpn, &evp,
    2397             :                 (attr.es_flags & ATTR_ES_IS_LOCAL) ? &attr.esi : NULL);
    2398             : 
    2399             :         /* Set up extended community. */
    2400           0 :         build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
    2401           0 :         seq = mac_mobility_seqnum(local_pi->attr);
    2402             : 
    2403           0 :         if (bgp_debug_zebra(NULL)) {
    2404           0 :                 char buf3[ESI_STR_LEN];
    2405             : 
    2406           0 :                 zlog_debug(
    2407             :                         "VRF %s vni %u evp %pFX RMAC %pEA nexthop %pI4 esi %s esf 0x%x from %s",
    2408             :                         vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
    2409             :                                      : " ",
    2410             :                         vpn->vni, &evp, &attr.rmac, &attr.mp_nexthop_global_in,
    2411             :                         esi_to_str(&attr.esi, buf3, sizeof(buf3)),
    2412             :                         attr.es_flags, caller);
    2413             :         }
    2414             : 
    2415             :         /* Update the route entry. */
    2416           0 :         route_change = update_evpn_route_entry(
    2417             :                 bgp, vpn, afi, safi, dest, &attr, NULL /* mac */, NULL /* ip */,
    2418             :                 0, &pi, 0, seq, true /* setup_sync */, &old_is_sync);
    2419             : 
    2420           0 :         assert(pi);
    2421           0 :         attr_new = pi->attr;
    2422             :         /* lock ri to prevent freeing in evpn_route_select_install */
    2423           0 :         bgp_path_info_lock(pi);
    2424             : 
    2425             :         /* Perform route selection. Normally, the local route in the
    2426             :          * VNI is expected to win and be the best route. However,
    2427             :          * under peculiar situations (e.g., tunnel (next hop) IP change
    2428             :          * that causes best selection to be based on next hop), a
    2429             :          * remote route could win. If the local route is the best,
    2430             :          * ensure it is updated in the global EVPN route table and
    2431             :          * advertised to peers; otherwise, ensure it is evicted and
    2432             :          * (re)install the remote route into zebra.
    2433             :          */
    2434           0 :         evpn_route_select_install(bgp, vpn, dest);
    2435             : 
    2436           0 :         if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    2437             :                 route_change = 0;
    2438             :         } else {
    2439           0 :                 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
    2440           0 :                         route_change = 0;
    2441           0 :                         evpn_cleanup_local_non_best_route(bgp, vpn, dest, pi);
    2442             :                 } else {
    2443           0 :                         bool new_is_sync;
    2444             : 
    2445             :                         /* If the local path already existed and is still the
    2446             :                          * best path we need to also check if it transitioned
    2447             :                          * from being a sync path to a non-sync path. If it
    2448             :                          * it did we need to notify zebra that the sync-path
    2449             :                          * has been removed.
    2450             :                          */
    2451           0 :                         new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
    2452           0 :                         if (!new_is_sync && old_is_sync)
    2453           0 :                                 evpn_zebra_uninstall(bgp, vpn, &evp, pi, true);
    2454             :                 }
    2455             :         }
    2456             : 
    2457             : 
    2458             :         /* unlock pi */
    2459           0 :         bgp_path_info_unlock(pi);
    2460             : 
    2461           0 :         if (route_change) {
    2462             :                 /* Update route in global routing table. */
    2463           0 :                 global_dest = bgp_evpn_global_node_get(
    2464             :                         bgp->rib[afi][safi], afi, safi, &evp, &vpn->prd, NULL);
    2465           0 :                 assert(global_dest);
    2466           0 :                 update_evpn_route_entry(
    2467             :                         bgp, vpn, afi, safi, global_dest, attr_new,
    2468             :                         NULL /* mac */, NULL /* ip */, 0, &global_pi, 0,
    2469             :                         mac_mobility_seqnum(attr_new), false /* setup_sync */,
    2470             :                         NULL /* old_is_sync */);
    2471             : 
    2472             :                 /* Schedule for processing and unlock node. */
    2473           0 :                 bgp_process(bgp, global_dest, afi, safi);
    2474           0 :                 bgp_dest_unlock_node(global_dest);
    2475             :         }
    2476             : 
    2477             :         /* Unintern temporary. */
    2478           0 :         aspath_unintern(&attr.aspath);
    2479             : }
    2480             : 
    2481           0 : static void update_type2_route(struct bgp *bgp, struct bgpevpn *vpn,
    2482             :                                struct bgp_dest *dest)
    2483             : {
    2484           0 :         struct bgp_path_info *tmp_pi;
    2485             : 
    2486           0 :         const struct prefix_evpn *evp =
    2487           0 :                 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    2488             : 
    2489           0 :         if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    2490             :                 return;
    2491             : 
    2492             :         /* Identify local route. */
    2493           0 :         for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
    2494           0 :              tmp_pi = tmp_pi->next) {
    2495           0 :                 if (tmp_pi->peer == bgp->peer_self &&
    2496           0 :                     tmp_pi->type == ZEBRA_ROUTE_BGP &&
    2497             :                     tmp_pi->sub_type == BGP_ROUTE_STATIC)
    2498             :                         break;
    2499             :         }
    2500             : 
    2501           0 :         if (!tmp_pi)
    2502             :                 return;
    2503             : 
    2504           0 :         bgp_evpn_update_type2_route_entry(bgp, vpn, dest, tmp_pi, __func__);
    2505             : }
    2506             : 
    2507             : /*
    2508             :  * Update all type-2 (MACIP) local routes for this VNI - these should also
    2509             :  * be scheduled for advertise to peers.
    2510             :  */
    2511           0 : static void update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
    2512             : {
    2513           0 :         struct bgp_dest *dest;
    2514             : 
    2515             :         /* Walk this VNI's route MAC & IP table and update local type-2
    2516             :          * routes. For any routes updated, update corresponding entry in the
    2517             :          * global table too.
    2518             :          */
    2519           0 :         for (dest = bgp_table_top(vpn->mac_table); dest;
    2520           0 :              dest = bgp_route_next(dest))
    2521           0 :                 update_type2_route(bgp, vpn, dest);
    2522             : 
    2523           0 :         for (dest = bgp_table_top(vpn->ip_table); dest;
    2524           0 :              dest = bgp_route_next(dest))
    2525           0 :                 update_type2_route(bgp, vpn, dest);
    2526           0 : }
    2527             : 
    2528             : /*
    2529             :  * Delete all type-2 (MACIP) local routes for this VNI - only from the
    2530             :  * global routing table. These are also scheduled for withdraw from peers.
    2531             :  */
    2532           0 : static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
    2533             : {
    2534           0 :         afi_t afi;
    2535           0 :         safi_t safi;
    2536           0 :         struct bgp_dest *rddest, *dest;
    2537           0 :         struct bgp_table *table;
    2538           0 :         struct bgp_path_info *pi;
    2539             : 
    2540           0 :         afi = AFI_L2VPN;
    2541           0 :         safi = SAFI_EVPN;
    2542             : 
    2543           0 :         rddest = bgp_node_lookup(bgp->rib[afi][safi],
    2544           0 :                                  (struct prefix *)&vpn->prd);
    2545           0 :         if (rddest) {
    2546           0 :                 table = bgp_dest_get_bgp_table_info(rddest);
    2547           0 :                 for (dest = bgp_table_top(table); dest;
    2548           0 :                      dest = bgp_route_next(dest)) {
    2549           0 :                         const struct prefix_evpn *evp =
    2550           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    2551             :                                         dest);
    2552             : 
    2553           0 :                         if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    2554           0 :                                 continue;
    2555             : 
    2556           0 :                         delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
    2557           0 :                         if (pi)
    2558           0 :                                 bgp_process(bgp, dest, afi, safi);
    2559             :                 }
    2560             : 
    2561             :                 /* Unlock RD node. */
    2562           0 :                 bgp_dest_unlock_node(rddest);
    2563             :         }
    2564           0 : }
    2565             : 
    2566           0 : static void delete_vni_type2_route(struct bgp *bgp, struct bgp_dest *dest)
    2567             : {
    2568           0 :         struct bgp_path_info *pi;
    2569           0 :         afi_t afi = AFI_L2VPN;
    2570           0 :         safi_t safi = SAFI_EVPN;
    2571             : 
    2572           0 :         const struct prefix_evpn *evp =
    2573           0 :                 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    2574             : 
    2575           0 :         if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    2576           0 :                 return;
    2577             : 
    2578           0 :         delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
    2579             : 
    2580             :         /* Route entry in local table gets deleted immediately. */
    2581           0 :         if (pi)
    2582           0 :                 bgp_path_info_reap(dest, pi);
    2583             : }
    2584             : 
    2585           0 : static void delete_vni_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
    2586             : {
    2587           0 :         struct bgp_dest *dest;
    2588             : 
    2589             :         /* Next, walk this VNI's MAC & IP route table and delete local type-2
    2590             :          * routes.
    2591             :          */
    2592           0 :         for (dest = bgp_table_top(vpn->mac_table); dest;
    2593           0 :              dest = bgp_route_next(dest))
    2594           0 :                 delete_vni_type2_route(bgp, dest);
    2595             : 
    2596           0 :         for (dest = bgp_table_top(vpn->ip_table); dest;
    2597           0 :              dest = bgp_route_next(dest))
    2598           0 :                 delete_vni_type2_route(bgp, dest);
    2599           0 : }
    2600             : 
    2601             : /*
    2602             :  * Delete all type-2 (MACIP) local routes for this VNI - from the global
    2603             :  * table as well as the per-VNI route table.
    2604             :  */
    2605           0 : static void delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
    2606             : {
    2607             :         /* First, walk the global route table for this VNI's type-2 local
    2608             :          * routes.
    2609             :          * EVPN routes are a 2-level table, first get the RD table.
    2610             :          */
    2611           0 :         delete_global_type2_routes(bgp, vpn);
    2612           0 :         delete_vni_type2_routes(bgp, vpn);
    2613           0 : }
    2614             : 
    2615             : /*
    2616             :  * Delete all routes in the per-VNI route table.
    2617             :  */
    2618           0 : static void delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
    2619             : {
    2620           0 :         struct bgp_dest *dest;
    2621           0 :         struct bgp_path_info *pi, *nextpi;
    2622             : 
    2623             :         /* Walk this VNI's MAC & IP route table and delete all routes. */
    2624           0 :         for (dest = bgp_table_top(vpn->mac_table); dest;
    2625           0 :              dest = bgp_route_next(dest)) {
    2626           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest);
    2627           0 :                      (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
    2628           0 :                         bgp_evpn_remote_ip_hash_del(vpn, pi);
    2629           0 :                         bgp_path_info_delete(dest, pi);
    2630           0 :                         bgp_path_info_reap(dest, pi);
    2631             :                 }
    2632             :         }
    2633             : 
    2634           0 :         for (dest = bgp_table_top(vpn->ip_table); dest;
    2635           0 :              dest = bgp_route_next(dest)) {
    2636           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest);
    2637           0 :                      (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
    2638           0 :                         bgp_path_info_delete(dest, pi);
    2639           0 :                         bgp_path_info_reap(dest, pi);
    2640             :                 }
    2641             :         }
    2642           0 : }
    2643             : 
    2644             : /* BUM traffic flood mode per-l2-vni */
    2645           0 : static int bgp_evpn_vni_flood_mode_get(struct bgp *bgp,
    2646             :                                         struct bgpevpn *vpn)
    2647             : {
    2648             :         /* if flooding has been globally disabled per-vni mode is
    2649             :          * not relevant
    2650             :          */
    2651           0 :         if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
    2652             :                 return VXLAN_FLOOD_DISABLED;
    2653             : 
    2654             :         /* if mcast group ip has been specified we use a PIM-SM MDT */
    2655           0 :         if (vpn->mcast_grp.s_addr != INADDR_ANY)
    2656             :                 return VXLAN_FLOOD_PIM_SM;
    2657             : 
    2658             :         /* default is ingress replication */
    2659             :         return VXLAN_FLOOD_HEAD_END_REPL;
    2660             : }
    2661             : 
    2662             : /*
    2663             :  * Update (and advertise) local routes for a VNI. Invoked upon the VNI
    2664             :  * export RT getting modified or change to tunnel IP. Note that these
    2665             :  * situations need the route in the per-VNI table as well as the global
    2666             :  * table to be updated (as attributes change).
    2667             :  */
    2668           0 : int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
    2669             : {
    2670           0 :         int ret;
    2671           0 :         struct prefix_evpn p;
    2672             : 
    2673           0 :         update_type1_routes_for_evi(bgp, vpn);
    2674             : 
    2675             :         /* Update and advertise the type-3 route (only one) followed by the
    2676             :          * locally learnt type-2 routes (MACIP) - for this VNI.
    2677             :          *
    2678             :          * RT-3 only if doing head-end replication
    2679             :          */
    2680           0 :         if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
    2681             :                                 == VXLAN_FLOOD_HEAD_END_REPL) {
    2682           0 :                 build_evpn_type3_prefix(&p, vpn->originator_ip);
    2683           0 :                 ret = update_evpn_route(bgp, vpn, &p, 0, 0, NULL);
    2684           0 :                 if (ret)
    2685             :                         return ret;
    2686             :         }
    2687             : 
    2688           0 :         update_all_type2_routes(bgp, vpn);
    2689           0 :         return 0;
    2690             : }
    2691             : 
    2692             : /*
    2693             :  * Delete (and withdraw) local routes for specified VNI from the global
    2694             :  * table and per-VNI table. After this, remove all other routes from
    2695             :  * the per-VNI table. Invoked upon the VNI being deleted or EVPN
    2696             :  * (advertise-all-vni) being disabled.
    2697             :  */
    2698           0 : static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
    2699             : {
    2700           0 :         int ret;
    2701           0 :         struct prefix_evpn p;
    2702             : 
    2703             :         /* Delete and withdraw locally learnt type-2 routes (MACIP)
    2704             :          * followed by type-3 routes (only one) - for this VNI.
    2705             :          */
    2706           0 :         delete_all_type2_routes(bgp, vpn);
    2707             : 
    2708           0 :         build_evpn_type3_prefix(&p, vpn->originator_ip);
    2709           0 :         ret = delete_evpn_route(bgp, vpn, &p);
    2710           0 :         if (ret)
    2711             :                 return ret;
    2712             : 
    2713             :         /* Delete all routes from the per-VNI table. */
    2714           0 :         delete_all_vni_routes(bgp, vpn);
    2715           0 :         return 0;
    2716             : }
    2717             : 
    2718             : /*
    2719             :  * There is a flood mcast IP address change. Update the mcast-grp and
    2720             :  * remove the type-3 route if any. A new type-3 route will be generated
    2721             :  * post tunnel_ip update if the new flood mode is head-end-replication.
    2722             :  */
    2723           0 : static int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn,
    2724             :                 struct in_addr mcast_grp)
    2725             : {
    2726           0 :         struct prefix_evpn p;
    2727             : 
    2728           0 :         vpn->mcast_grp = mcast_grp;
    2729             : 
    2730           0 :         if (is_vni_live(vpn)) {
    2731           0 :                 build_evpn_type3_prefix(&p, vpn->originator_ip);
    2732           0 :                 delete_evpn_route(bgp, vpn, &p);
    2733             :         }
    2734             : 
    2735           0 :         return 0;
    2736             : }
    2737             : 
    2738             : /*
    2739             :  * There is a tunnel endpoint IP address change for this VNI, delete
    2740             :  * prior type-3 route (if needed) and update.
    2741             :  * Note: Route re-advertisement happens elsewhere after other processing
    2742             :  * other changes.
    2743             :  */
    2744           0 : static void handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
    2745             :                                     struct in_addr originator_ip)
    2746             : {
    2747           0 :         struct prefix_evpn p;
    2748             : 
    2749           0 :         if (IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
    2750             :                 return;
    2751             : 
    2752             :         /* If VNI is not live, we only need to update the originator ip */
    2753           0 :         if (!is_vni_live(vpn)) {
    2754           0 :                 vpn->originator_ip = originator_ip;
    2755           0 :                 return;
    2756             :         }
    2757             : 
    2758             :         /* Update the tunnel-ip hash */
    2759           0 :         bgp_tip_del(bgp, &vpn->originator_ip);
    2760           0 :         if (bgp_tip_add(bgp, &originator_ip))
    2761             :                 /* The originator_ip was not already present in the
    2762             :                  * bgp martian next-hop table as a tunnel-ip, so we
    2763             :                  * need to go back and filter routes matching the new
    2764             :                  * martian next-hop.
    2765             :                  */
    2766           0 :                 bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
    2767             : 
    2768             :         /* Need to withdraw type-3 route as the originator IP is part
    2769             :          * of the key.
    2770             :          */
    2771           0 :         build_evpn_type3_prefix(&p, vpn->originator_ip);
    2772           0 :         delete_evpn_route(bgp, vpn, &p);
    2773             : 
    2774             :         /* Update the tunnel IP and re-advertise all routes for this VNI. */
    2775           0 :         vpn->originator_ip = originator_ip;
    2776           0 :         return;
    2777             : }
    2778             : 
    2779             : static struct bgp_path_info *
    2780           0 : bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
    2781             :                               struct bgp_dest *dest, struct attr *attr)
    2782             : {
    2783           0 :         struct attr *attr_new;
    2784           0 :         struct bgp_path_info *pi;
    2785             : 
    2786             :         /* Add (or update) attribute to hash. */
    2787           0 :         attr_new = bgp_attr_intern(attr);
    2788             : 
    2789             :         /* Create new route with its attribute. */
    2790           0 :         pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0, parent_pi->peer,
    2791             :                        attr_new, dest);
    2792           0 :         SET_FLAG(pi->flags, BGP_PATH_VALID);
    2793           0 :         bgp_path_info_extra_get(pi);
    2794           0 :         pi->extra->parent = bgp_path_info_lock(parent_pi);
    2795           0 :         bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
    2796           0 :         if (parent_pi->extra) {
    2797           0 :                 memcpy(&pi->extra->label, &parent_pi->extra->label,
    2798             :                        sizeof(pi->extra->label));
    2799           0 :                 pi->extra->num_labels = parent_pi->extra->num_labels;
    2800           0 :                 pi->extra->igpmetric = parent_pi->extra->igpmetric;
    2801             :         }
    2802             : 
    2803           0 :         bgp_path_info_add(dest, pi);
    2804             : 
    2805           0 :         return pi;
    2806             : }
    2807             : 
    2808             : /*
    2809             :  * Install route entry into the VRF routing table and invoke route selection.
    2810             :  */
    2811           0 : static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
    2812             :                                            const struct prefix_evpn *evp,
    2813             :                                            struct bgp_path_info *parent_pi)
    2814             : {
    2815           0 :         struct bgp_dest *dest;
    2816           0 :         struct bgp_path_info *pi;
    2817           0 :         struct attr attr;
    2818           0 :         struct attr *attr_new;
    2819           0 :         int ret = 0;
    2820           0 :         struct prefix p;
    2821           0 :         struct prefix *pp = &p;
    2822           0 :         afi_t afi = 0;
    2823           0 :         safi_t safi = 0;
    2824           0 :         bool new_pi = false;
    2825           0 :         bool use_l3nhg = false;
    2826           0 :         bool is_l3nhg_active = false;
    2827           0 :         char buf1[INET6_ADDRSTRLEN];
    2828             : 
    2829           0 :         memset(pp, 0, sizeof(struct prefix));
    2830           0 :         ip_prefix_from_evpn_prefix(evp, pp);
    2831             : 
    2832           0 :         if (bgp_debug_zebra(NULL))
    2833           0 :                 zlog_debug(
    2834             :                         "vrf %s: import evpn prefix %pFX parent %p flags 0x%x",
    2835             :                         vrf_id_to_name(bgp_vrf->vrf_id), evp, parent_pi,
    2836             :                         parent_pi->flags);
    2837             : 
    2838             :         /* Create (or fetch) route within the VRF. */
    2839             :         /* NOTE: There is no RD here. */
    2840           0 :         if (is_evpn_prefix_ipaddr_v4(evp)) {
    2841           0 :                 afi = AFI_IP;
    2842           0 :                 safi = SAFI_UNICAST;
    2843           0 :                 dest = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
    2844           0 :         } else if (is_evpn_prefix_ipaddr_v6(evp)) {
    2845           0 :                 afi = AFI_IP6;
    2846           0 :                 safi = SAFI_UNICAST;
    2847           0 :                 dest = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
    2848             :         } else
    2849             :                 return 0;
    2850             : 
    2851             :         /* EVPN routes currently only support a IPv4 next hop which corresponds
    2852             :          * to the remote VTEP. When importing into a VRF, if it is IPv6 host
    2853             :          * or prefix route, we have to convert the next hop to an IPv4-mapped
    2854             :          * address for the rest of the code to flow through. In the case of IPv4,
    2855             :          * make sure to set the flag for next hop attribute.
    2856             :          */
    2857           0 :         attr = *parent_pi->attr;
    2858           0 :         if (attr.evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP) {
    2859           0 :                 if (afi == AFI_IP6)
    2860           0 :                         evpn_convert_nexthop_to_ipv6(&attr);
    2861             :                 else {
    2862           0 :                         attr.nexthop = attr.mp_nexthop_global_in;
    2863           0 :                         attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    2864             :                 }
    2865             :         } else {
    2866             : 
    2867             :                 /*
    2868             :                  * If gateway IP overlay index is specified in the NLRI of
    2869             :                  * EVPN RT-5, this gateway IP should be used as the nexthop
    2870             :                  * for the prefix in the VRF
    2871             :                  */
    2872           0 :                 if (bgp_debug_zebra(NULL)) {
    2873           0 :                         zlog_debug(
    2874             :                                 "Install gateway IP %s as nexthop for prefix %pFX in vrf %s",
    2875             :                                 inet_ntop(pp->family, &attr.evpn_overlay.gw_ip,
    2876             :                                           buf1, sizeof(buf1)), pp,
    2877             :                                           vrf_id_to_name(bgp_vrf->vrf_id));
    2878             :                 }
    2879             : 
    2880           0 :                 if (afi == AFI_IP6) {
    2881           0 :                         memcpy(&attr.mp_nexthop_global,
    2882             :                                &attr.evpn_overlay.gw_ip.ipaddr_v6,
    2883             :                                sizeof(struct in6_addr));
    2884           0 :                         attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
    2885             :                 } else {
    2886           0 :                         attr.nexthop = attr.evpn_overlay.gw_ip.ipaddr_v4;
    2887           0 :                         attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    2888             :                 }
    2889             :         }
    2890             : 
    2891           0 :         bgp_evpn_es_vrf_use_nhg(bgp_vrf, &parent_pi->attr->esi, &use_l3nhg,
    2892             :                                 &is_l3nhg_active, NULL);
    2893           0 :         if (use_l3nhg)
    2894           0 :                 attr.es_flags |= ATTR_ES_L3_NHG_USE;
    2895           0 :         if (is_l3nhg_active)
    2896           0 :                 attr.es_flags |= ATTR_ES_L3_NHG_ACTIVE;
    2897             : 
    2898             :         /* Check if route entry is already present. */
    2899           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    2900           0 :                 if (pi->extra
    2901           0 :                     && (struct bgp_path_info *)pi->extra->parent == parent_pi)
    2902             :                         break;
    2903             : 
    2904           0 :         if (!pi) {
    2905           0 :                 pi = bgp_create_evpn_bgp_path_info(parent_pi, dest, &attr);
    2906           0 :                 new_pi = true;
    2907             :         } else {
    2908           0 :                 if (attrhash_cmp(pi->attr, &attr)
    2909           0 :                     && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
    2910           0 :                         bgp_dest_unlock_node(dest);
    2911           0 :                         return 0;
    2912             :                 }
    2913             :                 /* The attribute has changed. */
    2914             :                 /* Add (or update) attribute to hash. */
    2915           0 :                 attr_new = bgp_attr_intern(&attr);
    2916             : 
    2917             :                 /* Restore route, if needed. */
    2918           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
    2919           0 :                         bgp_path_info_restore(dest, pi);
    2920             : 
    2921             :                 /* Mark if nexthop has changed. */
    2922           0 :                 if ((afi == AFI_IP
    2923           0 :                      && !IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop))
    2924           0 :                     || (afi == AFI_IP6
    2925           0 :                         && !IPV6_ADDR_SAME(&pi->attr->mp_nexthop_global,
    2926             :                                            &attr_new->mp_nexthop_global)))
    2927           0 :                         SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
    2928             : 
    2929           0 :                 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
    2930             :                 /* Unintern existing, set to new. */
    2931           0 :                 bgp_attr_unintern(&pi->attr);
    2932           0 :                 pi->attr = attr_new;
    2933           0 :                 pi->uptime = monotime(NULL);
    2934             :         }
    2935             : 
    2936             :         /* Gateway IP nexthop should be resolved */
    2937           0 :         if (attr.evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
    2938           0 :                 if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi,
    2939             :                                             NULL, 0, NULL))
    2940           0 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
    2941             :                 else {
    2942           0 :                         if (BGP_DEBUG(nht, NHT)) {
    2943           0 :                                 inet_ntop(pp->family,
    2944             :                                           &attr.evpn_overlay.gw_ip,
    2945             :                                           buf1, sizeof(buf1));
    2946           0 :                                 zlog_debug("%s: gateway IP NH unresolved",
    2947             :                                            buf1);
    2948             :                         }
    2949           0 :                         bgp_path_info_unset_flag(dest, pi, BGP_PATH_VALID);
    2950             :                 }
    2951             :         } else {
    2952             : 
    2953             :                 /* as it is an importation, change nexthop */
    2954           0 :                 bgp_path_info_set_flag(dest, pi, BGP_PATH_ANNC_NH_SELF);
    2955             :         }
    2956             : 
    2957             :         /* Link path to evpn nexthop */
    2958           0 :         bgp_evpn_path_nh_add(bgp_vrf, pi);
    2959             : 
    2960           0 :         bgp_aggregate_increment(bgp_vrf, bgp_dest_get_prefix(dest), pi, afi,
    2961             :                                 safi);
    2962             : 
    2963             :         /* Perform route selection and update zebra, if required. */
    2964           0 :         bgp_process(bgp_vrf, dest, afi, safi);
    2965             : 
    2966             :         /* Process for route leaking. */
    2967           0 :         vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
    2968             : 
    2969           0 :         bgp_dest_unlock_node(dest);
    2970             : 
    2971           0 :         if (bgp_debug_zebra(NULL))
    2972           0 :                 zlog_debug("... %s pi dest %p (l %d) pi %p (l %d, f 0x%x)",
    2973             :                            new_pi ? "new" : "update", dest,
    2974             :                            bgp_dest_get_lock_count(dest), pi, pi->lock,
    2975             :                            pi->flags);
    2976             : 
    2977             :         return ret;
    2978             : }
    2979             : 
    2980             : /*
    2981             :  * Common handling for vni route tables install/selection.
    2982             :  */
    2983           0 : static int install_evpn_route_entry_in_vni_common(
    2984             :         struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p,
    2985             :         struct bgp_dest *dest, struct bgp_path_info *parent_pi)
    2986             : {
    2987           0 :         struct bgp_path_info *pi;
    2988           0 :         struct bgp_path_info *local_pi;
    2989           0 :         struct attr *attr_new;
    2990           0 :         int ret;
    2991           0 :         bool old_local_es = false;
    2992           0 :         bool new_local_es;
    2993             : 
    2994             :         /* Check if route entry is already present. */
    2995           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    2996           0 :                 if (pi->extra
    2997           0 :                     && (struct bgp_path_info *)pi->extra->parent == parent_pi)
    2998             :                         break;
    2999             : 
    3000           0 :         if (!pi) {
    3001             :                 /* Create an info */
    3002           0 :                 pi = bgp_create_evpn_bgp_path_info(parent_pi, dest,
    3003             :                                                     parent_pi->attr);
    3004             : 
    3005           0 :                 if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    3006           0 :                         if (is_evpn_type2_dest_ipaddr_none(dest))
    3007           0 :                                 evpn_type2_path_info_set_ip(
    3008             :                                         pi, p->prefix.macip_addr.ip);
    3009             :                         else
    3010           0 :                                 evpn_type2_path_info_set_mac(
    3011             :                                         pi, p->prefix.macip_addr.mac);
    3012             :                 }
    3013             : 
    3014           0 :                 new_local_es = bgp_evpn_attr_is_local_es(pi->attr);
    3015             :         } else {
    3016             :                 /* Return early if attributes haven't changed
    3017             :                  * and dest isn't flagged for removal.
    3018             :                  * dest will be unlocked by either
    3019             :                  * install_evpn_route_entry_in_vni_mac() or
    3020             :                  * install_evpn_route_entry_in_vni_ip()
    3021             :                  */
    3022           0 :                 if (attrhash_cmp(pi->attr, parent_pi->attr) &&
    3023           0 :                     !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
    3024             :                         return 0;
    3025             :                 /* The attribute has changed. */
    3026             :                 /* Add (or update) attribute to hash. */
    3027           0 :                 attr_new = bgp_attr_intern(parent_pi->attr);
    3028             : 
    3029             :                 /* Restore route, if needed. */
    3030           0 :                 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
    3031           0 :                         bgp_path_info_restore(dest, pi);
    3032             : 
    3033             :                 /* Mark if nexthop has changed. */
    3034           0 :                 if (!IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop))
    3035           0 :                         SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
    3036             : 
    3037           0 :                 old_local_es = bgp_evpn_attr_is_local_es(pi->attr);
    3038           0 :                 new_local_es = bgp_evpn_attr_is_local_es(attr_new);
    3039             :                 /* If ESI is different or if its type has changed we
    3040             :                  * need to reinstall the path in zebra
    3041             :                  */
    3042           0 :                 if ((old_local_es != new_local_es)
    3043           0 :                     || memcmp(&pi->attr->esi, &attr_new->esi,
    3044             :                               sizeof(attr_new->esi))) {
    3045             : 
    3046           0 :                         if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
    3047           0 :                                 zlog_debug("VNI %d path %pFX chg to %s es",
    3048             :                                            vpn->vni, &pi->net->p,
    3049             :                                            new_local_es ? "local"
    3050             :                                                         : "non-local");
    3051           0 :                         bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
    3052             :                 }
    3053             : 
    3054             :                 /* Unintern existing, set to new. */
    3055           0 :                 bgp_attr_unintern(&pi->attr);
    3056           0 :                 pi->attr = attr_new;
    3057           0 :                 pi->uptime = monotime(NULL);
    3058             :         }
    3059             : 
    3060             :         /* Add this route to remote IP hashtable */
    3061           0 :         bgp_evpn_remote_ip_hash_add(vpn, pi);
    3062             : 
    3063             :         /* Perform route selection and update zebra, if required. */
    3064           0 :         ret = evpn_route_select_install(bgp, vpn, dest);
    3065             : 
    3066             :         /* if the best path is a local path with a non-zero ES
    3067             :          * sync info against the local path may need to be updated
    3068             :          * when a remote path is added/updated (including changes
    3069             :          * from sync-path to remote-path)
    3070             :          */
    3071           0 :         local_pi = bgp_evpn_route_get_local_path(bgp, dest);
    3072           0 :         if (local_pi && (old_local_es || new_local_es))
    3073           0 :                 bgp_evpn_update_type2_route_entry(bgp, vpn, dest, local_pi,
    3074             :                                                   __func__);
    3075             : 
    3076             :         return ret;
    3077             : }
    3078             : 
    3079             : /*
    3080             :  * Common handling for vni route tables uninstall/selection.
    3081             :  */
    3082           0 : static int uninstall_evpn_route_entry_in_vni_common(
    3083             :         struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p,
    3084             :         struct bgp_dest *dest, struct bgp_path_info *parent_pi)
    3085             : {
    3086           0 :         struct bgp_path_info *pi;
    3087           0 :         struct bgp_path_info *local_pi;
    3088           0 :         int ret;
    3089             : 
    3090             :         /* Find matching route entry. */
    3091           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    3092           0 :                 if (pi->extra &&
    3093           0 :                     (struct bgp_path_info *)pi->extra->parent == parent_pi)
    3094             :                         break;
    3095             : 
    3096           0 :         if (!pi)
    3097             :                 return 0;
    3098             : 
    3099           0 :         bgp_evpn_remote_ip_hash_del(vpn, pi);
    3100             : 
    3101             :         /* Mark entry for deletion */
    3102           0 :         bgp_path_info_delete(dest, pi);
    3103             : 
    3104             :         /* Perform route selection and update zebra, if required. */
    3105           0 :         ret = evpn_route_select_install(bgp, vpn, dest);
    3106             : 
    3107             :         /* if the best path is a local path with a non-zero ES
    3108             :          * sync info against the local path may need to be updated
    3109             :          * when a remote path is deleted
    3110             :          */
    3111           0 :         local_pi = bgp_evpn_route_get_local_path(bgp, dest);
    3112           0 :         if (local_pi && bgp_evpn_attr_is_local_es(local_pi->attr))
    3113           0 :                 bgp_evpn_update_type2_route_entry(bgp, vpn, dest, local_pi,
    3114             :                                                   __func__);
    3115             : 
    3116             :         return ret;
    3117             : }
    3118             : 
    3119             : /*
    3120             :  * Install route entry into VNI IP table and invoke route selection.
    3121             :  */
    3122           0 : static int install_evpn_route_entry_in_vni_ip(struct bgp *bgp,
    3123             :                                               struct bgpevpn *vpn,
    3124             :                                               const struct prefix_evpn *p,
    3125             :                                               struct bgp_path_info *parent_pi)
    3126             : {
    3127           0 :         int ret;
    3128           0 :         struct bgp_dest *dest;
    3129             : 
    3130             :         /* Ignore MAC Only Type-2 */
    3131           0 :         if ((p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) &&
    3132           0 :             (is_evpn_prefix_ipaddr_none(p) == true))
    3133             :                 return 0;
    3134             : 
    3135             :         /* Create (or fetch) route within the VNI IP table. */
    3136           0 :         dest = bgp_evpn_vni_ip_node_get(vpn->ip_table, p, parent_pi);
    3137             : 
    3138           0 :         ret = install_evpn_route_entry_in_vni_common(bgp, vpn, p, dest,
    3139             :                                                      parent_pi);
    3140             : 
    3141           0 :         bgp_dest_unlock_node(dest);
    3142             : 
    3143           0 :         return ret;
    3144             : }
    3145             : 
    3146             : /*
    3147             :  * Install route entry into VNI MAC table and invoke route selection.
    3148             :  */
    3149           0 : static int install_evpn_route_entry_in_vni_mac(struct bgp *bgp,
    3150             :                                                struct bgpevpn *vpn,
    3151             :                                                const struct prefix_evpn *p,
    3152             :                                                struct bgp_path_info *parent_pi)
    3153             : {
    3154           0 :         int ret;
    3155           0 :         struct bgp_dest *dest;
    3156             : 
    3157             :         /* Only type-2 routes go into this table */
    3158           0 :         if (p->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    3159             :                 return 0;
    3160             : 
    3161             :         /* Create (or fetch) route within the VNI MAC table. */
    3162           0 :         dest = bgp_evpn_vni_mac_node_get(vpn->mac_table, p, parent_pi);
    3163             : 
    3164           0 :         ret = install_evpn_route_entry_in_vni_common(bgp, vpn, p, dest,
    3165             :                                                      parent_pi);
    3166             : 
    3167           0 :         bgp_dest_unlock_node(dest);
    3168             : 
    3169           0 :         return ret;
    3170             : }
    3171             : 
    3172             : /*
    3173             :  * Uninstall route entry from VNI IP table and invoke route selection.
    3174             :  */
    3175           0 : static int uninstall_evpn_route_entry_in_vni_ip(struct bgp *bgp,
    3176             :                                                 struct bgpevpn *vpn,
    3177             :                                                 const struct prefix_evpn *p,
    3178             :                                                 struct bgp_path_info *parent_pi)
    3179             : {
    3180           0 :         int ret;
    3181           0 :         struct bgp_dest *dest;
    3182             : 
    3183             :         /* Ignore MAC Only Type-2 */
    3184           0 :         if ((p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) &&
    3185           0 :             (is_evpn_prefix_ipaddr_none(p) == true))
    3186             :                 return 0;
    3187             : 
    3188             :         /* Locate route within the VNI IP table. */
    3189           0 :         dest = bgp_evpn_vni_ip_node_lookup(vpn->ip_table, p, parent_pi);
    3190           0 :         if (!dest)
    3191             :                 return 0;
    3192             : 
    3193           0 :         ret = uninstall_evpn_route_entry_in_vni_common(bgp, vpn, p, dest,
    3194             :                                                        parent_pi);
    3195             : 
    3196           0 :         bgp_dest_unlock_node(dest);
    3197             : 
    3198           0 :         return ret;
    3199             : }
    3200             : 
    3201             : /*
    3202             :  * Uninstall route entry from VNI IP table and invoke route selection.
    3203             :  */
    3204             : static int
    3205           0 : uninstall_evpn_route_entry_in_vni_mac(struct bgp *bgp, struct bgpevpn *vpn,
    3206             :                                       const struct prefix_evpn *p,
    3207             :                                       struct bgp_path_info *parent_pi)
    3208             : {
    3209           0 :         int ret;
    3210           0 :         struct bgp_dest *dest;
    3211             : 
    3212             :         /* Only type-2 routes go into this table */
    3213           0 :         if (p->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
    3214             :                 return 0;
    3215             : 
    3216             :         /* Locate route within the VNI MAC table. */
    3217           0 :         dest = bgp_evpn_vni_mac_node_lookup(vpn->mac_table, p, parent_pi);
    3218           0 :         if (!dest)
    3219             :                 return 0;
    3220             : 
    3221           0 :         ret = uninstall_evpn_route_entry_in_vni_common(bgp, vpn, p, dest,
    3222             :                                                        parent_pi);
    3223             : 
    3224           0 :         bgp_dest_unlock_node(dest);
    3225             : 
    3226           0 :         return ret;
    3227             : }
    3228             : /*
    3229             :  * Uninstall route entry from the VRF routing table and send message
    3230             :  * to zebra, if appropriate.
    3231             :  */
    3232           0 : static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
    3233             :                                              const struct prefix_evpn *evp,
    3234             :                                              struct bgp_path_info *parent_pi)
    3235             : {
    3236           0 :         struct bgp_dest *dest;
    3237           0 :         struct bgp_path_info *pi;
    3238           0 :         int ret = 0;
    3239           0 :         struct prefix p;
    3240           0 :         struct prefix *pp = &p;
    3241           0 :         afi_t afi = 0;
    3242           0 :         safi_t safi = 0;
    3243             : 
    3244           0 :         memset(pp, 0, sizeof(struct prefix));
    3245           0 :         ip_prefix_from_evpn_prefix(evp, pp);
    3246             : 
    3247           0 :         if (bgp_debug_zebra(NULL))
    3248           0 :                 zlog_debug(
    3249             :                         "vrf %s: unimport evpn prefix %pFX parent %p flags 0x%x",
    3250             :                         vrf_id_to_name(bgp_vrf->vrf_id), evp, parent_pi,
    3251             :                         parent_pi->flags);
    3252             : 
    3253             :         /* Locate route within the VRF. */
    3254             :         /* NOTE: There is no RD here. */
    3255           0 :         if (is_evpn_prefix_ipaddr_v4(evp)) {
    3256           0 :                 afi = AFI_IP;
    3257           0 :                 safi = SAFI_UNICAST;
    3258           0 :                 dest = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
    3259             :         } else {
    3260           0 :                 afi = AFI_IP6;
    3261           0 :                 safi = SAFI_UNICAST;
    3262           0 :                 dest = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
    3263             :         }
    3264             : 
    3265           0 :         if (!dest)
    3266             :                 return 0;
    3267             : 
    3268             :         /* Find matching route entry. */
    3269           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    3270           0 :                 if (pi->extra
    3271           0 :                     && (struct bgp_path_info *)pi->extra->parent == parent_pi)
    3272             :                         break;
    3273             : 
    3274           0 :         if (!pi) {
    3275           0 :                 bgp_dest_unlock_node(dest);
    3276           0 :                 return 0;
    3277             :         }
    3278             : 
    3279           0 :         if (bgp_debug_zebra(NULL))
    3280           0 :                 zlog_debug("... delete dest %p (l %d) pi %p (l %d, f 0x%x)",
    3281             :                            dest, bgp_dest_get_lock_count(dest), pi, pi->lock,
    3282             :                            pi->flags);
    3283             : 
    3284             :         /* Process for route leaking. */
    3285           0 :         vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp_vrf, pi);
    3286             : 
    3287           0 :         bgp_aggregate_decrement(bgp_vrf, bgp_dest_get_prefix(dest), pi, afi,
    3288             :                                 safi);
    3289             : 
    3290             :         /* Mark entry for deletion */
    3291           0 :         bgp_path_info_delete(dest, pi);
    3292             : 
    3293             :         /* Unlink path to evpn nexthop */
    3294           0 :         bgp_evpn_path_nh_del(bgp_vrf, pi);
    3295             : 
    3296             :         /* Perform route selection and update zebra, if required. */
    3297           0 :         bgp_process(bgp_vrf, dest, afi, safi);
    3298             : 
    3299             :         /* Unlock route node. */
    3300           0 :         bgp_dest_unlock_node(dest);
    3301             : 
    3302           0 :         return ret;
    3303             : }
    3304             : 
    3305             : /*
    3306             :  * Install route entry into the VNI routing tables.
    3307             :  */
    3308           0 : static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
    3309             :                                     const struct prefix_evpn *p,
    3310             :                                     struct bgp_path_info *parent_pi)
    3311             : {
    3312           0 :         int ret = 0;
    3313             : 
    3314           0 :         if (bgp_debug_update(parent_pi->peer, NULL, NULL, 1))
    3315           0 :                 zlog_debug(
    3316             :                         "%s (%u): Installing EVPN %pFX route in VNI %u IP/MAC table",
    3317             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3318             : 
    3319           0 :         ret = install_evpn_route_entry_in_vni_mac(bgp, vpn, p, parent_pi);
    3320             : 
    3321           0 :         if (ret) {
    3322           0 :                 flog_err(
    3323             :                         EC_BGP_EVPN_FAIL,
    3324             :                         "%s (%u): Failed to install EVPN %pFX route in VNI %u MAC table",
    3325             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3326             : 
    3327           0 :                 return ret;
    3328             :         }
    3329             : 
    3330           0 :         ret = install_evpn_route_entry_in_vni_ip(bgp, vpn, p, parent_pi);
    3331             : 
    3332           0 :         if (ret) {
    3333           0 :                 flog_err(
    3334             :                         EC_BGP_EVPN_FAIL,
    3335             :                         "%s (%u): Failed to install EVPN %pFX route in VNI %u IP table",
    3336             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3337             : 
    3338           0 :                 return ret;
    3339             :         }
    3340             : 
    3341             :         return ret;
    3342             : }
    3343             : 
    3344             : /*
    3345             :  * Uninstall route entry from the VNI routing tables.
    3346             :  */
    3347           0 : static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
    3348             :                                       const struct prefix_evpn *p,
    3349             :                                       struct bgp_path_info *parent_pi)
    3350             : {
    3351           0 :         int ret = 0;
    3352             : 
    3353           0 :         if (bgp_debug_update(parent_pi->peer, NULL, NULL, 1))
    3354           0 :                 zlog_debug(
    3355             :                         "%s (%u): Uninstalling EVPN %pFX route from VNI %u IP/MAC table",
    3356             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3357             : 
    3358           0 :         ret = uninstall_evpn_route_entry_in_vni_ip(bgp, vpn, p, parent_pi);
    3359             : 
    3360           0 :         if (ret) {
    3361           0 :                 flog_err(
    3362             :                         EC_BGP_EVPN_FAIL,
    3363             :                         "%s (%u): Failed to uninstall EVPN %pFX route from VNI %u IP table",
    3364             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3365             : 
    3366           0 :                 return ret;
    3367             :         }
    3368             : 
    3369           0 :         ret = uninstall_evpn_route_entry_in_vni_mac(bgp, vpn, p, parent_pi);
    3370             : 
    3371           0 :         if (ret) {
    3372           0 :                 flog_err(
    3373             :                         EC_BGP_EVPN_FAIL,
    3374             :                         "%s (%u): Failed to uninstall EVPN %pFX route from VNI %u MAC table",
    3375             :                         vrf_id_to_name(bgp->vrf_id), bgp->vrf_id, p, vpn->vni);
    3376             : 
    3377           0 :                 return ret;
    3378             :         }
    3379             : 
    3380             :         return ret;
    3381             : }
    3382             : 
    3383             : /*
    3384             :  * Given a route entry and a VRF, see if this route entry should be
    3385             :  * imported into the VRF i.e., RTs match.
    3386             :  */
    3387           0 : static int is_route_matching_for_vrf(struct bgp *bgp_vrf,
    3388             :                                      struct bgp_path_info *pi)
    3389             : {
    3390           0 :         struct attr *attr = pi->attr;
    3391           0 :         struct ecommunity *ecom;
    3392           0 :         uint32_t i;
    3393             : 
    3394           0 :         assert(attr);
    3395             :         /* Route should have valid RT to be even considered. */
    3396           0 :         if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
    3397             :                 return 0;
    3398             : 
    3399           0 :         ecom = bgp_attr_get_ecommunity(attr);
    3400           0 :         if (!ecom || !ecom->size)
    3401             :                 return 0;
    3402             : 
    3403             :         /* For each extended community RT, see if it matches this VNI. If any RT
    3404             :          * matches, we're done.
    3405             :          */
    3406           0 :         for (i = 0; i < ecom->size; i++) {
    3407           0 :                 uint8_t *pnt;
    3408           0 :                 uint8_t type, sub_type;
    3409           0 :                 struct ecommunity_val *eval;
    3410           0 :                 struct ecommunity_val eval_tmp;
    3411           0 :                 struct vrf_irt_node *irt;
    3412             : 
    3413             :                 /* Only deal with RTs */
    3414           0 :                 pnt = (ecom->val + (i * ecom->unit_size));
    3415           0 :                 eval = (struct ecommunity_val *)(ecom->val
    3416             :                                                  + (i * ecom->unit_size));
    3417           0 :                 type = *pnt++;
    3418           0 :                 sub_type = *pnt++;
    3419           0 :                 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
    3420           0 :                         continue;
    3421             : 
    3422             :                 /* See if this RT matches specified VNIs import RTs */
    3423           0 :                 irt = lookup_vrf_import_rt(eval);
    3424           0 :                 if (irt)
    3425           0 :                         if (is_vrf_present_in_irt_vrfs(irt->vrfs, bgp_vrf))
    3426           0 :                                 return 1;
    3427             : 
    3428             :                 /* Also check for non-exact match. In this, we mask out the AS
    3429             :                  * and
    3430             :                  * only check on the local-admin sub-field. This is to
    3431             :                  * facilitate using
    3432             :                  * VNI as the RT for EBGP peering too.
    3433             :                  */
    3434           0 :                 irt = NULL;
    3435           0 :                 if (type == ECOMMUNITY_ENCODE_AS
    3436           0 :                     || type == ECOMMUNITY_ENCODE_AS4
    3437           0 :                     || type == ECOMMUNITY_ENCODE_IP) {
    3438           0 :                         memcpy(&eval_tmp, eval, ecom->unit_size);
    3439           0 :                         mask_ecom_global_admin(&eval_tmp, eval);
    3440           0 :                         irt = lookup_vrf_import_rt(&eval_tmp);
    3441             :                 }
    3442           0 :                 if (irt)
    3443           0 :                         if (is_vrf_present_in_irt_vrfs(irt->vrfs, bgp_vrf))
    3444             :                                 return 1;
    3445             :         }
    3446             : 
    3447             :         return 0;
    3448             : }
    3449             : 
    3450             : /*
    3451             :  * Given a route entry and a VNI, see if this route entry should be
    3452             :  * imported into the VNI i.e., RTs match.
    3453             :  */
    3454           0 : static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn,
    3455             :                                      struct bgp_path_info *pi)
    3456             : {
    3457           0 :         struct attr *attr = pi->attr;
    3458           0 :         struct ecommunity *ecom;
    3459           0 :         uint32_t i;
    3460             : 
    3461           0 :         assert(attr);
    3462             :         /* Route should have valid RT to be even considered. */
    3463           0 :         if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
    3464             :                 return 0;
    3465             : 
    3466           0 :         ecom = bgp_attr_get_ecommunity(attr);
    3467           0 :         if (!ecom || !ecom->size)
    3468             :                 return 0;
    3469             : 
    3470             :         /* For each extended community RT, see if it matches this VNI. If any RT
    3471             :          * matches, we're done.
    3472             :          */
    3473           0 :         for (i = 0; i < ecom->size; i++) {
    3474           0 :                 uint8_t *pnt;
    3475           0 :                 uint8_t type, sub_type;
    3476           0 :                 struct ecommunity_val *eval;
    3477           0 :                 struct ecommunity_val eval_tmp;
    3478           0 :                 struct irt_node *irt;
    3479             : 
    3480             :                 /* Only deal with RTs */
    3481           0 :                 pnt = (ecom->val + (i * ecom->unit_size));
    3482           0 :                 eval = (struct ecommunity_val *)(ecom->val
    3483             :                                                  + (i * ecom->unit_size));
    3484           0 :                 type = *pnt++;
    3485           0 :                 sub_type = *pnt++;
    3486           0 :                 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
    3487           0 :                         continue;
    3488             : 
    3489             :                 /* See if this RT matches specified VNIs import RTs */
    3490           0 :                 irt = lookup_import_rt(bgp, eval);
    3491           0 :                 if (irt)
    3492           0 :                         if (is_vni_present_in_irt_vnis(irt->vnis, vpn))
    3493           0 :                                 return 1;
    3494             : 
    3495             :                 /* Also check for non-exact match. In this, we mask out the AS
    3496             :                  * and
    3497             :                  * only check on the local-admin sub-field. This is to
    3498             :                  * facilitate using
    3499             :                  * VNI as the RT for EBGP peering too.
    3500             :                  */
    3501           0 :                 irt = NULL;
    3502           0 :                 if (type == ECOMMUNITY_ENCODE_AS
    3503           0 :                     || type == ECOMMUNITY_ENCODE_AS4
    3504           0 :                     || type == ECOMMUNITY_ENCODE_IP) {
    3505           0 :                         memcpy(&eval_tmp, eval, ecom->unit_size);
    3506           0 :                         mask_ecom_global_admin(&eval_tmp, eval);
    3507           0 :                         irt = lookup_import_rt(bgp, &eval_tmp);
    3508             :                 }
    3509           0 :                 if (irt)
    3510           0 :                         if (is_vni_present_in_irt_vnis(irt->vnis, vpn))
    3511             :                                 return 1;
    3512             :         }
    3513             : 
    3514             :         return 0;
    3515             : }
    3516             : 
    3517             : /* This API will scan evpn routes for checking attribute's rmac
    3518             :  * macthes with bgp instance router mac. It avoid installing
    3519             :  * route into bgp vrf table and remote rmac in bridge table.
    3520             :  */
    3521           0 : static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf,
    3522             :                                           const struct prefix_evpn *evp,
    3523             :                                           struct bgp_path_info *pi)
    3524             : {
    3525             :         /* evpn route could have learnt prior to L3vni has come up,
    3526             :          * perform rmac check before installing route and
    3527             :          * remote router mac.
    3528             :          * The route will be removed from global bgp table once
    3529             :          * SVI comes up with MAC and stored in hash, triggers
    3530             :          * bgp_mac_rescan_all_evpn_tables.
    3531             :          */
    3532           0 :         if (memcmp(&bgp_vrf->rmac, &pi->attr->rmac, ETH_ALEN) == 0) {
    3533           0 :                 if (bgp_debug_update(pi->peer, NULL, NULL, 1)) {
    3534           0 :                         char attr_str[BUFSIZ] = {0};
    3535             : 
    3536           0 :                         bgp_dump_attr(pi->attr, attr_str, sizeof(attr_str));
    3537             : 
    3538           0 :                         zlog_debug(
    3539             :                                 "%s: bgp %u prefix %pFX with attr %s - DENIED due to self mac",
    3540             :                                 __func__, bgp_vrf->vrf_id, evp, attr_str);
    3541             :                 }
    3542             : 
    3543           0 :                 return 1;
    3544             :         }
    3545             : 
    3546             :         return 0;
    3547             : }
    3548             : 
    3549             : /* don't import hosts that are locally attached */
    3550             : static inline bool
    3551           0 : bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf,
    3552             :                                      const struct prefix_evpn *evp,
    3553             :                                      struct bgp_path_info *pi, int install)
    3554             : {
    3555           0 :         esi_t *esi;
    3556             : 
    3557           0 :         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    3558           0 :                 esi = bgp_evpn_attr_get_esi(pi->attr);
    3559             : 
    3560             :                 /* Don't import routes that point to a local destination */
    3561           0 :                 if (bgp_evpn_attr_is_local_es(pi->attr)) {
    3562           0 :                         if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) {
    3563           0 :                                 char esi_buf[ESI_STR_LEN];
    3564             : 
    3565           0 :                                 zlog_debug(
    3566             :                                         "vrf %s of evpn prefix %pFX skipped, local es %s",
    3567             :                                         install ? "import" : "unimport", evp,
    3568             :                                         esi_to_str(esi, esi_buf,
    3569             :                                                    sizeof(esi_buf)));
    3570             :                         }
    3571           0 :                         return true;
    3572             :                 }
    3573             :         }
    3574             :         return false;
    3575             : }
    3576             : 
    3577             : /*
    3578             :  * Install or uninstall a mac-ip route in the provided vrf if
    3579             :  * there is a rt match
    3580             :  */
    3581           0 : int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf,
    3582             :                                               struct bgp_path_info *pi,
    3583             :                                               int install)
    3584             : {
    3585           0 :         int ret = 0;
    3586           0 :         const struct prefix_evpn *evp =
    3587           0 :                 (const struct prefix_evpn *)bgp_dest_get_prefix(pi->net);
    3588             : 
    3589             :         /* Consider "valid" remote routes applicable for
    3590             :          * this VRF.
    3591             :          */
    3592           0 :         if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID)
    3593             :               && pi->type == ZEBRA_ROUTE_BGP
    3594             :               && pi->sub_type == BGP_ROUTE_NORMAL))
    3595             :                 return 0;
    3596             : 
    3597           0 :         if (is_route_matching_for_vrf(bgp_vrf, pi)) {
    3598           0 :                 if (bgp_evpn_route_rmac_self_check(bgp_vrf, evp, pi))
    3599             :                         return 0;
    3600             : 
    3601             :                 /* don't import hosts that are locally attached */
    3602           0 :                 if (install && bgp_evpn_skip_vrf_import_of_local_es(
    3603             :                                        bgp_vrf, evp, pi, install))
    3604             :                         return 0;
    3605             : 
    3606           0 :                 if (install)
    3607           0 :                         ret = install_evpn_route_entry_in_vrf(bgp_vrf, evp, pi);
    3608             :                 else
    3609           0 :                         ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf, evp,
    3610             :                                                                 pi);
    3611             : 
    3612           0 :                 if (ret)
    3613           0 :                         flog_err(EC_BGP_EVPN_FAIL,
    3614             :                                  "Failed to %s EVPN %pFX route in VRF %s",
    3615             :                                  install ? "install" : "uninstall", evp,
    3616             :                                  vrf_id_to_name(bgp_vrf->vrf_id));
    3617             :         }
    3618             : 
    3619             :         return ret;
    3620             : }
    3621             : 
    3622             : /*
    3623             :  * Install or uninstall mac-ip routes are appropriate for this
    3624             :  * particular VRF.
    3625             :  */
    3626           0 : static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
    3627             : {
    3628           0 :         afi_t afi;
    3629           0 :         safi_t safi;
    3630           0 :         struct bgp_dest *rd_dest, *dest;
    3631           0 :         struct bgp_table *table;
    3632           0 :         struct bgp_path_info *pi;
    3633           0 :         int ret;
    3634           0 :         struct bgp *bgp_evpn = NULL;
    3635             : 
    3636           0 :         afi = AFI_L2VPN;
    3637           0 :         safi = SAFI_EVPN;
    3638           0 :         bgp_evpn = bgp_get_evpn();
    3639           0 :         if (!bgp_evpn)
    3640             :                 return -1;
    3641             : 
    3642             :         /* Walk entire global routing table and evaluate routes which could be
    3643             :          * imported into this VRF. Note that we need to loop through all global
    3644             :          * routes to determine which route matches the import rt on vrf
    3645             :          */
    3646           0 :         for (rd_dest = bgp_table_top(bgp_evpn->rib[afi][safi]); rd_dest;
    3647           0 :              rd_dest = bgp_route_next(rd_dest)) {
    3648           0 :                 table = bgp_dest_get_bgp_table_info(rd_dest);
    3649           0 :                 if (!table)
    3650           0 :                         continue;
    3651             : 
    3652           0 :                 for (dest = bgp_table_top(table); dest;
    3653           0 :                      dest = bgp_route_next(dest)) {
    3654           0 :                         const struct prefix_evpn *evp =
    3655           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    3656             :                                         dest);
    3657             : 
    3658             :                         /* if not mac-ip route skip this route */
    3659           0 :                         if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    3660             :                               || evp->prefix.route_type
    3661             :                                          == BGP_EVPN_IP_PREFIX_ROUTE))
    3662           0 :                                 continue;
    3663             : 
    3664             :                         /* if not a mac+ip route skip this route */
    3665           0 :                         if (!(is_evpn_prefix_ipaddr_v4(evp)
    3666           0 :                               || is_evpn_prefix_ipaddr_v6(evp)))
    3667           0 :                                 continue;
    3668             : 
    3669           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
    3670           0 :                              pi = pi->next) {
    3671           0 :                                 ret = bgp_evpn_route_entry_install_if_vrf_match(
    3672             :                                         bgp_vrf, pi, install);
    3673           0 :                                 if (ret)
    3674           0 :                                         return ret;
    3675             :                         }
    3676             :                 }
    3677             :         }
    3678             : 
    3679             :         return 0;
    3680             : }
    3681             : 
    3682             : /*
    3683             :  * Install or uninstall routes of specified type that are appropriate for this
    3684             :  * particular VNI.
    3685             :  */
    3686           0 : static int install_uninstall_routes_for_vni(struct bgp *bgp,
    3687             :                                             struct bgpevpn *vpn,
    3688             :                                             bgp_evpn_route_type rtype,
    3689             :                                             int install)
    3690             : {
    3691           0 :         afi_t afi;
    3692           0 :         safi_t safi;
    3693           0 :         struct bgp_dest *rd_dest, *dest;
    3694           0 :         struct bgp_table *table;
    3695           0 :         struct bgp_path_info *pi;
    3696           0 :         int ret;
    3697             : 
    3698           0 :         afi = AFI_L2VPN;
    3699           0 :         safi = SAFI_EVPN;
    3700             : 
    3701             :         /* Walk entire global routing table and evaluate routes which could be
    3702             :          * imported into this VPN. Note that we cannot just look at the routes
    3703             :          * for
    3704             :          * the VNI's RD - remote routes applicable for this VNI could have any
    3705             :          * RD.
    3706             :          */
    3707             :         /* EVPN routes are a 2-level table. */
    3708           0 :         for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
    3709           0 :              rd_dest = bgp_route_next(rd_dest)) {
    3710           0 :                 table = bgp_dest_get_bgp_table_info(rd_dest);
    3711           0 :                 if (!table)
    3712           0 :                         continue;
    3713             : 
    3714           0 :                 for (dest = bgp_table_top(table); dest;
    3715           0 :                      dest = bgp_route_next(dest)) {
    3716           0 :                         const struct prefix_evpn *evp =
    3717           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    3718             :                                         dest);
    3719             : 
    3720           0 :                         if (evp->prefix.route_type != rtype)
    3721           0 :                                 continue;
    3722             : 
    3723           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
    3724           0 :                              pi = pi->next) {
    3725             :                                 /* Consider "valid" remote routes applicable for
    3726             :                                  * this VNI. */
    3727           0 :                                 if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID)
    3728             :                                       && pi->type == ZEBRA_ROUTE_BGP
    3729             :                                       && pi->sub_type == BGP_ROUTE_NORMAL))
    3730           0 :                                         continue;
    3731             : 
    3732           0 :                                 if (is_route_matching_for_vni(bgp, vpn, pi)) {
    3733           0 :                                         if (install)
    3734           0 :                                                 ret = install_evpn_route_entry(
    3735             :                                                         bgp, vpn, evp, pi);
    3736             :                                         else
    3737           0 :                                                 ret = uninstall_evpn_route_entry(
    3738             :                                                         bgp, vpn, evp, pi);
    3739             : 
    3740           0 :                                         if (ret) {
    3741           0 :                                                 flog_err(
    3742             :                                                         EC_BGP_EVPN_FAIL,
    3743             :                                                         "%u: Failed to %s EVPN %s route in VNI %u",
    3744             :                                                         bgp->vrf_id,
    3745             :                                                         install ? "install"
    3746             :                                                                 : "uninstall",
    3747             :                                                         rtype == BGP_EVPN_MAC_IP_ROUTE
    3748             :                                                                 ? "MACIP"
    3749             :                                                                 : "IMET",
    3750             :                                                         vpn->vni);
    3751             : 
    3752           0 :                                                 bgp_dest_unlock_node(rd_dest);
    3753           0 :                                                 bgp_dest_unlock_node(dest);
    3754           0 :                                                 return ret;
    3755             :                                         }
    3756             :                                 }
    3757             :                         }
    3758             :                 }
    3759             :         }
    3760             : 
    3761             :         return 0;
    3762             : }
    3763             : 
    3764             : /* Install any existing remote routes applicable for this VRF into VRF RIB. This
    3765             :  * is invoked upon l3vni-add or l3vni import rt change
    3766             :  */
    3767           0 : static int install_routes_for_vrf(struct bgp *bgp_vrf)
    3768             : {
    3769           0 :         install_uninstall_routes_for_vrf(bgp_vrf, 1);
    3770           0 :         return 0;
    3771             : }
    3772             : 
    3773             : /*
    3774             :  * Install any existing remote routes applicable for this VNI into its
    3775             :  * routing table. This is invoked when a VNI becomes "live" or its Import
    3776             :  * RT is changed.
    3777             :  */
    3778           0 : static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
    3779             : {
    3780           0 :         int ret;
    3781             : 
    3782             :         /* Install type-3 routes followed by type-2 routes - the ones applicable
    3783             :          * for this VNI.
    3784             :          */
    3785           0 :         ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
    3786             :                                                1);
    3787           0 :         if (ret)
    3788             :                 return ret;
    3789             : 
    3790           0 :         ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
    3791             :                                                1);
    3792           0 :         if (ret)
    3793             :                 return ret;
    3794             : 
    3795           0 :         return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
    3796             :                                                 1);
    3797             : }
    3798             : 
    3799             : /* uninstall routes from l3vni vrf. */
    3800           0 : static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
    3801             : {
    3802           0 :         install_uninstall_routes_for_vrf(bgp_vrf, 0);
    3803           0 :         return 0;
    3804             : }
    3805             : 
    3806             : /*
    3807             :  * Uninstall any existing remote routes for this VNI. One scenario in which
    3808             :  * this is invoked is upon an import RT change.
    3809             :  */
    3810           0 : static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
    3811             : {
    3812           0 :         int ret;
    3813             : 
    3814             :         /* Uninstall type-2 routes followed by type-3 routes - the ones
    3815             :          * applicable
    3816             :          * for this VNI.
    3817             :          */
    3818           0 :         ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
    3819             :                                                0);
    3820           0 :         if (ret)
    3821             :                 return ret;
    3822             : 
    3823           0 :         ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
    3824             :                                                0);
    3825           0 :         if (ret)
    3826             :                 return ret;
    3827             : 
    3828             : 
    3829           0 :         return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
    3830             :                                                 0);
    3831             : }
    3832             : 
    3833             : /*
    3834             :  * Install or uninstall route in matching VRFs (list).
    3835             :  */
    3836           0 : static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi,
    3837             :                                            safi_t safi, struct prefix_evpn *evp,
    3838             :                                            struct bgp_path_info *pi,
    3839             :                                            struct list *vrfs, int install)
    3840             : {
    3841           0 :         struct bgp *bgp_vrf;
    3842           0 :         struct listnode *node, *nnode;
    3843             : 
    3844             :         /* Only type-2/type-5 routes go into a VRF */
    3845           0 :         if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    3846             :               || evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE))
    3847             :                 return 0;
    3848             : 
    3849             :         /* if it is type-2 route and not a mac+ip route skip this route */
    3850           0 :         if ((evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
    3851           0 :             && !(is_evpn_prefix_ipaddr_v4(evp)
    3852           0 :                  || is_evpn_prefix_ipaddr_v6(evp)))
    3853             :                 return 0;
    3854             : 
    3855           0 :         for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
    3856           0 :                 int ret;
    3857             : 
    3858             :                 /* don't import hosts that are locally attached */
    3859           0 :                 if (install && bgp_evpn_skip_vrf_import_of_local_es(
    3860             :                                        bgp_vrf, evp, pi, install))
    3861             :                         return 0;
    3862             : 
    3863           0 :                 if (install)
    3864           0 :                         ret = install_evpn_route_entry_in_vrf(bgp_vrf, evp, pi);
    3865             :                 else
    3866           0 :                         ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf, evp,
    3867             :                                                                 pi);
    3868             : 
    3869           0 :                 if (ret) {
    3870           0 :                         flog_err(EC_BGP_EVPN_FAIL,
    3871             :                                  "%u: Failed to %s prefix %pFX in VRF %s",
    3872             :                                  bgp_def->vrf_id,
    3873             :                                  install ? "install" : "uninstall", evp,
    3874             :                                  vrf_id_to_name(bgp_vrf->vrf_id));
    3875           0 :                         return ret;
    3876             :                 }
    3877             :         }
    3878             : 
    3879             :         return 0;
    3880             : }
    3881             : 
    3882             : /*
    3883             :  * Install or uninstall route in matching VNIs (list).
    3884             :  */
    3885           0 : static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi,
    3886             :                                            safi_t safi, struct prefix_evpn *evp,
    3887             :                                            struct bgp_path_info *pi,
    3888             :                                            struct list *vnis, int install)
    3889             : {
    3890           0 :         struct bgpevpn *vpn;
    3891           0 :         struct listnode *node, *nnode;
    3892             : 
    3893           0 :         for (ALL_LIST_ELEMENTS(vnis, node, nnode, vpn)) {
    3894           0 :                 int ret;
    3895             : 
    3896           0 :                 if (!is_vni_live(vpn))
    3897           0 :                         continue;
    3898             : 
    3899           0 :                 if (install)
    3900           0 :                         ret = install_evpn_route_entry(bgp, vpn, evp, pi);
    3901             :                 else
    3902           0 :                         ret = uninstall_evpn_route_entry(bgp, vpn, evp, pi);
    3903             : 
    3904           0 :                 if (ret) {
    3905           0 :                         flog_err(EC_BGP_EVPN_FAIL,
    3906             :                                  "%u: Failed to %s EVPN %s route in VNI %u",
    3907             :                                  bgp->vrf_id, install ? "install" : "uninstall",
    3908             :                                  evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    3909             :                                          ? "MACIP"
    3910             :                                          : "IMET",
    3911             :                                  vpn->vni);
    3912           0 :                         return ret;
    3913             :                 }
    3914             :         }
    3915             : 
    3916             :         return 0;
    3917             : }
    3918             : 
    3919             : /*
    3920             :  * Install or uninstall route for appropriate VNIs/ESIs.
    3921             :  */
    3922           0 : static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi,
    3923             :                                             safi_t safi, const struct prefix *p,
    3924             :                                             struct bgp_path_info *pi,
    3925             :                                             int import, bool in_vni_rt,
    3926             :                                             bool in_vrf_rt)
    3927             : {
    3928           0 :         struct prefix_evpn *evp = (struct prefix_evpn *)p;
    3929           0 :         struct attr *attr = pi->attr;
    3930           0 :         struct ecommunity *ecom;
    3931           0 :         uint32_t i;
    3932           0 :         struct prefix_evpn ad_evp;
    3933             : 
    3934           0 :         assert(attr);
    3935             : 
    3936             :         /* Only type-1, type-2, type-3, type-4 and type-5
    3937             :          * are supported currently
    3938             :          */
    3939           0 :         if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    3940             :               || evp->prefix.route_type == BGP_EVPN_IMET_ROUTE
    3941             :               || evp->prefix.route_type == BGP_EVPN_ES_ROUTE
    3942             :               || evp->prefix.route_type == BGP_EVPN_AD_ROUTE
    3943             :               || evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE))
    3944             :                 return 0;
    3945             : 
    3946             :         /* If we don't have Route Target, nothing much to do. */
    3947           0 :         if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
    3948             :                 return 0;
    3949             : 
    3950             :         /* EAD prefix in the global table doesn't include the VTEP-IP so
    3951             :          * we need to create a different copy for the VNI
    3952             :          */
    3953           0 :         if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE)
    3954           0 :                 evp = evpn_type1_prefix_vni_ip_copy(&ad_evp, evp,
    3955             :                                                     attr->nexthop);
    3956             : 
    3957           0 :         ecom = bgp_attr_get_ecommunity(attr);
    3958           0 :         if (!ecom || !ecom->size)
    3959             :                 return -1;
    3960             : 
    3961             :         /* An EVPN route belongs to a VNI or a VRF or an ESI based on the RTs
    3962             :          * attached to the route */
    3963           0 :         for (i = 0; i < ecom->size; i++) {
    3964           0 :                 uint8_t *pnt;
    3965           0 :                 uint8_t type, sub_type;
    3966           0 :                 struct ecommunity_val *eval;
    3967           0 :                 struct ecommunity_val eval_tmp;
    3968           0 :                 struct irt_node *irt;    /* import rt for l2vni */
    3969           0 :                 struct vrf_irt_node *vrf_irt; /* import rt for l3vni */
    3970           0 :                 struct bgp_evpn_es *es;
    3971             : 
    3972             :                 /* Only deal with RTs */
    3973           0 :                 pnt = (ecom->val + (i * ecom->unit_size));
    3974           0 :                 eval = (struct ecommunity_val *)(ecom->val
    3975             :                                                  + (i * ecom->unit_size));
    3976           0 :                 type = *pnt++;
    3977           0 :                 sub_type = *pnt++;
    3978           0 :                 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
    3979           0 :                         continue;
    3980             : 
    3981             :                 /* non-local MAC-IP routes in the global route table are linked
    3982             :                  * to the destination ES
    3983             :                  */
    3984           0 :                 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
    3985           0 :                         bgp_evpn_path_es_link(pi, 0,
    3986             :                                               bgp_evpn_attr_get_esi(pi->attr));
    3987             : 
    3988             :                 /*
    3989             :                  * macip routes (type-2) are imported into VNI and VRF tables.
    3990             :                  * IMET route is imported into VNI table.
    3991             :                  * prefix routes are imported into VRF table.
    3992             :                  */
    3993           0 :                 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE ||
    3994             :                     evp->prefix.route_type == BGP_EVPN_IMET_ROUTE ||
    3995           0 :                     evp->prefix.route_type == BGP_EVPN_AD_ROUTE ||
    3996             :                     evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
    3997             : 
    3998           0 :                         irt = in_vni_rt ? lookup_import_rt(bgp, eval) : NULL;
    3999           0 :                         if (irt)
    4000           0 :                                 install_uninstall_route_in_vnis(
    4001             :                                         bgp, afi, safi, evp, pi, irt->vnis,
    4002             :                                         import);
    4003             : 
    4004           0 :                         vrf_irt = in_vrf_rt ? lookup_vrf_import_rt(eval) : NULL;
    4005           0 :                         if (vrf_irt)
    4006           0 :                                 install_uninstall_route_in_vrfs(
    4007             :                                         bgp, afi, safi, evp, pi, vrf_irt->vrfs,
    4008             :                                         import);
    4009             : 
    4010             :                         /* Also check for non-exact match.
    4011             :                          * In this, we mask out the AS and
    4012             :                          * only check on the local-admin sub-field.
    4013             :                          * This is to facilitate using
    4014             :                          * VNI as the RT for EBGP peering too.
    4015             :                          */
    4016           0 :                         irt = NULL;
    4017           0 :                         vrf_irt = NULL;
    4018           0 :                         if (type == ECOMMUNITY_ENCODE_AS
    4019           0 :                             || type == ECOMMUNITY_ENCODE_AS4
    4020           0 :                             || type == ECOMMUNITY_ENCODE_IP) {
    4021           0 :                                 memcpy(&eval_tmp, eval, ecom->unit_size);
    4022           0 :                                 mask_ecom_global_admin(&eval_tmp, eval);
    4023           0 :                                 if (in_vni_rt)
    4024           0 :                                         irt = lookup_import_rt(bgp, &eval_tmp);
    4025           0 :                                 if (in_vrf_rt)
    4026           0 :                                         vrf_irt =
    4027           0 :                                                 lookup_vrf_import_rt(&eval_tmp);
    4028             :                         }
    4029             : 
    4030           0 :                         if (irt)
    4031           0 :                                 install_uninstall_route_in_vnis(
    4032             :                                         bgp, afi, safi, evp, pi, irt->vnis,
    4033             :                                         import);
    4034           0 :                         if (vrf_irt)
    4035           0 :                                 install_uninstall_route_in_vrfs(
    4036             :                                         bgp, afi, safi, evp, pi, vrf_irt->vrfs,
    4037             :                                         import);
    4038             :                 }
    4039             : 
    4040             :                 /* es route is imported into the es table */
    4041           0 :                 if (evp->prefix.route_type == BGP_EVPN_ES_ROUTE) {
    4042             : 
    4043             :                         /* we will match based on the entire esi to avoid
    4044             :                          * import of an es route for esi2 into esi1
    4045             :                          */
    4046           0 :                         es = bgp_evpn_es_find(&evp->prefix.es_addr.esi);
    4047           0 :                         if (es && bgp_evpn_is_es_local(es))
    4048           0 :                                 bgp_evpn_es_route_install_uninstall(
    4049             :                                         bgp, es, afi, safi, evp, pi, import);
    4050             :                 }
    4051             :         }
    4052             : 
    4053             :         return 0;
    4054             : }
    4055             : 
    4056             : /*
    4057             :  * Install or uninstall route for appropriate VNIs/ESIs.
    4058             :  */
    4059           0 : static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
    4060             :                                         const struct prefix *p,
    4061             :                                         struct bgp_path_info *pi, int import)
    4062             : {
    4063           0 :         return bgp_evpn_install_uninstall_table(bgp, afi, safi, p, pi, import,
    4064             :                                                 true, true);
    4065             : }
    4066             : 
    4067           0 : void bgp_evpn_import_type2_route(struct bgp_path_info *pi, int import)
    4068             : {
    4069           0 :         struct bgp *bgp_evpn;
    4070             : 
    4071           0 :         bgp_evpn = bgp_get_evpn();
    4072           0 :         if (!bgp_evpn)
    4073             :                 return;
    4074             : 
    4075           0 :         install_uninstall_evpn_route(bgp_evpn, AFI_L2VPN, SAFI_EVPN,
    4076           0 :                                      &pi->net->p, pi, import);
    4077             : }
    4078             : 
    4079             : /*
    4080             :  * delete and withdraw all ipv4 and ipv6 routes in the vrf table as type-5
    4081             :  * routes
    4082             :  */
    4083           0 : static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
    4084             : {
    4085             :         /* Delete ipv4 default route and withdraw from peers */
    4086           0 :         if (evpn_default_originate_set(bgp_vrf, AFI_IP, SAFI_UNICAST))
    4087           0 :                 bgp_evpn_install_uninstall_default_route(bgp_vrf, AFI_IP,
    4088             :                                                          SAFI_UNICAST, false);
    4089             : 
    4090             :         /* delete all ipv4 routes and withdraw from peers */
    4091           0 :         if (advertise_type5_routes(bgp_vrf, AFI_IP))
    4092           0 :                 bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
    4093             : 
    4094             :         /* Delete ipv6 default route and withdraw from peers */
    4095           0 :         if (evpn_default_originate_set(bgp_vrf, AFI_IP6, SAFI_UNICAST))
    4096           0 :                 bgp_evpn_install_uninstall_default_route(bgp_vrf, AFI_IP6,
    4097             :                                                          SAFI_UNICAST, false);
    4098             : 
    4099             :         /* delete all ipv6 routes and withdraw from peers */
    4100           0 :         if (advertise_type5_routes(bgp_vrf, AFI_IP6))
    4101           0 :                 bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
    4102           0 : }
    4103             : 
    4104             : /*
    4105             :  * update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5
    4106             :  * routes
    4107             :  */
    4108           0 : void update_advertise_vrf_routes(struct bgp *bgp_vrf)
    4109             : {
    4110           0 :         struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */
    4111             : 
    4112           0 :         bgp_evpn = bgp_get_evpn();
    4113           0 :         if (!bgp_evpn)
    4114             :                 return;
    4115             : 
    4116             :         /* update all ipv4 routes */
    4117           0 :         if (advertise_type5_routes(bgp_vrf, AFI_IP))
    4118           0 :                 bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
    4119             : 
    4120             :         /* update ipv4 default route and withdraw from peers */
    4121           0 :         if (evpn_default_originate_set(bgp_vrf, AFI_IP, SAFI_UNICAST))
    4122           0 :                 bgp_evpn_install_uninstall_default_route(bgp_vrf, AFI_IP,
    4123             :                                                          SAFI_UNICAST, true);
    4124             : 
    4125             :         /* update all ipv6 routes */
    4126           0 :         if (advertise_type5_routes(bgp_vrf, AFI_IP6))
    4127           0 :                 bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
    4128             : 
    4129             :         /* update ipv6 default route and withdraw from peers */
    4130           0 :         if (evpn_default_originate_set(bgp_vrf, AFI_IP6, SAFI_UNICAST))
    4131           0 :                 bgp_evpn_install_uninstall_default_route(bgp_vrf, AFI_IP6,
    4132             :                                                          SAFI_UNICAST, true);
    4133             : 
    4134             : }
    4135             : 
    4136             : /*
    4137             :  * update and advertise local routes for a VRF as type-5 routes.
    4138             :  * This is invoked upon RD change for a VRF. Note taht the processing is only
    4139             :  * done in the global route table using the routes which already exist in the
    4140             :  * VRF routing table
    4141             :  */
    4142           0 : static void update_router_id_vrf(struct bgp *bgp_vrf)
    4143             : {
    4144             :         /* skip if the RD is configured */
    4145           0 :         if (is_vrf_rd_configured(bgp_vrf))
    4146             :                 return;
    4147             : 
    4148             :         /* derive the RD for the VRF based on new router-id */
    4149           0 :         bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
    4150             : 
    4151             :         /* update advertise ipv4|ipv6 routes as type-5 routes */
    4152           0 :         update_advertise_vrf_routes(bgp_vrf);
    4153             : }
    4154             : 
    4155             : /*
    4156             :  * Delete and withdraw all type-5 routes  for the RD corresponding to VRF.
    4157             :  * This is invoked upon VRF RD change. The processing is done only from global
    4158             :  * table.
    4159             :  */
    4160           0 : static void withdraw_router_id_vrf(struct bgp *bgp_vrf)
    4161             : {
    4162             :         /* skip if the RD is configured */
    4163           0 :         if (is_vrf_rd_configured(bgp_vrf))
    4164             :                 return;
    4165             : 
    4166             :         /* delete/withdraw ipv4|ipv6 routes as type-5 routes */
    4167           0 :         delete_withdraw_vrf_routes(bgp_vrf);
    4168             : }
    4169             : 
    4170           0 : static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn,
    4171             :                                        struct bgp_dest *dest)
    4172             : {
    4173           0 :         struct bgp_dest *global_dest;
    4174           0 :         struct bgp_path_info *pi, *global_pi;
    4175           0 :         struct attr *attr;
    4176           0 :         afi_t afi = AFI_L2VPN;
    4177           0 :         safi_t safi = SAFI_EVPN;
    4178             : 
    4179           0 :         struct prefix_evpn tmp_evp;
    4180           0 :         const struct prefix_evpn *evp =
    4181           0 :                 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    4182             : 
    4183             :         /*
    4184             :          * We have already processed type-3 routes.
    4185             :          * Process only type-1 and type-2 routes here.
    4186             :          */
    4187           0 :         if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE &&
    4188             :             evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
    4189           0 :                 return;
    4190             : 
    4191           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    4192           0 :                 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP &&
    4193             :                     pi->sub_type == BGP_ROUTE_STATIC)
    4194             :                         break;
    4195           0 :         if (!pi)
    4196             :                 return;
    4197             : 
    4198             :         /*
    4199             :          * VNI table MAC-IP prefixes don't have MAC so make sure it's
    4200             :          * set from path info here.
    4201             :          */
    4202           0 :         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    4203           0 :                 if (is_evpn_prefix_ipaddr_none(evp)) {
    4204             :                         /* VNI MAC -> Global */
    4205           0 :                         evpn_type2_prefix_global_copy(
    4206             :                                 &tmp_evp, evp, NULL /* mac */,
    4207           0 :                                 evpn_type2_path_info_get_ip(pi));
    4208             :                 } else {
    4209             :                         /* VNI IP -> Global */
    4210           0 :                         evpn_type2_prefix_global_copy(
    4211           0 :                                 &tmp_evp, evp, evpn_type2_path_info_get_mac(pi),
    4212             :                                 NULL /* ip */);
    4213             :                 }
    4214             :         } else {
    4215           0 :                 memcpy(&tmp_evp, evp, sizeof(tmp_evp));
    4216             :         }
    4217             : 
    4218             :         /* Create route in global routing table using this route entry's
    4219             :          * attribute.
    4220             :          */
    4221           0 :         attr = pi->attr;
    4222           0 :         global_dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
    4223             :                                                &tmp_evp, &vpn->prd, NULL);
    4224           0 :         assert(global_dest);
    4225             : 
    4226           0 :         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
    4227             :                 /* Type-2 route */
    4228           0 :                 update_evpn_route_entry(
    4229             :                         bgp, vpn, afi, safi, global_dest, attr, NULL /* mac */,
    4230             :                         NULL /* ip */, 1, &global_pi, 0,
    4231             :                         mac_mobility_seqnum(attr), false /* setup_sync */,
    4232             :                         NULL /* old_is_sync */);
    4233             :         } else {
    4234             :                 /* Type-1 route */
    4235           0 :                 struct bgp_evpn_es *es;
    4236           0 :                 int route_changed = 0;
    4237             : 
    4238           0 :                 es = bgp_evpn_es_find(&evp->prefix.ead_addr.esi);
    4239           0 :                 bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, global_dest,
    4240             :                                          attr, &global_pi, &route_changed);
    4241             :         }
    4242             : 
    4243             :         /* Schedule for processing and unlock node. */
    4244           0 :         bgp_process(bgp, global_dest, afi, safi);
    4245           0 :         bgp_dest_unlock_node(global_dest);
    4246             : }
    4247             : 
    4248             : /*
    4249             :  * Update and advertise local routes for a VNI. Invoked upon router-id
    4250             :  * change. Note that the processing is done only on the global route table
    4251             :  * using routes that already exist in the per-VNI table.
    4252             :  */
    4253           0 : static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
    4254             : {
    4255           0 :         struct prefix_evpn p;
    4256           0 :         struct bgp_dest *dest, *global_dest;
    4257           0 :         struct bgp_path_info *pi;
    4258           0 :         struct attr *attr;
    4259           0 :         afi_t afi = AFI_L2VPN;
    4260           0 :         safi_t safi = SAFI_EVPN;
    4261             : 
    4262             :         /* Locate type-3 route for VNI in the per-VNI table and use its
    4263             :          * attributes to create and advertise the type-3 route for this VNI
    4264             :          * in the global table.
    4265             :          *
    4266             :          * RT-3 only if doing head-end replication
    4267             :          */
    4268           0 :         if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
    4269             :                                 == VXLAN_FLOOD_HEAD_END_REPL) {
    4270           0 :                 build_evpn_type3_prefix(&p, vpn->originator_ip);
    4271           0 :                 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
    4272           0 :                 if (!dest) /* unexpected */
    4273           0 :                         return;
    4274           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    4275           0 :                         if (pi->peer == bgp->peer_self &&
    4276             :                             pi->type == ZEBRA_ROUTE_BGP
    4277           0 :                             && pi->sub_type == BGP_ROUTE_STATIC)
    4278             :                                 break;
    4279           0 :                 if (!pi) {
    4280           0 :                         bgp_dest_unlock_node(dest);
    4281           0 :                         return;
    4282             :                 }
    4283             : 
    4284           0 :                 attr = pi->attr;
    4285             : 
    4286           0 :                 global_dest = bgp_evpn_global_node_get(
    4287             :                         bgp->rib[afi][safi], afi, safi, &p, &vpn->prd, NULL);
    4288           0 :                 update_evpn_route_entry(
    4289             :                         bgp, vpn, afi, safi, global_dest, attr, NULL /* mac */,
    4290             :                         NULL /* ip */, 1, &pi, 0, mac_mobility_seqnum(attr),
    4291             :                         false /* setup_sync */, NULL /* old_is_sync */);
    4292             : 
    4293             :                 /* Schedule for processing and unlock node. */
    4294           0 :                 bgp_process(bgp, global_dest, afi, safi);
    4295           0 :                 bgp_dest_unlock_node(global_dest);
    4296             :         }
    4297             : 
    4298             :         /* Now, walk this VNI's MAC & IP route table and use the route and its
    4299             :          * attribute to create and schedule route in global table.
    4300             :          */
    4301           0 :         for (dest = bgp_table_top(vpn->mac_table); dest;
    4302           0 :              dest = bgp_route_next(dest))
    4303           0 :                 update_advertise_vni_route(bgp, vpn, dest);
    4304             : 
    4305           0 :         for (dest = bgp_table_top(vpn->ip_table); dest;
    4306           0 :              dest = bgp_route_next(dest))
    4307           0 :                 update_advertise_vni_route(bgp, vpn, dest);
    4308             : }
    4309             : 
    4310             : /*
    4311             :  * Delete (and withdraw) local routes for a VNI - only from the global
    4312             :  * table. Invoked upon router-id change.
    4313             :  */
    4314           0 : static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
    4315             : {
    4316           0 :         struct prefix_evpn p;
    4317           0 :         struct bgp_dest *global_dest;
    4318           0 :         struct bgp_path_info *pi;
    4319           0 :         afi_t afi = AFI_L2VPN;
    4320           0 :         safi_t safi = SAFI_EVPN;
    4321             : 
    4322             :         /* Delete and withdraw locally learnt type-2 routes (MACIP)
    4323             :          * for this VNI - from the global table.
    4324             :          */
    4325           0 :         delete_global_type2_routes(bgp, vpn);
    4326             : 
    4327             :         /* Remove type-3 route for this VNI from global table. */
    4328           0 :         build_evpn_type3_prefix(&p, vpn->originator_ip);
    4329           0 :         global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
    4330             :                                                   safi, &p, &vpn->prd, NULL);
    4331           0 :         if (global_dest) {
    4332             :                 /* Delete route entry in the global EVPN table. */
    4333           0 :                 delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
    4334             : 
    4335             :                 /* Schedule for processing - withdraws to peers happen from
    4336             :                  * this table.
    4337             :                  */
    4338           0 :                 if (pi)
    4339           0 :                         bgp_process(bgp, global_dest, afi, safi);
    4340           0 :                 bgp_dest_unlock_node(global_dest);
    4341             :         }
    4342             : 
    4343             : 
    4344           0 :         delete_global_ead_evi_routes(bgp, vpn);
    4345           0 :         return 0;
    4346             : }
    4347             : 
    4348             : /*
    4349             :  * Handle router-id change. Update and advertise local routes corresponding
    4350             :  * to this VNI from peers. Note that this is invoked after updating the
    4351             :  * router-id. The routes in the per-VNI table are used to create routes in
    4352             :  * the global table and schedule them.
    4353             :  */
    4354           0 : static void update_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp)
    4355             : {
    4356           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    4357             : 
    4358             :         /* Skip VNIs with configured RD. */
    4359           0 :         if (is_rd_configured(vpn))
    4360             :                 return;
    4361             : 
    4362           0 :         bgp_evpn_derive_auto_rd(bgp, vpn);
    4363           0 :         update_advertise_vni_routes(bgp, vpn);
    4364             : }
    4365             : 
    4366             : /*
    4367             :  * Handle router-id change. Delete and withdraw local routes corresponding
    4368             :  * to this VNI from peers. Note that this is invoked prior to updating
    4369             :  * the router-id and is done only on the global route table, the routes
    4370             :  * are needed in the per-VNI table to re-advertise with new router id.
    4371             :  */
    4372           0 : static void withdraw_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp)
    4373             : {
    4374           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    4375             : 
    4376             :         /* Skip VNIs with configured RD. */
    4377           0 :         if (is_rd_configured(vpn))
    4378             :                 return;
    4379             : 
    4380           0 :         delete_withdraw_vni_routes(bgp, vpn);
    4381             : }
    4382             : 
    4383             : /*
    4384             :  * Create RT-3 for a VNI and schedule for processing and advertisement.
    4385             :  * This is invoked upon flooding mode changing to head-end replication.
    4386             :  */
    4387           0 : static void create_advertise_type3(struct hash_bucket *bucket, void *data)
    4388             : {
    4389           0 :         struct bgpevpn *vpn = bucket->data;
    4390           0 :         struct bgp *bgp = data;
    4391           0 :         struct prefix_evpn p;
    4392             : 
    4393           0 :         if (!vpn || !is_vni_live(vpn) ||
    4394           0 :                 bgp_evpn_vni_flood_mode_get(bgp, vpn)
    4395             :                                         != VXLAN_FLOOD_HEAD_END_REPL)
    4396           0 :                 return;
    4397             : 
    4398           0 :         build_evpn_type3_prefix(&p, vpn->originator_ip);
    4399           0 :         if (update_evpn_route(bgp, vpn, &p, 0, 0, NULL))
    4400           0 :                 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
    4401             :                          "Type3 route creation failure for VNI %u", vpn->vni);
    4402             : }
    4403             : 
    4404             : /*
    4405             :  * Delete RT-3 for a VNI and schedule for processing and withdrawal.
    4406             :  * This is invoked upon flooding mode changing to drop BUM packets.
    4407             :  */
    4408           0 : static void delete_withdraw_type3(struct hash_bucket *bucket, void *data)
    4409             : {
    4410           0 :         struct bgpevpn *vpn = bucket->data;
    4411           0 :         struct bgp *bgp = data;
    4412           0 :         struct prefix_evpn p;
    4413             : 
    4414           0 :         if (!vpn || !is_vni_live(vpn))
    4415           0 :                 return;
    4416             : 
    4417           0 :         build_evpn_type3_prefix(&p, vpn->originator_ip);
    4418           0 :         delete_evpn_route(bgp, vpn, &p);
    4419             : }
    4420             : 
    4421             : /*
    4422             :  * Process received EVPN type-2 route (advertise or withdraw).
    4423             :  */
    4424           0 : static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
    4425             :                                struct attr *attr, uint8_t *pfx, int psize,
    4426             :                                uint32_t addpath_id)
    4427             : {
    4428           0 :         struct prefix_rd prd;
    4429           0 :         struct prefix_evpn p = {};
    4430           0 :         struct bgp_route_evpn evpn = {};
    4431           0 :         uint8_t ipaddr_len;
    4432           0 :         uint8_t macaddr_len;
    4433             :         /* holds the VNI(s) as in packet */
    4434           0 :         mpls_label_t label[BGP_MAX_LABELS] = {};
    4435           0 :         uint32_t num_labels = 0;
    4436           0 :         uint32_t eth_tag;
    4437           0 :         int ret = 0;
    4438             : 
    4439             :         /* Type-2 route should be either 33, 37 or 49 bytes or an
    4440             :          * additional 3 bytes if there is a second label (VNI):
    4441             :          * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1),
    4442             :          * MAC Addr (6), IP len (1), IP (0, 4 or 16),
    4443             :          * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3)
    4444             :          */
    4445           0 :         if (psize != 33 && psize != 37 && psize != 49 && psize != 36
    4446           0 :             && psize != 40 && psize != 52) {
    4447           0 :                 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4448             :                          "%u:%s - Rx EVPN Type-2 NLRI with invalid length %d",
    4449             :                          peer->bgp->vrf_id, peer->host, psize);
    4450           0 :                 return -1;
    4451             :         }
    4452             : 
    4453           0 :         struct stream *pkt = stream_new(psize);
    4454           0 :         stream_put(pkt, pfx, psize);
    4455             : 
    4456             :         /* Make prefix_rd */
    4457           0 :         prd.family = AF_UNSPEC;
    4458           0 :         prd.prefixlen = 64;
    4459             : 
    4460           0 :         STREAM_GET(&prd.val, pkt, 8);
    4461             : 
    4462             :         /* Make EVPN prefix. */
    4463           0 :         p.family = AF_EVPN;
    4464           0 :         p.prefixlen = EVPN_ROUTE_PREFIXLEN;
    4465           0 :         p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
    4466             : 
    4467             :         /* Copy Ethernet Seg Identifier */
    4468           0 :         if (attr) {
    4469           0 :                 STREAM_GET(&attr->esi, pkt, sizeof(esi_t));
    4470             : 
    4471           0 :                 if (bgp_evpn_is_esi_local_and_non_bypass(&attr->esi))
    4472           0 :                         attr->es_flags |= ATTR_ES_IS_LOCAL;
    4473             :                 else
    4474           0 :                         attr->es_flags &= ~ATTR_ES_IS_LOCAL;
    4475             :         } else {
    4476           0 :                 STREAM_FORWARD_GETP(pkt, sizeof(esi_t));
    4477             :         }
    4478             : 
    4479             :         /* Copy Ethernet Tag */
    4480           0 :         STREAM_GET(&eth_tag, pkt, 4);
    4481           0 :         p.prefix.macip_addr.eth_tag = ntohl(eth_tag);
    4482             : 
    4483             :         /* Get the MAC Addr len */
    4484           0 :         STREAM_GETC(pkt, macaddr_len);
    4485             : 
    4486             :         /* Get the MAC Addr */
    4487           0 :         if (macaddr_len == (ETH_ALEN * 8)) {
    4488           0 :                 STREAM_GET(&p.prefix.macip_addr.mac.octet, pkt, ETH_ALEN);
    4489             :         } else {
    4490           0 :                 flog_err(
    4491             :                         EC_BGP_EVPN_ROUTE_INVALID,
    4492             :                         "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d",
    4493             :                         peer->bgp->vrf_id, peer->host, macaddr_len);
    4494           0 :                 goto fail;
    4495             :         }
    4496             : 
    4497             : 
    4498             :         /* Get the IP. */
    4499           0 :         STREAM_GETC(pkt, ipaddr_len);
    4500             : 
    4501           0 :         if (ipaddr_len != 0 && ipaddr_len != IPV4_MAX_BITLEN
    4502           0 :             && ipaddr_len != IPV6_MAX_BITLEN) {
    4503           0 :                 flog_err(
    4504             :                         EC_BGP_EVPN_ROUTE_INVALID,
    4505             :                         "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d",
    4506             :                         peer->bgp->vrf_id, peer->host, ipaddr_len);
    4507           0 :                 goto fail;
    4508             :         }
    4509             : 
    4510           0 :         if (ipaddr_len) {
    4511           0 :                 ipaddr_len /= 8; /* Convert to bytes. */
    4512           0 :                 p.prefix.macip_addr.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
    4513             :                                                ? IPADDR_V4
    4514           0 :                                                : IPADDR_V6;
    4515           0 :                 STREAM_GET(&p.prefix.macip_addr.ip.ip.addr, pkt, ipaddr_len);
    4516             :         }
    4517             : 
    4518             :         /* Get the VNI(s). Stored as bytes here. */
    4519           0 :         STREAM_GET(&label[0], pkt, BGP_LABEL_BYTES);
    4520           0 :         num_labels++;
    4521             : 
    4522             :         /* Do we have a second VNI? */
    4523           0 :         if (STREAM_READABLE(pkt)) {
    4524           0 :                 num_labels++;
    4525           0 :                 STREAM_GET(&label[1], pkt, BGP_LABEL_BYTES);
    4526             :         }
    4527             : 
    4528             :         /* Process the route. */
    4529           0 :         if (attr)
    4530           0 :                 bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4531             :                            safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
    4532             :                            &label[0], num_labels, 0, &evpn);
    4533             :         else
    4534           0 :                 bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4535             :                              safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
    4536             :                              &label[0], num_labels, &evpn);
    4537           0 :         goto done;
    4538             : 
    4539           0 : fail:
    4540           0 : stream_failure:
    4541           0 :         flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4542             :                  "%u:%s - Rx EVPN Type-2 NLRI - corrupt, discarding",
    4543             :                  peer->bgp->vrf_id, peer->host);
    4544           0 :         ret = -1;
    4545           0 : done:
    4546           0 :         stream_free(pkt);
    4547           0 :         return ret;
    4548             : }
    4549             : 
    4550             : /*
    4551             :  * Process received EVPN type-3 route (advertise or withdraw).
    4552             :  */
    4553           0 : static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
    4554             :                                struct attr *attr, uint8_t *pfx, int psize,
    4555             :                                uint32_t addpath_id)
    4556             : {
    4557           0 :         struct prefix_rd prd;
    4558           0 :         struct prefix_evpn p;
    4559           0 :         uint8_t ipaddr_len;
    4560           0 :         uint32_t eth_tag;
    4561             : 
    4562             :         /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
    4563             :          * IP len (1) and IP (4 or 16).
    4564             :          */
    4565           0 :         if (psize != 17 && psize != 29) {
    4566           0 :                 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4567             :                          "%u:%s - Rx EVPN Type-3 NLRI with invalid length %d",
    4568             :                          peer->bgp->vrf_id, peer->host, psize);
    4569           0 :                 return -1;
    4570             :         }
    4571             : 
    4572             :         /* If PMSI is present, log if it is anything other than IR.
    4573             :          * Note: We just simply ignore the values as it is not clear if
    4574             :          * doing anything else is better.
    4575             :          */
    4576           0 :         if (attr &&
    4577           0 :             (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
    4578           0 :                 enum pta_type pmsi_tnl_type = bgp_attr_get_pmsi_tnl_type(attr);
    4579             : 
    4580           0 :                 if (pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL
    4581           0 :                     && pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) {
    4582           0 :                         flog_warn(
    4583             :                                 EC_BGP_EVPN_PMSI_PRESENT,
    4584             :                                 "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
    4585             :                                 peer->bgp->vrf_id, peer->host, pmsi_tnl_type);
    4586             :                 }
    4587             :         }
    4588             : 
    4589             :         /* Make prefix_rd */
    4590           0 :         prd.family = AF_UNSPEC;
    4591           0 :         prd.prefixlen = 64;
    4592           0 :         memcpy(&prd.val, pfx, 8);
    4593           0 :         pfx += 8;
    4594             : 
    4595             :         /* Make EVPN prefix. */
    4596           0 :         memset(&p, 0, sizeof(p));
    4597           0 :         p.family = AF_EVPN;
    4598           0 :         p.prefixlen = EVPN_ROUTE_PREFIXLEN;
    4599           0 :         p.prefix.route_type = BGP_EVPN_IMET_ROUTE;
    4600             : 
    4601             :         /* Copy Ethernet Tag */
    4602           0 :         memcpy(&eth_tag, pfx, 4);
    4603           0 :         p.prefix.imet_addr.eth_tag = ntohl(eth_tag);
    4604           0 :         pfx += 4;
    4605             : 
    4606             :         /* Get the IP. */
    4607           0 :         ipaddr_len = *pfx++;
    4608           0 :         if (ipaddr_len == IPV4_MAX_BITLEN) {
    4609           0 :                 p.prefix.imet_addr.ip.ipa_type = IPADDR_V4;
    4610           0 :                 memcpy(&p.prefix.imet_addr.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
    4611             :         } else {
    4612           0 :                 flog_err(
    4613             :                         EC_BGP_EVPN_ROUTE_INVALID,
    4614             :                         "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
    4615             :                         peer->bgp->vrf_id, peer->host, ipaddr_len);
    4616           0 :                 return -1;
    4617             :         }
    4618             : 
    4619             :         /* Process the route. */
    4620           0 :         if (attr)
    4621           0 :                 bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4622             :                            safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
    4623             :                            0, 0, NULL);
    4624             :         else
    4625           0 :                 bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4626             :                              safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
    4627             :                              NULL, 0, NULL);
    4628             :         return 0;
    4629             : }
    4630             : 
    4631             : /*
    4632             :  * Process received EVPN type-5 route (advertise or withdraw).
    4633             :  */
    4634           0 : static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
    4635             :                                struct attr *attr, uint8_t *pfx, int psize,
    4636             :                                uint32_t addpath_id)
    4637             : {
    4638           0 :         struct prefix_rd prd;
    4639           0 :         struct prefix_evpn p;
    4640           0 :         struct bgp_route_evpn evpn;
    4641           0 :         uint8_t ippfx_len;
    4642           0 :         uint32_t eth_tag;
    4643           0 :         mpls_label_t label; /* holds the VNI as in the packet */
    4644           0 :         bool is_valid_update = true;
    4645             : 
    4646             :         /* Type-5 route should be 34 or 58 bytes:
    4647             :          * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
    4648             :          * GW (4 or 16) and VNI (3).
    4649             :          * Note that the IP and GW should both be IPv4 or both IPv6.
    4650             :          */
    4651           0 :         if (psize != 34 && psize != 58) {
    4652           0 :                 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4653             :                          "%u:%s - Rx EVPN Type-5 NLRI with invalid length %d",
    4654             :                          peer->bgp->vrf_id, peer->host, psize);
    4655           0 :                 return -1;
    4656             :         }
    4657             : 
    4658             :         /* Make prefix_rd */
    4659           0 :         prd.family = AF_UNSPEC;
    4660           0 :         prd.prefixlen = 64;
    4661           0 :         memcpy(&prd.val, pfx, 8);
    4662           0 :         pfx += 8;
    4663             : 
    4664             :         /* Make EVPN prefix. */
    4665           0 :         memset(&p, 0, sizeof(p));
    4666           0 :         p.family = AF_EVPN;
    4667           0 :         p.prefixlen = EVPN_ROUTE_PREFIXLEN;
    4668           0 :         p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
    4669             : 
    4670             :         /* Additional information outside of prefix - ESI and GW IP */
    4671           0 :         memset(&evpn, 0, sizeof(evpn));
    4672             : 
    4673             :         /* Fetch ESI overlay index */
    4674           0 :         if (attr)
    4675           0 :                 memcpy(&evpn.eth_s_id, pfx, sizeof(esi_t));
    4676           0 :         pfx += ESI_BYTES;
    4677             : 
    4678             :         /* Fetch Ethernet Tag. */
    4679           0 :         memcpy(&eth_tag, pfx, 4);
    4680           0 :         p.prefix.prefix_addr.eth_tag = ntohl(eth_tag);
    4681           0 :         pfx += 4;
    4682             : 
    4683             :         /* Fetch IP prefix length. */
    4684           0 :         ippfx_len = *pfx++;
    4685           0 :         if (ippfx_len > IPV6_MAX_BITLEN) {
    4686           0 :                 flog_err(
    4687             :                         EC_BGP_EVPN_ROUTE_INVALID,
    4688             :                         "%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d",
    4689             :                         peer->bgp->vrf_id, peer->host, ippfx_len);
    4690           0 :                 return -1;
    4691             :         }
    4692           0 :         p.prefix.prefix_addr.ip_prefix_length = ippfx_len;
    4693             : 
    4694             :         /* Determine IPv4 or IPv6 prefix */
    4695             :         /* Since the address and GW are from the same family, this just becomes
    4696             :          * a simple check on the total size.
    4697             :          */
    4698           0 :         if (psize == 34) {
    4699           0 :                 SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
    4700           0 :                 memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
    4701           0 :                 pfx += 4;
    4702           0 :                 SET_IPADDR_V4(&evpn.gw_ip);
    4703           0 :                 memcpy(&evpn.gw_ip.ipaddr_v4, pfx, 4);
    4704           0 :                 pfx += 4;
    4705             :         } else {
    4706           0 :                 SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
    4707           0 :                 memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx,
    4708             :                        IPV6_MAX_BYTELEN);
    4709           0 :                 pfx += IPV6_MAX_BYTELEN;
    4710           0 :                 SET_IPADDR_V6(&evpn.gw_ip);
    4711           0 :                 memcpy(&evpn.gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN);
    4712           0 :                 pfx += IPV6_MAX_BYTELEN;
    4713             :         }
    4714             : 
    4715             :         /* Get the VNI (in MPLS label field). Stored as bytes here. */
    4716           0 :         memset(&label, 0, sizeof(label));
    4717           0 :         memcpy(&label, pfx, BGP_LABEL_BYTES);
    4718             : 
    4719             :         /*
    4720             :          * If in future, we are required to access additional fields,
    4721             :          * we MUST increment pfx by BGP_LABEL_BYTES in before reading the next
    4722             :          * field
    4723             :          */
    4724             : 
    4725             :         /*
    4726             :          * An update containing a non-zero gateway IP and a non-zero ESI
    4727             :          * at the same time is should be treated as withdraw
    4728             :          */
    4729           0 :         if (bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
    4730           0 :             !ipaddr_is_zero(&evpn.gw_ip)) {
    4731           0 :                 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4732             :                          "%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
    4733             :                          peer->host);
    4734           0 :                 is_valid_update = false;
    4735           0 :         } else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
    4736           0 :                 evpn.type = OVERLAY_INDEX_ESI;
    4737           0 :         else if (!ipaddr_is_zero(&evpn.gw_ip))
    4738           0 :                 evpn.type = OVERLAY_INDEX_GATEWAY_IP;
    4739           0 :         if (attr) {
    4740           0 :                 if (is_zero_mac(&attr->rmac) &&
    4741           0 :                     !bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
    4742           0 :                     ipaddr_is_zero(&evpn.gw_ip) && label == 0) {
    4743           0 :                         flog_err(EC_BGP_EVPN_ROUTE_INVALID,
    4744             :                                  "%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
    4745             :                                  peer->host);
    4746           0 :                         is_valid_update = false;
    4747             :                 }
    4748             : 
    4749           0 :                 if (is_mcast_mac(&attr->rmac) || is_bcast_mac(&attr->rmac))
    4750             :                         is_valid_update = false;
    4751             :         }
    4752             : 
    4753             :         /* Process the route. */
    4754           0 :         if (attr && is_valid_update)
    4755           0 :                 bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4756             :                            safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
    4757             :                            &label, 1, 0, &evpn);
    4758             :         else {
    4759           0 :                 if (!is_valid_update) {
    4760           0 :                         char attr_str[BUFSIZ] = {0};
    4761             : 
    4762           0 :                         bgp_dump_attr(attr, attr_str, BUFSIZ);
    4763           0 :                         zlog_warn(
    4764             :                                 "Invalid update from peer %s vrf %u prefix %pFX attr %s - treat as withdraw",
    4765             :                                 peer->hostname, peer->bgp->vrf_id, &p,
    4766             :                                 attr_str);
    4767             :                 }
    4768           0 :                 bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
    4769             :                              safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
    4770             :                              &label, 1, &evpn);
    4771             :         }
    4772             : 
    4773             :         return 0;
    4774             : }
    4775             : 
    4776           0 : static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
    4777             :                                      const struct prefix_rd *prd,
    4778             :                                      mpls_label_t *label, uint32_t num_labels,
    4779             :                                      struct attr *attr)
    4780             : {
    4781           0 :         int len;
    4782           0 :         char temp[16];
    4783           0 :         const struct evpn_addr *p_evpn_p;
    4784             : 
    4785           0 :         memset(&temp, 0, sizeof(temp));
    4786           0 :         if (p->family != AF_EVPN)
    4787           0 :                 return;
    4788           0 :         p_evpn_p = &(p->u.prefix_evpn);
    4789             : 
    4790             :         /* len denites the total len of IP and GW-IP in the route
    4791             :            IP and GW-IP have to be both ipv4 or ipv6
    4792             :          */
    4793           0 :         if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
    4794             :                 len = 8; /* IP and GWIP are both ipv4 */
    4795             :         else
    4796           0 :                 len = 32; /* IP and GWIP are both ipv6 */
    4797             :         /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
    4798           0 :         stream_putc(s, 8 + 10 + 4 + 1 + len + 3);
    4799           0 :         stream_put(s, prd->val, 8);
    4800           0 :         if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_ESI)
    4801           0 :                 stream_put(s, &attr->esi, sizeof(esi_t));
    4802             :         else
    4803           0 :                 stream_put(s, 0, sizeof(esi_t));
    4804           0 :         stream_putl(s, p_evpn_p->prefix_addr.eth_tag);
    4805           0 :         stream_putc(s, p_evpn_p->prefix_addr.ip_prefix_length);
    4806           0 :         if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
    4807           0 :                 stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr);
    4808             :         else
    4809           0 :                 stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
    4810           0 :         if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
    4811           0 :                 const struct bgp_route_evpn *evpn_overlay =
    4812           0 :                         bgp_attr_get_evpn_overlay(attr);
    4813             : 
    4814           0 :                 if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
    4815           0 :                         stream_put_ipv4(s,
    4816           0 :                                         evpn_overlay->gw_ip.ipaddr_v4.s_addr);
    4817             :                 else
    4818           0 :                         stream_put(s, &(evpn_overlay->gw_ip.ipaddr_v6), 16);
    4819             :         } else {
    4820           0 :                 if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
    4821           0 :                         stream_put_ipv4(s, 0);
    4822             :                 else
    4823           0 :                         stream_put(s, &temp, 16);
    4824             :         }
    4825             : 
    4826           0 :         if (num_labels)
    4827           0 :                 stream_put(s, label, 3);
    4828             :         else
    4829           0 :                 stream_put3(s, 0);
    4830             : }
    4831             : 
    4832             : /*
    4833             :  * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled.
    4834             :  */
    4835           0 : static void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp)
    4836             : {
    4837           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    4838             : 
    4839             :         /* Remove EVPN routes and schedule for processing. */
    4840           0 :         delete_routes_for_vni(bgp, vpn);
    4841             : 
    4842             :         /* Clear "live" flag and see if hash needs to be freed. */
    4843           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
    4844           0 :         if (!is_vni_configured(vpn))
    4845           0 :                 bgp_evpn_free(bgp, vpn);
    4846           0 : }
    4847             : 
    4848             : /*
    4849             :  * Free a VNI entry; iterator function called during cleanup.
    4850             :  */
    4851           0 : static void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp)
    4852             : {
    4853           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    4854             : 
    4855           0 :         delete_all_vni_routes(bgp, vpn);
    4856           0 :         bgp_evpn_free(bgp, vpn);
    4857           0 : }
    4858             : 
    4859             : /*
    4860             :  * Derive AUTO import RT for BGP VRF - L3VNI
    4861             :  */
    4862           0 : static void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf)
    4863             : {
    4864           0 :         struct bgp *bgp_evpn = NULL;
    4865             : 
    4866           0 :         form_auto_rt(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_import_rtl, true);
    4867             : 
    4868             :         /* Map RT to VRF */
    4869           0 :         bgp_evpn = bgp_get_evpn();
    4870             : 
    4871           0 :         if (!bgp_evpn)
    4872             :                 return;
    4873             : 
    4874           0 :         bgp_evpn_map_vrf_to_its_rts(bgp_vrf);
    4875             : }
    4876             : 
    4877             : /*
    4878             :  * Delete AUTO import RT from BGP VRF - L3VNI
    4879             :  */
    4880           0 : static void evpn_auto_rt_import_delete_for_vrf(struct bgp *bgp_vrf)
    4881             : {
    4882           0 :         evpn_rt_delete_auto(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_import_rtl,
    4883             :                             true);
    4884           0 : }
    4885             : 
    4886             : /*
    4887             :  * Derive AUTO export RT for BGP VRF - L3VNI
    4888             :  */
    4889           0 : static void evpn_auto_rt_export_add_for_vrf(struct bgp *bgp_vrf)
    4890             : {
    4891           0 :         form_auto_rt(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_export_rtl, true);
    4892           0 : }
    4893             : 
    4894             : /*
    4895             :  * Delete AUTO export RT from BGP VRF - L3VNI
    4896             :  */
    4897           0 : static void evpn_auto_rt_export_delete_for_vrf(struct bgp *bgp_vrf)
    4898             : {
    4899           0 :         evpn_rt_delete_auto(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_export_rtl,
    4900             :                             true);
    4901           0 : }
    4902             : 
    4903           0 : static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
    4904             : {
    4905           0 :         struct bgp *bgp_evpn = NULL;
    4906           0 :         struct listnode *node = NULL;
    4907           0 :         struct bgpevpn *vpn = NULL;
    4908             : 
    4909           0 :         bgp_evpn = bgp_get_evpn();
    4910           0 :         if (!bgp_evpn)
    4911             :                 return;
    4912             : 
    4913             :         /* update all type-5 routes */
    4914           0 :         update_advertise_vrf_routes(bgp_vrf);
    4915             : 
    4916             :         /* update all type-2 routes */
    4917           0 :         for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn))
    4918           0 :                 update_routes_for_vni(bgp_evpn, vpn);
    4919             : }
    4920             : 
    4921             : /*
    4922             :  * Handle autort change for a given VNI.
    4923             :  */
    4924           0 : static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp)
    4925             : {
    4926           0 :         struct bgpevpn *vpn = bucket->data;
    4927             : 
    4928           0 :         if (!is_import_rt_configured(vpn)) {
    4929           0 :                 if (is_vni_live(vpn))
    4930           0 :                         bgp_evpn_uninstall_routes(bgp, vpn);
    4931           0 :                 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
    4932           0 :                 list_delete_all_node(vpn->import_rtl);
    4933           0 :                 bgp_evpn_derive_auto_rt_import(bgp, vpn);
    4934           0 :                 if (is_vni_live(vpn))
    4935           0 :                         bgp_evpn_install_routes(bgp, vpn);
    4936             :         }
    4937           0 :         if (!is_export_rt_configured(vpn)) {
    4938           0 :                 list_delete_all_node(vpn->export_rtl);
    4939           0 :                 bgp_evpn_derive_auto_rt_export(bgp, vpn);
    4940           0 :                 if (is_vni_live(vpn))
    4941           0 :                         bgp_evpn_handle_export_rt_change(bgp, vpn);
    4942             :         }
    4943           0 : }
    4944             : 
    4945             : /*
    4946             :  * Handle autort change for L3VNI.
    4947             :  */
    4948           0 : static void update_autort_l3vni(struct bgp *bgp)
    4949             : {
    4950           0 :         if ((CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD))
    4951           0 :             && (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)))
    4952             :                 return;
    4953             : 
    4954           0 :         if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
    4955           0 :                 if (is_l3vni_live(bgp))
    4956           0 :                         uninstall_routes_for_vrf(bgp);
    4957             : 
    4958             :                 /* Cleanup the RT to VRF mapping */
    4959           0 :                 bgp_evpn_unmap_vrf_from_its_rts(bgp);
    4960             : 
    4961             :                 /* Remove auto generated RT */
    4962           0 :                 evpn_auto_rt_import_delete_for_vrf(bgp);
    4963             : 
    4964           0 :                 list_delete_all_node(bgp->vrf_import_rtl);
    4965             : 
    4966             :                 /* Map auto derive or configured RTs */
    4967           0 :                 evpn_auto_rt_import_add_for_vrf(bgp);
    4968             :         }
    4969             : 
    4970           0 :         if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
    4971           0 :                 list_delete_all_node(bgp->vrf_export_rtl);
    4972             : 
    4973           0 :                 evpn_auto_rt_export_delete_for_vrf(bgp);
    4974             : 
    4975           0 :                 evpn_auto_rt_export_add_for_vrf(bgp);
    4976             : 
    4977           0 :                 if (is_l3vni_live(bgp))
    4978           0 :                         bgp_evpn_map_vrf_to_its_rts(bgp);
    4979             :         }
    4980             : 
    4981           0 :         if (!is_l3vni_live(bgp))
    4982             :                 return;
    4983             : 
    4984             :         /* advertise type-5 routes if needed */
    4985           0 :         update_advertise_vrf_routes(bgp);
    4986             : 
    4987             :         /* install all remote routes belonging to this l3vni
    4988             :          * into corresponding vrf
    4989             :          */
    4990           0 :         install_routes_for_vrf(bgp);
    4991             : }
    4992             : 
    4993             : /*
    4994             :  * Public functions.
    4995             :  */
    4996             : 
    4997             : /* withdraw type-5 route corresponding to ip prefix */
    4998           0 : void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, const struct prefix *p,
    4999             :                                    afi_t afi, safi_t safi)
    5000             : {
    5001           0 :         int ret = 0;
    5002           0 :         struct prefix_evpn evp;
    5003             : 
    5004           0 :         build_type5_prefix_from_ip_prefix(&evp, p);
    5005           0 :         ret = delete_evpn_type5_route(bgp_vrf, &evp);
    5006           0 :         if (ret)
    5007           0 :                 flog_err(
    5008             :                         EC_BGP_EVPN_ROUTE_DELETE,
    5009             :                         "%u failed to delete type-5 route for prefix %pFX in vrf %s",
    5010             :                         bgp_vrf->vrf_id, p, vrf_id_to_name(bgp_vrf->vrf_id));
    5011           0 : }
    5012             : 
    5013             : /* withdraw all type-5 routes for an address family */
    5014           0 : void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi)
    5015             : {
    5016           0 :         struct bgp_table *table = NULL;
    5017           0 :         struct bgp_dest *dest = NULL;
    5018           0 :         struct bgp_path_info *pi;
    5019             : 
    5020           0 :         table = bgp_vrf->rib[afi][safi];
    5021           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    5022             :                 /* Only care about "selected" routes. Also ensure that
    5023             :                  * these are routes that are injectable into EVPN.
    5024             :                  */
    5025             :                 /* TODO: Support for AddPath for EVPN. */
    5026           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    5027           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
    5028           0 :                             && is_route_injectable_into_evpn(pi)) {
    5029           0 :                                 bgp_evpn_withdraw_type5_route(
    5030             :                                         bgp_vrf, bgp_dest_get_prefix(dest), afi,
    5031             :                                         safi);
    5032           0 :                                 break;
    5033             :                         }
    5034             :                 }
    5035             :         }
    5036           0 : }
    5037             : 
    5038             : /*
    5039             :  * evpn - enable advertisement of default g/w
    5040             :  */
    5041           0 : void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf, afi_t afi,
    5042             :                                               safi_t safi, bool add)
    5043             : {
    5044           0 :         struct prefix ip_prefix;
    5045             : 
    5046             :         /* form the default prefix 0.0.0.0/0 */
    5047           0 :         memset(&ip_prefix, 0, sizeof(ip_prefix));
    5048           0 :         ip_prefix.family = afi2family(afi);
    5049             : 
    5050           0 :         if (add) {
    5051           0 :                 bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
    5052             :                                                NULL, afi, safi);
    5053             :         } else {
    5054           0 :                 bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
    5055             :                                               afi, safi);
    5056             :         }
    5057           0 : }
    5058             : 
    5059             : 
    5060             : /*
    5061             :  * Advertise IP prefix as type-5 route. The afi/safi and src_attr passed
    5062             :  * to this function correspond to those of the source IP prefix (best
    5063             :  * path in the case of the attr. In the case of a local prefix (when we
    5064             :  * are advertising local subnets), the src_attr will be NULL.
    5065             :  */
    5066           0 : void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, const struct prefix *p,
    5067             :                                     struct attr *src_attr, afi_t afi,
    5068             :                                     safi_t safi)
    5069             : {
    5070           0 :         int ret = 0;
    5071           0 :         struct prefix_evpn evp;
    5072             : 
    5073           0 :         build_type5_prefix_from_ip_prefix(&evp, p);
    5074           0 :         ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr, afi, safi);
    5075           0 :         if (ret)
    5076           0 :                 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
    5077             :                          "%u: Failed to create type-5 route for prefix %pFX",
    5078             :                          bgp_vrf->vrf_id, p);
    5079           0 : }
    5080             : 
    5081             : /* Inject all prefixes of a particular address-family (currently, IPv4 or
    5082             :  * IPv6 unicast) into EVPN as type-5 routes. This is invoked when the
    5083             :  * advertisement is enabled.
    5084             :  */
    5085           0 : void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
    5086             :                                      safi_t safi)
    5087             : {
    5088           0 :         struct bgp_table *table = NULL;
    5089           0 :         struct bgp_dest *dest = NULL;
    5090           0 :         struct bgp_path_info *pi;
    5091             : 
    5092           0 :         table = bgp_vrf->rib[afi][safi];
    5093           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    5094             :                 /* Need to identify the "selected" route entry to use its
    5095             :                  * attribute. Also, ensure that the route is injectable
    5096             :                  * into EVPN.
    5097             :                  * TODO: Support for AddPath for EVPN.
    5098             :                  */
    5099           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    5100           0 :                         if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
    5101           0 :                             && is_route_injectable_into_evpn(pi)) {
    5102             : 
    5103             :                                 /* apply the route-map */
    5104           0 :                                 if (bgp_vrf->adv_cmd_rmap[afi][safi].map) {
    5105           0 :                                         route_map_result_t ret;
    5106           0 :                                         struct bgp_path_info tmp_pi;
    5107           0 :                                         struct bgp_path_info_extra tmp_pie;
    5108           0 :                                         struct attr tmp_attr;
    5109             : 
    5110           0 :                                         tmp_attr = *pi->attr;
    5111             : 
    5112             :                                         /* Fill temp path_info */
    5113           0 :                                         prep_for_rmap_apply(&tmp_pi, &tmp_pie,
    5114             :                                                             dest, pi, pi->peer,
    5115             :                                                             &tmp_attr);
    5116             : 
    5117           0 :                                         RESET_FLAG(tmp_attr.rmap_change_flags);
    5118             : 
    5119           0 :                                         ret = route_map_apply(
    5120             :                                                 bgp_vrf->adv_cmd_rmap[afi][safi]
    5121             :                                                         .map,
    5122             :                                                 bgp_dest_get_prefix(dest),
    5123             :                                                 &tmp_pi);
    5124           0 :                                         if (ret == RMAP_DENYMATCH) {
    5125           0 :                                                 bgp_attr_flush(&tmp_attr);
    5126           0 :                                                 continue;
    5127             :                                         }
    5128           0 :                                         bgp_evpn_advertise_type5_route(
    5129             :                                                 bgp_vrf,
    5130             :                                                 bgp_dest_get_prefix(dest),
    5131             :                                                 &tmp_attr, afi, safi);
    5132             :                                 } else
    5133           0 :                                         bgp_evpn_advertise_type5_route(
    5134             :                                                 bgp_vrf,
    5135             :                                                 bgp_dest_get_prefix(dest),
    5136             :                                                 pi->attr, afi, safi);
    5137             :                                 break;
    5138             :                         }
    5139             :                 }
    5140             :         }
    5141           0 : }
    5142             : 
    5143           0 : static void rt_list_remove_node(struct list *rt_list,
    5144             :                                 struct ecommunity *ecomdel, bool is_l3)
    5145             : {
    5146           0 :         struct listnode *node = NULL, *nnode = NULL, *node_to_del = NULL;
    5147           0 :         struct vrf_route_target *l3rt = NULL;
    5148           0 :         struct ecommunity *ecom = NULL;
    5149             : 
    5150           0 :         if (is_l3) {
    5151           0 :                 for (ALL_LIST_ELEMENTS(rt_list, node, nnode, l3rt)) {
    5152           0 :                         if (ecommunity_match(l3rt->ecom, ecomdel)) {
    5153           0 :                                 evpn_vrf_rt_del(l3rt);
    5154           0 :                                 node_to_del = node;
    5155           0 :                                 break;
    5156             :                         }
    5157             :                 }
    5158             :         } else {
    5159           0 :                 for (ALL_LIST_ELEMENTS(rt_list, node, nnode, ecom)) {
    5160           0 :                         if (ecommunity_match(ecom, ecomdel)) {
    5161           0 :                                 ecommunity_free(&ecom);
    5162           0 :                                 node_to_del = node;
    5163           0 :                                 break;
    5164             :                         }
    5165             :                 }
    5166             :         }
    5167             : 
    5168             : 
    5169           0 :         if (node_to_del)
    5170           0 :                 list_delete_node(rt_list, node_to_del);
    5171           0 : }
    5172             : 
    5173           0 : void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl,
    5174             :                          bool is_l3)
    5175             : {
    5176           0 :         struct ecommunity *ecom_auto;
    5177           0 :         struct ecommunity_val eval;
    5178             : 
    5179           0 :         if (bgp->advertise_autort_rfc8365)
    5180           0 :                 vni |= EVPN_AUTORT_VXLAN;
    5181             : 
    5182           0 :         encode_route_target_as((bgp->as & 0xFFFF), vni, &eval);
    5183             : 
    5184           0 :         ecom_auto = ecommunity_new();
    5185           0 :         ecommunity_add_val(ecom_auto, &eval, false, false);
    5186             : 
    5187           0 :         rt_list_remove_node(rtl, ecom_auto, is_l3);
    5188             : 
    5189           0 :         ecommunity_free(&ecom_auto);
    5190           0 : }
    5191             : 
    5192           0 : static void evpn_vrf_rt_routes_map(struct bgp *bgp_vrf)
    5193             : {
    5194             :         /* map VRFs to its RTs and install routes matching this new RT */
    5195           0 :         if (is_l3vni_live(bgp_vrf)) {
    5196           0 :                 bgp_evpn_map_vrf_to_its_rts(bgp_vrf);
    5197           0 :                 install_routes_for_vrf(bgp_vrf);
    5198             :         }
    5199           0 : }
    5200             : 
    5201           0 : static void evpn_vrf_rt_routes_unmap(struct bgp *bgp_vrf)
    5202             : {
    5203             :         /* uninstall routes from vrf */
    5204           0 :         if (is_l3vni_live(bgp_vrf))
    5205           0 :                 uninstall_routes_for_vrf(bgp_vrf);
    5206             : 
    5207             :         /* Cleanup the RT to VRF mapping */
    5208           0 :         bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
    5209           0 : }
    5210             : 
    5211           0 : static bool rt_list_has_cfgd_rt(struct list *rt_list)
    5212             : {
    5213           0 :         struct listnode *node = NULL, *nnode = NULL;
    5214           0 :         struct vrf_route_target *l3rt = NULL;
    5215             : 
    5216           0 :         for (ALL_LIST_ELEMENTS(rt_list, node, nnode, l3rt)) {
    5217           0 :                 if (!CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
    5218             :                         return true;
    5219             :         }
    5220             : 
    5221             :         return false;
    5222             : }
    5223             : 
    5224           0 : static void unconfigure_import_rt_for_vrf_fini(struct bgp *bgp_vrf)
    5225             : {
    5226           0 :         if (!bgp_vrf->vrf_import_rtl)
    5227             :                 return; /* this should never fail */
    5228             : 
    5229           0 :         if (!is_l3vni_live(bgp_vrf))
    5230             :                 return; /* Nothing to do if no vni */
    5231             : 
    5232             :         /* fall back to auto-generated RT if this was the last RT */
    5233           0 :         if (list_isempty(bgp_vrf->vrf_import_rtl))
    5234           0 :                 evpn_auto_rt_import_add_for_vrf(bgp_vrf);
    5235             : }
    5236             : 
    5237           0 : static void unconfigure_export_rt_for_vrf_fini(struct bgp *bgp_vrf)
    5238             : {
    5239             : 
    5240           0 :         if (!bgp_vrf->vrf_export_rtl)
    5241             :                 return; /* this should never fail */
    5242             : 
    5243           0 :         if (!is_l3vni_live(bgp_vrf))
    5244             :                 return; /* Nothing to do if no vni */
    5245             : 
    5246             :         /* fall back to auto-generated RT if this was the last RT */
    5247           0 :         if (list_isempty(bgp_vrf->vrf_export_rtl))
    5248           0 :                 evpn_auto_rt_export_add_for_vrf(bgp_vrf);
    5249             : 
    5250           0 :         bgp_evpn_handle_export_rt_change_for_vrf(bgp_vrf);
    5251             : }
    5252             : 
    5253           0 : void bgp_evpn_configure_import_rt_for_vrf(struct bgp *bgp_vrf,
    5254             :                                           struct ecommunity *ecomadd,
    5255             :                                           bool is_wildcard)
    5256             : {
    5257           0 :         struct vrf_route_target *newrt;
    5258             : 
    5259           0 :         newrt = evpn_vrf_rt_new(ecomadd);
    5260             : 
    5261           0 :         if (is_wildcard)
    5262           0 :                 SET_FLAG(newrt->flags, BGP_VRF_RT_WILD);
    5263             : 
    5264           0 :         evpn_vrf_rt_routes_unmap(bgp_vrf);
    5265             : 
    5266             :         /* Remove auto generated RT if not configured */
    5267           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
    5268           0 :                 evpn_auto_rt_import_delete_for_vrf(bgp_vrf);
    5269             : 
    5270             :         /* Add the newly configured RT to RT list */
    5271           0 :         listnode_add_sort(bgp_vrf->vrf_import_rtl, newrt);
    5272             : 
    5273           0 :         SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD);
    5274             : 
    5275           0 :         evpn_vrf_rt_routes_map(bgp_vrf);
    5276           0 : }
    5277             : 
    5278           0 : void bgp_evpn_configure_import_auto_rt_for_vrf(struct bgp *bgp_vrf)
    5279             : {
    5280           0 :         if (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
    5281             :                 return; /* Already configured */
    5282             : 
    5283           0 :         SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD);
    5284             : 
    5285           0 :         if (!is_l3vni_live(bgp_vrf))
    5286             :                 return; /* Wait for VNI before adding rts */
    5287             : 
    5288           0 :         evpn_vrf_rt_routes_unmap(bgp_vrf);
    5289             : 
    5290           0 :         evpn_auto_rt_import_add_for_vrf(bgp_vrf);
    5291             : 
    5292           0 :         evpn_vrf_rt_routes_map(bgp_vrf);
    5293             : }
    5294             : 
    5295           0 : void bgp_evpn_unconfigure_import_rt_for_vrf(struct bgp *bgp_vrf,
    5296             :                                             struct ecommunity *ecomdel)
    5297             : {
    5298           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD))
    5299             :                 return; /* Already un-configured */
    5300             : 
    5301           0 :         evpn_vrf_rt_routes_unmap(bgp_vrf);
    5302             : 
    5303             :         /* Remove rt */
    5304           0 :         rt_list_remove_node(bgp_vrf->vrf_import_rtl, ecomdel, true);
    5305             : 
    5306           0 :         if (!rt_list_has_cfgd_rt(bgp_vrf->vrf_import_rtl))
    5307           0 :                 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD);
    5308             : 
    5309           0 :         unconfigure_import_rt_for_vrf_fini(bgp_vrf);
    5310             : 
    5311           0 :         evpn_vrf_rt_routes_map(bgp_vrf);
    5312             : }
    5313             : 
    5314           0 : void bgp_evpn_unconfigure_import_auto_rt_for_vrf(struct bgp *bgp_vrf)
    5315             : {
    5316           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
    5317             :                 return; /* Already un-configured */
    5318             : 
    5319           0 :         evpn_vrf_rt_routes_unmap(bgp_vrf);
    5320             : 
    5321             :         /* remove auto-generated RT */
    5322           0 :         evpn_auto_rt_import_delete_for_vrf(bgp_vrf);
    5323             : 
    5324           0 :         UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD);
    5325             : 
    5326           0 :         unconfigure_import_rt_for_vrf_fini(bgp_vrf);
    5327             : 
    5328           0 :         evpn_vrf_rt_routes_map(bgp_vrf);
    5329             : }
    5330             : 
    5331           0 : void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf,
    5332             :                                           struct ecommunity *ecomadd)
    5333             : {
    5334           0 :         struct vrf_route_target *newrt;
    5335             : 
    5336           0 :         newrt = evpn_vrf_rt_new(ecomadd);
    5337             : 
    5338             :         /* Remove auto generated RT if not configured */
    5339           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
    5340           0 :                 evpn_auto_rt_export_delete_for_vrf(bgp_vrf);
    5341             : 
    5342             :         /* Add the new RT to the RT list */
    5343           0 :         listnode_add_sort(bgp_vrf->vrf_export_rtl, newrt);
    5344             : 
    5345           0 :         SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_RT_CFGD);
    5346             : 
    5347           0 :         if (is_l3vni_live(bgp_vrf))
    5348           0 :                 bgp_evpn_handle_export_rt_change_for_vrf(bgp_vrf);
    5349           0 : }
    5350             : 
    5351           0 : void bgp_evpn_configure_export_auto_rt_for_vrf(struct bgp *bgp_vrf)
    5352             : {
    5353           0 :         if (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
    5354             :                 return; /* Already configured */
    5355             : 
    5356           0 :         SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD);
    5357             : 
    5358           0 :         if (!is_l3vni_live(bgp_vrf))
    5359             :                 return; /* Wait for VNI before adding rts */
    5360             : 
    5361           0 :         evpn_auto_rt_export_add_for_vrf(bgp_vrf);
    5362             : 
    5363           0 :         bgp_evpn_handle_export_rt_change_for_vrf(bgp_vrf);
    5364             : }
    5365             : 
    5366           0 : void bgp_evpn_unconfigure_export_rt_for_vrf(struct bgp *bgp_vrf,
    5367             :                                             struct ecommunity *ecomdel)
    5368             : {
    5369           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_RT_CFGD))
    5370             :                 return; /* Already un-configured */
    5371             : 
    5372             :         /* Remove rt */
    5373           0 :         rt_list_remove_node(bgp_vrf->vrf_export_rtl, ecomdel, true);
    5374             : 
    5375           0 :         if (!rt_list_has_cfgd_rt(bgp_vrf->vrf_export_rtl))
    5376           0 :                 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_RT_CFGD);
    5377             : 
    5378           0 :         unconfigure_export_rt_for_vrf_fini(bgp_vrf);
    5379             : }
    5380             : 
    5381           0 : void bgp_evpn_unconfigure_export_auto_rt_for_vrf(struct bgp *bgp_vrf)
    5382             : {
    5383           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
    5384             :                 return; /* Already un-configured */
    5385             : 
    5386             :         /* remove auto-generated RT */
    5387           0 :         evpn_auto_rt_export_delete_for_vrf(bgp_vrf);
    5388             : 
    5389           0 :         UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD);
    5390             : 
    5391           0 :         unconfigure_export_rt_for_vrf_fini(bgp_vrf);
    5392             : }
    5393             : 
    5394             : /*
    5395             :  * Handle change to BGP router id. This is invoked twice by the change
    5396             :  * handler, first before the router id has been changed and then after
    5397             :  * the router id has been changed. The first invocation will result in
    5398             :  * local routes for all VNIs/VRF being deleted and withdrawn and the next
    5399             :  * will result in the routes being re-advertised.
    5400             :  */
    5401           0 : void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw)
    5402             : {
    5403           0 :         struct listnode *node;
    5404           0 :         struct bgp *bgp_vrf;
    5405             : 
    5406           0 :         if (withdraw) {
    5407             : 
    5408             :                 /* delete and withdraw all the type-5 routes
    5409             :                    stored in the global table for this vrf
    5410             :                  */
    5411           0 :                 withdraw_router_id_vrf(bgp);
    5412             : 
    5413             :                 /* delete all the VNI routes (type-2/type-3) routes for all the
    5414             :                  * L2-VNIs
    5415             :                  */
    5416           0 :                 hash_iterate(bgp->vnihash,
    5417             :                              (void (*)(struct hash_bucket *,
    5418             :                                        void *))withdraw_router_id_vni,
    5419             :                              bgp);
    5420             : 
    5421           0 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    5422           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
    5423           0 :                                 if (bgp_vrf->evpn_info->advertise_pip &&
    5424           0 :                                     (bgp_vrf->evpn_info->pip_ip_static.s_addr
    5425             :                                      == INADDR_ANY))
    5426           0 :                                         bgp_vrf->evpn_info->pip_ip.s_addr
    5427           0 :                                                 = INADDR_ANY;
    5428             :                         }
    5429             :                 }
    5430             :         } else {
    5431             : 
    5432             :                 /* Assign new default instance router-id */
    5433           0 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    5434           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
    5435           0 :                                 if (bgp_vrf->evpn_info->advertise_pip &&
    5436           0 :                                     (bgp_vrf->evpn_info->pip_ip_static.s_addr
    5437             :                                      == INADDR_ANY)) {
    5438           0 :                                         bgp_vrf->evpn_info->pip_ip =
    5439             :                                                 bgp->router_id;
    5440             :                                         /* advertise type-5 routes with
    5441             :                                          * new nexthop
    5442             :                                          */
    5443           0 :                                         update_advertise_vrf_routes(bgp_vrf);
    5444             :                                 }
    5445             :                         }
    5446             :                 }
    5447             : 
    5448             :                 /* advertise all routes in the vrf as type-5 routes with the new
    5449             :                  * RD
    5450             :                  */
    5451           0 :                 update_router_id_vrf(bgp);
    5452             : 
    5453             :                 /* advertise all the VNI routes (type-2/type-3) routes with the
    5454             :                  * new RD
    5455             :                  */
    5456           0 :                 hash_iterate(bgp->vnihash,
    5457             :                              (void (*)(struct hash_bucket *,
    5458             :                                        void *))update_router_id_vni,
    5459             :                              bgp);
    5460             :         }
    5461           0 : }
    5462             : 
    5463             : /*
    5464             :  * Handle change to auto-RT algorithm - update and advertise local routes.
    5465             :  */
    5466           0 : void bgp_evpn_handle_autort_change(struct bgp *bgp)
    5467             : {
    5468           0 :         hash_iterate(bgp->vnihash,
    5469             :                      (void (*)(struct hash_bucket *,
    5470             :                                void*))update_autort_vni,
    5471             :                      bgp);
    5472           0 :         if (bgp->l3vni)
    5473           0 :                 update_autort_l3vni(bgp);
    5474           0 : }
    5475             : 
    5476             : /*
    5477             :  * Handle change to export RT - update and advertise local routes.
    5478             :  */
    5479           0 : int bgp_evpn_handle_export_rt_change(struct bgp *bgp, struct bgpevpn *vpn)
    5480             : {
    5481           0 :         return update_routes_for_vni(bgp, vpn);
    5482             : }
    5483             : 
    5484           0 : void bgp_evpn_handle_vrf_rd_change(struct bgp *bgp_vrf, int withdraw)
    5485             : {
    5486           0 :         if (withdraw)
    5487           0 :                 delete_withdraw_vrf_routes(bgp_vrf);
    5488             :         else
    5489           0 :                 update_advertise_vrf_routes(bgp_vrf);
    5490           0 : }
    5491             : 
    5492             : /*
    5493             :  * Handle change to RD. This is invoked twice by the change handler,
    5494             :  * first before the RD has been changed and then after the RD has
    5495             :  * been changed. The first invocation will result in local routes
    5496             :  * of this VNI being deleted and withdrawn and the next will result
    5497             :  * in the routes being re-advertised.
    5498             :  */
    5499           0 : void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn,
    5500             :                                int withdraw)
    5501             : {
    5502           0 :         if (withdraw)
    5503           0 :                 delete_withdraw_vni_routes(bgp, vpn);
    5504             :         else
    5505           0 :                 update_advertise_vni_routes(bgp, vpn);
    5506           0 : }
    5507             : 
    5508             : /*
    5509             :  * Install routes for this VNI. Invoked upon change to Import RT.
    5510             :  */
    5511           0 : int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn)
    5512             : {
    5513           0 :         return install_routes_for_vni(bgp, vpn);
    5514             : }
    5515             : 
    5516             : /*
    5517             :  * Uninstall all routes installed for this VNI. Invoked upon change
    5518             :  * to Import RT.
    5519             :  */
    5520           0 : int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn)
    5521             : {
    5522           0 :         return uninstall_routes_for_vni(bgp, vpn);
    5523             : }
    5524             : 
    5525             : /*
    5526             :  * TODO: Hardcoded for a maximum of 2 VNIs right now
    5527             :  */
    5528           0 : char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf,
    5529             :                          int len)
    5530             : {
    5531           0 :         vni_t vni1, vni2;
    5532             : 
    5533           0 :         vni1 = label2vni(label);
    5534           0 :         if (num_labels == 2) {
    5535           0 :                 vni2 = label2vni(label + 1);
    5536           0 :                 snprintf(buf, len, "%u/%u", vni1, vni2);
    5537             :         } else
    5538           0 :                 snprintf(buf, len, "%u", vni1);
    5539           0 :         return buf;
    5540             : }
    5541             : 
    5542             : /*
    5543             :  * Function to convert evpn route to json format.
    5544             :  * NOTE: We don't use prefix2str as the output here is a bit different.
    5545             :  */
    5546           0 : void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json)
    5547             : {
    5548           0 :         char buf1[ETHER_ADDR_STRLEN];
    5549           0 :         char buf2[PREFIX2STR_BUFFER];
    5550           0 :         uint8_t family;
    5551           0 :         uint8_t prefixlen;
    5552             : 
    5553           0 :         if (!json)
    5554           0 :                 return;
    5555             : 
    5556           0 :         json_object_int_add(json, "routeType", p->prefix.route_type);
    5557             : 
    5558           0 :         switch (p->prefix.route_type) {
    5559           0 :         case BGP_EVPN_MAC_IP_ROUTE:
    5560           0 :                 json_object_int_add(json, "ethTag",
    5561           0 :                         p->prefix.macip_addr.eth_tag);
    5562           0 :                 json_object_int_add(json, "macLen", 8 * ETH_ALEN);
    5563           0 :                 json_object_string_add(json, "mac",
    5564           0 :                         prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
    5565             :                         sizeof(buf1)));
    5566             : 
    5567           0 :                 if (!is_evpn_prefix_ipaddr_none(p)) {
    5568           0 :                         family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET :
    5569             :                                 AF_INET6;
    5570           0 :                         prefixlen = (family == AF_INET) ?
    5571             :                                 IPV4_MAX_BITLEN : IPV6_MAX_BITLEN;
    5572           0 :                         inet_ntop(family, &p->prefix.macip_addr.ip.ip.addr,
    5573             :                                 buf2, PREFIX2STR_BUFFER);
    5574           0 :                         json_object_int_add(json, "ipLen", prefixlen);
    5575           0 :                         json_object_string_add(json, "ip", buf2);
    5576             :                 }
    5577             :         break;
    5578             : 
    5579           0 :         case BGP_EVPN_IMET_ROUTE:
    5580           0 :                 json_object_int_add(json, "ethTag",
    5581           0 :                         p->prefix.imet_addr.eth_tag);
    5582           0 :                 family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
    5583           0 :                 prefixlen = (family == AF_INET) ?  IPV4_MAX_BITLEN :
    5584             :                         IPV6_MAX_BITLEN;
    5585           0 :                 inet_ntop(family, &p->prefix.imet_addr.ip.ip.addr, buf2,
    5586             :                         PREFIX2STR_BUFFER);
    5587           0 :                 json_object_int_add(json, "ipLen", prefixlen);
    5588           0 :                 json_object_string_add(json, "ip", buf2);
    5589           0 :         break;
    5590             : 
    5591           0 :         case BGP_EVPN_IP_PREFIX_ROUTE:
    5592           0 :                 json_object_int_add(json, "ethTag",
    5593           0 :                         p->prefix.prefix_addr.eth_tag);
    5594           0 :                 family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
    5595           0 :                 inet_ntop(family, &p->prefix.prefix_addr.ip.ip.addr,
    5596             :                           buf2, sizeof(buf2));
    5597           0 :                 json_object_int_add(json, "ipLen",
    5598           0 :                                     p->prefix.prefix_addr.ip_prefix_length);
    5599           0 :                 json_object_string_add(json, "ip", buf2);
    5600           0 :         break;
    5601             : 
    5602             :         default:
    5603             :         break;
    5604             :         }
    5605             : }
    5606             : 
    5607             : /*
    5608             :  * Encode EVPN prefix in Update (MP_REACH)
    5609             :  */
    5610           0 : void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
    5611             :                             const struct prefix_rd *prd, mpls_label_t *label,
    5612             :                             uint32_t num_labels, struct attr *attr,
    5613             :                             bool addpath_capable, uint32_t addpath_tx_id)
    5614             : {
    5615           0 :         struct prefix_evpn *evp = (struct prefix_evpn *)p;
    5616           0 :         int len, ipa_len = 0;
    5617             : 
    5618           0 :         if (addpath_capable)
    5619           0 :                 stream_putl(s, addpath_tx_id);
    5620             : 
    5621             :         /* Route type */
    5622           0 :         stream_putc(s, evp->prefix.route_type);
    5623             : 
    5624           0 :         switch (evp->prefix.route_type) {
    5625           0 :         case BGP_EVPN_MAC_IP_ROUTE:
    5626           0 :                 if (is_evpn_prefix_ipaddr_v4(evp))
    5627             :                         ipa_len = IPV4_MAX_BYTELEN;
    5628           0 :                 else if (is_evpn_prefix_ipaddr_v6(evp))
    5629           0 :                         ipa_len = IPV6_MAX_BYTELEN;
    5630             :                 /* RD, ESI, EthTag, MAC+len, IP len, [IP], 1 VNI */
    5631           0 :                 len = 8 + 10 + 4 + 1 + 6 + 1 + ipa_len + 3;
    5632           0 :                 if (ipa_len && num_labels > 1) /* There are 2 VNIs */
    5633           0 :                         len += 3;
    5634           0 :                 stream_putc(s, len);
    5635           0 :                 stream_put(s, prd->val, 8);   /* RD */
    5636           0 :                 if (attr)
    5637           0 :                         stream_put(s, &attr->esi, ESI_BYTES);
    5638             :                 else
    5639           0 :                         stream_put(s, 0, 10);
    5640           0 :                 stream_putl(s, evp->prefix.macip_addr.eth_tag);      /* Ethernet Tag ID */
    5641           0 :                 stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
    5642           0 :                 stream_put(s, evp->prefix.macip_addr.mac.octet, 6); /* Mac Addr */
    5643           0 :                 stream_putc(s, 8 * ipa_len); /* IP address Length */
    5644           0 :                 if (ipa_len) /* IP */
    5645           0 :                         stream_put(s, &evp->prefix.macip_addr.ip.ip.addr,
    5646             :                                    ipa_len);
    5647             :                 /* 1st label is the L2 VNI */
    5648           0 :                 stream_put(s, label, BGP_LABEL_BYTES);
    5649             :                 /* Include 2nd label (L3 VNI) if advertising MAC+IP */
    5650           0 :                 if (ipa_len && num_labels > 1)
    5651           0 :                         stream_put(s, label + 1, BGP_LABEL_BYTES);
    5652             :                 break;
    5653             : 
    5654           0 :         case BGP_EVPN_IMET_ROUTE:
    5655           0 :                 stream_putc(s, 17); // TODO: length - assumes IPv4 address
    5656           0 :                 stream_put(s, prd->val, 8);      /* RD */
    5657           0 :                 stream_putl(s, evp->prefix.imet_addr.eth_tag); /* Ethernet Tag ID */
    5658           0 :                 stream_putc(s, IPV4_MAX_BITLEN); /* IP address Length - bits */
    5659             :                 /* Originating Router's IP Addr */
    5660           0 :                 stream_put_in_addr(s, &evp->prefix.imet_addr.ip.ipaddr_v4);
    5661           0 :                 break;
    5662             : 
    5663           0 :         case BGP_EVPN_ES_ROUTE:
    5664           0 :                 stream_putc(s, 23); /* TODO: length: assumes ipv4 VTEP */
    5665           0 :                 stream_put(s, prd->val, 8); /* RD */
    5666           0 :                 stream_put(s, evp->prefix.es_addr.esi.val, 10); /* ESI */
    5667           0 :                 stream_putc(s, IPV4_MAX_BITLEN); /* IP address Length - bits */
    5668             :                 /* VTEP IP */
    5669           0 :                 stream_put_in_addr(s, &evp->prefix.es_addr.ip.ipaddr_v4);
    5670           0 :                 break;
    5671             : 
    5672           0 :         case BGP_EVPN_AD_ROUTE:
    5673             :                 /* RD, ESI, EthTag, 1 VNI */
    5674           0 :                 len = RD_BYTES + ESI_BYTES + EVPN_ETH_TAG_BYTES + BGP_LABEL_BYTES;
    5675           0 :                 stream_putc(s, len);
    5676           0 :                 stream_put(s, prd->val, RD_BYTES); /* RD */
    5677           0 :                 stream_put(s, evp->prefix.ead_addr.esi.val, ESI_BYTES); /* ESI */
    5678           0 :                 stream_putl(s, evp->prefix.ead_addr.eth_tag); /* Ethernet Tag */
    5679           0 :                 stream_put(s, label, BGP_LABEL_BYTES);
    5680           0 :                 break;
    5681             : 
    5682           0 :         case BGP_EVPN_IP_PREFIX_ROUTE:
    5683             :                 /* TODO: AddPath support. */
    5684           0 :                 evpn_mpattr_encode_type5(s, p, prd, label, num_labels, attr);
    5685           0 :                 break;
    5686             : 
    5687             :         default:
    5688             :                 break;
    5689             :         }
    5690           0 : }
    5691             : 
    5692           0 : int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
    5693             :                         struct bgp_nlri *packet, int withdraw)
    5694             : {
    5695           0 :         uint8_t *pnt;
    5696           0 :         uint8_t *lim;
    5697           0 :         afi_t afi;
    5698           0 :         safi_t safi;
    5699           0 :         uint32_t addpath_id;
    5700           0 :         bool addpath_capable;
    5701           0 :         int psize = 0;
    5702           0 :         uint8_t rtype;
    5703           0 :         struct prefix p;
    5704             : 
    5705             :         /* Start processing the NLRI - there may be multiple in the MP_REACH */
    5706           0 :         pnt = packet->nlri;
    5707           0 :         lim = pnt + packet->length;
    5708           0 :         afi = packet->afi;
    5709           0 :         safi = packet->safi;
    5710           0 :         addpath_id = 0;
    5711             : 
    5712           0 :         addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
    5713             : 
    5714           0 :         for (; pnt < lim; pnt += psize) {
    5715             :                 /* Clear prefix structure. */
    5716           0 :                 memset(&p, 0, sizeof(p));
    5717             : 
    5718             :                 /* Deal with path-id if AddPath is supported. */
    5719           0 :                 if (addpath_capable) {
    5720             :                         /* When packet overflow occurs return immediately. */
    5721           0 :                         if (pnt + BGP_ADDPATH_ID_LEN > lim)
    5722             :                                 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
    5723             : 
    5724           0 :                         memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
    5725           0 :                         addpath_id = ntohl(addpath_id);
    5726           0 :                         pnt += BGP_ADDPATH_ID_LEN;
    5727             :                 }
    5728             : 
    5729             :                 /* All EVPN NLRI types start with type and length. */
    5730           0 :                 if (pnt + 2 > lim)
    5731             :                         return BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE;
    5732             : 
    5733           0 :                 rtype = *pnt++;
    5734           0 :                 psize = *pnt++;
    5735             : 
    5736             :                 /* When packet overflow occur return immediately. */
    5737           0 :                 if (pnt + psize > lim)
    5738             :                         return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
    5739             : 
    5740           0 :                 switch (rtype) {
    5741           0 :                 case BGP_EVPN_MAC_IP_ROUTE:
    5742           0 :                         if (process_type2_route(peer, afi, safi,
    5743             :                                                 withdraw ? NULL : attr, pnt,
    5744             :                                                 psize, addpath_id)) {
    5745           0 :                                 flog_err(
    5746             :                                         EC_BGP_EVPN_FAIL,
    5747             :                                         "%u:%s - Error in processing EVPN type-2 NLRI size %d",
    5748             :                                         peer->bgp->vrf_id, peer->host, psize);
    5749           0 :                                 return BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE;
    5750             :                         }
    5751             :                         break;
    5752             : 
    5753           0 :                 case BGP_EVPN_IMET_ROUTE:
    5754           0 :                         if (process_type3_route(peer, afi, safi,
    5755             :                                                 withdraw ? NULL : attr, pnt,
    5756             :                                                 psize, addpath_id)) {
    5757           0 :                                 flog_err(
    5758             :                                         EC_BGP_PKT_PROCESS,
    5759             :                                         "%u:%s - Error in processing EVPN type-3 NLRI size %d",
    5760             :                                         peer->bgp->vrf_id, peer->host, psize);
    5761           0 :                                 return BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE;
    5762             :                         }
    5763             :                         break;
    5764             : 
    5765           0 :                 case BGP_EVPN_ES_ROUTE:
    5766           0 :                         if (bgp_evpn_type4_route_process(peer, afi, safi,
    5767             :                                                 withdraw ? NULL : attr, pnt,
    5768             :                                                 psize, addpath_id)) {
    5769           0 :                                 flog_err(
    5770             :                                         EC_BGP_PKT_PROCESS,
    5771             :                                         "%u:%s - Error in processing EVPN type-4 NLRI size %d",
    5772             :                                         peer->bgp->vrf_id, peer->host, psize);
    5773           0 :                                 return BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE;
    5774             :                         }
    5775             :                         break;
    5776             : 
    5777           0 :                 case BGP_EVPN_AD_ROUTE:
    5778           0 :                         if (bgp_evpn_type1_route_process(peer, afi, safi,
    5779             :                                                 withdraw ? NULL : attr, pnt,
    5780             :                                                 psize, addpath_id)) {
    5781           0 :                                 flog_err(
    5782             :                                         EC_BGP_PKT_PROCESS,
    5783             :                                         "%u:%s - Error in processing EVPN type-1 NLRI size %d",
    5784             :                                         peer->bgp->vrf_id, peer->host, psize);
    5785           0 :                                 return BGP_NLRI_PARSE_ERROR_EVPN_TYPE1_SIZE;
    5786             :                         }
    5787             :                         break;
    5788             : 
    5789           0 :                 case BGP_EVPN_IP_PREFIX_ROUTE:
    5790           0 :                         if (process_type5_route(peer, afi, safi,
    5791             :                                                 withdraw ? NULL : attr, pnt,
    5792             :                                                 psize, addpath_id)) {
    5793           0 :                                 flog_err(
    5794             :                                         EC_BGP_PKT_PROCESS,
    5795             :                                         "%u:%s - Error in processing EVPN type-5 NLRI size %d",
    5796             :                                         peer->bgp->vrf_id, peer->host, psize);
    5797           0 :                                 return BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE;
    5798             :                         }
    5799             :                         break;
    5800             : 
    5801             :                 default:
    5802             :                         break;
    5803             :                 }
    5804             :         }
    5805             : 
    5806             :         /* Packet length consistency check. */
    5807           0 :         if (pnt != lim)
    5808           0 :                 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
    5809             : 
    5810             :         return BGP_NLRI_PARSE_OK;
    5811             : }
    5812             : 
    5813             : /*
    5814             :  * Map the RTs (configured or automatically derived) of a VRF to the VRF.
    5815             :  * The mapping will be used during route processing.
    5816             :  * bgp_vrf: specific bgp vrf instance on which RT is configured
    5817             :  */
    5818           0 : void bgp_evpn_map_vrf_to_its_rts(struct bgp *bgp_vrf)
    5819             : {
    5820           0 :         struct listnode *node, *nnode;
    5821           0 :         struct vrf_route_target *l3rt;
    5822             : 
    5823           0 :         for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt))
    5824           0 :                 map_vrf_to_rt(bgp_vrf, l3rt);
    5825           0 : }
    5826             : 
    5827             : /*
    5828             :  * Unmap the RTs (configured or automatically derived) of a VRF from the VRF.
    5829             :  */
    5830           2 : void bgp_evpn_unmap_vrf_from_its_rts(struct bgp *bgp_vrf)
    5831             : {
    5832           2 :         struct listnode *node, *nnode;
    5833           2 :         struct vrf_route_target *l3rt;
    5834             : 
    5835           4 :         for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt))
    5836           0 :                 unmap_vrf_from_rt(bgp_vrf, l3rt);
    5837           2 : }
    5838             : 
    5839             : /*
    5840             :  * Map the RTs (configured or automatically derived) of a VNI to the VNI.
    5841             :  * The mapping will be used during route processing.
    5842             :  */
    5843           0 : void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn)
    5844             : {
    5845           0 :         uint32_t i;
    5846           0 :         struct ecommunity_val *eval;
    5847           0 :         struct listnode *node, *nnode;
    5848           0 :         struct ecommunity *ecom;
    5849             : 
    5850           0 :         for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
    5851           0 :                 for (i = 0; i < ecom->size; i++) {
    5852           0 :                         eval = (struct ecommunity_val *)(ecom->val
    5853             :                                                          + (i
    5854           0 :                                                             * ECOMMUNITY_SIZE));
    5855           0 :                         map_vni_to_rt(bgp, vpn, eval);
    5856             :                 }
    5857             :         }
    5858           0 : }
    5859             : 
    5860             : /*
    5861             :  * Unmap the RTs (configured or automatically derived) of a VNI from the VNI.
    5862             :  */
    5863           0 : void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp, struct bgpevpn *vpn)
    5864             : {
    5865           0 :         uint32_t i;
    5866           0 :         struct ecommunity_val *eval;
    5867           0 :         struct listnode *node, *nnode;
    5868           0 :         struct ecommunity *ecom;
    5869             : 
    5870           0 :         for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
    5871           0 :                 for (i = 0; i < ecom->size; i++) {
    5872           0 :                         struct irt_node *irt;
    5873           0 :                         struct ecommunity_val eval_tmp;
    5874             : 
    5875           0 :                         eval = (struct ecommunity_val *)(ecom->val
    5876             :                                                          + (i
    5877           0 :                                                             * ECOMMUNITY_SIZE));
    5878             :                         /* If using "automatic" RT, we only care about the
    5879             :                          * local-admin sub-field.
    5880             :                          * This is to facilitate using VNI as the RT for EBGP
    5881             :                          * peering too.
    5882             :                          */
    5883           0 :                         memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE);
    5884           0 :                         if (!is_import_rt_configured(vpn))
    5885           0 :                                 mask_ecom_global_admin(&eval_tmp, eval);
    5886             : 
    5887           0 :                         irt = lookup_import_rt(bgp, &eval_tmp);
    5888           0 :                         if (irt)
    5889           0 :                                 unmap_vni_from_rt(bgp, vpn, irt);
    5890             :                 }
    5891             :         }
    5892           0 : }
    5893             : 
    5894             : /*
    5895             :  * Derive Import RT automatically for VNI and map VNI to RT.
    5896             :  * The mapping will be used during route processing.
    5897             :  */
    5898           0 : void bgp_evpn_derive_auto_rt_import(struct bgp *bgp, struct bgpevpn *vpn)
    5899             : {
    5900           0 :         form_auto_rt(bgp, vpn->vni, vpn->import_rtl, false);
    5901           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
    5902             : 
    5903             :         /* Map RT to VNI */
    5904           0 :         bgp_evpn_map_vni_to_its_rts(bgp, vpn);
    5905           0 : }
    5906             : 
    5907             : /*
    5908             :  * Derive Export RT automatically for VNI.
    5909             :  */
    5910           0 : void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, struct bgpevpn *vpn)
    5911             : {
    5912           0 :         form_auto_rt(bgp, vpn->vni, vpn->export_rtl, false);
    5913           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
    5914           0 : }
    5915             : 
    5916             : /*
    5917             :  * Derive RD automatically for VNI using passed information - it
    5918             :  * is of the form RouterId:unique-id-for-vni.
    5919             :  */
    5920           0 : void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp)
    5921             : {
    5922           0 :         if (is_vrf_rd_configured(bgp))
    5923             :                 return;
    5924             : 
    5925           0 :         form_auto_rd(bgp->router_id, bgp->vrf_rd_id, &bgp->vrf_prd);
    5926             : }
    5927             : 
    5928             : /*
    5929             :  * Derive RD automatically for VNI using passed information - it
    5930             :  * is of the form RouterId:unique-id-for-vni.
    5931             :  */
    5932           0 : void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
    5933             : {
    5934           0 :         char buf[BGP_EVPN_PREFIX_RD_LEN];
    5935             : 
    5936           0 :         vpn->prd.family = AF_UNSPEC;
    5937           0 :         vpn->prd.prefixlen = 64;
    5938           0 :         snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, vpn->rd_id);
    5939           0 :         (void)str2prefix_rd(buf, &vpn->prd);
    5940           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
    5941           0 : }
    5942             : 
    5943             : /*
    5944             :  * Lookup L3-VNI
    5945             :  */
    5946           0 : bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni)
    5947             : {
    5948           0 :         struct list *inst = bm->bgp;
    5949           0 :         struct listnode *node;
    5950           0 :         struct bgp *bgp_vrf;
    5951             : 
    5952           0 :         for (ALL_LIST_ELEMENTS_RO(inst, node, bgp_vrf)) {
    5953           0 :                 if (bgp_vrf->l3vni == vni)
    5954             :                         return true;
    5955             :         }
    5956             : 
    5957             :         return false;
    5958             : }
    5959             : 
    5960             : /*
    5961             :  * Lookup VNI.
    5962             :  */
    5963           0 : struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni)
    5964             : {
    5965           0 :         struct bgpevpn *vpn;
    5966           0 :         struct bgpevpn tmp;
    5967             : 
    5968           0 :         memset(&tmp, 0, sizeof(tmp));
    5969           0 :         tmp.vni = vni;
    5970           0 :         vpn = hash_lookup(bgp->vnihash, &tmp);
    5971           0 :         return vpn;
    5972             : }
    5973             : 
    5974             : /*
    5975             :  * Create a new vpn - invoked upon configuration or zebra notification.
    5976             :  */
    5977           0 : struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
    5978             :                 struct in_addr originator_ip,
    5979             :                 vrf_id_t tenant_vrf_id,
    5980             :                 struct in_addr mcast_grp,
    5981             :                 ifindex_t svi_ifindex)
    5982             : {
    5983           0 :         struct bgpevpn *vpn;
    5984             : 
    5985           0 :         vpn = XCALLOC(MTYPE_BGP_EVPN, sizeof(struct bgpevpn));
    5986             : 
    5987             :         /* Set values - RD and RT set to defaults. */
    5988           0 :         vpn->vni = vni;
    5989           0 :         vpn->originator_ip = originator_ip;
    5990           0 :         vpn->tenant_vrf_id = tenant_vrf_id;
    5991           0 :         vpn->mcast_grp = mcast_grp;
    5992           0 :         vpn->svi_ifindex = svi_ifindex;
    5993             : 
    5994             :         /* Initialize route-target import and export lists */
    5995           0 :         vpn->import_rtl = list_new();
    5996           0 :         vpn->import_rtl->cmp =
    5997             :                 (int (*)(void *, void *))bgp_evpn_route_target_cmp;
    5998           0 :         vpn->import_rtl->del = bgp_evpn_xxport_delete_ecomm;
    5999           0 :         vpn->export_rtl = list_new();
    6000           0 :         vpn->export_rtl->cmp =
    6001             :                 (int (*)(void *, void *))bgp_evpn_route_target_cmp;
    6002           0 :         vpn->export_rtl->del = bgp_evpn_xxport_delete_ecomm;
    6003           0 :         bf_assign_index(bm->rd_idspace, vpn->rd_id);
    6004           0 :         derive_rd_rt_for_vni(bgp, vpn);
    6005             : 
    6006             :         /* Initialize EVPN route tables. */
    6007           0 :         vpn->ip_table = bgp_table_init(bgp, AFI_L2VPN, SAFI_EVPN);
    6008           0 :         vpn->mac_table = bgp_table_init(bgp, AFI_L2VPN, SAFI_EVPN);
    6009             : 
    6010             :         /* Add to hash */
    6011           0 :         (void)hash_get(bgp->vnihash, vpn, hash_alloc_intern);
    6012             : 
    6013           0 :         bgp_evpn_remote_ip_hash_init(vpn);
    6014           0 :         bgp_evpn_link_to_vni_svi_hash(bgp, vpn);
    6015             : 
    6016             :         /* add to l2vni list on corresponding vrf */
    6017           0 :         bgpevpn_link_to_l3vni(vpn);
    6018             : 
    6019           0 :         bgp_evpn_vni_es_init(vpn);
    6020             : 
    6021           0 :         QOBJ_REG(vpn, bgpevpn);
    6022           0 :         return vpn;
    6023             : }
    6024             : 
    6025             : /*
    6026             :  * Free a given VPN - called in multiple scenarios such as zebra
    6027             :  * notification, configuration being deleted, advertise-all-vni disabled etc.
    6028             :  * This just frees appropriate memory, caller should have taken other
    6029             :  * needed actions.
    6030             :  */
    6031           0 : void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
    6032             : {
    6033           0 :         bgp_evpn_remote_ip_hash_destroy(vpn);
    6034           0 :         bgp_evpn_vni_es_cleanup(vpn);
    6035           0 :         bgpevpn_unlink_from_l3vni(vpn);
    6036           0 :         bgp_table_unlock(vpn->ip_table);
    6037           0 :         bgp_table_unlock(vpn->mac_table);
    6038           0 :         bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
    6039           0 :         list_delete(&vpn->import_rtl);
    6040           0 :         list_delete(&vpn->export_rtl);
    6041           0 :         bf_release_index(bm->rd_idspace, vpn->rd_id);
    6042           0 :         hash_release(bgp->vni_svi_hash, vpn);
    6043           0 :         hash_release(bgp->vnihash, vpn);
    6044           0 :         QOBJ_UNREG(vpn);
    6045           0 :         XFREE(MTYPE_BGP_EVPN, vpn);
    6046           0 : }
    6047             : 
    6048           0 : static void hash_evpn_free(struct bgpevpn *vpn)
    6049             : {
    6050           0 :         XFREE(MTYPE_BGP_EVPN, vpn);
    6051           0 : }
    6052             : 
    6053             : /*
    6054             :  * Import evpn route from global table to VNI/VRF/ESI.
    6055             :  */
    6056           0 : int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
    6057             :                           const struct prefix *p, struct bgp_path_info *pi)
    6058             : {
    6059           0 :         return install_uninstall_evpn_route(bgp, afi, safi, p, pi, 1);
    6060             : }
    6061             : 
    6062             : /*
    6063             :  * Unimport evpn route from VNI/VRF/ESI.
    6064             :  */
    6065           0 : int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
    6066             :                             const struct prefix *p, struct bgp_path_info *pi)
    6067             : {
    6068           0 :         return install_uninstall_evpn_route(bgp, afi, safi, p, pi, 0);
    6069             : }
    6070             : 
    6071             : /* filter routes which have martian next hops */
    6072           0 : int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
    6073             : {
    6074           0 :         afi_t afi;
    6075           0 :         safi_t safi;
    6076           0 :         struct bgp_dest *rd_dest, *dest;
    6077           0 :         struct bgp_table *table;
    6078           0 :         struct bgp_path_info *pi;
    6079             : 
    6080           0 :         afi = AFI_L2VPN;
    6081           0 :         safi = SAFI_EVPN;
    6082             : 
    6083             :         /* Walk entire global routing table and evaluate routes which could be
    6084             :          * imported into this VPN. Note that we cannot just look at the routes
    6085             :          * for the VNI's RD -
    6086             :          * remote routes applicable for this VNI could have any RD.
    6087             :          */
    6088             :         /* EVPN routes are a 2-level table. */
    6089           0 :         for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
    6090           0 :              rd_dest = bgp_route_next(rd_dest)) {
    6091           0 :                 table = bgp_dest_get_bgp_table_info(rd_dest);
    6092           0 :                 if (!table)
    6093           0 :                         continue;
    6094             : 
    6095           0 :                 for (dest = bgp_table_top(table); dest;
    6096           0 :                      dest = bgp_route_next(dest)) {
    6097             : 
    6098           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
    6099           0 :                              pi = pi->next) {
    6100             : 
    6101             :                                 /* Consider "valid" remote routes applicable for
    6102             :                                  * this VNI. */
    6103           0 :                                 if (!(pi->type == ZEBRA_ROUTE_BGP
    6104             :                                       && pi->sub_type == BGP_ROUTE_NORMAL))
    6105           0 :                                         continue;
    6106           0 :                                 if (bgp_nexthop_self(bgp, afi, pi->type,
    6107           0 :                                                      pi->sub_type, pi->attr,
    6108             :                                                      dest)) {
    6109           0 :                                         const struct prefix *p =
    6110           0 :                                                 bgp_dest_get_prefix(dest);
    6111             : 
    6112           0 :                                         if (bgp_debug_update(pi->peer, p, NULL,
    6113             :                                                              1)) {
    6114           0 :                                                 char attr_str[BUFSIZ] = {0};
    6115             : 
    6116           0 :                                                 bgp_dump_attr(pi->attr,
    6117             :                                                               attr_str,
    6118             :                                                               sizeof(attr_str));
    6119             : 
    6120           0 :                                                 zlog_debug(
    6121             :                                                         "%u: prefix %pBD with attr %s - DENIED due to martian or self nexthop",
    6122             :                                                         bgp->vrf_id, dest,
    6123             :                                                         attr_str);
    6124             :                                         }
    6125           0 :                                         bgp_evpn_unimport_route(bgp, afi, safi,
    6126             :                                                                 p, pi);
    6127             : 
    6128           0 :                                         bgp_rib_remove(dest, pi, pi->peer, afi,
    6129             :                                                        safi);
    6130             :                                 }
    6131             :                         }
    6132             :                 }
    6133             :         }
    6134             : 
    6135           0 :         return 0;
    6136             : }
    6137             : 
    6138             : /*
    6139             :  * Handle del of a local MACIP.
    6140             :  */
    6141           0 : int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
    6142             :                              struct ipaddr *ip, int state)
    6143             : {
    6144           0 :         struct bgpevpn *vpn;
    6145           0 :         struct prefix_evpn p;
    6146           0 :         struct bgp_dest *dest;
    6147             : 
    6148             :         /* Lookup VNI hash - should exist. */
    6149           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    6150           0 :         if (!vpn || !is_vni_live(vpn)) {
    6151           0 :                 flog_warn(EC_BGP_EVPN_VPN_VNI,
    6152             :                           "%u: VNI hash entry for VNI %u %s at MACIP DEL",
    6153             :                           bgp->vrf_id, vni, vpn ? "not live" : "not found");
    6154           0 :                 return -1;
    6155             :         }
    6156             : 
    6157           0 :         build_evpn_type2_prefix(&p, mac, ip);
    6158           0 :         if (state == ZEBRA_NEIGH_ACTIVE) {
    6159             :                 /* Remove EVPN type-2 route and schedule for processing. */
    6160           0 :                 delete_evpn_route(bgp, vpn, &p);
    6161             :         } else {
    6162             :                 /* Re-instate the current remote best path if any */
    6163           0 :                 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
    6164           0 :                 if (dest) {
    6165           0 :                         evpn_zebra_reinstall_best_route(bgp, vpn, dest);
    6166           0 :                         bgp_dest_unlock_node(dest);
    6167             :                 }
    6168             :         }
    6169             : 
    6170             :         return 0;
    6171             : }
    6172             : 
    6173             : /*
    6174             :  * Handle add of a local MACIP.
    6175             :  */
    6176           0 : int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
    6177             :                 struct ipaddr *ip, uint8_t flags, uint32_t seq, esi_t *esi)
    6178             : {
    6179           0 :         struct bgpevpn *vpn;
    6180           0 :         struct prefix_evpn p;
    6181             : 
    6182             :         /* Lookup VNI hash - should exist. */
    6183           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    6184           0 :         if (!vpn || !is_vni_live(vpn)) {
    6185           0 :                 flog_warn(EC_BGP_EVPN_VPN_VNI,
    6186             :                           "%u: VNI hash entry for VNI %u %s at MACIP ADD",
    6187             :                           bgp->vrf_id, vni, vpn ? "not live" : "not found");
    6188           0 :                 return -1;
    6189             :         }
    6190             : 
    6191             :         /* Create EVPN type-2 route and schedule for processing. */
    6192           0 :         build_evpn_type2_prefix(&p, mac, ip);
    6193           0 :         if (update_evpn_route(bgp, vpn, &p, flags, seq, esi)) {
    6194           0 :                 flog_err(
    6195             :                         EC_BGP_EVPN_ROUTE_CREATE,
    6196             :                         "%u:Failed to create Type-2 route, VNI %u %s MAC %pEA IP %pIA (flags: 0x%x)",
    6197             :                         bgp->vrf_id, vpn->vni,
    6198             :                         CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY)
    6199             :                                 ? "sticky gateway"
    6200             :                                 : "",
    6201             :                         mac, ip, flags);
    6202           0 :                 return -1;
    6203             :         }
    6204             : 
    6205             :         return 0;
    6206             : }
    6207             : 
    6208           0 : static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket,
    6209             :                                      struct bgp *bgp_vrf)
    6210             : {
    6211           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    6212           0 :         struct bgp *bgp_evpn = NULL;
    6213             : 
    6214           0 :         bgp_evpn = bgp_get_evpn();
    6215           0 :         assert(bgp_evpn);
    6216             : 
    6217           0 :         if (vpn->tenant_vrf_id == bgp_vrf->vrf_id)
    6218           0 :                 bgpevpn_link_to_l3vni(vpn);
    6219           0 : }
    6220             : 
    6221           0 : int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,
    6222             :                              struct ethaddr *svi_rmac,
    6223             :                              struct ethaddr *vrr_rmac,
    6224             :                              struct in_addr originator_ip, int filter,
    6225             :                              ifindex_t svi_ifindex,
    6226             :                              bool is_anycast_mac)
    6227             : {
    6228           0 :         struct bgp *bgp_vrf = NULL; /* bgp VRF instance */
    6229           0 :         struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */
    6230           0 :         struct listnode *node = NULL;
    6231           0 :         struct bgpevpn *vpn = NULL;
    6232           0 :         as_t as = 0;
    6233             : 
    6234             :         /* get the EVPN instance - required to get the AS number for VRF
    6235             :          * auto-creatio
    6236             :          */
    6237           0 :         bgp_evpn = bgp_get_evpn();
    6238           0 :         if (!bgp_evpn) {
    6239           0 :                 flog_err(
    6240             :                         EC_BGP_NO_DFLT,
    6241             :                         "Cannot process L3VNI  %u ADD - EVPN BGP instance not yet created",
    6242             :                         l3vni);
    6243           0 :                 return -1;
    6244             :         }
    6245           0 :         as = bgp_evpn->as;
    6246             : 
    6247             :         /* if the BGP vrf instance doesn't exist - create one */
    6248           0 :         bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
    6249           0 :         if (!bgp_vrf) {
    6250             : 
    6251           0 :                 int ret = 0;
    6252             : 
    6253           0 :                 ret = bgp_get_vty(&bgp_vrf, &as, vrf_id_to_name(vrf_id),
    6254             :                                   vrf_id == VRF_DEFAULT
    6255             :                                   ? BGP_INSTANCE_TYPE_DEFAULT
    6256             :                                   : BGP_INSTANCE_TYPE_VRF);
    6257           0 :                 switch (ret) {
    6258           0 :                 case BGP_ERR_AS_MISMATCH:
    6259           0 :                         flog_err(EC_BGP_EVPN_AS_MISMATCH,
    6260             :                                  "BGP instance is already running; AS is %u",
    6261             :                                  as);
    6262           0 :                         return -1;
    6263           0 :                 case BGP_ERR_INSTANCE_MISMATCH:
    6264           0 :                         flog_err(EC_BGP_EVPN_INSTANCE_MISMATCH,
    6265             :                                  "BGP instance type mismatch");
    6266           0 :                         return -1;
    6267             :                 }
    6268             : 
    6269             :                 /* mark as auto created */
    6270           0 :                 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO);
    6271             :         }
    6272             : 
    6273             :         /* associate the vrf with l3vni and related parameters */
    6274           0 :         bgp_vrf->l3vni = l3vni;
    6275           0 :         bgp_vrf->originator_ip = originator_ip;
    6276           0 :         bgp_vrf->l3vni_svi_ifindex = svi_ifindex;
    6277           0 :         bgp_vrf->evpn_info->is_anycast_mac = is_anycast_mac;
    6278             : 
    6279             :         /* copy anycast MAC from VRR MAC */
    6280           0 :         memcpy(&bgp_vrf->rmac, vrr_rmac, ETH_ALEN);
    6281             :         /* copy sys RMAC from SVI MAC */
    6282           0 :         memcpy(&bgp_vrf->evpn_info->pip_rmac_zebra, svi_rmac, ETH_ALEN);
    6283             :         /* PIP user configured mac is not present use svi mac as sys mac */
    6284           0 :         if (is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_static))
    6285           0 :                 memcpy(&bgp_vrf->evpn_info->pip_rmac, svi_rmac, ETH_ALEN);
    6286             : 
    6287           0 :         if (bgp_debug_zebra(NULL))
    6288           0 :                 zlog_debug(
    6289             :                         "VRF %s vni %u pip %s RMAC %pEA sys RMAC %pEA static RMAC %pEA is_anycast_mac %s",
    6290             :                         vrf_id_to_name(bgp_vrf->vrf_id), bgp_vrf->l3vni,
    6291             :                         bgp_vrf->evpn_info->advertise_pip ? "enable"
    6292             :                                                           : "disable",
    6293             :                         &bgp_vrf->rmac, &bgp_vrf->evpn_info->pip_rmac,
    6294             :                         &bgp_vrf->evpn_info->pip_rmac_static,
    6295             :                         is_anycast_mac ? "Enable" : "Disable");
    6296             : 
    6297             :         /* set the right filter - are we using l3vni only for prefix routes? */
    6298           0 :         if (filter) {
    6299           0 :                 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY);
    6300             : 
    6301             :                 /*
    6302             :                  * VNI_FLAG_USE_TWO_LABELS flag for linked L2VNIs should not be
    6303             :                  * set before linking vrf to L3VNI. Thus, no need to clear
    6304             :                  * that explicitly.
    6305             :                  */
    6306             :         } else {
    6307           0 :                 UNSET_FLAG(bgp_vrf->vrf_flags,
    6308             :                            BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY);
    6309             : 
    6310           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
    6311           0 :                         if (!CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) {
    6312             : 
    6313             :                                 /*
    6314             :                                  * If we are flapping VNI_FLAG_USE_TWO_LABELS
    6315             :                                  * flag, update all MACIP routes in this VNI
    6316             :                                  */
    6317           0 :                                 SET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
    6318           0 :                                 update_all_type2_routes(bgp_evpn, vpn);
    6319             :                         }
    6320             :                 }
    6321             :         }
    6322             : 
    6323             :         /* Map auto derive or configured RTs */
    6324           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD) ||
    6325             :             CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
    6326           0 :                 evpn_auto_rt_import_add_for_vrf(bgp_vrf);
    6327             :         else
    6328           0 :                 bgp_evpn_map_vrf_to_its_rts(bgp_vrf);
    6329             : 
    6330           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_RT_CFGD) ||
    6331             :             CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
    6332           0 :                 evpn_auto_rt_export_add_for_vrf(bgp_vrf);
    6333             : 
    6334             :         /* auto derive RD */
    6335           0 :         bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
    6336             : 
    6337             :         /* link all corresponding l2vnis */
    6338           0 :         hash_iterate(bgp_evpn->vnihash,
    6339             :                      (void (*)(struct hash_bucket *,
    6340             :                                void *))link_l2vni_hash_to_l3vni,
    6341             :                      bgp_vrf);
    6342             : 
    6343             :         /* Only update all corresponding type-2 routes if we are advertising two
    6344             :          * labels along with type-2 routes
    6345             :          */
    6346           0 :         if (!filter)
    6347           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn))
    6348           0 :                         update_routes_for_vni(bgp_evpn, vpn);
    6349             : 
    6350             :         /* advertise type-5 routes if needed */
    6351           0 :         update_advertise_vrf_routes(bgp_vrf);
    6352             : 
    6353             :         /* install all remote routes belonging to this l3vni into correspondng
    6354             :          * vrf */
    6355           0 :         install_routes_for_vrf(bgp_vrf);
    6356             : 
    6357           0 :         return 0;
    6358             : }
    6359             : 
    6360           0 : int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
    6361             : {
    6362           0 :         struct bgp *bgp_vrf = NULL; /* bgp vrf instance */
    6363           0 :         struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */
    6364           0 :         struct listnode *node = NULL;
    6365           0 :         struct listnode *next = NULL;
    6366           0 :         struct bgpevpn *vpn = NULL;
    6367             : 
    6368           0 :         bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
    6369           0 :         if (!bgp_vrf) {
    6370           0 :                 flog_err(
    6371             :                         EC_BGP_NO_DFLT,
    6372             :                         "Cannot process L3VNI %u Del - Could not find BGP instance",
    6373             :                         l3vni);
    6374           0 :                 return -1;
    6375             :         }
    6376             : 
    6377           0 :         bgp_evpn = bgp_get_evpn();
    6378           0 :         if (!bgp_evpn) {
    6379           0 :                 flog_err(
    6380             :                         EC_BGP_NO_DFLT,
    6381             :                         "Cannot process L3VNI %u Del - Could not find EVPN BGP instance",
    6382             :                         l3vni);
    6383           0 :                 return -1;
    6384             :         }
    6385             : 
    6386             :         /* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured,
    6387             :          * bgp_delete would not remove/decrement bgp_path_info of the ip_prefix
    6388             :          * routes. This will uninstalling the routes from zebra and decremnt the
    6389             :          * bgp info count.
    6390             :          */
    6391           0 :         uninstall_routes_for_vrf(bgp_vrf);
    6392             : 
    6393             :         /* delete/withdraw all type-5 routes */
    6394           0 :         delete_withdraw_vrf_routes(bgp_vrf);
    6395             : 
    6396             :         /* remove the l3vni from vrf instance */
    6397           0 :         bgp_vrf->l3vni = 0;
    6398             : 
    6399             :         /* remove the Rmac from the BGP vrf */
    6400           0 :         memset(&bgp_vrf->rmac, 0, sizeof(struct ethaddr));
    6401           0 :         memset(&bgp_vrf->evpn_info->pip_rmac_zebra, 0, ETH_ALEN);
    6402           0 :         if (is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_static) &&
    6403           0 :             !is_zero_mac(&bgp_vrf->evpn_info->pip_rmac))
    6404           0 :                 memset(&bgp_vrf->evpn_info->pip_rmac, 0, ETH_ALEN);
    6405             : 
    6406             :         /* remove default import RT or Unmap non-default import RT */
    6407           0 :         if (!list_isempty(bgp_vrf->vrf_import_rtl)) {
    6408           0 :                 bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
    6409           0 :                 if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD))
    6410           0 :                         list_delete_all_node(bgp_vrf->vrf_import_rtl);
    6411             :         }
    6412             : 
    6413             :         /* remove default export RT */
    6414           0 :         if (!list_isempty(bgp_vrf->vrf_export_rtl) &&
    6415           0 :             !CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
    6416           0 :                 list_delete_all_node(bgp_vrf->vrf_export_rtl);
    6417             :         }
    6418             : 
    6419             :         /* update all corresponding local mac-ip routes */
    6420           0 :         if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)) {
    6421           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
    6422           0 :                         UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
    6423           0 :                         update_routes_for_vni(bgp_evpn, vpn);
    6424             :                 }
    6425             :         }
    6426             : 
    6427             :         /* If any L2VNIs point to this instance, unlink them. */
    6428           0 :         for (ALL_LIST_ELEMENTS(bgp_vrf->l2vnis, node, next, vpn))
    6429           0 :                 bgpevpn_unlink_from_l3vni(vpn);
    6430             : 
    6431           0 :         UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY);
    6432             : 
    6433             :         /* Delete the instance if it was autocreated */
    6434           0 :         if (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO))
    6435           0 :                 bgp_delete(bgp_vrf);
    6436             : 
    6437             :         return 0;
    6438             : }
    6439             : 
    6440             : /*
    6441             :  * Handle del of a local VNI.
    6442             :  */
    6443           0 : int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
    6444             : {
    6445           0 :         struct bgpevpn *vpn;
    6446             : 
    6447             :         /* Locate VNI hash */
    6448           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    6449           0 :         if (!vpn)
    6450             :                 return 0;
    6451             : 
    6452             :         /* Remove all local EVPN routes and schedule for processing (to
    6453             :          * withdraw from peers).
    6454             :          */
    6455           0 :         delete_routes_for_vni(bgp, vpn);
    6456             : 
    6457           0 :         bgp_evpn_unlink_from_vni_svi_hash(bgp, vpn);
    6458             : 
    6459           0 :         vpn->svi_ifindex = 0;
    6460             :         /*
    6461             :          * tunnel is no longer active, del tunnel ip address from tip_hash
    6462             :          */
    6463           0 :         bgp_tip_del(bgp, &vpn->originator_ip);
    6464             : 
    6465             :         /* Clear "live" flag and see if hash needs to be freed. */
    6466           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
    6467           0 :         if (!is_vni_configured(vpn))
    6468           0 :                 bgp_evpn_free(bgp, vpn);
    6469             : 
    6470             :         return 0;
    6471             : }
    6472             : 
    6473             : /*
    6474             :  * Handle add (or update) of a local VNI. The VNI changes we care
    6475             :  * about are for the local-tunnel-ip and the (tenant) VRF.
    6476             :  */
    6477           0 : int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
    6478             :                            struct in_addr originator_ip,
    6479             :                            vrf_id_t tenant_vrf_id,
    6480             :                            struct in_addr mcast_grp,
    6481             :                            ifindex_t svi_ifindex)
    6482             : {
    6483           0 :         struct bgpevpn *vpn;
    6484           0 :         struct prefix_evpn p;
    6485             : 
    6486             :         /* Lookup VNI. If present and no change, exit. */
    6487           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    6488           0 :         if (vpn) {
    6489             : 
    6490           0 :                 if (is_vni_live(vpn)
    6491           0 :                     && IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip)
    6492           0 :                     && IPV4_ADDR_SAME(&vpn->mcast_grp, &mcast_grp)
    6493           0 :                     && vpn->tenant_vrf_id == tenant_vrf_id
    6494           0 :                     && vpn->svi_ifindex == svi_ifindex)
    6495             :                         /* Probably some other param has changed that we don't
    6496             :                          * care about. */
    6497             :                         return 0;
    6498             : 
    6499           0 :                 bgp_evpn_mcast_grp_change(bgp, vpn, mcast_grp);
    6500             : 
    6501           0 :                 if (vpn->svi_ifindex != svi_ifindex) {
    6502             : 
    6503             :                         /*
    6504             :                          * Unresolve all the gateway IP nexthops for this VNI
    6505             :                          * for old SVI
    6506             :                          */
    6507           0 :                         bgp_evpn_remote_ip_hash_iterate(
    6508             :                                 vpn,
    6509             :                                 (void (*)(struct hash_bucket *, void *))
    6510             :                                         bgp_evpn_remote_ip_hash_unlink_nexthop,
    6511             :                                 vpn);
    6512           0 :                         bgp_evpn_unlink_from_vni_svi_hash(bgp, vpn);
    6513           0 :                         vpn->svi_ifindex = svi_ifindex;
    6514           0 :                         bgp_evpn_link_to_vni_svi_hash(bgp, vpn);
    6515             : 
    6516             :                         /*
    6517             :                          * Resolve all the gateway IP nexthops for this VNI
    6518             :                          * for new SVI
    6519             :                          */
    6520           0 :                         bgp_evpn_remote_ip_hash_iterate(
    6521             :                                 vpn,
    6522             :                                 (void (*)(struct hash_bucket *, void *))
    6523             :                                         bgp_evpn_remote_ip_hash_link_nexthop,
    6524             :                                 vpn);
    6525             :                 }
    6526             : 
    6527             :                 /* Update tenant_vrf_id if it has changed. */
    6528           0 :                 if (vpn->tenant_vrf_id != tenant_vrf_id) {
    6529             : 
    6530             :                         /*
    6531             :                          * Unresolve all the gateway IP nexthops for this VNI
    6532             :                          * in old tenant vrf
    6533             :                          */
    6534           0 :                         bgp_evpn_remote_ip_hash_iterate(
    6535             :                                 vpn,
    6536             :                                 (void (*)(struct hash_bucket *, void *))
    6537             :                                         bgp_evpn_remote_ip_hash_unlink_nexthop,
    6538             :                                 vpn);
    6539           0 :                         bgpevpn_unlink_from_l3vni(vpn);
    6540           0 :                         vpn->tenant_vrf_id = tenant_vrf_id;
    6541           0 :                         bgpevpn_link_to_l3vni(vpn);
    6542             : 
    6543             :                         /*
    6544             :                          * Resolve all the gateway IP nexthops for this VNI
    6545             :                          * in new tenant vrf
    6546             :                          */
    6547           0 :                         bgp_evpn_remote_ip_hash_iterate(
    6548             :                                 vpn,
    6549             :                                 (void (*)(struct hash_bucket *, void *))
    6550             :                                         bgp_evpn_remote_ip_hash_link_nexthop,
    6551             :                                 vpn);
    6552             :                 }
    6553             : 
    6554             :                 /* If tunnel endpoint IP has changed, update (and delete prior
    6555             :                  * type-3 route, if needed.)
    6556             :                  */
    6557           0 :                 handle_tunnel_ip_change(bgp, vpn, originator_ip);
    6558             : 
    6559             :                 /* Update all routes with new endpoint IP and/or export RT
    6560             :                  * for VRFs
    6561             :                  */
    6562           0 :                 if (is_vni_live(vpn))
    6563           0 :                         update_routes_for_vni(bgp, vpn);
    6564             :         } else {
    6565             :                 /* Create or update as appropriate. */
    6566           0 :                 vpn = bgp_evpn_new(bgp, vni, originator_ip, tenant_vrf_id,
    6567             :                                    mcast_grp, svi_ifindex);
    6568             :         }
    6569             : 
    6570             :         /* if the VNI is live already, there is nothing more to do */
    6571           0 :         if (is_vni_live(vpn))
    6572             :                 return 0;
    6573             : 
    6574             :         /* Mark as "live" */
    6575           0 :         SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
    6576             : 
    6577             :         /* tunnel is now active, add tunnel-ip to db */
    6578           0 :         if (bgp_tip_add(bgp, &originator_ip))
    6579             :                 /* The originator_ip was not already present in the
    6580             :                  * bgp martian next-hop table as a tunnel-ip, so we
    6581             :                  * need to go back and filter routes matching the new
    6582             :                  * martian next-hop.
    6583             :                  */
    6584           0 :                 bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
    6585             : 
    6586             :         /*
    6587             :          * Create EVPN type-3 route and schedule for processing.
    6588             :          *
    6589             :          * RT-3 only if doing head-end replication
    6590             :          */
    6591           0 :         if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
    6592             :                         == VXLAN_FLOOD_HEAD_END_REPL) {
    6593           0 :                 build_evpn_type3_prefix(&p, vpn->originator_ip);
    6594           0 :                 if (update_evpn_route(bgp, vpn, &p, 0, 0, NULL)) {
    6595           0 :                         flog_err(EC_BGP_EVPN_ROUTE_CREATE,
    6596             :                                  "%u: Type3 route creation failure for VNI %u",
    6597             :                                  bgp->vrf_id, vni);
    6598           0 :                         return -1;
    6599             :                 }
    6600             :         }
    6601             : 
    6602             :         /* If we have learnt and retained remote routes (VTEPs, MACs) for this
    6603             :          * VNI,
    6604             :          * install them.
    6605             :          */
    6606           0 :         install_routes_for_vni(bgp, vpn);
    6607             : 
    6608             :         /* If we are advertising gateway mac-ip
    6609             :            It needs to be conveyed again to zebra */
    6610           0 :         bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip, vpn->vni);
    6611             : 
    6612             :         /* advertise svi mac-ip knob to zebra */
    6613           0 :         bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip, vpn->vni);
    6614             : 
    6615           0 :         return 0;
    6616             : }
    6617             : 
    6618             : /*
    6619             :  * Handle change in setting for BUM handling. The supported values
    6620             :  * are head-end replication and dropping all BUM packets. Any change
    6621             :  * should be registered with zebra. Also, if doing head-end replication,
    6622             :  * need to advertise local VNIs as EVPN RT-3 wheras, if BUM packets are
    6623             :  * to be dropped, the RT-3s must be withdrawn.
    6624             :  */
    6625           0 : void bgp_evpn_flood_control_change(struct bgp *bgp)
    6626             : {
    6627           0 :         zlog_info("L2VPN EVPN BUM handling is %s",
    6628             :                   bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL ?
    6629             :                   "Flooding" : "Flooding Disabled");
    6630             : 
    6631           0 :         bgp_zebra_vxlan_flood_control(bgp, bgp->vxlan_flood_ctrl);
    6632           0 :         if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL)
    6633           0 :                 hash_iterate(bgp->vnihash, create_advertise_type3, bgp);
    6634           0 :         else if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
    6635           0 :                 hash_iterate(bgp->vnihash, delete_withdraw_type3, bgp);
    6636           0 : }
    6637             : 
    6638             : /*
    6639             :  * Cleanup EVPN information on disable - Need to delete and withdraw
    6640             :  * EVPN routes from peers.
    6641             :  */
    6642           0 : void bgp_evpn_cleanup_on_disable(struct bgp *bgp)
    6643             : {
    6644           0 :         hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
    6645             :                                              void *))cleanup_vni_on_disable,
    6646             :                      bgp);
    6647           0 : }
    6648             : 
    6649             : /*
    6650             :  * Cleanup EVPN information - invoked at the time of bgpd exit or when the
    6651             :  * BGP instance (default) is being freed.
    6652             :  */
    6653           1 : void bgp_evpn_cleanup(struct bgp *bgp)
    6654             : {
    6655           1 :         hash_iterate(bgp->vnihash,
    6656             :                      (void (*)(struct hash_bucket *, void *))free_vni_entry,
    6657             :                      bgp);
    6658             : 
    6659           1 :         hash_clean(bgp->import_rt_hash, (void (*)(void *))hash_import_rt_free);
    6660           1 :         hash_free(bgp->import_rt_hash);
    6661           1 :         bgp->import_rt_hash = NULL;
    6662             : 
    6663           1 :         hash_clean(bgp->vrf_import_rt_hash,
    6664             :                    (void (*)(void *))hash_vrf_import_rt_free);
    6665           1 :         hash_free(bgp->vrf_import_rt_hash);
    6666           1 :         bgp->vrf_import_rt_hash = NULL;
    6667             : 
    6668           1 :         hash_clean(bgp->vni_svi_hash, (void (*)(void *))hash_evpn_free);
    6669           1 :         hash_free(bgp->vni_svi_hash);
    6670           1 :         bgp->vni_svi_hash = NULL;
    6671           1 :         hash_free(bgp->vnihash);
    6672           1 :         bgp->vnihash = NULL;
    6673             : 
    6674           1 :         list_delete(&bgp->vrf_import_rtl);
    6675           1 :         list_delete(&bgp->vrf_export_rtl);
    6676           1 :         list_delete(&bgp->l2vnis);
    6677           1 : }
    6678             : 
    6679             : /*
    6680             :  * Initialization for EVPN
    6681             :  * Create
    6682             :  *  VNI hash table
    6683             :  *  hash for RT to VNI
    6684             :  */
    6685           2 : void bgp_evpn_init(struct bgp *bgp)
    6686             : {
    6687           4 :         bgp->vnihash =
    6688           2 :                 hash_create(vni_hash_key_make, vni_hash_cmp, "BGP VNI Hash");
    6689           4 :         bgp->vni_svi_hash =
    6690           2 :                 hash_create(vni_svi_hash_key_make, vni_svi_hash_cmp,
    6691             :                             "BGP VNI hash based on SVI ifindex");
    6692           4 :         bgp->import_rt_hash =
    6693           2 :                 hash_create(import_rt_hash_key_make, import_rt_hash_cmp,
    6694             :                             "BGP Import RT Hash");
    6695           4 :         bgp->vrf_import_rt_hash =
    6696           2 :                 hash_create(vrf_import_rt_hash_key_make, vrf_import_rt_hash_cmp,
    6697             :                             "BGP VRF Import RT Hash");
    6698           2 :         bgp->vrf_import_rtl = list_new();
    6699           2 :         bgp->vrf_import_rtl->cmp =
    6700             :                 (int (*)(void *, void *))evpn_vrf_route_target_cmp;
    6701           2 :         bgp->vrf_import_rtl->del = evpn_vrf_rt_del;
    6702           2 :         bgp->vrf_export_rtl = list_new();
    6703           2 :         bgp->vrf_export_rtl->cmp =
    6704             :                 (int (*)(void *, void *))evpn_vrf_route_target_cmp;
    6705           2 :         bgp->vrf_export_rtl->del = evpn_vrf_rt_del;
    6706           2 :         bgp->l2vnis = list_new();
    6707           2 :         bgp->l2vnis->cmp = vni_list_cmp;
    6708             :         /* By default Duplicate Address Dection is enabled.
    6709             :          * Max-moves (N) 5, detection time (M) 180
    6710             :          * default action is warning-only
    6711             :          * freeze action permanently freezes address,
    6712             :          * and freeze time (auto-recovery) is disabled.
    6713             :          */
    6714           2 :         if (bgp->evpn_info) {
    6715           2 :                 bgp->evpn_info->dup_addr_detect = true;
    6716           2 :                 bgp->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
    6717           2 :                 bgp->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
    6718           2 :                 bgp->evpn_info->dad_freeze = false;
    6719           2 :                 bgp->evpn_info->dad_freeze_time = 0;
    6720             :                 /* Initialize zebra vxlan */
    6721           2 :                 bgp_zebra_dup_addr_detection(bgp);
    6722             :                 /* Enable PIP feature by default for bgp vrf instance */
    6723           2 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
    6724           0 :                         struct bgp *bgp_default;
    6725             : 
    6726           0 :                         bgp->evpn_info->advertise_pip = true;
    6727           0 :                         bgp_default = bgp_get_default();
    6728           0 :                         if (bgp_default)
    6729           0 :                                 bgp->evpn_info->pip_ip = bgp_default->router_id;
    6730             :                 }
    6731             :         }
    6732             : 
    6733             :         /* Default BUM handling is to do head-end replication. */
    6734           2 :         bgp->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
    6735             : 
    6736           2 :         bgp_evpn_nh_init(bgp);
    6737           2 : }
    6738             : 
    6739           2 : void bgp_evpn_vrf_delete(struct bgp *bgp_vrf)
    6740             : {
    6741           2 :         bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
    6742           2 :         bgp_evpn_nh_finish(bgp_vrf);
    6743           2 : }
    6744             : 
    6745             : /*
    6746             :  * Get the prefixlen of the ip prefix carried within the type5 evpn route.
    6747             :  */
    6748           0 : int bgp_evpn_get_type5_prefixlen(const struct prefix *pfx)
    6749             : {
    6750           0 :         struct prefix_evpn *evp = (struct prefix_evpn *)pfx;
    6751             : 
    6752           0 :         if (!pfx || pfx->family != AF_EVPN)
    6753             :                 return 0;
    6754             : 
    6755           0 :         if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
    6756             :                 return 0;
    6757             : 
    6758           0 :         return evp->prefix.prefix_addr.ip_prefix_length;
    6759             : }
    6760             : 
    6761             : /*
    6762             :  * Should we register nexthop for this EVPN prefix for nexthop tracking?
    6763             :  */
    6764           0 : bool bgp_evpn_is_prefix_nht_supported(const struct prefix *pfx)
    6765             : {
    6766           0 :         struct prefix_evpn *evp = (struct prefix_evpn *)pfx;
    6767             : 
    6768             :         /*
    6769             :          * EVPN routes should be marked as valid only if the nexthop is
    6770             :          * reachable. Only if this happens, the route should be imported
    6771             :          * (into VNI or VRF routing tables) and/or advertised.
    6772             :          * Note: This is currently applied for EVPN type-1, type-2,
    6773             :          * type-3, type-4 and type-5 routes.
    6774             :          * It may be tweaked later on for other routes, or
    6775             :          * even removed completely when all routes are handled.
    6776             :          */
    6777           0 :         if (pfx && pfx->family == AF_EVPN
    6778           0 :             && (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
    6779             :                 || evp->prefix.route_type == BGP_EVPN_AD_ROUTE
    6780           0 :                 || evp->prefix.route_type == BGP_EVPN_ES_ROUTE
    6781           0 :                 || evp->prefix.route_type == BGP_EVPN_IMET_ROUTE
    6782           0 :                 || evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE))
    6783           0 :                 return true;
    6784             : 
    6785             :         return false;
    6786             : }
    6787             : 
    6788           0 : static void *bgp_evpn_remote_ip_hash_alloc(void *p)
    6789             : {
    6790           0 :         const struct evpn_remote_ip *key = (const struct evpn_remote_ip *)p;
    6791           0 :         struct evpn_remote_ip *ip;
    6792             : 
    6793           0 :         ip = XMALLOC(MTYPE_EVPN_REMOTE_IP, sizeof(struct evpn_remote_ip));
    6794           0 :         *ip = *key;
    6795           0 :         ip->macip_path_list = list_new();
    6796             : 
    6797           0 :         return ip;
    6798             : }
    6799             : 
    6800           0 : static unsigned int bgp_evpn_remote_ip_hash_key_make(const void *p)
    6801             : {
    6802           0 :         const struct evpn_remote_ip *ip = p;
    6803           0 :         const struct ipaddr *addr = &ip->addr;
    6804             : 
    6805           0 :         if (IS_IPADDR_V4(addr))
    6806           0 :                 return jhash_1word(addr->ipaddr_v4.s_addr, 0);
    6807             : 
    6808           0 :         return jhash2(addr->ipaddr_v6.s6_addr32,
    6809             :                       array_size(addr->ipaddr_v6.s6_addr32), 0);
    6810             : }
    6811             : 
    6812           0 : static bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2)
    6813             : {
    6814           0 :         const struct evpn_remote_ip *ip1 = p1;
    6815           0 :         const struct evpn_remote_ip *ip2 = p2;
    6816             : 
    6817           0 :         return !ipaddr_cmp(&ip1->addr, &ip2->addr);
    6818             : }
    6819             : 
    6820           0 : static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn)
    6821             : {
    6822           0 :         if (!evpn_resolve_overlay_index())
    6823             :                 return;
    6824             : 
    6825           0 :         vpn->remote_ip_hash = hash_create(bgp_evpn_remote_ip_hash_key_make,
    6826             :                                           bgp_evpn_remote_ip_hash_cmp,
    6827             :                                           "BGP EVPN remote IP hash");
    6828             : }
    6829             : 
    6830           0 : static void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args)
    6831             : {
    6832           0 :         struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data;
    6833           0 :         struct bgpevpn *vpn = (struct bgpevpn *)args;
    6834             : 
    6835           0 :         bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, false);
    6836             : 
    6837           0 :         list_delete(&ip->macip_path_list);
    6838             : 
    6839           0 :         hash_release(vpn->remote_ip_hash, ip);
    6840           0 :         XFREE(MTYPE_EVPN_REMOTE_IP, ip);
    6841           0 : }
    6842             : 
    6843           0 : static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn)
    6844             : {
    6845           0 :         if (!evpn_resolve_overlay_index() || vpn->remote_ip_hash == NULL)
    6846             :                 return;
    6847             : 
    6848           0 :         hash_iterate(vpn->remote_ip_hash,
    6849             :         (void (*)(struct hash_bucket *, void *))bgp_evpn_remote_ip_hash_free,
    6850             :         vpn);
    6851             : 
    6852           0 :         hash_free(vpn->remote_ip_hash);
    6853           0 :         vpn->remote_ip_hash = NULL;
    6854             : }
    6855             : 
    6856             : /* Add a remote MAC/IP route to hash table */
    6857           0 : static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn,
    6858             :                                         struct bgp_path_info *pi)
    6859             : {
    6860           0 :         struct evpn_remote_ip tmp;
    6861           0 :         struct evpn_remote_ip *ip;
    6862           0 :         struct prefix_evpn *evp;
    6863             : 
    6864           0 :         if (!evpn_resolve_overlay_index())
    6865           0 :                 return;
    6866             : 
    6867           0 :         if (pi->type != ZEBRA_ROUTE_BGP || pi->sub_type != BGP_ROUTE_IMPORTED
    6868           0 :             || !CHECK_FLAG(pi->flags, BGP_PATH_VALID))
    6869             :                 return;
    6870             : 
    6871           0 :         evp = (struct prefix_evpn *)&pi->net->p;
    6872             : 
    6873           0 :         if (evp->family != AF_EVPN
    6874           0 :             || evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
    6875           0 :             || is_evpn_prefix_ipaddr_none(evp))
    6876             :                 return;
    6877             : 
    6878           0 :         tmp.addr = evp->prefix.macip_addr.ip;
    6879           0 :         ip = hash_lookup(vpn->remote_ip_hash, &tmp);
    6880           0 :         if (ip) {
    6881           0 :                 if (listnode_lookup(ip->macip_path_list, pi) != NULL)
    6882             :                         return;
    6883           0 :                 (void)listnode_add(ip->macip_path_list, pi);
    6884           0 :                 return;
    6885             :         }
    6886             : 
    6887           0 :         ip = hash_get(vpn->remote_ip_hash, &tmp, bgp_evpn_remote_ip_hash_alloc);
    6888           0 :         (void)listnode_add(ip->macip_path_list, pi);
    6889             : 
    6890           0 :         bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, true);
    6891             : }
    6892             : 
    6893             : /* Delete a remote MAC/IP route from hash table */
    6894           0 : static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn,
    6895             :                                         struct bgp_path_info *pi)
    6896             : {
    6897           0 :         struct evpn_remote_ip tmp;
    6898           0 :         struct evpn_remote_ip *ip;
    6899           0 :         struct prefix_evpn *evp;
    6900             : 
    6901           0 :         if (!evpn_resolve_overlay_index())
    6902           0 :                 return;
    6903             : 
    6904           0 :         evp = (struct prefix_evpn *)&pi->net->p;
    6905             : 
    6906           0 :         if (evp->family != AF_EVPN
    6907           0 :             || evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
    6908           0 :             || is_evpn_prefix_ipaddr_none(evp))
    6909             :                 return;
    6910             : 
    6911           0 :         tmp.addr = evp->prefix.macip_addr.ip;
    6912           0 :         ip = hash_lookup(vpn->remote_ip_hash, &tmp);
    6913           0 :         if (ip == NULL)
    6914             :                 return;
    6915             : 
    6916           0 :         listnode_delete(ip->macip_path_list, pi);
    6917             : 
    6918           0 :         if (ip->macip_path_list->count == 0) {
    6919           0 :                 bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, false);
    6920           0 :                 hash_release(vpn->remote_ip_hash, ip);
    6921           0 :                 list_delete(&ip->macip_path_list);
    6922           0 :                 XFREE(MTYPE_EVPN_REMOTE_IP, ip);
    6923             :         }
    6924             : }
    6925             : 
    6926           0 : static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn,
    6927             :                                             void (*func)(struct hash_bucket *,
    6928             :                                                          void *),
    6929             :                                             void *arg)
    6930             : {
    6931           0 :         if (!evpn_resolve_overlay_index())
    6932             :                 return;
    6933             : 
    6934           0 :         hash_iterate(vpn->remote_ip_hash, func, arg);
    6935             : }
    6936             : 
    6937           0 : static void show_remote_ip_entry(struct hash_bucket *bucket, void *args)
    6938             : {
    6939           0 :         char buf[INET6_ADDRSTRLEN];
    6940           0 :         struct listnode *node = NULL;
    6941           0 :         struct bgp_path_info *pi = NULL;
    6942           0 :         struct vty *vty = (struct vty *)args;
    6943           0 :         struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data;
    6944             : 
    6945           0 :         vty_out(vty, "  Remote IP: %s\n",
    6946           0 :                 ipaddr2str(&ip->addr, buf, sizeof(buf)));
    6947           0 :         vty_out(vty, "      Linked MAC/IP routes:\n");
    6948           0 :         for (ALL_LIST_ELEMENTS_RO(ip->macip_path_list, node, pi))
    6949           0 :                 vty_out(vty, "        %pFX\n", &pi->net->p);
    6950           0 : }
    6951             : 
    6952           0 : void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args)
    6953             : {
    6954           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    6955           0 :         struct vty *vty = (struct vty *)args;
    6956             : 
    6957           0 :         vty_out(vty, "VNI: %u\n", vpn->vni);
    6958           0 :         bgp_evpn_remote_ip_hash_iterate(
    6959             :                 vpn,
    6960             :                 (void (*)(struct hash_bucket *, void *))show_remote_ip_entry,
    6961             :                 vty);
    6962           0 :         vty_out(vty, "\n");
    6963           0 : }
    6964             : 
    6965           0 : static void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket,
    6966             :                                                  void *args)
    6967             : {
    6968           0 :         struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data;
    6969           0 :         struct bgpevpn *vpn = (struct bgpevpn *)args;
    6970             : 
    6971           0 :         bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, true);
    6972           0 : }
    6973             : 
    6974           0 : static void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket,
    6975             :                                                    void *args)
    6976             : {
    6977           0 :         struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data;
    6978           0 :         struct bgpevpn *vpn = (struct bgpevpn *)args;
    6979             : 
    6980           0 :         bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, false);
    6981           0 : }
    6982             : 
    6983           0 : static unsigned int vni_svi_hash_key_make(const void *p)
    6984             : {
    6985           0 :         const struct bgpevpn *vpn = p;
    6986             : 
    6987           0 :         return jhash_1word(vpn->svi_ifindex, 0);
    6988             : }
    6989             : 
    6990           0 : static bool vni_svi_hash_cmp(const void *p1, const void *p2)
    6991             : {
    6992           0 :         const struct bgpevpn *vpn1 = p1;
    6993           0 :         const struct bgpevpn *vpn2 = p2;
    6994             : 
    6995           0 :         return (vpn1->svi_ifindex == vpn2->svi_ifindex);
    6996             : }
    6997             : 
    6998           0 : static struct bgpevpn *bgp_evpn_vni_svi_hash_lookup(struct bgp *bgp,
    6999             :                                                     ifindex_t svi)
    7000             : {
    7001           0 :         struct bgpevpn *vpn;
    7002           0 :         struct bgpevpn tmp;
    7003             : 
    7004           0 :         memset(&tmp, 0, sizeof(tmp));
    7005           0 :         tmp.svi_ifindex = svi;
    7006           0 :         vpn = hash_lookup(bgp->vni_svi_hash, &tmp);
    7007           0 :         return vpn;
    7008             : }
    7009             : 
    7010           0 : static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn)
    7011             : {
    7012           0 :         if (vpn->svi_ifindex == 0)
    7013             :                 return;
    7014             : 
    7015           0 :         (void)hash_get(bgp->vni_svi_hash, vpn, hash_alloc_intern);
    7016             : }
    7017             : 
    7018           0 : static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp,
    7019             :                                               struct bgpevpn *vpn)
    7020             : {
    7021           0 :         if (vpn->svi_ifindex == 0)
    7022             :                 return;
    7023             : 
    7024           0 :         hash_release(bgp->vni_svi_hash, vpn);
    7025             : }
    7026             : 
    7027           0 : void bgp_evpn_show_vni_svi_hash(struct hash_bucket *bucket, void *args)
    7028             : {
    7029           0 :         struct bgpevpn *evpn = (struct bgpevpn *)bucket->data;
    7030           0 :         struct vty *vty = (struct vty *)args;
    7031             : 
    7032           0 :         vty_out(vty, "SVI: %u VNI: %u\n", evpn->svi_ifindex, evpn->vni);
    7033           0 : }
    7034             : 
    7035             : /*
    7036             :  * This function is called for a bgp_nexthop_cache entry when the nexthop is
    7037             :  * gateway IP overlay index.
    7038             :  * This function returns true if there is a remote MAC/IP route for the gateway
    7039             :  * IP in the EVI of the nexthop SVI.
    7040             :  */
    7041           0 : bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc)
    7042             : {
    7043           0 :         struct bgp *bgp_evpn = NULL;
    7044           0 :         struct bgpevpn *vpn = NULL;
    7045           0 :         struct evpn_remote_ip tmp;
    7046           0 :         struct prefix *p;
    7047             : 
    7048           0 :         if (!evpn_resolve_overlay_index())
    7049             :                 return false;
    7050             : 
    7051           0 :         if (!bnc->nexthop || bnc->nexthop->ifindex == 0)
    7052             :                 return false;
    7053             : 
    7054           0 :         bgp_evpn = bgp_get_evpn();
    7055           0 :         if (!bgp_evpn)
    7056             :                 return false;
    7057             : 
    7058             :         /*
    7059             :          * Gateway IP is resolved by nht over SVI interface.
    7060             :          * Use this SVI to find corresponding EVI(L2 context)
    7061             :          */
    7062           0 :         vpn = bgp_evpn_vni_svi_hash_lookup(bgp_evpn, bnc->nexthop->ifindex);
    7063           0 :         if (!vpn)
    7064             :                 return false;
    7065             : 
    7066           0 :         if (vpn->bgp_vrf != bnc->bgp)
    7067             :                 return false;
    7068             : 
    7069             :         /*
    7070             :          * Check if the gateway IP is present in the EVI remote_ip_hash table
    7071             :          * which stores all the remote IP addresses received via MAC/IP routes
    7072             :          * in this EVI
    7073             :          */
    7074           0 :         memset(&tmp, 0, sizeof(tmp));
    7075             : 
    7076           0 :         p = &bnc->prefix;
    7077           0 :         if (p->family == AF_INET) {
    7078           0 :                 tmp.addr.ipa_type = IPADDR_V4;
    7079           0 :                 memcpy(&(tmp.addr.ipaddr_v4), &(p->u.prefix4),
    7080             :                        sizeof(struct in_addr));
    7081           0 :         } else if (p->family == AF_INET6) {
    7082           0 :                 tmp.addr.ipa_type = IPADDR_V6;
    7083           0 :                 memcpy(&(tmp.addr.ipaddr_v6), &(p->u.prefix6),
    7084             :                        sizeof(struct in6_addr));
    7085             :         } else
    7086             :                 return false;
    7087             : 
    7088           0 :         if (hash_lookup(vpn->remote_ip_hash, &tmp) == NULL)
    7089             :                 return false;
    7090             : 
    7091             :         return true;
    7092             : }
    7093             : 
    7094             : /* Resolve/Unresolve nexthops when a MAC/IP route is added/deleted */
    7095           0 : static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn,
    7096             :                                                 struct ipaddr *addr,
    7097             :                                                 bool resolve)
    7098             : {
    7099           0 :         afi_t afi;
    7100           0 :         struct prefix p;
    7101           0 :         struct bgp_nexthop_cache *bnc;
    7102           0 :         struct bgp_nexthop_cache_head *tree = NULL;
    7103             : 
    7104           0 :         if (!vpn->bgp_vrf || vpn->svi_ifindex == 0)
    7105           0 :                 return;
    7106             : 
    7107           0 :         memset(&p, 0, sizeof(p));
    7108             : 
    7109           0 :         if (addr->ipa_type == IPADDR_V4) {
    7110           0 :                 afi = AFI_IP;
    7111           0 :                 p.family = AF_INET;
    7112           0 :                 memcpy(&(p.u.prefix4), &(addr->ipaddr_v4),
    7113             :                        sizeof(struct in_addr));
    7114           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
    7115           0 :         } else if (addr->ipa_type == IPADDR_V6) {
    7116           0 :                 afi = AFI_IP6;
    7117           0 :                 p.family = AF_INET6;
    7118           0 :                 memcpy(&(p.u.prefix6), &(addr->ipaddr_v6),
    7119             :                        sizeof(struct in6_addr));
    7120           0 :                 p.prefixlen = IPV6_MAX_BITLEN;
    7121             :         } else
    7122             :                 return;
    7123             : 
    7124           0 :         tree = &vpn->bgp_vrf->nexthop_cache_table[afi];
    7125           0 :         bnc = bnc_find(tree, &p, 0, 0);
    7126             : 
    7127           0 :         if (!bnc || !bnc->is_evpn_gwip_nexthop)
    7128             :                 return;
    7129             : 
    7130           0 :         if (!bnc->nexthop || bnc->nexthop->ifindex != vpn->svi_ifindex)
    7131             :                 return;
    7132             : 
    7133           0 :         if (BGP_DEBUG(nht, NHT))
    7134           0 :                 zlog_debug("%s(%u): vni %u mac/ip %s for NH %pFX",
    7135             :                            vpn->bgp_vrf->name_pretty, vpn->tenant_vrf_id,
    7136             :                            vpn->vni, (resolve ? "add" : "delete"),
    7137             :                            &bnc->prefix);
    7138             : 
    7139             :         /*
    7140             :          * MAC/IP route or SVI or tenant vrf being added to EVI.
    7141             :          * Set nexthop as valid only if it is already L3 reachable
    7142             :          */
    7143           0 :         if (resolve && bnc->flags & BGP_NEXTHOP_EVPN_INCOMPLETE) {
    7144           0 :                 bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
    7145           0 :                 bnc->flags |= BGP_NEXTHOP_VALID;
    7146           0 :                 bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
    7147           0 :                 evaluate_paths(bnc);
    7148             :         }
    7149             : 
    7150             :          /* MAC/IP route or SVI or tenant vrf being deleted from EVI */
    7151           0 :         if (!resolve &&  bnc->flags & BGP_NEXTHOP_VALID) {
    7152           0 :                 bnc->flags &= ~BGP_NEXTHOP_VALID;
    7153           0 :                 bnc->flags |= BGP_NEXTHOP_EVPN_INCOMPLETE;
    7154           0 :                 bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
    7155           0 :                 evaluate_paths(bnc);
    7156             :         }
    7157             : }
    7158             : 
    7159           0 : void bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket,
    7160             :                                                void *arg)
    7161             : {
    7162           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    7163           0 :         struct bgp_dest *dest;
    7164           0 :         struct bgp_path_info *pi;
    7165             : 
    7166           0 :         bgp_evpn_remote_ip_hash_init(vpn);
    7167             : 
    7168           0 :         for (dest = bgp_table_top(vpn->ip_table); dest;
    7169           0 :              dest = bgp_route_next(dest))
    7170           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
    7171           0 :                         bgp_evpn_remote_ip_hash_add(vpn, pi);
    7172           0 : }
    7173             : 
    7174           0 : void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
    7175             :                                                  void *arg)
    7176             : {
    7177           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    7178             : 
    7179           0 :         bgp_evpn_remote_ip_hash_destroy(vpn);
    7180           0 : }

Generated by: LCOV version v1.16-topotato