2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-05-15 07:37:42 +02:00
|
|
|
/*
|
|
|
|
* Zebra VxLAN (EVPN) Data structures and definitions
|
|
|
|
* These are "internal" to this function.
|
|
|
|
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _ZEBRA_VXLAN_PRIVATE_H
|
|
|
|
#define _ZEBRA_VXLAN_PRIVATE_H
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "if.h"
|
|
|
|
#include "linklist.h"
|
2017-11-14 08:12:15 +01:00
|
|
|
#include "zebra_vxlan.h"
|
2021-07-27 10:10:48 +02:00
|
|
|
#include "zebra_vxlan_if.h"
|
2020-07-23 23:58:45 +02:00
|
|
|
#include "zebra_evpn.h"
|
|
|
|
#include "zebra_evpn_mac.h"
|
2017-05-15 07:37:42 +02:00
|
|
|
|
2019-03-25 15:11:55 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
#define ERR_STR_SZ 256
|
|
|
|
|
|
|
|
/* L3 VNI hash table */
|
2021-08-20 14:58:24 +02:00
|
|
|
struct zebra_l3vni {
|
2017-10-08 03:49:27 +02:00
|
|
|
|
|
|
|
/* VNI key */
|
|
|
|
vni_t vni;
|
|
|
|
|
|
|
|
/* vrf_id */
|
|
|
|
vrf_id_t vrf_id;
|
|
|
|
|
2018-02-06 23:28:22 +01:00
|
|
|
uint32_t filter;
|
|
|
|
#define PREFIX_ROUTES_ONLY (1 << 0) /* l3-vni used for prefix routes only */
|
|
|
|
|
2021-07-27 11:24:40 +02:00
|
|
|
/* Corresponding Bridge information */
|
|
|
|
vlanid_t vid;
|
|
|
|
struct interface *bridge_if;
|
|
|
|
|
2017-10-31 00:58:15 +01:00
|
|
|
/* Local IP */
|
|
|
|
struct in_addr local_vtep_ip;
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
/* kernel interface for l3vni */
|
|
|
|
struct interface *vxlan_if;
|
|
|
|
|
|
|
|
/* SVI interface corresponding to the l3vni */
|
|
|
|
struct interface *svi_if;
|
|
|
|
|
2019-08-02 08:33:24 +02:00
|
|
|
struct interface *mac_vlan_if;
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
/* list of L2 VNIs associated with the L3 VNI */
|
|
|
|
struct list *l2vnis;
|
|
|
|
|
|
|
|
/* list of remote router-macs */
|
|
|
|
struct hash *rmac_table;
|
|
|
|
|
|
|
|
/* list of remote vtep-ip neigh */
|
|
|
|
struct hash *nh_table;
|
|
|
|
};
|
|
|
|
|
2021-04-01 18:00:04 +02:00
|
|
|
#define IS_ZL3VNI_SVD_BACKED(zl3vni) \
|
|
|
|
(zl3vni->vxlan_if && zl3vni->vxlan_if->info && \
|
|
|
|
IS_ZEBRA_VXLAN_IF_SVD((struct zebra_if *)zl3vni->vxlan_if->info))
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
/* get the vx-intf name for l3vni */
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_vxlan_if_name(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
return zl3vni->vxlan_if ? zl3vni->vxlan_if->name : "None";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the svi intf name for l3vni */
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_svi_if_name(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
return zl3vni->svi_if ? zl3vni->svi_if->name : "None";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the vrf name for l3vni */
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_vrf_name(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
return vrf_id_to_name(zl3vni->vrf_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the rmac string */
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_rmac2str(struct zebra_l3vni *zl3vni, char *buf,
|
2017-10-08 03:49:27 +02:00
|
|
|
int size)
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
if (!buf)
|
2020-01-07 19:54:04 +01:00
|
|
|
ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
|
2017-10-08 03:49:27 +02:00
|
|
|
else {
|
|
|
|
assert(size >= ETHER_ADDR_STRLEN);
|
|
|
|
ptr = buf;
|
|
|
|
}
|
|
|
|
|
zebra: print rmac and sys mac values
"show vrf vni" and "show evpn vni <l3vni>" commands
need to display correct router mac value.
"show evpn vni <l3vni>" detail l3vni needs to display
system mac as in PIP scenario value can be different.
Syste MAC would be derived from SVI interface MAC wherelse
Router MAC would be derived from macvlan interface MAC value.
Ticket:CM-26710
Reviewed By:CCR-9334
Testing Done:
TORC11# show evpn vni 4001
VNI: 4001
Type: L3
Tenant VRF: vrf1
Local Vtep Ip: 36.0.0.11
Vxlan-Intf: vx-4001
SVI-If: vlan4001
State: Up
VNI Filter: none
System MAC: 00:02:00:00:00:2e
Router MAC: 44:38:39:ff:ff:01
L2 VNIs: 1000
TORC11# show vrf vni
VRF VNI VxLAN IF L3-SVI State Rmac
vrf1 4001 vx-4001 vlan4001 Up 44:38:39:ff:ff:01
TORC11# show evpn vni 4001 json
{
"vni":4001,
"type":"L3",
"localVtepIp":"36.0.0.11",
"vxlanIntf":"vx-4001",
"sviIntf":"vlan4001",
"state":"Up",
"vrf":"vrf1",
"sysMac":"00:02:00:00:00:2e",
"routerMac":"44:38:39:ff:ff:01",
"vniFilter":"none",
"l2Vnis":[
1000,
]
}
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2019-10-15 02:46:10 +02:00
|
|
|
if (zl3vni->mac_vlan_if)
|
|
|
|
snprintf(ptr, (ETHER_ADDR_STRLEN),
|
|
|
|
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[0],
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[1],
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[2],
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[3],
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[4],
|
|
|
|
(uint8_t)zl3vni->mac_vlan_if->hw_addr[5]);
|
|
|
|
else if (zl3vni->svi_if)
|
|
|
|
snprintf(ptr, (ETHER_ADDR_STRLEN),
|
|
|
|
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[0],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[1],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[2],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[3],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[4],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[5]);
|
|
|
|
else
|
|
|
|
snprintf(ptr, ETHER_ADDR_STRLEN, "None");
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the sys mac string */
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_sysmac2str(struct zebra_l3vni *zl3vni,
|
|
|
|
char *buf, int size)
|
zebra: print rmac and sys mac values
"show vrf vni" and "show evpn vni <l3vni>" commands
need to display correct router mac value.
"show evpn vni <l3vni>" detail l3vni needs to display
system mac as in PIP scenario value can be different.
Syste MAC would be derived from SVI interface MAC wherelse
Router MAC would be derived from macvlan interface MAC value.
Ticket:CM-26710
Reviewed By:CCR-9334
Testing Done:
TORC11# show evpn vni 4001
VNI: 4001
Type: L3
Tenant VRF: vrf1
Local Vtep Ip: 36.0.0.11
Vxlan-Intf: vx-4001
SVI-If: vlan4001
State: Up
VNI Filter: none
System MAC: 00:02:00:00:00:2e
Router MAC: 44:38:39:ff:ff:01
L2 VNIs: 1000
TORC11# show vrf vni
VRF VNI VxLAN IF L3-SVI State Rmac
vrf1 4001 vx-4001 vlan4001 Up 44:38:39:ff:ff:01
TORC11# show evpn vni 4001 json
{
"vni":4001,
"type":"L3",
"localVtepIp":"36.0.0.11",
"vxlanIntf":"vx-4001",
"sviIntf":"vlan4001",
"state":"Up",
"vrf":"vrf1",
"sysMac":"00:02:00:00:00:2e",
"routerMac":"44:38:39:ff:ff:01",
"vniFilter":"none",
"l2Vnis":[
1000,
]
}
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2019-10-15 02:46:10 +02:00
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
if (!buf)
|
2020-01-07 19:54:04 +01:00
|
|
|
ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
|
zebra: print rmac and sys mac values
"show vrf vni" and "show evpn vni <l3vni>" commands
need to display correct router mac value.
"show evpn vni <l3vni>" detail l3vni needs to display
system mac as in PIP scenario value can be different.
Syste MAC would be derived from SVI interface MAC wherelse
Router MAC would be derived from macvlan interface MAC value.
Ticket:CM-26710
Reviewed By:CCR-9334
Testing Done:
TORC11# show evpn vni 4001
VNI: 4001
Type: L3
Tenant VRF: vrf1
Local Vtep Ip: 36.0.0.11
Vxlan-Intf: vx-4001
SVI-If: vlan4001
State: Up
VNI Filter: none
System MAC: 00:02:00:00:00:2e
Router MAC: 44:38:39:ff:ff:01
L2 VNIs: 1000
TORC11# show vrf vni
VRF VNI VxLAN IF L3-SVI State Rmac
vrf1 4001 vx-4001 vlan4001 Up 44:38:39:ff:ff:01
TORC11# show evpn vni 4001 json
{
"vni":4001,
"type":"L3",
"localVtepIp":"36.0.0.11",
"vxlanIntf":"vx-4001",
"sviIntf":"vlan4001",
"state":"Up",
"vrf":"vrf1",
"sysMac":"00:02:00:00:00:2e",
"routerMac":"44:38:39:ff:ff:01",
"vniFilter":"none",
"l2Vnis":[
1000,
]
}
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2019-10-15 02:46:10 +02:00
|
|
|
else {
|
|
|
|
assert(size >= ETHER_ADDR_STRLEN);
|
|
|
|
ptr = buf;
|
|
|
|
}
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
if (zl3vni->svi_if)
|
|
|
|
snprintf(ptr, (ETHER_ADDR_STRLEN),
|
|
|
|
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[0],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[1],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[2],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[3],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[4],
|
|
|
|
(uint8_t)zl3vni->svi_if->hw_addr[5]);
|
|
|
|
else
|
|
|
|
snprintf(ptr, ETHER_ADDR_STRLEN, "None");
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* l3-vni is oper up when:
|
2017-11-14 08:12:15 +01:00
|
|
|
* 0. if EVPN is enabled (advertise-all-vni cfged)
|
2017-10-08 03:49:27 +02:00
|
|
|
* 1. it is associated to a vxlan-intf
|
|
|
|
* 2. Associated vxlan-intf is oper up
|
|
|
|
* 3. it is associated to an SVI
|
|
|
|
* 4. associated SVI is oper up
|
|
|
|
*/
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline int is_l3vni_oper_up(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
2017-11-14 08:12:15 +01:00
|
|
|
return (is_evpn_enabled() && zl3vni && (zl3vni->vrf_id != VRF_UNKNOWN)
|
2017-10-08 03:49:27 +02:00
|
|
|
&& zl3vni->vxlan_if && if_is_operative(zl3vni->vxlan_if)
|
|
|
|
&& zl3vni->svi_if && if_is_operative(zl3vni->svi_if));
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline const char *zl3vni_state2str(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
if (!zl3vni)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (is_l3vni_oper_up(zl3vni))
|
|
|
|
return "Up";
|
|
|
|
else
|
|
|
|
return "Down";
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline vrf_id_t zl3vni_vrf_id(struct zebra_l3vni *zl3vni)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
return zl3vni->vrf_id;
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:58:24 +02:00
|
|
|
static inline void zl3vni_get_svi_rmac(struct zebra_l3vni *zl3vni,
|
2019-08-02 08:33:24 +02:00
|
|
|
struct ethaddr *rmac)
|
2017-10-08 03:49:27 +02:00
|
|
|
{
|
|
|
|
if (!zl3vni)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!is_l3vni_oper_up(zl3vni))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (zl3vni->svi_if && if_is_operative(zl3vni->svi_if))
|
|
|
|
memcpy(rmac->octet, zl3vni->svi_if->hw_addr, ETH_ALEN);
|
|
|
|
}
|
|
|
|
|
2017-05-15 07:37:42 +02:00
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
/* context for neigh hash walk - update l3vni and rmac */
|
|
|
|
struct neigh_l3info_walk_ctx {
|
|
|
|
|
2021-08-19 22:08:53 +02:00
|
|
|
struct zebra_evpn *zevpn;
|
2021-08-20 14:58:24 +02:00
|
|
|
struct zebra_l3vni *zl3vni;
|
2017-10-08 03:49:27 +02:00
|
|
|
int add;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct nh_walk_ctx {
|
|
|
|
|
|
|
|
struct vty *vty;
|
|
|
|
struct json_object *json;
|
|
|
|
};
|
|
|
|
|
2021-08-20 14:58:24 +02:00
|
|
|
extern struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id);
|
|
|
|
extern struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni);
|
|
|
|
extern struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni);
|
|
|
|
extern struct interface *zl3vni_map_to_mac_vlan_if(struct zebra_l3vni *zl3vni);
|
|
|
|
extern struct zebra_l3vni *zl3vni_lookup(vni_t vni);
|
2021-01-11 20:08:43 +01:00
|
|
|
extern vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if);
|
Zebra: Handle RMAC add/delete operation and add fpm_mac_info_t
- Define a hook "zebra_mac_update" which can be registered by multiple
data plane components (e.g. FPM, dplane).
DEFINE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, bool
delete, const char *reason), (rmac, zl3vni, delete, reason))
- While performing RMAC add/delete for an L3VNI, call "zebra_mac_update" hook.
- This hook call triggers "zfpm_trigger_rmac_update". In this function, we do a
lookup for the RMAC in fpm_mac_info_table. If already present, this node is
updated with the latest RMAC info. Else, a new fpm_mac_info_t node is created
and inserted in the queue and hash data structures.
Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
2019-05-16 23:43:41 +02:00
|
|
|
|
2021-08-19 22:33:53 +02:00
|
|
|
DECLARE_HOOK(zebra_rmac_update,
|
2021-08-20 14:58:24 +02:00
|
|
|
(struct zebra_mac * rmac, struct zebra_l3vni *zl3vni, bool delete,
|
2021-08-19 22:33:53 +02:00
|
|
|
const char *reason),
|
|
|
|
(rmac, zl3vni, delete, reason));
|
Zebra: Handle RMAC add/delete operation and add fpm_mac_info_t
- Define a hook "zebra_mac_update" which can be registered by multiple
data plane components (e.g. FPM, dplane).
DEFINE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, bool
delete, const char *reason), (rmac, zl3vni, delete, reason))
- While performing RMAC add/delete for an L3VNI, call "zebra_mac_update" hook.
- This hook call triggers "zfpm_trigger_rmac_update". In this function, we do a
lookup for the RMAC in fpm_mac_info_table. If already present, this node is
updated with the latest RMAC info. Else, a new fpm_mac_info_t node is created
and inserted in the queue and hash data structures.
Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
2019-05-16 23:43:41 +02:00
|
|
|
|
2019-05-17 03:38:03 +02:00
|
|
|
|
2019-03-25 15:11:55 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-03-26 21:30:29 +01:00
|
|
|
/*
|
|
|
|
* Multicast hash table.
|
|
|
|
*
|
|
|
|
* This table contains -
|
|
|
|
* 1. The (S, G) entries used for encapsulating and forwarding BUM traffic.
|
|
|
|
* S is the local VTEP-IP and G is a BUM mcast group address.
|
|
|
|
* 2. The (X, G) entries used for terminating a BUM flow.
|
|
|
|
* Multiple L2-VNIs can share the same MDT hence the need to maintain
|
|
|
|
* an aggregated table that pimd can consume without much
|
|
|
|
* re-interpretation.
|
|
|
|
*/
|
2021-08-20 14:53:44 +02:00
|
|
|
struct zebra_vxlan_sg {
|
2019-03-26 21:30:29 +01:00
|
|
|
struct zebra_vrf *zvrf;
|
|
|
|
|
|
|
|
struct prefix_sg sg;
|
|
|
|
char sg_str[PREFIX_SG_STR_LEN];
|
|
|
|
|
|
|
|
/* For SG - num of L2 VNIs using this entry for sending BUM traffic */
|
|
|
|
/* For XG - num of SG using this as parent */
|
|
|
|
uint32_t ref_cnt;
|
2021-08-20 14:53:44 +02:00
|
|
|
};
|
2019-03-26 21:30:29 +01:00
|
|
|
|
2021-08-19 22:08:53 +02:00
|
|
|
extern struct zebra_evpn *zevpn_lookup(vni_t vni);
|
2021-08-19 22:33:53 +02:00
|
|
|
extern void zebra_vxlan_sync_mac_dp_install(struct zebra_mac *mac,
|
|
|
|
bool set_inactive,
|
|
|
|
bool force_clear_static,
|
|
|
|
const char *caller);
|
2020-05-11 03:02:37 +02:00
|
|
|
extern bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf);
|
2021-07-27 09:47:52 +02:00
|
|
|
extern void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
|
|
|
|
struct in_addr mcast_grp);
|
|
|
|
extern void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
|
|
|
|
struct in_addr mcast_grp);
|
|
|
|
extern void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
|
|
|
|
extern void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
|
2021-07-27 10:10:48 +02:00
|
|
|
extern int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn);
|
2020-03-28 01:14:45 +01:00
|
|
|
|
2017-05-15 07:37:42 +02:00
|
|
|
#endif /* _ZEBRA_VXLAN_PRIVATE_H */
|