summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c228
-rw-r--r--lib/command.h2
-rw-r--r--lib/ipaddr.h10
-rw-r--r--lib/prefix.c128
-rw-r--r--lib/prefix.h91
-rw-r--r--lib/zclient.c14
-rw-r--r--lib/zclient.h4
7 files changed, 336 insertions, 141 deletions
diff --git a/lib/command.c b/lib/command.c
index 2744061b5a..69e301fcfa 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -85,6 +85,7 @@ const char *node_names[] = {
"keychain", // KEYCHAIN_NODE,
"keychain key", // KEYCHAIN_KEY_NODE,
"logical-router", // LOGICALROUTER_NODE,
+ "static ip", // IP_NODE,
"vrf", // VRF_NODE,
"interface", // INTERFACE_NODE,
"nexthop-group", // NH_GROUP_NODE,
@@ -119,7 +120,6 @@ const char *node_names[] = {
"ldp l2vpn", // LDP_L2VPN_NODE,
"ldp", // LDP_PSEUDOWIRE_NODE,
"isis", // ISIS_NODE,
- "static ip", // IP_NODE,
"ipv4 access list", // ACCESS_NODE,
"ipv4 prefix list", // PREFIX_NODE,
"ipv6 access list", // ACCESS_IPV6_NODE,
@@ -529,87 +529,103 @@ static int config_write_host(struct vty *vty)
if (cmd_domainname_get())
vty_out(vty, "domainname %s\n", cmd_domainname_get());
- if (host.encrypt) {
- if (host.password_encrypt)
- vty_out(vty, "password 8 %s\n", host.password_encrypt);
- if (host.enable_encrypt)
- vty_out(vty, "enable password 8 %s\n",
- host.enable_encrypt);
- } else {
- if (host.password)
- vty_out(vty, "password %s\n", host.password);
- if (host.enable)
- vty_out(vty, "enable password %s\n", host.enable);
- }
+ /* The following are all configuration commands that are not sent to
+ * watchfrr. For instance watchfrr is hardcoded to log to syslog so
+ * we would always display 'log syslog informational' in the config
+ * which would cause other daemons to then switch to syslog when they
+ * parse frr.conf.
+ */
+ if (strcmp(zlog_default->protoname, "WATCHFRR")) {
+ if (host.encrypt) {
+ if (host.password_encrypt)
+ vty_out(vty, "password 8 %s\n",
+ host.password_encrypt);
+ if (host.enable_encrypt)
+ vty_out(vty, "enable password 8 %s\n",
+ host.enable_encrypt);
+ } else {
+ if (host.password)
+ vty_out(vty, "password %s\n", host.password);
+ if (host.enable)
+ vty_out(vty, "enable password %s\n",
+ host.enable);
+ }
- if (zlog_default->default_lvl != LOG_DEBUG) {
- vty_out(vty, "! N.B. The 'log trap' command is deprecated.\n");
- vty_out(vty, "log trap %s\n",
- zlog_priority[zlog_default->default_lvl]);
- }
+ if (zlog_default->default_lvl != LOG_DEBUG) {
+ vty_out(vty,
+ "! N.B. The 'log trap' command is deprecated.\n");
+ vty_out(vty, "log trap %s\n",
+ zlog_priority[zlog_default->default_lvl]);
+ }
- if (host.logfile
- && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) {
- vty_out(vty, "log file %s", host.logfile);
- if (zlog_default->maxlvl[ZLOG_DEST_FILE]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority
- [zlog_default->maxlvl[ZLOG_DEST_FILE]]);
- vty_out(vty, "\n");
- }
+ if (host.logfile
+ && (zlog_default->maxlvl[ZLOG_DEST_FILE]
+ != ZLOG_DISABLED)) {
+ vty_out(vty, "log file %s", host.logfile);
+ if (zlog_default->maxlvl[ZLOG_DEST_FILE]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority
+ [zlog_default->maxlvl
+ [ZLOG_DEST_FILE]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
- vty_out(vty, "log stdout");
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority[zlog_default->maxlvl
- [ZLOG_DEST_STDOUT]]);
- vty_out(vty, "\n");
- }
+ if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
+ vty_out(vty, "log stdout");
+ if (zlog_default->maxlvl[ZLOG_DEST_STDOUT]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority
+ [zlog_default->maxlvl
+ [ZLOG_DEST_STDOUT]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
- vty_out(vty, "no log monitor\n");
- else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR]
- != zlog_default->default_lvl)
- vty_out(vty, "log monitor %s\n",
- zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]]);
-
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
- vty_out(vty, "log syslog");
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG]
- != zlog_default->default_lvl)
- vty_out(vty, " %s",
+ if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
+ vty_out(vty, "no log monitor\n");
+ else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR]
+ != zlog_default->default_lvl)
+ vty_out(vty, "log monitor %s\n",
zlog_priority[zlog_default->maxlvl
- [ZLOG_DEST_SYSLOG]]);
- vty_out(vty, "\n");
- }
+ [ZLOG_DEST_MONITOR]]);
+
+ if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
+ vty_out(vty, "log syslog");
+ if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG]
+ != zlog_default->default_lvl)
+ vty_out(vty, " %s",
+ zlog_priority[zlog_default->maxlvl
+ [ZLOG_DEST_SYSLOG]]);
+ vty_out(vty, "\n");
+ }
- if (zlog_default->facility != LOG_DAEMON)
- vty_out(vty, "log facility %s\n",
- facility_name(zlog_default->facility));
+ if (zlog_default->facility != LOG_DAEMON)
+ vty_out(vty, "log facility %s\n",
+ facility_name(zlog_default->facility));
- if (zlog_default->record_priority == 1)
- vty_out(vty, "log record-priority\n");
+ if (zlog_default->record_priority == 1)
+ vty_out(vty, "log record-priority\n");
- if (zlog_default->timestamp_precision > 0)
- vty_out(vty, "log timestamp precision %d\n",
- zlog_default->timestamp_precision);
+ if (zlog_default->timestamp_precision > 0)
+ vty_out(vty, "log timestamp precision %d\n",
+ zlog_default->timestamp_precision);
- if (host.advanced)
- vty_out(vty, "service advanced-vty\n");
+ if (host.advanced)
+ vty_out(vty, "service advanced-vty\n");
- if (host.encrypt)
- vty_out(vty, "service password-encryption\n");
+ if (host.encrypt)
+ vty_out(vty, "service password-encryption\n");
- if (host.lines >= 0)
- vty_out(vty, "service terminal-length %d\n", host.lines);
+ if (host.lines >= 0)
+ vty_out(vty, "service terminal-length %d\n",
+ host.lines);
- if (host.motdfile)
- vty_out(vty, "banner motd file %s\n", host.motdfile);
- else if (!host.motd)
- vty_out(vty, "no banner motd\n");
+ if (host.motdfile)
+ vty_out(vty, "banner motd file %s\n", host.motdfile);
+ else if (!host.motd)
+ vty_out(vty, "no banner motd\n");
+ }
if (debug_memstats_at_exit)
vty_out(vty, "!\ndebug memstats-at-exit\n");
@@ -1895,7 +1911,7 @@ DEFUN (config_no_hostname,
DEFUN (config_password,
password_cmd,
"password [(8-8)] WORD",
- "Assign the terminal connection password\n"
+ "Modify the terminal connection password\n"
"Specifies a HIDDEN password will follow\n"
"The password string\n")
{
@@ -1934,6 +1950,36 @@ DEFUN (config_password,
return CMD_SUCCESS;
}
+/* VTY interface password delete. */
+DEFUN (no_config_password,
+ no_password_cmd,
+ "no password",
+ NO_STR
+ "Modify the terminal connection password\n")
+{
+ bool warned = false;
+
+ if (host.password) {
+ vty_out(vty,
+ "Please be aware that removing the password is a security risk and "
+ "you should think twice about this command\n");
+ warned = true;
+ XFREE(MTYPE_HOST, host.password);
+ }
+ host.password = NULL;
+
+ if (host.password_encrypt) {
+ if (!warned)
+ vty_out(vty,
+ "Please be aware that removing the password is a security risk "
+ "and you should think twice about this command\n");
+ XFREE(MTYPE_HOST, host.password_encrypt);
+ }
+ host.password_encrypt = NULL;
+
+ return CMD_SUCCESS;
+}
+
/* VTY enable password set. */
DEFUN (config_enable_password,
enable_password_cmd,
@@ -1995,12 +2041,24 @@ DEFUN (no_config_enable_password,
"Modify enable password parameters\n"
"Assign the privileged level password\n")
{
- if (host.enable)
+ bool warned = false;
+
+ if (host.enable) {
+ vty_out(vty,
+ "Please be aware that removing the password is a security risk and "
+ "you should think twice about this command\n");
+ warned = true;
XFREE(MTYPE_HOST, host.enable);
+ }
host.enable = NULL;
- if (host.enable_encrypt)
+ if (host.enable_encrypt) {
+ if (!warned)
+ vty_out(vty,
+ "Please be aware that removing the password is a security risk "
+ "and you should think twice about this command\n");
XFREE(MTYPE_HOST, host.enable_encrypt);
+ }
host.enable_encrypt = NULL;
return CMD_SUCCESS;
@@ -2304,7 +2362,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
#if defined(HAVE_CUMULUS)
if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
- zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED;
+ zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
#endif
return CMD_SUCCESS;
}
@@ -2330,6 +2388,16 @@ DEFUN (config_log_file,
zlog_default->default_lvl);
}
+static void disable_log_file(void)
+{
+ zlog_reset_file();
+
+ if (host.logfile)
+ XFREE(MTYPE_HOST, host.logfile);
+
+ host.logfile = NULL;
+}
+
DEFUN (no_config_log_file,
no_config_log_file_cmd,
"no log file [FILENAME [LEVEL]]",
@@ -2339,13 +2407,7 @@ DEFUN (no_config_log_file,
"Logging file name\n"
"Logging level\n")
{
- zlog_reset_file();
-
- if (host.logfile)
- XFREE(MTYPE_HOST, host.logfile);
-
- host.logfile = NULL;
-
+ disable_log_file();
return CMD_SUCCESS;
}
@@ -2357,6 +2419,9 @@ DEFUN (config_log_syslog,
LOG_LEVEL_DESC)
{
int idx_log_levels = 2;
+
+ disable_log_file();
+
if (argc == 3) {
int level;
if ((level = level_match(argv[idx_log_levels]->arg))
@@ -2710,6 +2775,7 @@ void cmd_init(int terminal)
if (terminal > 0) {
install_element(CONFIG_NODE, &password_cmd);
+ install_element(CONFIG_NODE, &no_password_cmd);
install_element(CONFIG_NODE, &enable_password_cmd);
install_element(CONFIG_NODE, &no_enable_password_cmd);
diff --git a/lib/command.h b/lib/command.h
index f18de3417c..9ba53e0907 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -85,6 +85,7 @@ enum node_type {
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
LOGICALROUTER_NODE, /* Logical-Router node. */
+ IP_NODE, /* Static ip route node. */
VRF_NODE, /* VRF mode node. */
INTERFACE_NODE, /* Interface mode node. */
NH_GROUP_NODE, /* Nexthop-Group mode node. */
@@ -119,7 +120,6 @@ enum node_type {
LDP_L2VPN_NODE, /* LDP L2VPN node */
LDP_PSEUDOWIRE_NODE, /* LDP Pseudowire node */
ISIS_NODE, /* ISIS protocol mode */
- IP_NODE, /* Static ip route node. */
ACCESS_NODE, /* Access list node. */
PREFIX_NODE, /* Prefix list node. */
ACCESS_IPV6_NODE, /* Access list node. */
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index 33591cb4e7..7f2d06548b 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -102,4 +102,14 @@ static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6,
memcpy((char *)in6 + 12, &in, sizeof(struct in_addr));
}
+/*
+ * convert an ipv4 mapped ipv6 address back to ipv4 address
+ */
+static inline void ipv4_mapped_ipv6_to_ipv4(struct in6_addr *in6,
+ struct in_addr *in)
+{
+ memset(in, 0, sizeof(struct in_addr));
+ memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
+}
+
#endif /* __IPADDR_H__ */
diff --git a/lib/prefix.c b/lib/prefix.c
index b38dd94589..05af190e9d 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1206,54 +1206,104 @@ int str2prefix(const char *str, struct prefix *p)
return 0;
}
-static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
+static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ snprintf(str, size, "Unsupported EVPN prefix");
+ return str;
+}
+
+static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
+ int size)
{
uint8_t family;
char buf[PREFIX2STR_BUFFER];
char buf2[ETHER_ADDR_STRLEN];
- if (p->u.prefix_evpn.route_type == 2) {
- if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p))
- snprintf(str, size, "[%d]:[%s]/%d",
- p->u.prefix_evpn.route_type,
- prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
- sizeof(buf2)),
- p->prefixlen);
- else {
- family = IS_EVPN_PREFIX_IPADDR_V4(
- (struct prefix_evpn *)p)
- ? AF_INET
- : AF_INET6;
- snprintf(str, size, "[%d]:[%s]:[%s]/%d",
- p->u.prefix_evpn.route_type,
- prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
- sizeof(buf2)),
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
- buf, PREFIX2STR_BUFFER),
- p->prefixlen);
- }
- } else if (p->u.prefix_evpn.route_type == 3) {
- family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
- ? AF_INET
- : AF_INET6;
- snprintf(str, size, "[%d]:[%s]/%d", p->u.prefix_evpn.route_type,
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
- PREFIX2STR_BUFFER),
+ if (is_evpn_prefix_ipaddr_none(p))
+ snprintf(str, size, "[%d]:[%s]/%d",
+ p->prefix.route_type,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
+ buf2, sizeof(buf2)),
p->prefixlen);
- } else if (p->u.prefix_evpn.route_type == 5) {
- family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
+ else {
+ family = is_evpn_prefix_ipaddr_v4(p)
? AF_INET
: AF_INET6;
- snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
- p->u.prefix_evpn.route_type, p->u.prefix_evpn.eth_tag,
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
- PREFIX2STR_BUFFER),
- p->u.prefix_evpn.ip_prefix_length, p->prefixlen);
- } else {
- sprintf(str, "Unsupported EVPN route type %d",
- p->u.prefix_evpn.route_type);
+ snprintf(str, size, "[%d]:[%s]:[%s]/%d",
+ p->prefix.route_type,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
+ buf2, sizeof(buf2)),
+ inet_ntop(family,
+ &p->prefix.macip_addr.ip.ip.addr,
+ buf, PREFIX2STR_BUFFER),
+ p->prefixlen);
}
+ return str;
+}
+
+static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ uint8_t family;
+ char buf[PREFIX2STR_BUFFER];
+
+ family = is_evpn_prefix_ipaddr_v4(p)
+ ? AF_INET
+ : AF_INET6;
+ snprintf(str, size, "[%d]:[%s]/%d", p->prefix.route_type,
+ inet_ntop(family,
+ &p->prefix.imet_addr.ip.ip.addr, buf,
+ PREFIX2STR_BUFFER),
+ p->prefixlen);
+ return str;
+}
+static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ snprintf(str, size, "Unsupported EVPN prefix");
+ return str;
+}
+
+static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ uint8_t family;
+ char buf[PREFIX2STR_BUFFER];
+
+ family = is_evpn_prefix_ipaddr_v4(p)
+ ? AF_INET
+ : AF_INET6;
+ snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
+ p->prefix.route_type,
+ p->prefix.prefix_addr.eth_tag,
+ inet_ntop(family,
+ &p->prefix.prefix_addr.ip.ip.addr, buf,
+ PREFIX2STR_BUFFER),
+ p->prefix.prefix_addr.ip_prefix_length,
+ p->prefixlen);
+ return str;
+}
+
+static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ switch (p->prefix.route_type) {
+ case 1:
+ return prefixevpn_ead2str(p, str, size);
+ case 2:
+ return prefixevpn_macip2str(p, str, size);
+ case 3:
+ return prefixevpn_imet2str(p, str, size);
+ case 4:
+ return prefixevpn_es2str(p, str, size);
+ case 5:
+ return prefixevpn_prefix2str(p, str, size);
+ default:
+ snprintf(str, size, "Unsupported EVPN prefix");
+ break;
+ }
return str;
}
@@ -1277,7 +1327,7 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
break;
case AF_EVPN:
- prefixevpn2str(p, str, size);
+ prefixevpn2str((const struct prefix_evpn *)p, str, size);
break;
case AF_FLOWSPEC:
diff --git a/lib/prefix.h b/lib/prefix.h
index f01c85b811..ab3c05ae74 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -56,26 +56,56 @@ struct ethaddr {
#define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8)
#define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8)
-/* EVPN address (RFC 7432) */
-struct evpn_addr {
- uint8_t route_type;
+typedef struct esi_t_ {
+ uint8_t val[10];
+} esi_t;
+
+struct evpn_ead_addr {
+ esi_t esi;
+ uint32_t eth_tag;
+};
+
+struct evpn_macip_addr {
+ uint32_t eth_tag;
uint8_t ip_prefix_length;
struct ethaddr mac;
+ struct ipaddr ip;
+};
+
+struct evpn_imet_addr {
uint32_t eth_tag;
+ uint8_t ip_prefix_length;
struct ipaddr ip;
-#if 0
- union
- {
- uint8_t addr;
- struct in_addr v4_addr;
- struct in6_addr v6_addr;
- } ip;
-#endif
};
-#define IS_EVPN_PREFIX_IPADDR_NONE(evp) IS_IPADDR_NONE(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V4(evp) IS_IPADDR_V4(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V6(evp) IS_IPADDR_V6(&(evp)->prefix.ip)
+struct evpn_es_addr {
+ esi_t esi;
+ uint8_t ip_prefix_length;
+ struct ipaddr ip;
+};
+
+struct evpn_prefix_addr {
+ uint32_t eth_tag;
+ uint8_t ip_prefix_length;
+ struct ipaddr ip;
+};
+
+/* EVPN address (RFC 7432) */
+struct evpn_addr {
+ uint8_t route_type;
+ union {
+ struct evpn_ead_addr _ead_addr;
+ struct evpn_macip_addr _macip_addr;
+ struct evpn_imet_addr _imet_addr;
+ struct evpn_es_addr _es_addr;
+ struct evpn_prefix_addr _prefix_addr;
+ } u;
+#define ead_addr u._ead_addr
+#define macip_addr u._macip_addr
+#define imet_addr u._imet_addr
+#define es_addr u._es_addr
+#define prefix_addr u._prefix_addr
+};
/*
* A struct prefix contains an address family, a prefix length, and an
@@ -177,6 +207,39 @@ struct prefix_evpn {
struct evpn_addr prefix __attribute__((aligned(8)));
};
+static inline int is_evpn_prefix_ipaddr_none(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_NONE(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_NONE(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_NONE(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v4(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_V4(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_V4(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_V4(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_V6(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_V6(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_V6(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
/* Prefix for a generic pointer */
struct prefix_ptr {
uint8_t family;
diff --git a/lib/zclient.c b/lib/zclient.c
index cb39099fc2..05bd907589 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -975,8 +975,6 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putc(s, api->safi);
- if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
- stream_put(s, &(api->rmac), sizeof(struct ethaddr));
/* Put prefix information. */
stream_putc(s, api->prefix.family);
@@ -1061,6 +1059,11 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
api_nh->label_num
* sizeof(mpls_label_t));
}
+
+ /* Router MAC for EVPN routes. */
+ if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+ stream_put(s, &(api_nh->rmac),
+ sizeof(struct ethaddr));
}
}
@@ -1101,8 +1104,6 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETL(s, api->flags);
STREAM_GETC(s, api->message);
STREAM_GETC(s, api->safi);
- if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
- STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
/* Prefix. */
STREAM_GETC(s, api->prefix.family);
@@ -1212,6 +1213,11 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
api_nh->label_num
* sizeof(mpls_label_t));
}
+
+ /* Router MAC for EVPN routes. */
+ if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+ stream_get(&(api_nh->rmac), s,
+ sizeof(struct ethaddr));
}
}
diff --git a/lib/zclient.h b/lib/zclient.h
index 8d26b7fe59..c5eaf9c0fd 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -302,6 +302,8 @@ struct zapi_nexthop {
/* MPLS labels for BGP-LU or Segment Routing */
uint8_t label_num;
mpls_label_t labels[MPLS_MAX_LABELS];
+
+ struct ethaddr rmac;
};
/*
@@ -342,8 +344,6 @@ struct zapi_route {
vrf_id_t vrf_id;
uint32_t tableid;
-
- struct ethaddr rmac;
};
/* Zebra IPv4 route message API. */