mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 13:13:08 +00:00
zebra: support for type-0 ESI
Earlier type-3 ESI was the only format supported for evpn-mh. Updated the CLI to allow a 10-byte type-0 ESI. Both type-0 and type-3 ESIs are statically configured; just in two different ways - 1. type-0 is configured as a complete 10-byte string 2. type-3 is configured as a 6-byte es-sys-mac and a 3-byte local-discriminator. Sample config - ! interface hostbond1 evpn mh es-id 00:44:38:39:ff:ff:01:00:00:01 ! This is a CLI-only change and has no functional impact. Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
parent
78695ce3a4
commit
325d694b93
@ -279,8 +279,12 @@ struct irdp_interface;
|
|||||||
/* Ethernet segment info used for setting up EVPN multihoming */
|
/* Ethernet segment info used for setting up EVPN multihoming */
|
||||||
struct zebra_evpn_es;
|
struct zebra_evpn_es;
|
||||||
struct zebra_es_if_info {
|
struct zebra_es_if_info {
|
||||||
|
/* type-3 esi config */
|
||||||
struct ethaddr sysmac;
|
struct ethaddr sysmac;
|
||||||
uint32_t lid; /* local-id; has to be unique per-ES-sysmac */
|
uint32_t lid; /* local-id; has to be unique per-ES-sysmac */
|
||||||
|
|
||||||
|
esi_t esi;
|
||||||
|
|
||||||
uint16_t df_pref;
|
uint16_t df_pref;
|
||||||
struct zebra_evpn_es *es; /* local ES */
|
struct zebra_evpn_es *es; /* local ES */
|
||||||
};
|
};
|
||||||
|
@ -62,8 +62,7 @@ static void zebra_evpn_es_get_one_base_evpn(void);
|
|||||||
static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
|
static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
|
||||||
zebra_evpn_t *zevpn, bool add);
|
zebra_evpn_t *zevpn, bool add);
|
||||||
static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp);
|
static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp);
|
||||||
static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid,
|
static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi);
|
||||||
struct ethaddr *sysmac);
|
|
||||||
static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
|
static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
|
||||||
const char *caller);
|
const char *caller);
|
||||||
static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set);
|
static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set);
|
||||||
@ -934,7 +933,7 @@ void zebra_evpn_if_init(struct zebra_if *zif)
|
|||||||
/* if an es_id and sysmac are already present against the interface
|
/* if an es_id and sysmac are already present against the interface
|
||||||
* activate it
|
* activate it
|
||||||
*/
|
*/
|
||||||
zebra_evpn_local_es_update(zif, zif->es_info.lid, &zif->es_info.sysmac);
|
zebra_evpn_local_es_update(zif, &zif->es_info.esi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle deletion of an access port by removing it from all associated
|
/* handle deletion of an access port by removing it from all associated
|
||||||
@ -1396,6 +1395,9 @@ static struct zebra_evpn_es *zebra_evpn_es_new(esi_t *esi)
|
|||||||
{
|
{
|
||||||
struct zebra_evpn_es *es;
|
struct zebra_evpn_es *es;
|
||||||
|
|
||||||
|
if (!memcmp(esi, zero_esi, sizeof(esi_t)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
es = XCALLOC(MTYPE_ZES, sizeof(struct zebra_evpn_es));
|
es = XCALLOC(MTYPE_ZES, sizeof(struct zebra_evpn_es));
|
||||||
|
|
||||||
/* fill in ESI */
|
/* fill in ESI */
|
||||||
@ -1818,17 +1820,50 @@ static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp)
|
|||||||
/* A new local es is created when a local-es-id and sysmac is configured
|
/* A new local es is created when a local-es-id and sysmac is configured
|
||||||
* against an interface.
|
* against an interface.
|
||||||
*/
|
*/
|
||||||
static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid,
|
static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi)
|
||||||
struct ethaddr *sysmac)
|
|
||||||
{
|
{
|
||||||
struct zebra_evpn_es *old_es = zif->es_info.es;
|
struct zebra_evpn_es *old_es = zif->es_info.es;
|
||||||
struct zebra_evpn_es *es;
|
struct zebra_evpn_es *es;
|
||||||
|
|
||||||
|
memcpy(&zif->es_info.esi, esi, sizeof(*esi));
|
||||||
|
if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi)))
|
||||||
|
/* dup - nothing to be done */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* release the old_es against the zif */
|
||||||
|
if (old_es)
|
||||||
|
zebra_evpn_local_es_del(&old_es);
|
||||||
|
|
||||||
|
es = zebra_evpn_es_find(esi);
|
||||||
|
if (es) {
|
||||||
|
/* if it exists against another interface flag an error */
|
||||||
|
if (es->zif && es->zif != zif) {
|
||||||
|
memset(&zif->es_info.esi, 0, sizeof(*esi));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* create new es */
|
||||||
|
es = zebra_evpn_es_new(esi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (es)
|
||||||
|
zebra_evpn_es_local_info_set(es, zif);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zebra_evpn_type3_esi_update(struct zebra_if *zif, uint32_t lid,
|
||||||
|
struct ethaddr *sysmac)
|
||||||
|
{
|
||||||
|
struct zebra_evpn_es *old_es = zif->es_info.es;
|
||||||
esi_t esi;
|
esi_t esi;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int field_bytes = 0;
|
int field_bytes = 0;
|
||||||
|
|
||||||
/* Complete config of the ES-ID bootstraps the ES */
|
/* Complete config of the ES-ID bootstraps the ES */
|
||||||
if (!lid || is_zero_mac(sysmac)) {
|
if (!lid || is_zero_mac(sysmac)) {
|
||||||
|
/* clear old esi */
|
||||||
|
memset(&zif->es_info.esi, 0, sizeof(zif->es_info.esi));
|
||||||
/* if in ES is attached to zif delete it */
|
/* if in ES is attached to zif delete it */
|
||||||
if (old_es)
|
if (old_es)
|
||||||
zebra_evpn_local_es_del(&old_es);
|
zebra_evpn_local_es_del(&old_es);
|
||||||
@ -1850,27 +1885,7 @@ static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid,
|
|||||||
esi.val[offset++] = (uint8_t)(lid >> 8);
|
esi.val[offset++] = (uint8_t)(lid >> 8);
|
||||||
esi.val[offset++] = (uint8_t)lid;
|
esi.val[offset++] = (uint8_t)lid;
|
||||||
|
|
||||||
if (old_es && !memcmp(&old_es->esi, &esi, sizeof(esi_t)))
|
return zebra_evpn_local_es_update(zif, &esi);
|
||||||
/* dup - nothing to be done */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* release the old_es against the zif */
|
|
||||||
if (old_es)
|
|
||||||
zebra_evpn_local_es_del(&old_es);
|
|
||||||
|
|
||||||
es = zebra_evpn_es_find(&esi);
|
|
||||||
if (es) {
|
|
||||||
/* if it exists against another interface flag an error */
|
|
||||||
if (es->zif && es->zif != zif)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
/* create new es */
|
|
||||||
es = zebra_evpn_es_new(&esi);
|
|
||||||
}
|
|
||||||
|
|
||||||
zebra_evpn_es_local_info_set(es, zif);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip)
|
static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip)
|
||||||
@ -2077,7 +2092,7 @@ static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif,
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = zebra_evpn_local_es_update(zif, zif->es_info.lid, sysmac);
|
rv = zebra_evpn_type3_esi_update(zif, zif->es_info.lid, sysmac);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
|
memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
|
||||||
|
|
||||||
@ -2089,13 +2104,29 @@ static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = zebra_evpn_local_es_update(zif, lid, &zif->es_info.sysmac);
|
rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
zif->es_info.lid = lid;
|
zif->es_info.lid = lid;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* type-0 esi has changed */
|
||||||
|
static int zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = zebra_evpn_local_es_update(zif, esi);
|
||||||
|
|
||||||
|
/* clear the old es_lid, es_sysmac - type-0 is being set so old
|
||||||
|
* type-3 params need to be flushed
|
||||||
|
*/
|
||||||
|
memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr));
|
||||||
|
zif->es_info.lid = 0;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
void zebra_evpn_es_cleanup(void)
|
void zebra_evpn_es_cleanup(void)
|
||||||
{
|
{
|
||||||
struct zebra_evpn_es *es;
|
struct zebra_evpn_es *es;
|
||||||
@ -2153,6 +2184,7 @@ void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif)
|
|||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
char mh_buf[80];
|
char mh_buf[80];
|
||||||
bool vty_print = false;
|
bool vty_print = false;
|
||||||
|
char esi_buf[ESI_STR_LEN];
|
||||||
|
|
||||||
mh_buf[0] = '\0';
|
mh_buf[0] = '\0';
|
||||||
snprintf(mh_buf + strlen(mh_buf), sizeof(mh_buf) - strlen(mh_buf),
|
snprintf(mh_buf + strlen(mh_buf), sizeof(mh_buf) - strlen(mh_buf),
|
||||||
@ -2164,6 +2196,13 @@ void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif)
|
|||||||
sizeof(mh_buf) - strlen(mh_buf),
|
sizeof(mh_buf) - strlen(mh_buf),
|
||||||
" ES id %u ES sysmac %s", zif->es_info.lid,
|
" ES id %u ES sysmac %s", zif->es_info.lid,
|
||||||
prefix_mac2str(&zif->es_info.sysmac, buf, sizeof(buf)));
|
prefix_mac2str(&zif->es_info.sysmac, buf, sizeof(buf)));
|
||||||
|
} else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) {
|
||||||
|
vty_print = true;
|
||||||
|
snprintf(mh_buf + strnlen(mh_buf, sizeof(mh_buf)),
|
||||||
|
sizeof(mh_buf) - strnlen(mh_buf, sizeof(mh_buf)),
|
||||||
|
" ES id %s",
|
||||||
|
esi_to_str(&zif->es_info.esi, esi_buf,
|
||||||
|
sizeof(esi_buf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) {
|
if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) {
|
||||||
@ -2495,14 +2534,25 @@ int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
|
|||||||
{
|
{
|
||||||
struct zebra_if *zif = ifp->info;
|
struct zebra_if *zif = ifp->info;
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
|
bool type_3_esi = false;
|
||||||
|
char esi_buf[ESI_STR_LEN];
|
||||||
|
|
||||||
if (zif->es_info.lid)
|
if (zif->es_info.lid) {
|
||||||
vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid);
|
vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid);
|
||||||
|
type_3_esi = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_zero_mac(&zif->es_info.sysmac))
|
if (!is_zero_mac(&zif->es_info.sysmac)) {
|
||||||
vty_out(vty, " evpn mh es-sys-mac %s\n",
|
vty_out(vty, " evpn mh es-sys-mac %s\n",
|
||||||
prefix_mac2str(&zif->es_info.sysmac,
|
prefix_mac2str(&zif->es_info.sysmac,
|
||||||
buf, sizeof(buf)));
|
buf, sizeof(buf)));
|
||||||
|
type_3_esi = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type_3_esi
|
||||||
|
&& memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
|
||||||
|
vty_out(vty, " evpn mh es-id %s\n",
|
||||||
|
esi_to_str(&zif->es_info.esi, esi_buf, sizeof(esi_buf)));
|
||||||
|
|
||||||
if (zif->es_info.df_pref)
|
if (zif->es_info.df_pref)
|
||||||
vty_out(vty, " evpn mh es-df-pref %u\n", zif->es_info.df_pref);
|
vty_out(vty, " evpn mh es-df-pref %u\n", zif->es_info.df_pref);
|
||||||
@ -2591,22 +2641,28 @@ DEFPY(zebra_evpn_es_sys_mac,
|
|||||||
/* CLI for setting up local-ID part of ESI on an access port */
|
/* CLI for setting up local-ID part of ESI on an access port */
|
||||||
DEFPY(zebra_evpn_es_id,
|
DEFPY(zebra_evpn_es_id,
|
||||||
zebra_evpn_es_id_cmd,
|
zebra_evpn_es_id_cmd,
|
||||||
"[no$no] evpn mh es-id [(1-16777215)$es_lid]",
|
"[no$no] evpn mh es-id [(1-16777215)$es_lid | NAME$esi_str]",
|
||||||
NO_STR
|
NO_STR
|
||||||
"EVPN\n"
|
"EVPN\n"
|
||||||
EVPN_MH_VTY_STR
|
EVPN_MH_VTY_STR
|
||||||
"Ethernet segment local identifier\n"
|
"Ethernet segment identifier\n"
|
||||||
"ID\n"
|
"local discriminator\n"
|
||||||
|
"10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n"
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
struct zebra_if *zif;
|
struct zebra_if *zif;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
esi_t esi;
|
||||||
|
|
||||||
zif = ifp->info;
|
zif = ifp->info;
|
||||||
|
|
||||||
if (no) {
|
if (no) {
|
||||||
ret = zebra_evpn_es_lid_update(zif, 0);
|
if (zif->es_info.lid)
|
||||||
|
ret = zebra_evpn_es_lid_update(zif, 0);
|
||||||
|
else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
|
||||||
|
ret = zebra_evpn_es_type0_esi_update(zif, zero_esi);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
vty_out(vty, "%%Failed to clear ES local id\n");
|
vty_out(vty, "%%Failed to clear ES local id\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -2618,14 +2674,23 @@ DEFPY(zebra_evpn_es_id,
|
|||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!es_lid) {
|
if (esi_str) {
|
||||||
vty_out(vty, "%%Specify local ES ID\n");
|
if (!str_to_esi(esi_str, &esi)) {
|
||||||
return CMD_WARNING;
|
vty_out(vty, "%% Malformed ESI\n");
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
ret = zebra_evpn_es_type0_esi_update(zif, &esi);
|
||||||
|
} else {
|
||||||
|
if (!es_lid) {
|
||||||
|
vty_out(vty, "%%Specify local ES ID\n");
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
ret = zebra_evpn_es_lid_update(zif, es_lid);
|
||||||
}
|
}
|
||||||
ret = zebra_evpn_es_lid_update(zif, es_lid);
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%%ESI already exists on a different interface\n");
|
"%%ESI already exists on a different interface\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user