back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_evpn_mh.h (source / functions) Hit Total Coverage
Test: test_pim_cbsr.py::PIMCandidateBSRTest Lines: 1 14 7.1 %
Date: 2023-02-16 02:09:14 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Zebra EVPN MH Data structures and definitions
       3             :  *
       4             :  * Copyright (C) 2019 Cumulus Networks, Inc.
       5             :  * Anuradha Karuppiah
       6             :  *
       7             :  * This file is part of FRR.
       8             :  *
       9             :  * FRR is free software; you can redistribute it and/or modify it
      10             :  * under the terms of the GNU General Public License as published by the
      11             :  * Free Software Foundation; either version 2, or (at your option) any
      12             :  * later version.
      13             :  *
      14             :  * FRR is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * General Public License for more details.
      18             :  */
      19             : 
      20             : #ifndef _ZEBRA_EVPN_MH_H
      21             : #define _ZEBRA_EVPN_MH_H
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #include "if.h"
      26             : #include "linklist.h"
      27             : #include "bitfield.h"
      28             : #include "zebra_vxlan.h"
      29             : #include "zebra_vxlan_private.h"
      30             : #include "zebra_nhg.h"
      31             : 
      32             : #define EVPN_MH_VTY_STR "Multihoming\n"
      33             : 
      34             : /* Ethernet Segment entry -
      35             :  * - Local and remote ESs are maintained in a global RB tree,
      36             :  * zmh_info->es_rb_tree using ESI as key
      37             :  * - Local ESs are added via zebra config (ZEBRA_EVPNES_LOCAL) when an
      38             :  *   access port is associated with an ES-ID
      39             :  * - Remotes ESs are added by BGP based on received/remote EAD/Type-1 routes
      40             :  *   (ZEBRA_EVPNES_REMOTE)
      41             :  * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are
      42             :  *   expected to have REMOTE ES peers.
      43             :  */
      44             : struct zebra_evpn_es {
      45             :         esi_t esi;
      46             :         char esi_str[ESI_STR_LEN];
      47             : 
      48             :         /* ES flags */
      49             :         uint32_t flags;
      50             : #define ZEBRA_EVPNES_LOCAL         (1 << 0) /* configured in zebra */
      51             : #define ZEBRA_EVPNES_REMOTE        (1 << 1) /* added by bgp */
      52             : #define ZEBRA_EVPNES_OPER_UP       (1 << 2) /* es->ifp is oper-up */
      53             : #define ZEBRA_EVPNES_READY_FOR_BGP (1 << 3) /* ready to be sent to BGP */
      54             : #define ZEBRA_EVPNES_NHG_ACTIVE    (1 << 4) /* NHG has been installed */
      55             : /* This flag is only applicable to local ESs and signifies that this
      56             :  * VTEP is not the DF
      57             :  */
      58             : #define ZEBRA_EVPNES_NON_DF (1 << 5)
      59             : /* When the ES becomes a bridge port we need to activate the BUM non-DF
      60             :  * filter, SPH filter and backup NHG for fast-failover
      61             :  */
      62             : #define ZEBRA_EVPNES_BR_PORT (1 << 6)
      63             : /* ES is in bypass mode i.e. must not be advertised. ES-bypass is set
      64             :  * when the associated host bond goes into LACP bypass
      65             :  */
      66             : #define ZEBRA_EVPNES_BYPASS (1 << 7)
      67             : 
      68             :         /* memory used for adding the es to zmh_info->es_rb_tree */
      69             :         RB_ENTRY(zebra_evpn_es) rb_node;
      70             : 
      71             :         /* [EVPNES_LOCAL] memory used for linking the es to
      72             :          * zmh_info->local_es_list
      73             :          */
      74             :         struct listnode local_es_listnode;
      75             : 
      76             :         /* [EVPNES_LOCAL] corresponding interface */
      77             :         struct zebra_if *zif;
      78             : 
      79             :         /* list of ES-EVIs associated with the ES */
      80             :         struct list *es_evi_list;
      81             : 
      82             :         /* [!EVPNES_LOCAL] List of remote VTEPs (zebra_evpn_es_vtep) */
      83             :         struct list *es_vtep_list;
      84             : 
      85             :         /* list of zebra_mac entries using this ES as destination */
      86             :         struct list *mac_list;
      87             : 
      88             :         /* Nexthop group id */
      89             :         uint32_t nhg_id;
      90             : 
      91             :         /* Preference config for BUM-DF election. Sent to BGP and
      92             :          * advertised via the ESR
      93             :          */
      94             :         uint16_t df_pref;
      95             : 
      96             :         /* When a new ES is configured it is held in a non-DF state
      97             :          * for 3 seconds. This allows the peer Type-4 routes to be
      98             :          * imported before running the DF election.
      99             :          */
     100             : #define ZEBRA_EVPN_MH_DF_DELAY_TIME 3 /* seconds */
     101             :         struct thread *df_delay_timer;
     102             : };
     103             : RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
     104           6 : RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
     105             : 
     106             : /* ES per-EVI info
     107             :  * - ES-EVIs are maintained per-EVPN (vni->es_evi_rb_tree)
     108             :  * - Local ES-EVIs are linked to per-EVPN list for quick access
     109             :  * - Although some infrastucture is present for remote ES-EVIs, currently
     110             :  *   BGP does NOT send remote ES-EVIs to zebra. This may change in the
     111             :  *   future (but must be changed thoughtfully and only if needed as ES-EVI
     112             :  *   can get prolific and come in the way of rapid failovers)
     113             :  */
     114             : struct zebra_evpn_es_evi {
     115             :         struct zebra_evpn_es *es;
     116             :         struct zebra_evpn *zevpn;
     117             : 
     118             :         /* ES-EVI flags */
     119             :         uint32_t flags;
     120             :         /* local ES-EVI */
     121             : #define ZEBRA_EVPNES_EVI_LOCAL         (1 << 0) /* created by zebra */
     122             : #define ZEBRA_EVPNES_EVI_READY_FOR_BGP (1 << 1) /* ready to be sent to BGP */
     123             : 
     124             :         /* memory used for adding the es_evi to
     125             :          * es_evi->zevpn->es_evi_rb_tree
     126             :          */
     127             :         RB_ENTRY(zebra_evpn_es_evi) rb_node;
     128             :         /* memory used for linking the es_evi to
     129             :          * es_evi->zevpn->local_es_evi_list
     130             :          */
     131             :         struct listnode l2vni_listnode;
     132             :         /* memory used for linking the es_evi to
     133             :          * es_evi->es->es_evi_list
     134             :          */
     135             :         struct listnode es_listnode;
     136             : };
     137             : 
     138             : /* A single L2 nexthop is allocated across all ESs with the same PE/VTEP
     139             :  * nexthop
     140             :  */
     141             : struct zebra_evpn_l2_nh {
     142             :         struct in_addr vtep_ip;
     143             : 
     144             :         /* MAC nexthop id */
     145             :         uint32_t nh_id;
     146             : 
     147             :         /* es_vtep entries using this nexthop */
     148             :         uint32_t ref_cnt;
     149             : };
     150             : 
     151             : /* PE attached to an ES */
     152             : struct zebra_evpn_es_vtep {
     153             :         struct zebra_evpn_es *es; /* parent ES */
     154             :         struct in_addr vtep_ip;
     155             : 
     156             :         uint32_t flags;
     157             :         /* Rxed Type-4 route from this VTEP */
     158             : #define ZEBRA_EVPNES_VTEP_RXED_ESR (1 << 0)
     159             : #define ZEBRA_EVPNES_VTEP_DEL_IN_PROG (1 << 1)
     160             : 
     161             :         /* MAC nexthop info */
     162             :         struct zebra_evpn_l2_nh *nh;
     163             : 
     164             :         /* memory used for adding the entry to es->es_vtep_list */
     165             :         struct listnode es_listnode;
     166             : 
     167             :         /* Parameters for DF election */
     168             :         uint8_t df_alg;
     169             :         uint32_t df_pref;
     170             : 
     171             :         /* XXX - maintain a backpointer to struct zebra_vtep */
     172             : };
     173             : 
     174             : /* Local/access-side broadcast domain - zebra_evpn_access_bd is added to -
     175             :  * zrouter->evpn_vlan_table (for VLAN aware bridges) OR
     176             :  * zrouter->evpn_bridge_table (for VLAN unaware bridges)
     177             :  * XXX - support for VLAN unaware bridges is yet to be flushed out
     178             :  */
     179             : struct zebra_evpn_access_bd {
     180             :         vlanid_t vid;
     181             : 
     182             :         struct zebra_if *vxlan_zif; /* vxlan device */
     183             :         /* list of members associated with the BD i.e. (potential) ESs */
     184             :         struct list *mbr_zifs;
     185             :         /* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
     186             :         struct zebra_evpn *zevpn;
     187             :         /* SVI associated with the VLAN */
     188             :         struct zebra_if *vlan_zif;
     189             : };
     190             : 
     191             : /* multihoming information stored in zrouter */
     192             : #define zmh_info (zrouter.mh_info)
     193             : struct zebra_evpn_mh_info {
     194             :         uint32_t flags;
     195             : /* If the dataplane is not capable of handling a backup NHG on an access
     196             :  * port we will need to explicitly failover each MAC entry on
     197             :  * local ES down
     198             :  */
     199             : #define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
     200             : /* DAD support for EVPN-MH is yet to be added. So on detection of
     201             :  * first local ES, DAD is turned off
     202             :  */
     203             : #define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
     204             : /* If EVPN MH is enabled we only advertise REACHABLE neigh entries as Type-2
     205             :  * routes. As there is no global config knob for enabling EVPN MH we turn
     206             :  * this flag when the first local ES is detected.
     207             :  */
     208             : #define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
     209             : /* If EVPN MH is enabled we advertise the SVI MAC address to avoid
     210             :  * flooding of ARP replies rxed from the multi-homed host
     211             :  */
     212             : #define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
     213             : 
     214             :         /* RB tree of Ethernet segments (used for EVPN-MH)  */
     215             :         struct zebra_es_rb_head es_rb_tree;
     216             :         /* List of local ESs */
     217             :         struct list *local_es_list;
     218             : 
     219             :         /* EVPN MH broadcast domains indexed by the VID */
     220             :         struct hash *evpn_vlan_table;
     221             : 
     222             :         /* A base L2-VNI is maintained to derive parameters such as
     223             :          * ES originator-IP.
     224             :          * XXX: once single vxlan device model becomes available this will
     225             :          * not be necessary
     226             :          */
     227             :         struct zebra_evpn *es_base_evpn;
     228             :         struct in_addr es_originator_ip;
     229             : 
     230             :         /* L2 NH and NHG ids -
     231             :          * Most significant 4 bits is type. Lower 28 bits is the value
     232             :          * allocated from the nh_id_bitmap.
     233             :          */
     234             :         bitfield_t nh_id_bitmap;
     235             : #define EVPN_NH_ID_MAX       (16*1024)
     236             : #define EVPN_NH_ID_VAL_MASK  0xffffff
     237             : /* The purpose of using different types for NHG and NH is NOT to manage the
     238             :  * id space separately. It is simply to make debugging easier.
     239             :  */
     240             : #define EVPN_NH_ID_TYPE_BIT (NHG_TYPE_L2_NH << NHG_ID_TYPE_POS)
     241             : #define EVPN_NHG_ID_TYPE_BIT (NHG_TYPE_L2 << NHG_ID_TYPE_POS)
     242             :         /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
     243             :         struct hash *nhg_table;
     244             :         /* L2-NH table - key: vtep_up, data: zebra_evpn_nh */
     245             :         struct hash *nh_ip_table;
     246             : 
     247             :         /* XXX - re-visit the default hold timer value */
     248             :         int mac_hold_time;
     249             : #define ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF (18 * 60)
     250             :         int neigh_hold_time;
     251             : #define ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF (18 * 60)
     252             : 
     253             :         /* During this period access ports will be held in a protodown
     254             :          * state
     255             :          */
     256             :         int startup_delay_time; /* seconds */
     257             : #define ZEBRA_EVPN_MH_STARTUP_DELAY_DEF (3 * 60)
     258             :         struct thread *startup_delay_timer;
     259             : 
     260             :         /* Number of configured uplinks */
     261             :         uint32_t uplink_cfg_cnt;
     262             :         /* Number of operationally-up uplinks */
     263             :         uint32_t uplink_oper_up_cnt;
     264             : 
     265             :         /* These protodown bits are inherited by all ES bonds */
     266             :         uint32_t protodown_rc;
     267             : };
     268             : 
     269             : /* returns TRUE if the EVPN is ready to be sent to BGP */
     270           0 : static inline bool zebra_evpn_send_to_client_ok(struct zebra_evpn *zevpn)
     271             : {
     272           0 :         return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
     273             : }
     274             : 
     275             : static inline bool zebra_evpn_mac_is_es_local(struct zebra_mac *mac)
     276             : {
     277             :         return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
     278             : }
     279             : 
     280             : /* Returns true if the id is of L2-NHG or L2-NH type */
     281           0 : static inline bool zebra_evpn_mh_is_fdb_nh(uint32_t id)
     282             : {
     283           0 :         return ((id & EVPN_NHG_ID_TYPE_BIT) ||
     284             :                         (id & EVPN_NH_ID_TYPE_BIT));
     285             : }
     286             : 
     287             : static inline bool
     288           0 : zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es *es)
     289             : {
     290           0 :         return !(es->flags & ZEBRA_EVPNES_OPER_UP)
     291           0 :                && (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF);
     292             : }
     293             : 
     294           0 : static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
     295             : {
     296           0 :         return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
     297             : }
     298             : 
     299           0 : static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
     300             : {
     301           0 :         return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
     302             : }
     303             : 
     304           0 : static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
     305             : {
     306           0 :         return zmh_info && (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC);
     307             : }
     308             : 
     309             : /*****************************************************************************/
     310             : extern esi_t *zero_esi;
     311             : extern void zebra_evpn_mh_init(void);
     312             : extern void zebra_evpn_mh_terminate(void);
     313             : extern bool zebra_evpn_is_if_es_capable(struct zebra_if *zif);
     314             : extern void zebra_evpn_if_init(struct zebra_if *zif);
     315             : extern void zebra_evpn_if_cleanup(struct zebra_if *zif);
     316             : extern void zebra_evpn_es_evi_init(struct zebra_evpn *zevpn);
     317             : extern void zebra_evpn_es_evi_cleanup(struct zebra_evpn *zevpn);
     318             : extern void zebra_evpn_vxl_evpn_set(struct zebra_if *zif,
     319             :                                     struct zebra_evpn *zevpn, bool set);
     320             : extern void zebra_evpn_es_set_base_evpn(struct zebra_evpn *zevpn);
     321             : extern void zebra_evpn_es_clear_base_evpn(struct zebra_evpn *zevpn);
     322             : extern void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif);
     323             : extern void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif);
     324             : extern void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif);
     325             : extern void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif);
     326             : extern void zebra_evpn_es_send_all_to_client(bool add);
     327             : extern void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up);
     328             : extern void zebra_evpn_es_show(struct vty *vty, bool uj);
     329             : extern void zebra_evpn_es_show_detail(struct vty *vty, bool uj);
     330             : extern void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi);
     331             : extern void zebra_evpn_update_all_es(struct zebra_evpn *zevpn);
     332             : extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS);
     333             : int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
     334             :                              bool esr_rxed, uint8_t df_alg, uint16_t df_pref);
     335             : int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip);
     336             : extern void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail);
     337             : extern void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj,
     338             :                 vni_t vni, int detail);
     339             : extern void zebra_evpn_es_mac_deref_entry(struct zebra_mac *mac);
     340             : extern bool zebra_evpn_es_mac_ref_entry(struct zebra_mac *mac,
     341             :                                         struct zebra_evpn_es *es);
     342             : extern bool zebra_evpn_es_mac_ref(struct zebra_mac *mac, const esi_t *esi);
     343             : extern struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi);
     344             : extern void zebra_evpn_interface_init(void);
     345             : extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
     346             : extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
     347             : extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj);
     348             : extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid);
     349             : extern void zebra_evpn_if_es_print(struct vty *vty, json_object *json,
     350             :                                    struct zebra_if *zif);
     351             : extern void zebra_evpn_es_cleanup(void);
     352             : extern int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
     353             :                 uint32_t duration, bool set_default);
     354             : void zebra_evpn_mh_config_write(struct vty *vty);
     355             : int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
     356             :                 uint32_t duration, bool set_default);
     357             : void zebra_evpn_es_local_br_port_update(struct zebra_if *zif);
     358             : extern int zebra_evpn_mh_startup_delay_update(struct vty *vty,
     359             :                                               uint32_t duration,
     360             :                                               bool set_default);
     361             : extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif);
     362             : extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif,
     363             :                                                     bool clear,
     364             :                                                     const char *caller);
     365             : extern bool zebra_evpn_is_es_bond(struct interface *ifp);
     366             : extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
     367             : extern void zebra_evpn_mh_print(struct vty *vty);
     368             : extern void zebra_evpn_mh_json(json_object *json);
     369             : extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
     370             :                                        struct zebra_evpn_es **local_es);
     371             : extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
     372             : extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
     373             : extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
     374             :                                       struct zebra_if *br_zif, bool is_up);
     375             : extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
     376             : extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
     377             :                                         struct interface *ifp, bool bypass);
     378             : extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
     379             : extern struct zebra_evpn_es_evi *
     380             : zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
     381             : 
     382             : #endif /* _ZEBRA_EVPN_MH_H */

Generated by: LCOV version v1.16-topotato