1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2009 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * Author: Nathan Rutman <nathan.rutman@sun.com>
38 * Kernel - userspace communication routines. We'll use a shorthand term
39 * "lnl" (Lustre NetLink) for the interface names for all arches (even though
40 * implemtation may not use NetLink).
41 * For Linux, we use Netlink sockets.
44 #define DEBUG_SUBSYSTEM S_CLASS
46 /* This is the userspace side.
47 * See libcfs/linux/linux-kernelcomm.c for the kernel side.
52 #include <libcfs/libcfs.h>
53 #include <sys/socket.h>
54 #include <linux/netlink.h>
56 /** Start the userspace side of a LNL pipe.
57 * @param link Private descriptor for pipe/socket.
58 * @param groups LNL broadcast group to listen to
59 * (can be null for unicast to this pid)
61 int libcfs_ulnl_start(lustre_netlink *link, int groups)
63 struct sockaddr_nl src_addr;
67 sock = socket(PF_NETLINK, SOCK_RAW, LNL_SOCKET);
71 memset(&src_addr, 0, sizeof(src_addr));
72 src_addr.nl_family = AF_NETLINK;
73 src_addr.nl_pid = getpid(); /* self pid */
74 src_addr.nl_groups = groups;
75 rc = bind(sock, (struct sockaddr*)&src_addr, sizeof(src_addr));
84 int libcfs_ulnl_stop(lustre_netlink *link)
89 /** Read a message from the netlink layer.
91 * @param link Private descriptor for pipe/socket.
92 * @param maxsize Maximum message size allowed
93 * @param transport Only listen to messages on this transport
94 * (and the generic transport)
95 * @param lnlhh Handle to the new LNL message
97 int libcfs_ulnl_msg_get(lustre_netlink *link, int maxsize, int transport,
98 struct lnl_hdr **lnlhh)
101 struct sockaddr_nl dest_addr;
103 struct nlmsghdr *nlh = NULL;
104 struct lnl_hdr *lnlh;
107 nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(maxsize));
111 memset(nlh, 0, NLMSG_SPACE(maxsize));
112 iov.iov_base = (void *)nlh;
113 iov.iov_len = NLMSG_SPACE(maxsize);
115 memset(&dest_addr, 0, sizeof(dest_addr));
116 msg.msg_name = (void *)&dest_addr;
117 msg.msg_namelen = sizeof(dest_addr);
121 CDEBUG(0, "Waiting for message from kernel on pid %d\n", getpid());
124 /* Read message from kernel */
125 rc = recvmsg(*link, &msg, 0);
131 lnlh = (struct lnl_hdr *)NLMSG_DATA(nlh);
132 CDEBUG(0, " Received message mg=%x t=%d m=%d l=%d\n",
133 lnlh->lnl_magic, lnlh->lnl_transport, lnlh->lnl_msgtype,
135 if (lnlh->lnl_magic != LNL_MAGIC) {
136 CERROR("bad message magic %x != %x\n",
137 lnlh->lnl_magic, LNL_MAGIC);
141 if (lnlh->lnl_transport == transport ||
142 lnlh->lnl_transport == LNL_TRANSPORT_GENERIC) {
146 /* Ignore messages on other transports */
152 /* Free a message returned by the above fn */
153 int libcfs_ulnl_msg_free(struct lnl_hdr **lnlhh)
155 /* compute nlmsdghdr offset */
156 char *p = (char *)NLMSG_DATA(0);
158 free((void *)((char *)*lnlhh - p));
163 #else /* HAVE_NETLINK */
167 typedef int lustre_netlink;
168 int libcfs_ulnl_start(lustre_netlink *link, int groups) {
171 int libcfs_ulnl_stop(lustre_netlink *link) {
175 int libcfs_ulnl_msg_get(lustre_netlink *link, int maxsize, int transport,
176 struct lnl_hdr **lnlhh) {
179 int libcfs_ulnl_msg_free(struct lnl_hdr **lnlhh) {
182 #endif /* HAVE_NETLINK */