diff --git a/lib/zclient.c b/lib/zclient.c index 25c6e2b8e5..51ebb56275 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4520,6 +4520,24 @@ static void zclient_event(enum zclient_event event, struct zclient *zclient) } } +enum zclient_send_status zclient_interface_set_arp(struct zclient *client, + struct interface *ifp, + bool arp_enable) +{ + struct stream *s; + + s = client->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_INTERFACE_SET_ARP, ifp->vrf->vrf_id); + + stream_putl(s, ifp->ifindex); + stream_putc(s, arp_enable); + + stream_putw_at(s, 0, stream_get_endp(s)); + return zclient_send_message(client); +} + enum zclient_send_status zclient_interface_set_master(struct zclient *client, struct interface *master, struct interface *slave) diff --git a/lib/zclient.h b/lib/zclient.h index 3027c2c378..1bf91064e2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -98,6 +98,7 @@ typedef enum { ZEBRA_INTERFACE_UP, ZEBRA_INTERFACE_DOWN, ZEBRA_INTERFACE_SET_MASTER, + ZEBRA_INTERFACE_SET_ARP, ZEBRA_INTERFACE_SET_PROTODOWN, ZEBRA_ROUTE_ADD, ZEBRA_ROUTE_DELETE, @@ -1036,6 +1037,9 @@ extern int zclient_read_header(struct stream *s, int sock, uint16_t *size, */ extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr); +extern enum zclient_send_status zclient_interface_set_arp(struct zclient *client, + struct interface *ifp, + bool arp_enable); extern enum zclient_send_status zclient_interface_set_master(struct zclient *client, struct interface *master, struct interface *slave); diff --git a/zebra/interface.c b/zebra/interface.c index 4c6fc8c36a..9be4b469e7 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -3662,6 +3662,27 @@ DEFUN (show_interface_desc_vrf_all, return CMD_SUCCESS; } +void if_arp(struct interface *ifp, bool enable) +{ + int ret; + + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) + return; + + if (enable) + ret = if_unset_flags(ifp, IFF_NOARP); + else + ret = if_set_flags(ifp, IFF_NOARP); + + if (ret < 0) { + zlog_debug("Can't %sset noarp flag on interface %s", + enable ? "" : "un", ifp->name); + return; + } + + if_refresh(ifp); +} + int if_multicast_set(struct interface *ifp) { struct zebra_if *if_data; diff --git a/zebra/interface.h b/zebra/interface.h index 62de2abc80..a96f2ec718 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -314,6 +314,7 @@ extern int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix, extern int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix); extern int if_shutdown(struct interface *ifp); extern int if_no_shutdown(struct interface *ifp); +extern void if_arp(struct interface *ifp, bool enable); extern int if_multicast_set(struct interface *ifp); extern int if_multicast_unset(struct interface *ifp); extern int if_linkdetect(struct interface *ifp, bool detect); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 296bf12bb5..76cabd1bf0 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3124,6 +3124,28 @@ stream_failure: } +static void zread_interface_set_arp(ZAPI_HANDLER_ARGS) +{ + struct stream *s = msg; + struct interface *ifp; + bool arp_enable; + vrf_id_t vrf_id = zvrf->vrf->vrf_id; + int ifindex; + + STREAM_GETL(s, ifindex); + STREAM_GETC(s, arp_enable); + ifp = if_lookup_by_index(ifindex, vrf_id); + + if (!ifp) + return; + + if_arp(ifp, arp_enable); + +stream_failure: + return; +} + + static void zread_vrf_label(ZAPI_HANDLER_ARGS) { struct interface *ifp; @@ -3905,6 +3927,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del, [ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection, [ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master, + [ZEBRA_INTERFACE_SET_ARP] = zread_interface_set_arp, [ZEBRA_PW_ADD] = zread_pseudowire, [ZEBRA_PW_DELETE] = zread_pseudowire, [ZEBRA_PW_SET] = zread_pseudowire,