From: Donald Sharp Date: Tue, 13 Jun 2017 12:59:32 +0000 (-0400) Subject: lib, pimd, zebra: Allow pim to set pimregX into appropriate vrf X-Git-Tag: frr-4.0-dev~468^2~54 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e0ae31b88690aa93159a018e383e4e6ba6dc9937;p=mirror%2Ffrr.git lib, pimd, zebra: Allow pim to set pimregX into appropriate vrf The pimregX devices when created by the kernel are put into the default vrf. When pim gets the callback that the device exists, check to see if it is a pimregX device and if so move it into the appropriate vrf. Signed-off-by: Donald Sharp --- diff --git a/lib/log.c b/lib/log.c index 28e0865354..5adb06d28c 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 a54d8749a3..a6252af403 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 efa5c32c16..435d26e2f9 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 47b97339f0..b86b683948 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 acec2db526..bd7673d6c8 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 ead6a6c508..f5f0fa195b 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 73054594b7..e4cf1a1261 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 683086f109..699fe6eb24 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 3bc5f83f64..ab46a1f29f 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);