summaryrefslogtreecommitdiff
path: root/zebra/zapi_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zapi_msg.c')
-rw-r--r--zebra/zapi_msg.c335
1 files changed, 299 insertions, 36 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index dc7c595d26..285f28ccec 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -51,6 +51,7 @@
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_mroute.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_evpn_mh.h"
#include "zebra/rt.h"
#include "zebra/zebra_pbr.h"
#include "zebra/table_manager.h"
@@ -59,6 +60,7 @@
#include "zebra/zebra_mlag.h"
#include "zebra/connected.h"
#include "zebra/zebra_opaque.h"
+#include "zebra/zebra_srte.h"
/* Encoding helpers -------------------------------------------------------- */
@@ -729,9 +731,10 @@ static int route_notify_internal(const struct prefix *p, int type,
char buff[PREFIX_STRLEN];
zlog_debug(
- "Not Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
- type, prefix2str(p, buff, sizeof(buff)),
- table_id, note, vrf_id);
+ "Not Notifying Owner: %s about prefix %s(%u) %d vrf: %u",
+ zebra_route_string(type),
+ prefix2str(p, buff, sizeof(buff)), table_id,
+ note, vrf_id);
}
return 0;
}
@@ -739,9 +742,10 @@ static int route_notify_internal(const struct prefix *p, int type,
if (IS_ZEBRA_DEBUG_PACKET) {
char buff[PREFIX_STRLEN];
- zlog_debug("Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
- type, prefix2str(p, buff, sizeof(buff)),
- table_id, note, vrf_id);
+ zlog_debug("Notifying Owner: %s about prefix %s(%u) %d vrf: %u",
+ zebra_route_string(type),
+ prefix2str(p, buff, sizeof(buff)), table_id, note,
+ vrf_id);
}
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
@@ -904,17 +908,18 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
zserv_send_message(client, s);
}
-/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
-int zsend_router_id_update(struct zserv *client, struct prefix *p,
+/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
+int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
vrf_id_t vrf_id)
{
int blen;
+ struct stream *s;
/* Check this client need interface information. */
- if (!vrf_bitmap_check(client->ridinfo, vrf_id))
+ if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id))
return 0;
- struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
/* Message type. */
zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
@@ -1073,7 +1078,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
s = msg;
- client->nh_reg_time = monotime(NULL);
+ if (!client->nh_reg_time)
+ client->nh_reg_time = monotime(NULL);
while (l < hdr->length) {
STREAM_GETC(s, flags);
@@ -1416,6 +1422,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re,
struct nexthop *nexthop = NULL;
struct ipaddr vtep_ip;
struct interface *ifp;
+ int i;
char nhbuf[INET6_ADDRSTRLEN] = "";
switch (api_nh->type) {
@@ -1521,17 +1528,36 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re,
nexthop->weight = api_nh->weight;
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
- if (api_nh->backup_idx < api->backup_nexthop_num) {
- /* Capture backup info */
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
- nexthop->backup_idx = api_nh->backup_idx;
- } else {
- /* Warn about invalid backup index */
+ /* Validate count */
+ if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: invalid backup nh idx %d",
- __func__, api_nh->backup_idx);
+ zlog_debug("%s: invalid backup nh count %d",
+ __func__, api_nh->backup_num);
+ nexthop_free(nexthop);
+ nexthop = NULL;
+ goto done;
+ }
+
+ /* Copy backup info */
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
+ nexthop->backup_num = api_nh->backup_num;
+
+ for (i = 0; i < api_nh->backup_num; i++) {
+ /* Validate backup index */
+ if (api_nh->backup_idx[i] < api->backup_nexthop_num) {
+ nexthop->backup_idx[i] = api_nh->backup_idx[i];
+ } else {
+ if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: invalid backup nh idx %d",
+ __func__,
+ api_nh->backup_idx[i]);
+ nexthop_free(nexthop);
+ nexthop = NULL;
+ goto done;
+ }
}
}
+
done:
return nexthop;
}
@@ -1627,6 +1653,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
return;
}
+ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) {
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
+ nexthop->srte_color = api_nh->srte_color;
+ }
+
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
@@ -1703,7 +1734,12 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
__func__, nhbuf);
}
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
- nexthop->backup_idx = 0;
+ nexthop->backup_num = 0;
+ }
+
+ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) {
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
+ nexthop->srte_color = api_nh->srte_color;
}
/* MPLS labels for BGP-LU or Segment Routing */
@@ -1874,20 +1910,48 @@ stream_failure:
/* Register zebra server router-id information. Send current router-id */
static void zread_router_id_add(ZAPI_HANDLER_ARGS)
{
+ afi_t afi;
+
struct prefix p;
+ STREAM_GETW(msg, afi);
+
+ if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+ zlog_warn(
+ "Invalid AFI %u while registering for router ID notifications",
+ afi);
+ goto stream_failure;
+ }
+
/* Router-id information is needed. */
- vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf));
+ vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf));
+
+ router_id_get(afi, &p, zvrf);
- router_id_get(&p, zvrf_id(zvrf));
+ zsend_router_id_update(client, afi, &p, zvrf_id(zvrf));
- zsend_router_id_update(client, &p, zvrf_id(zvrf));
+stream_failure:
+ return;
}
/* Unregister zebra server router-id information. */
static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
{
- vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
+ afi_t afi;
+
+ STREAM_GETW(msg, afi);
+
+ if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+ zlog_warn(
+ "Invalid AFI %u while unregistering from router ID notifications",
+ afi);
+ goto stream_failure;
+ }
+
+ vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
+
+stream_failure:
+ return;
}
static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
@@ -1976,8 +2040,58 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
+ }
+}
+
+/*
+ * Validate incoming zapi mpls lsp / labels message
+ */
+static int zapi_labels_validate(const struct zapi_labels *zl)
+{
+ int ret = -1;
+ int i, j, idx;
+ uint32_t bits[8];
+ uint32_t ival;
+ const struct zapi_nexthop *znh;
+
+ /* Validate backup info: no duplicates for a single primary */
+ if (zl->backup_nexthop_num == 0) {
+ ret = 0;
+ goto done;
+ }
+
+ for (j = 0; j < zl->nexthop_num; j++) {
+ znh = &zl->nexthops[j];
+
+ memset(bits, 0, sizeof(bits));
+
+ for (i = 0; i < znh->backup_num; i++) {
+ idx = znh->backup_idx[i] / 32;
+
+ ival = 1 << znh->backup_idx[i] % 32;
+
+ /* Check whether value is already used */
+ if (ival & bits[idx]) {
+ /* Fail */
+
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d",
+ __func__,
+ znh->backup_idx[i]);
+ goto done;
+ }
+
+ /* Mark index value */
+ bits[idx] |= ival;
+ }
}
- vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
+
+ ret = 0;
+
+done:
+
+ return ret;
}
/*
@@ -2006,6 +2120,10 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
if (!mpls_enabled)
return;
+ /* Validate; will debug on failure */
+ if (zapi_labels_validate(&zl) < 0)
+ return;
+
ret = mpls_zapi_labels_process(true, zvrf, &zl);
if (ret < 0) {
if (IS_ZEBRA_DEBUG_RECV)
@@ -2087,6 +2205,10 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
if (!mpls_enabled)
return;
+ /* Validate; will debug on failure */
+ if (zapi_labels_validate(&zl) < 0)
+ return;
+
/* This removes everything, then re-adds from the client's
* zapi message. Since the LSP will be processed later, on this
* this same pthread, all of the changes will 'appear' at once.
@@ -2099,6 +2221,107 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
mpls_zapi_labels_process(true, zvrf, &zl);
}
+static void zread_sr_policy_set(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ struct zapi_sr_policy zp;
+ struct zapi_srte_tunnel *zt;
+ struct zebra_sr_policy *policy;
+
+ /* Get input stream. */
+ s = msg;
+ if (zapi_sr_policy_decode(s, &zp) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_sr_policy sent",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+ zt = &zp.segment_list;
+ if (zt->label_num < 1) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug(
+ "%s: SR-TE tunnel must contain at least one label",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ if (!mpls_enabled)
+ return;
+
+ policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
+ if (!policy)
+ policy = zebra_sr_policy_add(zp.color, &zp.endpoint, zp.name);
+ /* TODO: per-VRF list of SR-TE policies. */
+ policy->zvrf = zvrf;
+
+ zebra_sr_policy_validate(policy, &zp.segment_list);
+}
+
+static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ struct zapi_sr_policy zp;
+ struct zebra_sr_policy *policy;
+
+ /* Get input stream. */
+ s = msg;
+ if (zapi_sr_policy_decode(s, &zp) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_sr_policy sent",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ if (!mpls_enabled)
+ return;
+
+ policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
+ if (!policy) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to find SR-TE policy",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ zebra_sr_policy_del(policy);
+}
+
+int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
+ char *name, int status)
+{
+ struct zserv *client;
+ struct stream *s;
+
+ client = zserv_find_client(ZEBRA_ROUTE_SRTE, 0);
+ if (!client) {
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug(
+ "Not notifying pathd about policy %s"
+ " status change to %d",
+ name, status);
+ return 0;
+ }
+
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug(
+ "Notifying pathd about policy %s status change"
+ " to %d",
+ name, status);
+
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_SR_POLICY_NOTIFY_STATUS, VRF_DEFAULT);
+ stream_putl(s, color);
+ stream_put_ipaddr(s, endpoint);
+ stream_write(s, name, SRTE_POLICY_NAME_MAX_LENGTH);
+ stream_putl(s, status);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zserv_send_message(client, s);
+}
+
/* Send response to a table manager connect request to client */
static void zread_table_manager_connect(struct zserv *client,
struct stream *msg, vrf_id_t vrf_id)
@@ -2526,6 +2749,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s,
prefix_blen(&zpr.rule.filter.dst_ip));
STREAM_GETW(s, zpr.rule.filter.dst_port);
+ STREAM_GETC(s, zpr.rule.filter.dsfield);
STREAM_GETL(s, zpr.rule.filter.fwmark);
STREAM_GETL(s, zpr.rule.action.table);
STREAM_GETL(s, zpr.rule.ifindex);
@@ -2556,14 +2780,16 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
if (zpr.rule.filter.dst_port)
zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT;
+ if (zpr.rule.filter.dsfield)
+ zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD;
+
if (zpr.rule.filter.fwmark)
zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK;
if (!(zpr.rule.filter.src_ip.family == AF_INET
|| zpr.rule.filter.src_ip.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR source IP family: %s (%" PRIu8
- ")",
+ "Unsupported PBR source IP family: %s (%hhu)",
family2str(zpr.rule.filter.src_ip.family),
zpr.rule.filter.src_ip.family);
return;
@@ -2571,8 +2797,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
if (!(zpr.rule.filter.dst_ip.family == AF_INET
|| zpr.rule.filter.dst_ip.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR destination IP family: %s (%" PRIu8
- ")",
+ "Unsupported PBR destination IP family: %s (%hhu)",
family2str(zpr.rule.filter.dst_ip.family),
zpr.rule.filter.dst_ip.family);
return;
@@ -2667,16 +2892,14 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
if (!(zpi.dst.family == AF_INET
|| zpi.dst.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR destination IP family: %s (%" PRIu8
- ")",
+ "Unsupported PBR destination IP family: %s (%hhu)",
family2str(zpi.dst.family), zpi.dst.family);
goto stream_failure;
}
if (!(zpi.src.family == AF_INET
|| zpi.src.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR source IP family: %s (%" PRIu8
- ")",
+ "Unsupported PBR source IP family: %s (%hhu)",
family2str(zpi.src.family), zpi.src.family);
goto stream_failure;
}
@@ -2739,6 +2962,41 @@ stream_failure:
return;
}
+static inline void zread_neigh_discover(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ ifindex_t ifindex;
+ struct interface *ifp;
+ struct prefix p;
+ struct ipaddr ip;
+
+ s = msg;
+
+ STREAM_GETL(s, ifindex);
+
+ ifp = if_lookup_by_index_per_ns(zvrf->zns, ifindex);
+ if (!ifp) {
+ zlog_debug("Failed to lookup ifindex: %u", ifindex);
+ return;
+ }
+
+ STREAM_GETC(s, p.family);
+ STREAM_GETC(s, p.prefixlen);
+ STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
+
+ if (p.family == AF_INET)
+ SET_IPADDR_V4(&ip);
+ else
+ SET_IPADDR_V6(&ip);
+
+ memcpy(&ip.ip.addr, &p.u.prefix, prefix_blen(&p));
+
+ dplane_neigh_discover(ifp, &ip);
+
+stream_failure:
+ return;
+}
+
static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
struct zmsghdr *bad_hdr)
{
@@ -2798,6 +3056,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
[ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
[ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable,
+ [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set,
+ [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete,
[ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,
[ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete,
[ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,
@@ -2812,6 +3072,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ADVERTISE_SVI_MACIP] = zebra_vxlan_advertise_svi_macip,
[ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet,
[ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
+ [ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es,
+ [ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es,
[ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
[ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
[ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
@@ -2838,8 +3100,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
- [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities
-};
+ [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
+ [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover};
#if defined(HANDLE_ZAPI_FUZZING)
extern struct zebra_privs_t zserv_privs;
@@ -2890,7 +3152,8 @@ void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo)
zapi_parse_header(msg, &hdr);
- if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+ if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV
+ && IS_ZEBRA_DEBUG_DETAIL)
zserv_log_message(NULL, msg, &hdr);
#if defined(HANDLE_ZAPI_FUZZING)