summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/log.c1
-rw-r--r--lib/zclient.c20
-rw-r--r--lib/zclient.h4
-rw-r--r--pimd/pim_zebra.c48
-rw-r--r--zebra/if_netlink.c27
-rw-r--r--zebra/rt.h3
-rw-r--r--zebra/rt_netlink.c3
-rw-r--r--zebra/rt_socket.c6
-rw-r--r--zebra/zserv.c28
9 files changed, 122 insertions, 18 deletions
diff --git a/lib/log.c b/lib/log.c
index 28e086535..5adb06d28 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -857,6 +857,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_DELETE),
DESC_ENTRY(ZEBRA_INTERFACE_UP),
DESC_ENTRY(ZEBRA_INTERFACE_DOWN),
+ DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
diff --git a/lib/zclient.c b/lib/zclient.c
index a54d8749a..a6252af40 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2184,3 +2184,23 @@ void zclient_serv_path_set(char *path)
/* it seems that path is unix socket */
zclient_serv_path = path;
}
+
+void zclient_interface_set_master(struct zclient *client,
+ struct interface *master,
+ struct interface *slave)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
+
+ stream_putw(s, master->vrf_id);
+ stream_putl(s, master->ifindex);
+ stream_putw(s, slave->vrf_id);
+ stream_putl(s, slave->ifindex);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(client);
+}
diff --git a/lib/zclient.h b/lib/zclient.h
index efa5c32c1..435d26e2f 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -44,6 +44,7 @@ typedef enum {
ZEBRA_INTERFACE_ADDRESS_DELETE,
ZEBRA_INTERFACE_UP,
ZEBRA_INTERFACE_DOWN,
+ ZEBRA_INTERFACE_SET_MASTER,
ZEBRA_IPV4_ROUTE_ADD,
ZEBRA_IPV4_ROUTE_DELETE,
ZEBRA_IPV6_ROUTE_ADD,
@@ -311,6 +312,9 @@ extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size,
u_char *marker, u_char *version,
vrf_id_t *vrf_id, u_int16_t *cmd);
+extern void zclient_interface_set_master(struct zclient *client,
+ struct interface *master,
+ struct interface *slave);
extern struct interface *zebra_interface_add_read(struct stream *, vrf_id_t);
extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t);
extern struct connected *zebra_interface_address_read(int, struct stream *,
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 47b97339f..b86b68394 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -80,8 +80,8 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -113,8 +113,8 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -129,6 +129,7 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
+ uint32_t table_id;
/*
zebra api notifies interface up/down events by using the same call
@@ -140,8 +141,8 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -154,6 +155,23 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
pim_if_addr_add_all(ifp);
}
+ /*
+ * If we have a pimreg device callback and it's for a specific
+ * table set the master appropriately
+ */
+ if (sscanf(ifp->name, "pimreg%d", &table_id) == 1) {
+ struct vrf *vrf;
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if ((table_id == vrf->data.l.table_id)
+ && (ifp->vrf_id != vrf->vrf_id)) {
+ struct interface *master = if_lookup_by_name(
+ vrf->name, vrf->vrf_id);
+ zclient_interface_set_master(zclient, master,
+ ifp);
+ }
+ }
+ }
return 0;
}
@@ -172,8 +190,8 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d flags %ld metric %d mtu %d operative %d",
- __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+ "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
+ __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
}
@@ -252,11 +270,11 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
- zlog_debug("%s: %s connected IP address %s flags %u %s",
- __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags,
- CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
- ? "secondary"
- : "primary");
+ zlog_debug("%s: %s(%d) connected IP address %s flags %u %s",
+ __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
+ c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
+ ? "secondary"
+ : "primary");
#ifdef PIM_DEBUG_IFADDR_DUMP
dump_if_address(c->ifp);
@@ -327,8 +345,8 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
zlog_debug(
- "%s: %s disconnected IP address %s flags %u %s",
- __PRETTY_FUNCTION__, c->ifp->name, buf,
+ "%s: %s(%d) disconnected IP address %s flags %u %s",
+ __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags,
CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
? "secondary"
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index acec2db52..bd7673d6c 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -768,6 +768,33 @@ int interface_lookup_netlink(struct zebra_ns *zns)
return 0;
}
+int kernel_interface_set_master(struct interface *master,
+ struct interface *slave)
+{
+ 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 = slave->ifindex;
+
+ addattr_l(&req.n, sizeof req, IFLA_MASTER, &master->ifindex, 4);
+ addattr_l(&req.n, sizeof req, IFLA_LINK, &slave->ifindex, 4);
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
+}
+
/* Interface address modification. */
static int netlink_address(int cmd, int family, struct interface *ifp,
struct connected *ifc)
diff --git a/zebra/rt.h b/zebra/rt.h
index ead6a6c50..f5f0fa195 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -36,7 +36,8 @@ extern int kernel_route_rib(struct prefix *, struct prefix *,
extern int kernel_address_add_ipv4(struct interface *, struct connected *);
extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
extern int kernel_neigh_update(int, int, uint32_t, char *, int);
-
+extern int kernel_interface_set_master(struct interface *master,
+ struct interface *slave);
extern int kernel_add_lsp(zebra_lsp_t *);
extern int kernel_upd_lsp(zebra_lsp_t *);
extern int kernel_del_lsp(zebra_lsp_t *);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 73054594b..e4cf1a126 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1525,8 +1525,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
struct zebra_ns *zns = zvrf->zns;
mroute = mr;
- suc = netlink_request(RTNL_FAMILY_IPMR, RTM_GETROUTE,
- &zns->netlink_cmd);
+ suc = netlink_request_route(zns, RTNL_FAMILY_IPMR, RTM_GETROUTE);
if (suc < 0)
return suc;
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 683086f10..699fe6eb2 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -443,3 +443,9 @@ int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{
return 0;
}
+
+extern int kernel_interface_set_master(struct interface *master,
+ struct interface *slave)
+{
+ return 0;
+}
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 3bc5f83f6..ab46a1f29 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -55,6 +55,7 @@
#include "zebra/zebra_mroute.h"
#include "zebra/label_manager.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/rt.h"
/* Event list of zebra. */
enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
@@ -2164,6 +2165,31 @@ static void zebra_client_create(int sock)
zebra_vrf_update_all(client);
}
+static int zread_interface_set_master(struct zserv *client, int sock,
+ u_short length)
+{
+ struct interface *master;
+ struct interface *slave;
+ struct stream *s = client->ibuf;
+ int ifindex;
+ vrf_id_t vrf_id;
+
+ vrf_id = stream_getw(s);
+ ifindex = stream_getl(s);
+ master = if_lookup_by_index(ifindex, vrf_id);
+
+ vrf_id = stream_getw(s);
+ ifindex = stream_getl(s);
+ slave = if_lookup_by_index(ifindex, vrf_id);
+
+ if (!master || !slave)
+ return 0;
+
+ kernel_interface_set_master(master, slave);
+
+ return 1;
+}
+
/* Handler of zebra service request. */
static int zebra_client_read(struct thread *thread)
{
@@ -2406,6 +2432,8 @@ static int zebra_client_read(struct thread *thread)
break;
case ZEBRA_REMOTE_MACIP_DEL:
zebra_vxlan_remote_macip_del(client, sock, length, zvrf);
+ case ZEBRA_INTERFACE_SET_MASTER:
+ zread_interface_set_master(client, sock, length);
break;
default:
zlog_info("Zebra received unknown command %d", command);