+------------------------------------+-------+
| ZEBRA_OPAQUE_UNREGISTER | 109 |
+------------------------------------+-------+
+| ZEBRA_NEIGH_DISCOVER | 110 |
++------------------------------------+-------+
Dataplane batching
-=========================
+==================
Dataplane batching is an optimization feature that reduces the processing
time involved in the user space to kernel space transition for every message we
Remove a test zapi client session that was created with the
specified session id.
+
+.. index:: sharp neigh discover
+.. clicmd:: sharp neigh discover [vrf NAME] <A.B.C.D|X:X::X:X> IFNAME
+
+ Send an ARP/NDP request to trigger the addition of a neighbor in the ARP
+ table.
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES),
DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE),
DESC_ENTRY(ZEBRA_OPAQUE_REGISTER),
- DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER)};
+ DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER),
+ DESC_ENTRY(ZEBRA_NEIGH_DISCOVER)};
#undef DESC_ENTRY
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
stream_failure:
return 0;
}
+
+int zclient_send_neigh_discovery_req(struct zclient *zclient,
+ const struct interface *ifp,
+ const struct prefix *p)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
+ stream_putl(s, ifp->ifindex);
+
+ stream_putc(s, p->family);
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->u.prefix, prefix_blen(p));
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+ return zclient_send_message(zclient);
+}
ZEBRA_OPAQUE_MESSAGE,
ZEBRA_OPAQUE_REGISTER,
ZEBRA_OPAQUE_UNREGISTER,
+ ZEBRA_NEIGH_DISCOVER,
} zebra_message_types_t;
enum zebra_error_types {
*/
extern int zclient_send_hello(struct zclient *client);
+extern int zclient_send_neigh_discovery_req(struct zclient *zclient,
+ const struct interface *ifp,
+ const struct prefix *p);
+
#ifdef __cplusplus
}
#endif
case DPLANE_OP_NEIGH_DELETE:
case DPLANE_OP_VTEP_ADD:
case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
return netlink_put_neigh_update_msg(bth, ctx);
case DPLANE_OP_RULE_ADD:
case DPLANE_OP_NEIGH_DELETE:
case DPLANE_OP_VTEP_ADD:
case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
res = kernel_neigh_update_ctx(ctx);
break;
flags |= NTF_EXT_LEARNED;
if (dplane_flags & DPLANE_NTF_ROUTER)
flags |= NTF_ROUTER;
+ if (dplane_flags & DPLANE_NTF_USE)
+ flags |= NTF_USE;
return flags;
}
state |= NUD_NOARP;
if (dplane_state & DPLANE_NUD_PROBE)
state |= NUD_PROBE;
+ if (dplane_state & DPLANE_NUD_INCOMPLETE)
+ state |= NUD_INCOMPLETE;
return state;
}
switch (dplane_ctx_get_op(ctx)) {
case DPLANE_OP_NEIGH_INSTALL:
case DPLANE_OP_NEIGH_UPDATE:
+ case DPLANE_OP_NEIGH_DISCOVER:
ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH, buf, buflen);
break;
case DPLANE_OP_NEIGH_DELETE:
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)
{
[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;
};
/*
- * EVPN neighbor info for the dataplane
+ * Neighbor info for the dataplane
*/
struct dplane_neigh_info {
struct ipaddr ip_addr;
case DPLANE_OP_RULE_ADD:
case DPLANE_OP_RULE_DELETE:
case DPLANE_OP_RULE_UPDATE:
+ case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_NONE:
break;
}
case DPLANE_OP_RULE_UPDATE:
ret = "RULE_UPDATE";
break;
+
+ case DPLANE_OP_NEIGH_DISCOVER:
+ ret = "NEIGH_DISCOVER";
+ break;
}
return ret;
return result;
}
+enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
+ const struct ipaddr *ip)
+{
+ enum zebra_dplane_result result;
+
+ result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL, ip,
+ DPLANE_NTF_USE, DPLANE_NUD_INCOMPLETE, 0);
+
+ return result;
+}
+
/*
- * Common helper api for evpn neighbor updates
+ * Common helper api for neighbor updates
*/
static enum zebra_dplane_result
neigh_update_internal(enum dplane_op_e op,
char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
zlog_debug("init neigh ctx %s: ifp %s, mac %s, ip %s",
- dplane_op2str(op),
+ dplane_op2str(op), ifp->name,
prefix_mac2str(mac, buf1, sizeof(buf1)),
- ifp->name,
ipaddr2str(ip, buf2, sizeof(buf2)));
}
out_max = atomic_load_explicit(&prov->dp_out_max,
memory_order_relaxed);
- vty_out(vty, "%s (%u): in: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q_max: %"PRIu64"\n",
+ vty_out(vty,
+ "%s (%u): in: %" PRIu64 ", q_max: %" PRIu64
+ ", out: %" PRIu64 ", q_max: %" PRIu64 "\n",
prov->dp_name, prov->dp_id, in, in_max, out, out_max);
DPLANE_LOCK();
case DPLANE_OP_NEIGH_DELETE:
case DPLANE_OP_VTEP_ADD:
case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
ipaddr2str(dplane_ctx_neigh_get_ipaddr(ctx), buf,
sizeof(buf));
case DPLANE_OP_NEIGH_DELETE:
case DPLANE_OP_VTEP_ADD:
case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
atomic_fetch_add_explicit(&zdplane_info.dg_neigh_errors,
1, memory_order_relaxed);
DPLANE_OP_RULE_ADD,
DPLANE_OP_RULE_DELETE,
DPLANE_OP_RULE_UPDATE,
+
+ /* Link layer address discovery */
+ DPLANE_OP_NEIGH_DISCOVER,
};
/*
/* Neighbor cache flags */
#define DPLANE_NTF_EXT_LEARNED 0x01
#define DPLANE_NTF_ROUTER 0x02
+#define DPLANE_NTF_USE 0x04
/* Neighbor cache states */
#define DPLANE_NUD_REACHABLE 0x01
#define DPLANE_NUD_STALE 0x02
#define DPLANE_NUD_NOARP 0x04
#define DPLANE_NUD_PROBE 0x08
+#define DPLANE_NUD_INCOMPLETE 0x10
/* MAC update flags - dplane_mac_info.update_flags */
#define DPLANE_MAC_REMOTE (1 << 0)
const struct in_addr *ip,
vni_t vni);
+/*
+ * Enqueue a neighbour discovery request for the dataplane.
+ */
+enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
+ const struct ipaddr *ip);
+
/* Forward ref of zebra_pbr_rule */
struct zebra_pbr_rule;
case DPLANE_OP_RULE_ADD:
case DPLANE_OP_RULE_DELETE:
case DPLANE_OP_RULE_UPDATE:
+ case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_NONE:
break;
}
case DPLANE_OP_NEIGH_DELETE:
case DPLANE_OP_VTEP_ADD:
case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_NONE:
/* Don't expect this: just return the struct? */
dplane_ctx_fini(&ctx);