zebra: Start abstraction of zebra_dplane_info for context passing

Reduce or eliminate use of global zebra_ns structs in
a couple of netlink/kernel code paths, so that those paths
can potentially be made asynch eventually.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Mark Stapp 2018-09-12 14:59:57 -04:00 committed by Donald Sharp
parent ea1c14f680
commit 85a75f1e77
7 changed files with 99 additions and 42 deletions

View File

@ -698,8 +698,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
/* Request for specific interface or address information from the kernel */
static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type,
uint32_t filter_mask)
static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
int type, uint32_t filter_mask)
{
struct {
struct nlmsghdr n;
@ -717,57 +717,62 @@ static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type,
if (filter_mask)
addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
return netlink_request(&zns->netlink_cmd, &req.n);
return netlink_request(netlink_cmd, &req.n);
}
/* Interface lookup by netlink socket. */
int interface_lookup_netlink(struct zebra_ns *zns)
{
int ret;
struct zebra_dplane_info dp_info;
struct nlsock *netlink_cmd = &zns->netlink_cmd;
/* Capture key info from ns struct */
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
/* Get interface information. */
ret = netlink_request_intf_addr(zns, AF_PACKET, RTM_GETLINK, 0);
ret = netlink_request_intf_addr(netlink_cmd, AF_PACKET, RTM_GETLINK, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
1);
if (ret < 0)
return ret;
/* Get interface information - for bridge interfaces. */
ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK,
ret = netlink_request_intf_addr(netlink_cmd, AF_BRIDGE, RTM_GETLINK,
RTEXT_FILTER_BRVLAN);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
0);
if (ret < 0)
return ret;
/* Get interface information - for bridge interfaces. */
ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK,
ret = netlink_request_intf_addr(netlink_cmd, AF_BRIDGE, RTM_GETLINK,
RTEXT_FILTER_BRVLAN);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
0);
if (ret < 0)
return ret;
/* Get IPv4 address of the interfaces. */
ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0);
ret = netlink_request_intf_addr(netlink_cmd, AF_INET, RTM_GETADDR, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns,
ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
0, 1);
if (ret < 0)
return ret;
/* Get IPv6 address of the interfaces. */
ret = netlink_request_intf_addr(zns, AF_INET6, RTM_GETADDR, 0);
ret = netlink_request_intf_addr(netlink_cmd, AF_INET6, RTM_GETADDR, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns,
ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
0, 1);
if (ret < 0)
return ret;

View File

@ -373,7 +373,13 @@ static long netlink_read_file(char *buf, const char *fname)
static int kernel_read(struct thread *thread)
{
struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread);
netlink_parse_info(netlink_information_fetch, &zns->netlink, zns, 5, 0);
struct zebra_dplane_info dp_info;
/* Capture key info from ns struct */
zebra_dplane_info_from_zns(&dp_info, zns, false);
netlink_parse_info(netlink_information_fetch, &zns->netlink, &dp_info,
5, 0);
zns->t_netlink = NULL;
thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock,
&zns->t_netlink);
@ -672,8 +678,8 @@ static void netlink_parse_extended_ack(struct nlmsghdr *h)
* the filter.
*/
int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
struct nlsock *nl, struct zebra_ns *zns, int count,
int startup)
struct nlsock *nl, struct zebra_dplane_info *zns,
int count, int startup)
{
int status;
int ret = 0;
@ -811,7 +817,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
/* Deal with errors that occur because of races
* in link handling */
if (nl == &zns->netlink_cmd
if (zns->is_cmd
&& ((msg_type == RTM_DELROUTE
&& (-errnum == ENODEV
|| -errnum == ESRCH))
@ -838,8 +844,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
* so do not log these as an error.
*/
if (msg_type == RTM_DELNEIGH
|| (nl == &zns->netlink_cmd
&& msg_type == RTM_NEWROUTE
|| (zns->is_cmd && msg_type == RTM_NEWROUTE
&& (-errnum == ESRCH
|| -errnum == ENETUNREACH))) {
/* This is known to happen in some
@ -935,6 +940,7 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
struct iovec iov;
struct msghdr msg;
int save_errno = 0;
struct zebra_dplane_info dp_info;
memset(&snl, 0, sizeof snl);
memset(&iov, 0, sizeof iov);
@ -981,7 +987,8 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
* Get reply from netlink socket.
* The reply should either be an acknowlegement or an error.
*/
return netlink_parse_info(filter, nl, zns, 0, startup);
zebra_dplane_info_from_zns(&dp_info, zns, (nl == &(zns->netlink_cmd)));
return netlink_parse_info(filter, nl, &dp_info, 0, startup);
}
/* Issue request message to kernel via netlink socket. GET messages

View File

@ -52,7 +52,7 @@ extern bool netlink_read;
extern void netlink_read_init(const char *fname);
#endif /* HANDLE_NETLINK_FUZZING */
extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
struct nlsock *nl, struct zebra_ns *zns,
struct nlsock *nl, struct zebra_dplane_info *zns,
int count, int startup);
extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup);
extern int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),

View File

@ -890,13 +890,16 @@ static int netlink_request_route(struct zebra_ns *zns, int family, int type)
int netlink_route_read(struct zebra_ns *zns)
{
int ret;
struct zebra_dplane_info dp_info;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
/* Get IPv4 routing table. */
ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_route_change_read_unicast,
&zns->netlink_cmd, zns, 0, 1);
&zns->netlink_cmd, &dp_info, 0, 1);
if (ret < 0)
return ret;
@ -905,7 +908,7 @@ int netlink_route_read(struct zebra_ns *zns)
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_route_change_read_unicast,
&zns->netlink_cmd, zns, 0, 1);
&zns->netlink_cmd, &dp_info, 0, 1);
if (ret < 0)
return ret;
@ -2102,8 +2105,8 @@ static int netlink_macfdb_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
/* Request for MAC FDB information from the kernel */
static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
ifindex_t master_ifindex)
static int netlink_request_macs(struct nlsock *netlink_cmd, int family,
int type, ifindex_t master_ifindex)
{
struct {
struct nlmsghdr n;
@ -2119,7 +2122,7 @@ static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
if (master_ifindex)
addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
return netlink_request(&zns->netlink_cmd, &req.n);
return netlink_request(netlink_cmd, &req.n);
}
/*
@ -2129,15 +2132,19 @@ static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
int netlink_macfdb_read(struct zebra_ns *zns)
{
int ret;
struct zebra_dplane_info dp_info;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
/* Get bridge FDB table. */
ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0);
ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
0);
if (ret < 0)
return ret;
/* We are reading entire table. */
filter_vlan = 0;
ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
0, 1);
ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
&dp_info, 0, 1);
return ret;
}
@ -2152,8 +2159,10 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
struct zebra_if *br_zif;
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
struct zebra_dplane_info dp_info;
int ret = 0;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
/* Save VLAN we're filtering on, if needed. */
br_zif = (struct zebra_if *)br_if->info;
@ -2164,12 +2173,12 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
/* Get bridge FDB table for specific bridge - we do the VLAN filtering.
*/
ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH,
ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
br_if->ifindex);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
0, 0);
ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
&dp_info, 0, 0);
/* Reset VLAN filter. */
filter_vlan = 0;
@ -2421,8 +2430,8 @@ static int netlink_neigh_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
/* Request for IP neighbor information from the kernel */
static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
ifindex_t ifindex)
static int netlink_request_neigh(struct nlsock *netlink_cmd, int family,
int type, ifindex_t ifindex)
{
struct {
struct nlmsghdr n;
@ -2438,7 +2447,7 @@ static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
if (ifindex)
addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
return netlink_request(&zns->netlink_cmd, &req.n);
return netlink_request(netlink_cmd, &req.n);
}
/*
@ -2448,13 +2457,17 @@ static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
int netlink_neigh_read(struct zebra_ns *zns)
{
int ret;
struct zebra_dplane_info dp_info;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
/* Get IP neighbor table. */
ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0);
ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
0);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
1);
ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
&dp_info, 0, 1);
return ret;
}
@ -2466,13 +2479,16 @@ int netlink_neigh_read(struct zebra_ns *zns)
int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
int ret = 0;
struct zebra_dplane_info dp_info;
ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH,
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
vlan_if->ifindex);
if (ret < 0)
return ret;
ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
0);
ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
&dp_info, 0, 0);
return ret;
}

View File

@ -32,6 +32,33 @@
* context.
*/
/* Key netlink info from zebra ns */
struct zebra_dplane_info {
ns_id_t ns_id;
#if defined(HAVE_NETLINK)
uint32_t nl_pid;
bool is_cmd;
#endif
};
/* Utility to fill in zns info from main zns struct */
static inline void
zebra_dplane_info_from_zns(struct zebra_dplane_info *zns_info,
const struct zebra_ns *zns, bool is_cmd)
{
zns_info->ns_id = zns->ns_id;
#if defined(HAVE_NETLINK)
zns_info->is_cmd = is_cmd;
if (is_cmd) {
zns_info->nl_pid = zns->netlink_cmd.snl.nl_pid;
} else {
zns_info->nl_pid = zns->netlink.snl.nl_pid;
}
#endif /* NETLINK */
}
/*
* Enqueue a route install or update for the dataplane.
*/

View File

@ -32,6 +32,7 @@
#include "prefix.h"
#include "zebra/zserv.h"
#include "zebra/zebra_dplane.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/kernel_netlink.h"

View File

@ -24,13 +24,14 @@
#include "log.h"
#include "lib_errors.h"
#include "zebra/rib.h"
#include "zebra/zebra_dplane.h"
#if defined(HAVE_NETLINK)
#include <linux/net_namespace.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include "rib.h"
#include "zebra_ns.h"
#include "kernel_netlink.h"
#endif /* defined(HAVE_NETLINK) */