mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 14:17:20 +00:00
zebra: convert interface evpn mh es-id commands to NB
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
parent
be712fc697
commit
a6db1c14a4
@ -1019,6 +1019,13 @@ void yang_str2mac(const char *value, struct ethaddr *mac)
|
|||||||
(void)prefix_str2mac(value, mac);
|
(void)prefix_str2mac(value, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode,
|
||||||
|
const char *xpath_fmt, ...)
|
||||||
|
{
|
||||||
|
const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
|
||||||
|
(void)prefix_str2mac(canon, mac);
|
||||||
|
}
|
||||||
|
|
||||||
struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time)
|
struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time)
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
@ -195,6 +195,8 @@ extern void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
|
|||||||
extern struct yang_data *yang_data_new_mac(const char *xpath,
|
extern struct yang_data *yang_data_new_mac(const char *xpath,
|
||||||
const struct ethaddr *mac);
|
const struct ethaddr *mac);
|
||||||
extern void yang_str2mac(const char *value, struct ethaddr *mac);
|
extern void yang_str2mac(const char *value, struct ethaddr *mac);
|
||||||
|
extern void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode,
|
||||||
|
const char *xpath_fmt, ...) PRINTFRR(3, 4);
|
||||||
|
|
||||||
/*data-and-time */
|
/*data-and-time */
|
||||||
extern struct yang_data *yang_data_new_date_and_time(const char *xpath,
|
extern struct yang_data *yang_data_new_date_and_time(const char *xpath,
|
||||||
|
@ -2217,6 +2217,35 @@ module frr-zebra {
|
|||||||
// TODO -- other link-params options
|
// TODO -- other link-params options
|
||||||
// for (experimental/partial TE use in IGP extensions)
|
// for (experimental/partial TE use in IGP extensions)
|
||||||
}
|
}
|
||||||
|
container evpn-mh {
|
||||||
|
description "EVPN multihoming configuration";
|
||||||
|
choice esi-choice {
|
||||||
|
description "ESI type";
|
||||||
|
container type-0 {
|
||||||
|
leaf esi {
|
||||||
|
type yang:hex-string {
|
||||||
|
length "29";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"10-octet ESI.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container type-3 {
|
||||||
|
leaf system-mac {
|
||||||
|
type yang:mac-address;
|
||||||
|
description
|
||||||
|
"System MAC address.";
|
||||||
|
}
|
||||||
|
leaf local-discriminator {
|
||||||
|
type uint32 {
|
||||||
|
range "1..16777215";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"Local discriminator.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
container state {
|
container state {
|
||||||
config false;
|
config false;
|
||||||
description
|
description
|
||||||
|
@ -28,7 +28,7 @@ man8 += $(MANBUILD)/frr-zebra.8
|
|||||||
## endif ZEBRA
|
## endif ZEBRA
|
||||||
endif
|
endif
|
||||||
|
|
||||||
zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP) $(UST_LIBS)
|
zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP) $(LIBYANG_LIBS) $(UST_LIBS)
|
||||||
if HAVE_PROTOBUF3
|
if HAVE_PROTOBUF3
|
||||||
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
|
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
|
||||||
zebra/zebra_mlag.$(OBJEXT): mlag/mlag.pb-c.h
|
zebra/zebra_mlag.$(OBJEXT): mlag/mlag.pb-c.h
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "vlan.h"
|
#include "vlan.h"
|
||||||
#include "vxlan.h"
|
#include "vxlan.h"
|
||||||
|
#include "northbound_cli.h"
|
||||||
|
|
||||||
#include "zebra/zebra_router.h"
|
#include "zebra/zebra_router.h"
|
||||||
#include "zebra/debug.h"
|
#include "zebra/debug.h"
|
||||||
@ -52,7 +53,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,
|
||||||
struct zebra_evpn *zevpn, bool add);
|
struct zebra_evpn *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, esi_t *esi);
|
static void zebra_evpn_local_es_update(struct zebra_if *zif);
|
||||||
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);
|
||||||
@ -1139,7 +1140,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.esi);
|
zebra_evpn_local_es_update(zif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle deletion of an access port by removing it from all associated
|
/* handle deletion of an access port by removing it from all associated
|
||||||
@ -2402,73 +2403,63 @@ static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
int field_bytes = 0;
|
||||||
|
|
||||||
|
/* build 10-byte type-3-ESI -
|
||||||
|
* Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
|
||||||
|
*/
|
||||||
|
field_bytes = 1;
|
||||||
|
esi->val[offset] = ESI_TYPE_MAC;
|
||||||
|
offset += field_bytes;
|
||||||
|
|
||||||
|
field_bytes = ETH_ALEN;
|
||||||
|
memcpy(&esi->val[offset], (uint8_t *)mac, field_bytes);
|
||||||
|
offset += field_bytes;
|
||||||
|
|
||||||
|
esi->val[offset++] = (uint8_t)(lid >> 16);
|
||||||
|
esi->val[offset++] = (uint8_t)(lid >> 8);
|
||||||
|
esi->val[offset++] = (uint8_t)lid;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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, esi_t *esi)
|
static void zebra_evpn_local_es_update(struct zebra_if *zif)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
esi_t _esi, *esi;
|
||||||
|
|
||||||
|
if (!zebra_evpn_is_if_es_capable(zif))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) {
|
||||||
|
esi = &zif->es_info.esi;
|
||||||
|
} else if (zif->es_info.lid && !is_zero_mac(&zif->es_info.sysmac)) {
|
||||||
|
zebra_build_type3_esi(zif->es_info.lid, &zif->es_info.sysmac,
|
||||||
|
&_esi);
|
||||||
|
esi = &_esi;
|
||||||
|
} else {
|
||||||
|
esi = zero_esi;
|
||||||
|
}
|
||||||
|
|
||||||
if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi)))
|
if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi)))
|
||||||
/* dup - nothing to be done */
|
/* dup - nothing to be done */
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
/* release the old_es against the zif */
|
/* release the old_es against the zif */
|
||||||
if (old_es)
|
if (old_es)
|
||||||
zebra_evpn_local_es_del(&old_es);
|
zebra_evpn_local_es_del(&old_es);
|
||||||
|
|
||||||
es = zebra_evpn_es_find(esi);
|
es = zebra_evpn_es_find(esi);
|
||||||
if (es) {
|
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);
|
es = zebra_evpn_es_new(esi);
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&zif->es_info.esi, esi, sizeof(*esi));
|
|
||||||
if (es)
|
if (es)
|
||||||
zebra_evpn_es_local_info_set(es, zif);
|
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;
|
|
||||||
int offset = 0;
|
|
||||||
int field_bytes = 0;
|
|
||||||
|
|
||||||
/* Complete config of the ES-ID bootstraps the ES */
|
|
||||||
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 (old_es)
|
|
||||||
zebra_evpn_local_es_del(&old_es);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build 10-byte type-3-ESI -
|
|
||||||
* Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
|
|
||||||
*/
|
|
||||||
field_bytes = 1;
|
|
||||||
esi.val[offset] = ESI_TYPE_MAC;
|
|
||||||
offset += field_bytes;
|
|
||||||
|
|
||||||
field_bytes = ETH_ALEN;
|
|
||||||
memcpy(&esi.val[offset], (uint8_t *)sysmac, field_bytes);
|
|
||||||
offset += field_bytes;
|
|
||||||
|
|
||||||
esi.val[offset++] = (uint8_t)(lid >> 16);
|
|
||||||
esi.val[offset++] = (uint8_t)(lid >> 8);
|
|
||||||
esi.val[offset++] = (uint8_t)lid;
|
|
||||||
|
|
||||||
return zebra_evpn_local_es_update(zif, &esi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip)
|
int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip)
|
||||||
@ -2673,44 +2664,33 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sysmac part of a local ESI has changed */
|
/* sysmac part of a local ESI has changed */
|
||||||
static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif,
|
void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac)
|
||||||
struct ethaddr *sysmac)
|
|
||||||
{
|
{
|
||||||
int rv;
|
if (sysmac)
|
||||||
|
|
||||||
rv = zebra_evpn_type3_esi_update(zif, zif->es_info.lid, sysmac);
|
|
||||||
if (!rv)
|
|
||||||
memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
|
memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
|
||||||
|
else
|
||||||
|
memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr));
|
||||||
|
|
||||||
return rv;
|
zebra_evpn_local_es_update(zif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* local-ID part of ESI has changed */
|
/* local-ID part of ESI has changed */
|
||||||
static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
|
void zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
|
||||||
{
|
{
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac);
|
|
||||||
if (!rv)
|
|
||||||
zif->es_info.lid = lid;
|
zif->es_info.lid = lid;
|
||||||
|
|
||||||
return rv;
|
zebra_evpn_local_es_update(zif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* type-0 esi has changed */
|
/* type-0 esi has changed */
|
||||||
static int zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
|
void zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
|
||||||
{
|
{
|
||||||
int rv;
|
if (esi)
|
||||||
|
memcpy(&zif->es_info.esi, esi, sizeof(*esi));
|
||||||
|
else
|
||||||
|
memset(&zif->es_info.esi, 0, sizeof(*esi));
|
||||||
|
|
||||||
rv = zebra_evpn_local_es_update(zif, esi);
|
zebra_evpn_local_es_update(zif);
|
||||||
|
|
||||||
/* 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)
|
||||||
@ -3409,9 +3389,9 @@ DEFPY(zebra_evpn_es_pref, zebra_evpn_es_pref_cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* CLI for setting up sysmac part of ESI on an access port */
|
/* CLI for setting up sysmac part of ESI on an access port */
|
||||||
DEFPY(zebra_evpn_es_sys_mac,
|
DEFPY_YANG (zebra_evpn_es_sys_mac,
|
||||||
zebra_evpn_es_sys_mac_cmd,
|
zebra_evpn_es_sys_mac_cmd,
|
||||||
"[no$no] evpn mh es-sys-mac [X:X:X:X:X:X$mac]",
|
"[no$no] evpn mh es-sys-mac ![X:X:X:X:X:X$mac]",
|
||||||
NO_STR
|
NO_STR
|
||||||
"EVPN\n"
|
"EVPN\n"
|
||||||
EVPN_MH_VTY_STR
|
EVPN_MH_VTY_STR
|
||||||
@ -3419,47 +3399,21 @@ DEFPY(zebra_evpn_es_sys_mac,
|
|||||||
MAC_STR
|
MAC_STR
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
if (!no)
|
||||||
struct zebra_if *zif;
|
nb_cli_enqueue_change(vty,
|
||||||
int ret = 0;
|
"./frr-zebra:zebra/evpn-mh/type-3/system-mac",
|
||||||
|
NB_OP_MODIFY, mac_str);
|
||||||
zif = ifp->info;
|
else
|
||||||
|
nb_cli_enqueue_change(vty,
|
||||||
if (no) {
|
"./frr-zebra:zebra/evpn-mh/type-3/system-mac",
|
||||||
static struct ethaddr zero_mac;
|
NB_OP_DESTROY, NULL);
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
ret = zebra_evpn_es_sys_mac_update(zif, &zero_mac);
|
|
||||||
if (ret == -1) {
|
|
||||||
vty_out(vty, "%% Failed to clear ES sysmac\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!zebra_evpn_is_if_es_capable(zif)) {
|
|
||||||
vty_out(vty,
|
|
||||||
"%% ESI cannot be associated with this interface type\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mac || is_zero_mac(&mac->eth_addr)) {
|
|
||||||
vty_out(vty, "%% ES sysmac value is invalid\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = zebra_evpn_es_sys_mac_update(zif, &mac->eth_addr);
|
|
||||||
if (ret == -1) {
|
|
||||||
vty_out(vty,
|
|
||||||
"%% ESI already exists on a different interface\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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_YANG (zebra_evpn_es_id,
|
||||||
zebra_evpn_es_id_cmd,
|
zebra_evpn_es_id_cmd,
|
||||||
"[no$no] evpn mh es-id [(1-16777215)$es_lid | NAME$esi_str]",
|
"[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
|
||||||
@ -3468,53 +3422,25 @@ DEFPY(zebra_evpn_es_id,
|
|||||||
"10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n"
|
"10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n"
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
||||||
struct zebra_if *zif;
|
|
||||||
int ret = 0;
|
|
||||||
esi_t esi;
|
|
||||||
|
|
||||||
zif = ifp->info;
|
|
||||||
|
|
||||||
if (no) {
|
if (no) {
|
||||||
if (zif->es_info.lid)
|
/* We don't know which one is configured, so detroy both types. */
|
||||||
ret = zebra_evpn_es_lid_update(zif, 0);
|
nb_cli_enqueue_change(vty,
|
||||||
else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
|
"./frr-zebra:zebra/evpn-mh/type-0/esi",
|
||||||
ret = zebra_evpn_es_type0_esi_update(zif, zero_esi);
|
NB_OP_DESTROY, NULL);
|
||||||
|
nb_cli_enqueue_change(vty,
|
||||||
if (ret == -1) {
|
"./frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
|
||||||
vty_out(vty,
|
NB_OP_DESTROY, NULL);
|
||||||
"%% Failed to clear ES local id or ESI name\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!zebra_evpn_is_if_es_capable(zif)) {
|
if (esi_str)
|
||||||
vty_out(vty,
|
nb_cli_enqueue_change(vty,
|
||||||
"%% ESI cannot be associated with this interface type\n");
|
"./frr-zebra:zebra/evpn-mh/type-0/esi",
|
||||||
return CMD_WARNING;
|
NB_OP_MODIFY, esi_str);
|
||||||
|
else
|
||||||
|
nb_cli_enqueue_change(vty,
|
||||||
|
"./frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
|
||||||
|
NB_OP_MODIFY, es_lid_str);
|
||||||
}
|
}
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
if (esi_str) {
|
|
||||||
if (!str_to_esi(esi_str, &esi)) {
|
|
||||||
vty_out(vty, "%% Malformed ESI name\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
ret = zebra_evpn_es_type0_esi_update(zif, &esi);
|
|
||||||
} else {
|
|
||||||
if (!es_lid) {
|
|
||||||
vty_out(vty,
|
|
||||||
"%% Specify ES local id or ESI name\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
ret = zebra_evpn_es_lid_update(zif, es_lid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == -1) {
|
|
||||||
vty_out(vty,
|
|
||||||
"%% ESI already exists on a different interface\n");
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLI for tagging an interface as an uplink */
|
/* CLI for tagging an interface as an uplink */
|
||||||
|
@ -382,4 +382,10 @@ extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
|
|||||||
extern struct zebra_evpn_es_evi *
|
extern struct zebra_evpn_es_evi *
|
||||||
zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
|
zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
|
||||||
|
|
||||||
|
void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi);
|
||||||
|
|
||||||
|
void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac);
|
||||||
|
void zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid);
|
||||||
|
void zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi);
|
||||||
|
|
||||||
#endif /* _ZEBRA_EVPN_MH_H */
|
#endif /* _ZEBRA_EVPN_MH_H */
|
||||||
|
@ -507,6 +507,27 @@ const struct frr_yang_module_info frr_zebra_info = {
|
|||||||
.destroy = lib_interface_zebra_link_params_packet_loss_destroy,
|
.destroy = lib_interface_zebra_link_params_packet_loss_destroy,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_interface_zebra_evpn_mh_type_0_esi_modify,
|
||||||
|
.destroy = lib_interface_zebra_evpn_mh_type_0_esi_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_interface_zebra_evpn_mh_type_3_system_mac_modify,
|
||||||
|
.destroy = lib_interface_zebra_evpn_mh_type_3_system_mac_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify,
|
||||||
|
.destroy = lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
|
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
|
||||||
.cbs = {
|
.cbs = {
|
||||||
|
@ -166,6 +166,17 @@ int lib_interface_zebra_link_params_packet_loss_modify(
|
|||||||
struct nb_cb_modify_args *args);
|
struct nb_cb_modify_args *args);
|
||||||
int lib_interface_zebra_link_params_packet_loss_destroy(
|
int lib_interface_zebra_link_params_packet_loss_destroy(
|
||||||
struct nb_cb_destroy_args *args);
|
struct nb_cb_destroy_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_0_esi_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_system_mac_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_system_mac_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
struct yang_data *
|
struct yang_data *
|
||||||
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
|
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
|
||||||
struct yang_data *
|
struct yang_data *
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "zebra/debug.h"
|
#include "zebra/debug.h"
|
||||||
#include "zebra/zebra_vxlan_private.h"
|
#include "zebra/zebra_vxlan_private.h"
|
||||||
#include "zebra/zebra_vxlan.h"
|
#include "zebra/zebra_vxlan.h"
|
||||||
|
#include "zebra/zebra_evpn_mh.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath: /frr-zebra:zebra/mcast-rpf-lookup
|
* XPath: /frr-zebra:zebra/mcast-rpf-lookup
|
||||||
@ -2200,6 +2201,205 @@ int lib_interface_zebra_link_params_packet_loss_destroy(
|
|||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool evpn_mh_dnode_to_esi(const struct lyd_node *dnode, esi_t *esi)
|
||||||
|
{
|
||||||
|
if (yang_dnode_exists(dnode, "type-0/esi")) {
|
||||||
|
str_to_esi(yang_dnode_get_string(dnode, "type-0/esi"), esi);
|
||||||
|
} else if (yang_dnode_exists(dnode, "type-3/system-mac") &&
|
||||||
|
yang_dnode_exists(dnode, "type-3/local-discriminator")) {
|
||||||
|
struct ethaddr mac;
|
||||||
|
uint32_t lid;
|
||||||
|
|
||||||
|
yang_dnode_get_mac(&mac, dnode, "type-3/system-mac");
|
||||||
|
lid = yang_dnode_get_uint32(dnode, "type-3/local-discriminator");
|
||||||
|
|
||||||
|
zebra_build_type3_esi(lid, &mac, esi);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct esi_cmp_iter_arg {
|
||||||
|
struct lyd_node *dnode;
|
||||||
|
esi_t esi;
|
||||||
|
bool exists;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int esi_cmp_iter_cb(const struct lyd_node *dnode, void *arg)
|
||||||
|
{
|
||||||
|
struct esi_cmp_iter_arg *iter = arg;
|
||||||
|
esi_t esi;
|
||||||
|
|
||||||
|
if (dnode == iter->dnode)
|
||||||
|
return YANG_ITER_CONTINUE;
|
||||||
|
|
||||||
|
if (!evpn_mh_dnode_to_esi(dnode, &esi))
|
||||||
|
return YANG_ITER_CONTINUE;
|
||||||
|
|
||||||
|
if (!memcmp(&esi, &iter->esi, ESI_BYTES)) {
|
||||||
|
iter->exists = true;
|
||||||
|
return YANG_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YANG_ITER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* evpn-mh should be passed to this function */
|
||||||
|
static bool esi_unique(struct lyd_node *dnode)
|
||||||
|
{
|
||||||
|
struct esi_cmp_iter_arg iter;
|
||||||
|
|
||||||
|
iter.dnode = dnode;
|
||||||
|
evpn_mh_dnode_to_esi(dnode, &iter.esi);
|
||||||
|
iter.exists = false;
|
||||||
|
|
||||||
|
yang_dnode_iterate(esi_cmp_iter_cb, &iter, dnode,
|
||||||
|
"/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh");
|
||||||
|
|
||||||
|
if (iter.exists)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi
|
||||||
|
*/
|
||||||
|
int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
esi_t esi;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
|
||||||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||||||
|
"ESI already exists on a different interface");
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
str_to_esi(yang_dnode_get_string(args->dnode, NULL), &esi);
|
||||||
|
zebra_evpn_es_type0_esi_update(ifp->info, &esi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lib_interface_zebra_evpn_mh_type_0_esi_destroy(struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
|
||||||
|
if (args->event != NB_EV_APPLY)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zebra_evpn_es_type0_esi_update(ifp->info, NULL);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac
|
||||||
|
*/
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_system_mac_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
struct ethaddr mac;
|
||||||
|
|
||||||
|
yang_dnode_get_mac(&mac, args->dnode, NULL);
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
if (is_zero_mac(&mac)) {
|
||||||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||||||
|
"MAC cannot be all-zeroes");
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
|
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
|
||||||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||||||
|
"ESI already exists on a different interface");
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zebra_evpn_es_sys_mac_update(ifp->info, &mac);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_system_mac_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
|
||||||
|
if (args->event != NB_EV_APPLY)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zebra_evpn_es_sys_mac_update(ifp->info, NULL);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator
|
||||||
|
*/
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
uint32_t lid;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
|
||||||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||||||
|
"ESI already exists on a different interface");
|
||||||
|
return NB_ERR_VALIDATION;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
lid = yang_dnode_get_uint32(args->dnode, NULL);
|
||||||
|
zebra_evpn_es_lid_update(ifp->info, lid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
|
||||||
|
if (args->event != NB_EV_APPLY)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zebra_evpn_es_lid_update(ifp->info, 0);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
|
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user