summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/zclient.c19
-rw-r--r--lib/zclient.h4
-rw-r--r--vrrpd/vrrp.c4
-rw-r--r--vrrpd/vrrp_zebra.c6
-rw-r--r--vrrpd/vrrp_zebra.h6
-rw-r--r--zebra/if_netlink.c26
-rw-r--r--zebra/if_netlink.h14
-rw-r--r--zebra/interface.c6
-rw-r--r--zebra/interface.h1
-rw-r--r--zebra/zapi_msg.c25
10 files changed, 110 insertions, 1 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 96a78efad6..6647a1ab18 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -555,6 +555,25 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
zclient_send_message(zclient);
}
+int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
+ struct interface *ifp, bool down)
+{
+ struct stream *s;
+
+ if (zclient->sock < 0)
+ return -1;
+
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s, ZEBRA_INTERFACE_SET_PROTODOWN, vrf_id);
+ stream_putl(s, ifp->ifindex);
+ stream_putc(s, !!down);
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(zclient);
+
+ return 0;
+}
+
/* Make connection to zebra daemon. */
int zclient_start(struct zclient *zclient)
{
diff --git a/lib/zclient.h b/lib/zclient.h
index c46d63bfab..09f0acad84 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -76,6 +76,7 @@ typedef enum {
ZEBRA_INTERFACE_UP,
ZEBRA_INTERFACE_DOWN,
ZEBRA_INTERFACE_SET_MASTER,
+ ZEBRA_INTERFACE_SET_PROTODOWN,
ZEBRA_ROUTE_ADD,
ZEBRA_ROUTE_DELETE,
ZEBRA_ROUTE_NOTIFY_OWNER,
@@ -466,6 +467,9 @@ extern void zclient_send_interface_radv_req(struct zclient *zclient,
vrf_id_t vrf_id,
struct interface *ifp, int enable,
int ra_interval);
+extern int zclient_send_interface_protodown(struct zclient *zclient,
+ vrf_id_t vrf_id,
+ struct interface *ifp, bool down);
/* Send redistribute command to zebra daemon. Do not update zclient state. */
extern int zebra_redistribute_send(int command, struct zclient *, afi_t,
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index e5018d5853..76f8dfea5d 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -1028,6 +1028,8 @@ static void vrrp_change_state_master(struct vrrp_router *r)
/* Enable ND Router Advertisements */
if (r->family == AF_INET6)
vrrp_zebra_radv_set(r, true);
+
+ vrrp_zclient_send_interface_protodown(r->mvl_ifp, false);
}
/*
@@ -1041,6 +1043,8 @@ static void vrrp_change_state_backup(struct vrrp_router *r)
/* Disable ND Router Advertisements */
if (r->family == AF_INET6)
vrrp_zebra_radv_set(r, false);
+
+ vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
}
/*
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index 1bd5aa013f..c41915cbd9 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -226,6 +226,12 @@ void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
enable, VRRP_RADV_INT);
}
+int vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
+{
+ return zclient_send_interface_protodown(zclient, VRF_DEFAULT, ifp,
+ down);
+}
+
void vrrp_zebra_init(void)
{
/* Socket for receiving updates from Zebra daemon */
diff --git a/vrrpd/vrrp_zebra.h b/vrrpd/vrrp_zebra.h
index 5e8ff09543..84bcba23c1 100644
--- a/vrrpd/vrrp_zebra.h
+++ b/vrrpd/vrrp_zebra.h
@@ -20,7 +20,13 @@
#ifndef __VRRP_ZEBRA_H__
#define __VRRP_ZEBRA_H__
+#include <zebra.h>
+
+#include "lib/if.h"
+
extern void vrrp_zebra_init(void);
extern void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable);
+extern int vrrp_zclient_send_interface_protodown(struct interface *ifp,
+ bool down);
#endif /* __VRRP_ZEBRA_H__ */
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index ce0834f190..e7d988cd9f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1396,6 +1396,32 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
}
+int netlink_protodown(struct interface *ifp, bool down)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifa;
+ char buf[NL_PKT_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof req);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_SETLINK;
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+
+ req.ifa.ifi_index = ifp->ifindex;
+
+ addattr_l(&req.n, sizeof req, IFLA_PROTO_DOWN, &down, 4);
+ addattr_l(&req.n, sizeof req, IFLA_LINK, &ifp->ifindex, 4);
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
+}
+
/* Interface information read by netlink. */
void interface_list(struct zebra_ns *zns)
{
diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h
index 710fd52558..29fd2aca35 100644
--- a/zebra/if_netlink.h
+++ b/zebra/if_netlink.h
@@ -32,6 +32,20 @@ extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
extern int interface_lookup_netlink(struct zebra_ns *zns);
+/*
+ * Set protodown status of interface.
+ *
+ * ifp
+ * Interface to set protodown on.
+ *
+ * down
+ * If true, set protodown on. If false, set protodown off.
+ *
+ * Returns:
+ * 0
+ */
+int netlink_protodown(struct interface *ifp, bool down);
+
#ifdef __cplusplus
}
#endif
diff --git a/zebra/interface.c b/zebra/interface.c
index b0ddcaf8bc..2ed8a82000 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -47,6 +47,7 @@
#include "zebra/irdp.h"
#include "zebra/zebra_ptm.h"
#include "zebra/rt_netlink.h"
+#include "zebra/if_netlink.h"
#include "zebra/interface.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_errors.h"
@@ -1063,7 +1064,10 @@ void zebra_if_update_all_links(void)
}
}
-
+void zebra_if_set_protodown(struct interface *ifp, bool down)
+{
+ netlink_protodown(ifp, down);
+}
/* Output prefix string to vty. */
static int prefix_vty_out(struct vty *vty, struct prefix *p)
diff --git a/zebra/interface.h b/zebra/interface.h
index bbb5445cc6..6a3914451a 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -422,6 +422,7 @@ extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id);
extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
ns_id_t ns_id);
extern void zebra_if_update_all_links(void);
+extern void zebra_if_set_protodown(struct interface *ifp, bool down);
extern void vrf_add_update(struct vrf *vrfp);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 03b9653ce6..a497331702 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1336,6 +1336,30 @@ static void zread_interface_delete(ZAPI_HANDLER_ARGS)
{
}
+/*
+ * Handle message requesting interface be set up or down.
+ */
+static void zread_interface_set_protodown(ZAPI_HANDLER_ARGS)
+{
+ ifindex_t ifindex;
+ struct interface *ifp;
+ char down;
+
+ STREAM_GETL(msg, ifindex);
+ STREAM_GETC(msg, down);
+
+ /* set ifdown */
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
+ zlog_info("Setting interface %s (%u): protodown %s", ifp->name, ifindex,
+ down ? "on" : "off");
+
+ zebra_if_set_protodown(ifp, down);
+
+stream_failure:
+ return;
+}
+
+
void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
const unsigned int nexthop_num)
{
@@ -2412,6 +2436,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
[ZEBRA_INTERFACE_ADD] = zread_interface_add,
[ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
+ [ZEBRA_INTERFACE_SET_PROTODOWN] = zread_interface_set_protodown,
[ZEBRA_ROUTE_ADD] = zread_route_add,
[ZEBRA_ROUTE_DELETE] = zread_route_del,
[ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,