NOTE: This patch is just for some comments, so that we can try to
improve netlink support in libvirt.
This patch introduces a new global array servers[MAX_LINKS],
and all the netlink protocol (at most 32 protocols)
can be supportted.
And also, it creates a NETLINK_KOBJECT_UEVENT socket to listen
to hotplug events.
Signed-off-by: Tang Chen <tangchen(a)cn.fujitsu.com>
---
src/libvirt_private.syms | 1 +
src/util/virnetlink.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/virnetlink.h | 5 +++
3 files changed, 109 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7373281..0ef21d9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1378,6 +1378,7 @@ virNetlinkEventServiceIsRunning;
virNetlinkEventServiceLocalPid;
virNetlinkEventServiceStop;
virNetlinkEventServiceStart;
+virNetlinkEventServiceStartProtocol;
virNetlinkShutdown;
virNetlinkStartup;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index bb0dae9..489c149 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -98,6 +98,7 @@ static int nextWatch = 1;
# define NETLINK_EVENT_ALLOC_EXTENT 10
static virNetlinkEventSrvPrivatePtr server = NULL;
+static virNetlinkEventSrvPrivatePtr servers[MAX_LINKS] = {NULL};
static virNetlinkHandle *placeholder_nlhandle = NULL;
/* Function definitions */
@@ -307,6 +308,8 @@ virNetlinkEventCallback(int watch,
return;
}
+ VIR_INFO("%s", msg);
+
virNetlinkEventServerLock(srv);
VIR_DEBUG("dispatching to max %d clients, called from event watch %d",
@@ -398,6 +401,106 @@ int virNetlinkEventServiceLocalPid(void)
/**
+ * virNetlinkEventServiceStartProtocol:
+ *
+ * start a monitor to receive netlink messages for libvirtd.
+ * This registers a netlink socket with the event interface.
+ *
+ * @protocol: netlink protocol
+ * @groups: broadcast groups to join
+ * Returns -1 if the monitor cannot be registered, 0 upon success
+ */
+int
+virNetlinkEventServiceStartProtocol(int protocol, int groups)
+{
+ virNetlinkEventSrvPrivatePtr srv;
+ int fd;
+ int ret = -1;
+
+ if (protocol < 0 || protocol >= MAX_LINKS ||
+ groups < 0 || groups >= 32) {
+ return -EINVAL;
+ }
+
+ if (servers[protocol])
+ return 0;
+
+ VIR_INFO("starting netlink event service with protocol %d", protocol);
+
+ if (VIR_ALLOC(srv) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (virMutexInit(&srv->lock) < 0) {
+ VIR_FREE(srv);
+ return -1;
+ }
+
+ virNetlinkEventServerLock(srv);
+
+ /* Allocate a new socket and get fd */
+ srv->netlinknh = virNetlinkAlloc();
+
+ if (!srv->netlinknh) {
+ virReportSystemError(errno,
+ "%s", _("cannot allocate nlhandle for
virNetlinkEvent server"));
+ goto error_locked;
+ }
+
+ nl_join_groups(srv->netlinknh, groups);
+
+ if (nl_connect(srv->netlinknh, protocol) < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot connect to netlink
socket"));
+ goto error_server;
+ }
+
+ fd = nl_socket_get_fd(srv->netlinknh);
+
+ if (fd < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot get netlink socket
fd"));
+ goto error_server;
+ }
+
+ if (nl_socket_set_nonblocking(srv->netlinknh)) {
+ virReportSystemError(errno, "%s",
+ _("cannot set netlink socket nonblocking"));
+ goto error_server;
+ }
+
+ if ((srv->eventwatch = virEventAddHandle(fd,
+ VIR_EVENT_HANDLE_READABLE,
+ virNetlinkEventCallback,
+ srv, NULL)) < 0) {
+ netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to add netlink event handle watch"));
+ goto error_server;
+ }
+
+ srv->netlinkfd = fd;
+ VIR_DEBUG("netlink event listener on fd: %i running", fd);
+
+ ret = 0;
+ servers[protocol] = srv;
+
+error_server:
+ if (ret < 0) {
+ nl_close(srv->netlinknh);
+ virNetlinkFree(srv->netlinknh);
+ }
+error_locked:
+ virNetlinkEventServerUnlock(srv);
+ if (ret < 0) {
+ virMutexDestroy(&srv->lock);
+ VIR_FREE(srv);
+ }
+ return ret;
+}
+
+
+/**
* virNetlinkEventServiceStart:
*
* start a monitor to receive netlink messages for libvirtd.
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 8ec27c9..256f129 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -59,6 +59,11 @@ int virNetlinkEventServiceStop(void);
int virNetlinkEventServiceStart(void);
/**
+ * startNetlinkEventServerProtocol: start a monitor with specified protocol to receive
netlink messages for libvirtd
+ */
+int virNetlinkEventServiceStartProtocol(int protocol, int groups);
+
+/**
* virNetlinkEventServiceIsRunning: returns if the netlink event service is running.
*/
bool virNetlinkEventServiceIsRunning(void);
--
1.7.10.2