diff options
| -rw-r--r-- | doc/developer/zebra.rst | 4 | ||||
| -rw-r--r-- | doc/user/sharp.rst | 6 | ||||
| -rw-r--r-- | lib/log.c | 3 | ||||
| -rw-r--r-- | lib/zclient.c | 20 | ||||
| -rw-r--r-- | lib/zclient.h | 5 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 14 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.c | 5 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.h | 4 | ||||
| -rw-r--r-- | sharpd/sharp_vty.c | 46 | ||||
| -rw-r--r-- | sharpd/sharp_zebra.c | 5 | ||||
| -rw-r--r-- | sharpd/sharp_zebra.h | 3 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 1 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 1 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 5 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 39 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 29 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 11 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 1 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 1 |
19 files changed, 182 insertions, 21 deletions
diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst index edd8b9ae29..d51cbc9a14 100644 --- a/doc/developer/zebra.rst +++ b/doc/developer/zebra.rst @@ -382,9 +382,11 @@ Zebra Protocol Commands +------------------------------------+-------+ | 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 diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index 5a27be22b9..57ef141c7e 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -138,3 +138,9 @@ keyword. At present, no sharp commands will be preserved in the config. 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. @@ -451,7 +451,8 @@ static const struct zebra_desc_table command_types[] = { 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", '?'}; diff --git a/lib/zclient.c b/lib/zclient.c index 6449fe15b9..808aa18bbe 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3953,3 +3953,23 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api) 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); +} diff --git a/lib/zclient.h b/lib/zclient.h index bcdae85823..dab384d5ec 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -214,6 +214,7 @@ typedef enum { ZEBRA_OPAQUE_MESSAGE, ZEBRA_OPAQUE_REGISTER, ZEBRA_OPAQUE_UNREGISTER, + ZEBRA_NEIGH_DISCOVER, } zebra_message_types_t; enum zebra_error_types { @@ -956,6 +957,10 @@ enum zapi_opaque_registry { */ 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 diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index b0dd5c6fc2..49cd42d030 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -53,6 +53,7 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_dump.h" #include "ospfd/ospf_errors.h" +#include "ospfd/ospf_zebra.h" /* * OSPF Fragmentation / fragmented writes @@ -4319,21 +4320,10 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi) * punt-to-CPU set on them. This may overload the CPU control path that * can be avoided if the MAC was known apriori. */ -#define OSPF_PING_NBR_STR_MAX (BUFSIZ) void ospf_proactively_arp(struct ospf_neighbor *nbr) { - char ping_nbr[OSPF_PING_NBR_STR_MAX]; - int ret; - if (!nbr) return; - snprintf(ping_nbr, sizeof(ping_nbr), - "ping -c 1 -I %s %s > /dev/null 2>&1 &", nbr->oi->ifp->name, - inet_ntoa(nbr->address.u.prefix4)); - - ret = system(ping_nbr); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("Executed %s %s", ping_nbr, - ((ret == 0) ? "successfully" : "but failed")); + ospf_zebra_send_arp(nbr->oi->ifp, &nbr->address); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 84bdb9ec5b..2b8769a4a8 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1741,3 +1741,8 @@ void ospf_zebra_init(struct thread_master *master, unsigned short instance) prefix_list_add_hook(ospf_prefix_list_update); prefix_list_delete_hook(ospf_prefix_list_update); } + +void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p) +{ + zclient_send_neigh_discovery_req(zclient, ifp, p); +} diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 80abf62369..6a79f39fa4 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -41,6 +41,7 @@ struct ospf_distance { }; /* Prototypes */ +struct ospf_route; extern void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *, struct ospf_route *); extern void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *, @@ -98,4 +99,7 @@ bool ospf_external_default_routemap_apply_walk( int ospf_external_info_apply_default_routemap(struct ospf *ospf, struct external_info *ei, struct external_info *default_ei); + +extern void ospf_zebra_send_arp(const struct interface *ifp, + const struct prefix *p); #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 049b8475e4..d390ea8192 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -649,6 +649,51 @@ DEFPY (send_opaque_reg, return CMD_SUCCESS; } +DEFPY (neigh_discover, + neigh_discover_cmd, + "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname", + SHARP_STR + "Discover neighbours\n" + "Send an ARP/NDP request\n" + VRF_CMD_HELP_STR + "v4 Destination address\n" + "v6 Destination address\n" + "Interface name\n") +{ + struct vrf *vrf; + struct interface *ifp; + struct prefix prefix; + + memset(&prefix, 0, sizeof(prefix)); + + if (dst4.s_addr != 0) { + prefix.family = AF_INET; + prefix.prefixlen = 32; + prefix.u.prefix4 = dst4; + } else { + prefix.family = AF_INET6; + prefix.prefixlen = 128; + prefix.u.prefix6 = dst6; + } + + vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME); + if (!vrf) { + vty_out(vty, "The vrf NAME specified: %s does not exist\n", + vrf_name ? vrf_name : VRF_DEFAULT_NAME); + return CMD_WARNING; + } + + ifp = if_lookup_by_name_vrf(ifname, vrf); + if (ifp == NULL) { + vty_out(vty, "%% Can't find interface %s\n", ifname); + return CMD_WARNING; + } + + sharp_zebra_send_arp(ifp, &prefix); + + return CMD_SUCCESS; +} + void sharp_vty_init(void) { install_element(ENABLE_NODE, &install_routes_data_dump_cmd); @@ -666,6 +711,7 @@ void sharp_vty_init(void) install_element(ENABLE_NODE, &send_opaque_cmd); install_element(ENABLE_NODE, &send_opaque_unicast_cmd); install_element(ENABLE_NODE, &send_opaque_reg_cmd); + install_element(ENABLE_NODE, &neigh_discover_cmd); install_element(VIEW_NODE, &show_debugging_sharpd_cmd); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index e0f16d71f5..08f5a07b7e 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -663,6 +663,11 @@ void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance, } +void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p) +{ + zclient_send_neigh_discovery_req(zclient, ifp, p); +} + void sharp_zebra_init(void) { struct zclient_options opt = {.receive_notify = true}; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index e40585aa6a..0a44fa694f 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -58,4 +58,7 @@ void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance, void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance, uint32_t session_id, uint32_t type); +extern void sharp_zebra_send_arp(const struct interface *ifp, + const struct prefix *p); + #endif diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index b04076b945..d0c1bc812d 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1417,6 +1417,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth, 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: diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 9e56e2988d..4c29b999f0 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1526,6 +1526,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list) 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; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 190af3f59d..4a6839d3b1 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -147,6 +147,8 @@ static uint8_t neigh_flags_to_netlink(uint8_t dplane_flags) flags |= NTF_EXT_LEARNED; if (dplane_flags & DPLANE_NTF_ROUTER) flags |= NTF_ROUTER; + if (dplane_flags & DPLANE_NTF_USE) + flags |= NTF_USE; return flags; } @@ -166,6 +168,8 @@ static uint16_t neigh_state_to_netlink(uint16_t dplane_state) state |= NUD_NOARP; if (dplane_state & DPLANE_NUD_PROBE) state |= NUD_PROBE; + if (dplane_state & DPLANE_NUD_INCOMPLETE) + state |= NUD_INCOMPLETE; return state; } @@ -3631,6 +3635,7 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx, 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: diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 17114f820c..fbed99dc59 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2962,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) { @@ -3065,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; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index d34e1433ce..8ab7a7f5bc 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -185,7 +185,7 @@ struct dplane_mac_info { }; /* - * EVPN neighbor info for the dataplane + * Neighbor info for the dataplane */ struct dplane_neigh_info { struct ipaddr ip_addr; @@ -607,6 +607,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) 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; } @@ -839,6 +840,10 @@ const char *dplane_op2str(enum dplane_op_e op) case DPLANE_OP_RULE_UPDATE: ret = "RULE_UPDATE"; break; + + case DPLANE_OP_NEIGH_DISCOVER: + ret = "NEIGH_DISCOVER"; + break; } return ret; @@ -3223,8 +3228,19 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp, 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, @@ -3243,9 +3259,8 @@ 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))); } @@ -3446,7 +3461,9 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) 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(); @@ -3780,6 +3797,7 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx) 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)); @@ -3886,6 +3904,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx) 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); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 3b5eda2486..c68a617f38 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -149,6 +149,9 @@ enum dplane_op_e { DPLANE_OP_RULE_ADD, DPLANE_OP_RULE_DELETE, DPLANE_OP_RULE_UPDATE, + + /* Link layer address discovery */ + DPLANE_OP_NEIGH_DISCOVER, }; /* @@ -160,12 +163,14 @@ enum dplane_op_e { /* 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) @@ -572,6 +577,12 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp, 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; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 1c5b843539..b8faaa43fd 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2663,6 +2663,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) 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; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 55dccc4a12..d1d56f2cdb 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3764,6 +3764,7 @@ static int rib_process_dplane_results(struct thread *thread) 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); |
