diff options
-rw-r--r-- | lib/log.c | 1 | ||||
-rw-r--r-- | lib/zclient.c | 20 | ||||
-rw-r--r-- | lib/zclient.h | 4 | ||||
-rw-r--r-- | pimd/pim_zebra.c | 48 | ||||
-rw-r--r-- | zebra/if_netlink.c | 27 | ||||
-rw-r--r-- | zebra/rt.h | 3 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 3 | ||||
-rw-r--r-- | zebra/rt_socket.c | 6 | ||||
-rw-r--r-- | zebra/zserv.c | 28 |
9 files changed, 122 insertions, 18 deletions
@@ -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); |