#include "vrf.h"
#include "mpls.h"
#include "lib_errors.h"
+#include "hash.h"
//#include "zebra/zserv.h"
#include "zebra/zebra_router.h"
DEFINE_MTYPE_STATIC(ZEBRA, NL_BUF, "Zebra Netlink buffers");
+struct hash *nlsock_hash;
size_t nl_batch_tx_bufsize;
char *nl_batch_tx_buf;
*/
int kernel_dplane_read(struct zebra_dplane_info *info)
{
- netlink_parse_info(dplane_netlink_information_fetch, &info->nls, info,
- 5, false);
+ struct nlsock *nl = kernel_netlink_nlsock_lookup(info->sock);
+
+ netlink_parse_info(dplane_netlink_information_fetch, nl, info, 5,
+ false);
return 0;
}
struct nlmsghdr *n, const struct zebra_dplane_info *dp_info,
bool startup)
{
- const struct nlsock *nl;
+ struct nlsock *nl;
- nl = &(dp_info->nls);
+ nl = kernel_netlink_nlsock_lookup(dp_info->sock);
n->nlmsg_seq = dp_info->seq;
n->nlmsg_pid = nl->snl.nl_pid;
struct sockaddr_nl snl;
struct msghdr msg = {};
int status, seq;
- const struct nlsock *nl;
+ struct nlsock *nl;
struct zebra_dplane_ctx *ctx;
bool ignore_msg;
- nl = &(bth->zns->nls);
+ nl = kernel_netlink_nlsock_lookup(bth->zns->sock);
msg.msg_name = (void *)&snl;
msg.msg_namelen = sizeof(snl);
bool err = false;
if (bth->curlen != 0 && bth->zns != NULL) {
+ struct nlsock *nl =
+ kernel_netlink_nlsock_lookup(bth->zns->sock);
+
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: %s, batch size=%zu, msg cnt=%zu",
- __func__, bth->zns->nls.name, bth->curlen,
+ __func__, nl->name, bth->curlen,
bth->msgcnt);
- if (netlink_send_msg(&(bth->zns->nls), bth->buf, bth->curlen)
- == -1)
+ if (netlink_send_msg(nl, bth->buf, bth->curlen) == -1)
err = true;
if (!err) {
int seq;
ssize_t size;
struct nlmsghdr *msgh;
+ struct nlsock *nl;
size = (*msg_encoder)(ctx, bth->buf_head, bth->bufsiz - bth->curlen);
}
seq = dplane_ctx_get_ns(ctx)->seq;
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
if (ignore_res)
seq++;
msgh = (struct nlmsghdr *)bth->buf_head;
msgh->nlmsg_seq = seq;
- msgh->nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
+ msgh->nlmsg_pid = nl->snl.nl_pid;
bth->zns = dplane_ctx_get_ns(ctx);
bth->buf_head = ((char *)bth->buf_head) + size;
dplane_ctx_list_append(ctx_list, &handled_list);
}
+struct nlsock *kernel_netlink_nlsock_lookup(int sock)
+{
+ struct nlsock lookup;
+
+ lookup.sock = sock;
+
+ return hash_lookup(nlsock_hash, &lookup);
+}
+
+static uint32_t kernel_netlink_nlsock_key(const void *arg)
+{
+ const struct nlsock *nl = arg;
+
+ return nl->sock;
+}
+
+static bool kernel_netlink_nlsock_hash_equal(const void *arg1, const void *arg2)
+{
+ const struct nlsock *nl1 = arg1;
+ const struct nlsock *nl2 = arg2;
+
+ if (nl1->sock == nl2->sock)
+ return true;
+
+ return false;
+}
+
/* Exported interface function. This function simply calls
netlink_socket (). */
void kernel_init(struct zebra_ns *zns)
int one, ret;
#endif
+ if (!nlsock_hash)
+ nlsock_hash = hash_create_size(8, kernel_netlink_nlsock_key,
+ kernel_netlink_nlsock_hash_equal,
+ "Netlink Socket Hash");
+
/*
* Initialize netlink sockets
*
zns->netlink.name);
exit(-1);
}
+ (void)hash_get(nlsock_hash, &zns->netlink, hash_alloc_intern);
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.name);
exit(-1);
}
+ (void)hash_get(nlsock_hash, &zns->netlink_cmd, hash_alloc_intern);
/* Outbound socket for dplane programming of the host OS. */
snprintf(zns->netlink_dplane_out.name,
zns->netlink_dplane_out.name);
exit(-1);
}
+ (void)hash_get(nlsock_hash, &zns->netlink_dplane_out,
+ hash_alloc_intern);
/* Inbound socket for OS events coming to the dplane. */
snprintf(zns->netlink_dplane_in.name,
zns->netlink_dplane_in.name);
exit(-1);
}
+ (void)hash_get(nlsock_hash, &zns->netlink_dplane_in, hash_alloc_intern);
/*
* SOL_NETLINK is not available on all platforms yet
thread_cancel(&zns->t_netlink);
if (zns->netlink.sock >= 0) {
+ hash_release(nlsock_hash, &zns->netlink);
close(zns->netlink.sock);
zns->netlink.sock = -1;
}
if (zns->netlink_cmd.sock >= 0) {
+ hash_release(nlsock_hash, &zns->netlink_cmd);
close(zns->netlink_cmd.sock);
zns->netlink_cmd.sock = -1;
}
if (zns->netlink_dplane_in.sock >= 0) {
+ hash_release(nlsock_hash, &zns->netlink_dplane_in);
close(zns->netlink_dplane_in.sock);
zns->netlink_dplane_in.sock = -1;
}
*/
if (complete) {
if (zns->netlink_dplane_out.sock >= 0) {
+ hash_release(nlsock_hash, &zns->netlink_dplane_out);
close(zns->netlink_dplane_out.sock);
zns->netlink_dplane_out.sock = -1;
}
+
+ hash_free(nlsock_hash);
}
}
#endif /* HAVE_NETLINK */
union g_addr src;
const struct prefix *p, *src_p;
uint32_t table_id;
+ struct nlsock *nl;
struct {
struct nlmsghdr n;
if (datalen < sizeof(*req))
return 0;
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
memset(req, 0, sizeof(*req));
bytelen = (p->family == AF_INET ? 4 : 16);
req->n.nlmsg_type = cmd;
- req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
+ req->n.nlmsg_pid = nl->snl.nl_pid;
req->r.rtm_family = p->family;
req->r.rtm_dst_len = p->prefixlen;
int type = dplane_ctx_get_nhe_type(ctx);
struct rtattr *nest;
uint16_t encap;
+ struct nlsock *nl =
+ kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
if (!id) {
flog_err(
req->n.nlmsg_flags |= NLM_F_REPLACE;
req->n.nlmsg_type = cmd;
- req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
+ req->n.nlmsg_pid = nl->snl.nl_pid;
req->nhm.nh_family = AF_UNSPEC;
/* TODO: Scope? */
const char *routedesc;
int route_type;
struct prefix p = {0};
+ struct nlsock *nl =
+ kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
struct {
struct nlmsghdr n;
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
req->n.nlmsg_type = cmd;
- req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
+ req->n.nlmsg_pid = nl->snl.nl_pid;
req->r.rtm_family = AF_MPLS;
req->r.rtm_table = RT_TABLE_MAIN;
return &(ctx->zd_ns_info);
}
+int dplane_ctx_get_ns_sock(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ns_info.sock;
+}
+
/* Accessors for nexthop information */
uint32_t dplane_ctx_get_nhe_id(const struct zebra_dplane_ctx *ctx)
{
#if defined(HAVE_NETLINK)
ns_info->is_cmd = true;
- ns_info->nls = zns->netlink_dplane_out;
+ ns_info->sock = zns->netlink_dplane_out.sock;
#endif /* NETLINK */
}
/* Re-start read task */
thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
- zi->info.nls.sock, &zi->t_read);
+ zi->info.sock, &zi->t_read);
return 0;
}
/* Make sure we're up-to-date with the zns object */
#if defined(HAVE_NETLINK)
zi->info.is_cmd = false;
- zi->info.nls = zns->netlink_dplane_in;
+ zi->info.sock = zns->netlink_dplane_in.sock;
/* Start read task for the dplane pthread. */
if (zdplane_info.dg_master)
thread_add_read(zdplane_info.dg_master,
- dplane_incoming_read, zi,
- zi->info.nls.sock, &zi->t_read);
+ dplane_incoming_read, zi, zi->info.sock,
+ &zi->t_read);
#endif
} else if (zi) {
if (IS_ZEBRA_DEBUG_DPLANE)
frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) {
#if defined(HAVE_NETLINK)
thread_add_read(zdplane_info.dg_master, dplane_incoming_read,
- zi, zi->info.nls.sock, &zi->t_read);
+ zi, zi->info.sock, &zi->t_read);
#endif
}