This patch improve all the API in virnetlink.c to support
all kinds of netlink protocols, and make all netlink sockets
be able to join in groups.
SOL_NETLINK is not defined on every system, so this patch defines
SOL_NETLINK as 270.
Signed-off-by: Tang Chen <tangchen(a)cn.fujitsu.com>
---
daemon/libvirtd.c | 6 +-
src/util/virnetdev.c | 6 +-
src/util/virnetdevmacvlan.c | 12 +--
src/util/virnetdevvportprofile.c | 7 +-
src/util/virnetlink.c | 178 +++++++++++++++++++++++++++++---------
src/util/virnetlink.h | 17 ++--
6 files changed, 165 insertions(+), 61 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index f0b0a3c..e2e4fbd 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1310,8 +1310,8 @@ int main(int argc, char **argv) {
goto cleanup;
}
- /* Register the netlink event service */
- if (virNetlinkEventServiceStart() < 0) {
+ /* Register the netlink event service for NETLINK_ROUTE */
+ if (virNetlinkEventServiceStart(NETLINK_ROUTE, 0) < 0) {
ret = VIR_DAEMON_ERR_NETWORK;
goto cleanup;
}
@@ -1325,7 +1325,7 @@ int main(int argc, char **argv) {
0, "shutdown", NULL, NULL);
cleanup:
- virNetlinkEventServiceStop();
+ virNetlinkEventServiceStop(NETLINK_ROUTE);
virObjectUnref(remoteProgram);
virObjectUnref(qemuProgram);
virNetServerClose(srv);
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index f9eba1a..d97820e 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1277,7 +1277,8 @@ virNetDevLinkDump(const char *ifname, int ifindex,
goto buffer_too_small;
}
- if (virNetlinkCommand(nl_msg, recvbuf, &recvbuflen, src_pid, dst_pid) < 0)
+ if (virNetlinkCommand(nl_msg, recvbuf, &recvbuflen,
+ src_pid, dst_pid, NETLINK_ROUTE, 0) < 0)
goto cleanup;
if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
@@ -1405,7 +1406,8 @@ virNetDevSetVfConfig(const char *ifname, int ifindex, int vf,
}
}
- if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, pid) < 0)
+ if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, pid,
+ NETLINK_ROUTE, 0) < 0)
goto cleanup;
if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index cfad2de..74c56e0 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -149,7 +149,8 @@ virNetDevMacVLanCreate(const char *ifname,
nla_nest_end(nl_msg, linkinfo);
- if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, 0) < 0) {
+ if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, 0,
+ NETLINK_ROUTE, 0) < 0) {
goto cleanup;
}
@@ -237,7 +238,8 @@ int virNetDevMacVLanDelete(const char *ifname)
if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
goto buffer_too_small;
- if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, 0) < 0) {
+ if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, 0, 0,
+ NETLINK_ROUTE, 0) < 0) {
goto cleanup;
}
@@ -757,7 +759,7 @@ virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname,
{
virNetlinkCallbackDataPtr calld = NULL;
- if (virtPortProfile && virNetlinkEventServiceIsRunning()) {
+ if (virtPortProfile && virNetlinkEventServiceIsRunning(NETLINK_ROUTE)) {
if (VIR_ALLOC(calld) < 0)
goto memory_error;
if ((calld->cr_ifname = strdup(ifname)) == NULL)
@@ -774,7 +776,7 @@ virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname,
if (virNetlinkEventAddClient(virNetDevMacVLanVPortProfileCallback,
virNetDevMacVLanVPortProfileDestroyCallback,
- calld, macaddress) < 0)
+ calld, macaddress, NETLINK_ROUTE) < 0)
goto error;
}
@@ -1000,7 +1002,7 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
ret = -1;
}
- virNetlinkEventRemoveClient(0, macaddr);
+ virNetlinkEventRemoveClient(0, macaddr, NETLINK_ROUTE);
return ret;
}
diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
index f3f53c9..5213378 100644
--- a/src/util/virnetdevvportprofile.c
+++ b/src/util/virnetdevvportprofile.c
@@ -705,13 +705,14 @@ virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex,
}
if (!nltarget_kernel) {
- if ((src_pid = virNetlinkEventServiceLocalPid()) < 0)
+ if ((src_pid = virNetlinkEventServiceLocalPid(NETLINK_ROUTE)) < 0)
goto cleanup;
if ((dst_pid = virNetDevVPortProfileGetLldpadPid()) == 0)
goto cleanup;
}
- if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen, src_pid, dst_pid) <
0)
+ if (virNetlinkCommand(nl_msg, &recvbuf, &recvbuflen,
+ src_pid, dst_pid, NETLINK_ROUTE, 0) < 0)
goto cleanup;
if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
@@ -868,7 +869,7 @@ virNetDevVPortProfileOpCommon(const char *ifname, int ifindex,
return 0;
if (!nltarget_kernel &&
- (((src_pid = virNetlinkEventServiceLocalPid()) < 0) ||
+ (((src_pid = virNetlinkEventServiceLocalPid(NETLINK_ROUTE)) < 0) ||
((dst_pid = virNetDevVPortProfileGetLldpadPid()) == 0))) {
rc = -1;
goto cleanup;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index 4a31b1c..8a227df 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include "virnetlink.h"
#include "logging.h"
@@ -41,6 +42,10 @@
#include "virmacaddr.h"
#include "virterror_internal.h"
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
#define VIR_FROM_THIS VIR_FROM_NET
#define NETLINK_ACK_TIMEOUT_S 2
@@ -93,7 +98,7 @@ static int nextWatch = 1;
records in this multiple */
# define NETLINK_EVENT_ALLOC_EXTENT 10
-static virNetlinkEventSrvPrivatePtr server = NULL;
+static virNetlinkEventSrvPrivatePtr server[MAX_LINKS] = {NULL};
static virNetlinkHandle *placeholder_nlhandle = NULL;
/* Function definitions */
@@ -158,6 +163,7 @@ virNetlinkShutdown(void)
* @respbuflen: pointer to integer holding the size of the response buffer
* on return of the function.
* @nl_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
+ * @protocol: netlink protocol
*
* Send the given message to the netlink layer and receive response.
* Returns 0 on success, -1 on error. In case of error, no response
@@ -165,7 +171,8 @@ virNetlinkShutdown(void)
*/
int virNetlinkCommand(struct nl_msg *nl_msg,
unsigned char **respbuf, unsigned int *respbuflen,
- uint32_t src_pid, uint32_t dst_pid)
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups)
{
int rc = 0;
struct sockaddr_nl nladdr = {
@@ -181,17 +188,46 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
int fd;
int n;
struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
- virNetlinkHandle *nlhandle = virNetlinkAlloc();
+ virNetlinkHandle *nlhandle = NULL;
+
+ if (protocol >= MAX_LINKS) {
+ virReportSystemError(EINVAL,
+ _("invalid protocol argument: %d"), protocol);
+ return -EINVAL;
+ }
+
+ if (groups >= 32) {
+ virReportSystemError(EINVAL,
+ _("invalid group argument: %d"), groups);
+ return -EINVAL;
+ }
+ nlhandle = virNetlinkAlloc();
if (!nlhandle) {
virReportSystemError(errno,
"%s", _("cannot allocate nlhandle for
netlink"));
return -1;
}
- if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) {
+ if (nl_connect(nlhandle, protocol) < 0) {
virReportSystemError(errno,
- "%s", _("cannot connect to netlink
socket"));
+ _("cannot connect to netlink socket with protocol
%d"), protocol);
+ rc = -1;
+ goto error;
+ }
+
+ fd = nl_socket_get_fd(nlhandle);
+ if (fd < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot get netlink socket
fd"));
+ rc = -1;
+ goto error;
+ }
+
+ if (groups && setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &groups, sizeof(groups)) < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot add netlink
membership"));
rc = -1;
goto error;
}
@@ -208,8 +244,6 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
goto error;
}
- fd = nl_socket_get_fd(nlhandle);
-
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
@@ -258,6 +292,7 @@ virNetlinkEventServerUnlock(virNetlinkEventSrvPrivatePtr driver)
* virNetlinkEventRemoveClientPrimitive:
*
* @i: index of the client to remove from the table
+ * @protocol: netlink protocol
*
* This static function does the low level removal of a client from
* the table once its index is known, including calling the remove
@@ -267,17 +302,21 @@ virNetlinkEventServerUnlock(virNetlinkEventSrvPrivatePtr driver)
*
* assumes success, returns nothing.
*/
-static void
-virNetlinkEventRemoveClientPrimitive(size_t i)
+static int
+virNetlinkEventRemoveClientPrimitive(size_t i, unsigned int protocol)
{
- virNetlinkEventRemoveCallback removeCB = server->handles[i].removeCB;
+ if (protocol >= MAX_LINKS)
+ return -EINVAL;
+
+ virNetlinkEventRemoveCallback removeCB = server[protocol]->handles[i].removeCB;
if (removeCB) {
- (removeCB)(server->handles[i].watch,
- &server->handles[i].macaddr,
- server->handles[i].opaque);
+ (removeCB)(server[protocol]->handles[i].watch,
+ &server[protocol]->handles[i].macaddr,
+ server[protocol]->handles[i].opaque);
}
- server->handles[i].deleted = VIR_NETLINK_HANDLE_DELETED;
+ server[protocol]->handles[i].deleted = VIR_NETLINK_HANDLE_DELETED;
+ return 0;
}
static void
@@ -330,17 +369,22 @@ virNetlinkEventCallback(int watch,
* stop the monitor to receive netlink messages for libvirtd.
* This removes the netlink socket fd from the event handler.
*
+ * @protocol: netlink protocol
+ *
* Returns -1 if the monitor cannot be unregistered, 0 upon success
*/
int
-virNetlinkEventServiceStop(void)
+virNetlinkEventServiceStop(unsigned int protocol)
{
- virNetlinkEventSrvPrivatePtr srv = server;
+ if (protocol >= MAX_LINKS)
+ return -EINVAL;
+
+ virNetlinkEventSrvPrivatePtr srv = server[protocol];
int i;
VIR_INFO("stopping netlink event service");
- if (!server)
+ if (!server[protocol])
return 0;
virNetlinkEventServerLock(srv);
@@ -351,10 +395,10 @@ virNetlinkEventServiceStop(void)
/* free any remaining clients on the list */
for (i = 0; i < srv->handlesCount; i++) {
if (srv->handles[i].deleted == VIR_NETLINK_HANDLE_VALID)
- virNetlinkEventRemoveClientPrimitive(i);
+ virNetlinkEventRemoveClientPrimitive(i, protocol);
}
- server = 0;
+ server[protocol] = NULL;
virNetlinkEventServerUnlock(srv);
virMutexDestroy(&srv->lock);
@@ -367,29 +411,42 @@ virNetlinkEventServiceStop(void)
*
* Returns if the netlink event service is running.
*
+ * @protocol: netlink protocol
+ *
* Returns 'true' if the service is running, 'false' if stopped.
*/
bool
-virNetlinkEventServiceIsRunning(void)
+virNetlinkEventServiceIsRunning(unsigned int protocol)
{
- return server != NULL;
+ if (protocol >= MAX_LINKS) {
+ virReportSystemError(EINVAL,
+ _("invalid protocol argument: %d"), protocol);
+ return false;
+ }
+
+ return server[protocol] != NULL;
}
/**
* virNetlinkEventServiceLocalPid:
*
+ * @protocol: netlink protocol
+ *
* Returns the nl_pid value that was used to bind() the netlink socket
* used by the netlink event service, or -1 on error (netlink
* guarantees that this value will always be > 0).
*/
-int virNetlinkEventServiceLocalPid(void)
+int virNetlinkEventServiceLocalPid(unsigned int protocol)
{
- if (!(server && server->netlinknh)) {
+ if (protocol >= MAX_LINKS)
+ return -EINVAL;
+
+ if (!(server[protocol] && server[protocol]->netlinknh)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("netlink event service not running"));
return -1;
}
- return (int)nl_socket_get_local_port(server->netlinknh);
+ return (int)nl_socket_get_local_port(server[protocol]->netlinknh);
}
@@ -399,19 +456,33 @@ int virNetlinkEventServiceLocalPid(void)
* 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 in
* Returns -1 if the monitor cannot be registered, 0 upon success
*/
int
-virNetlinkEventServiceStart(void)
+virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups)
{
virNetlinkEventSrvPrivatePtr srv;
int fd;
int ret = -1;
- if (server)
+ if (protocol >= MAX_LINKS) {
+ virReportSystemError(EINVAL,
+ _("invalid protocol argument: %d"), protocol);
+ return -EINVAL;
+ }
+
+ if (groups >= 32) {
+ virReportSystemError(EINVAL,
+ _("invalid group argument: %d"), groups);
+ return -EINVAL;
+ }
+
+ if (server[protocol])
return 0;
- VIR_INFO("starting netlink event service");
+ VIR_INFO("starting netlink event service with protocol %d", protocol);
if (VIR_ALLOC(srv) < 0) {
virReportOOMError();
@@ -434,20 +505,26 @@ virNetlinkEventServiceStart(void)
goto error_locked;
}
- if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) {
+ if (nl_connect(srv->netlinknh, protocol) < 0) {
virReportSystemError(errno,
- "%s", _("cannot connect to netlink
socket"));
+ _("cannot connect to netlink socket with protocol
%d"), protocol);
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 (groups && setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &groups, sizeof(groups)) < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot add netlink
membership"));
+ goto error_server;
+ }
+
if (nl_socket_set_nonblocking(srv->netlinknh)) {
virReportSystemError(errno, "%s",
_("cannot set netlink socket nonblocking"));
@@ -467,7 +544,7 @@ virNetlinkEventServiceStart(void)
VIR_DEBUG("netlink event listener on fd: %i running", fd);
ret = 0;
- server = srv;
+ server[protocol] = srv;
error_server:
if (ret < 0) {
@@ -491,6 +568,7 @@ error_locked:
* @opaque: user data to pass to callback
* @macaddr: macaddr to store with the data. Used to identify callers.
* May be null.
+ * @protocol: netlink protocol
*
* register a callback for handling of netlink messages. The
* registered function receives the entire netlink message and
@@ -502,10 +580,16 @@ error_locked:
int
virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
virNetlinkEventRemoveCallback removeCB,
- void *opaque, const virMacAddrPtr macaddr)
+ void *opaque, const virMacAddrPtr macaddr,
+ unsigned int protocol)
{
int i, r, ret = -1;
- virNetlinkEventSrvPrivatePtr srv = server;
+ virNetlinkEventSrvPrivatePtr srv = NULL;
+
+ if (protocol >= MAX_LINKS)
+ return -EINVAL;
+
+ srv = server[protocol];
if (handleCB == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -562,6 +646,7 @@ error:
*
* @watch: watch whose handle to remove
* @macaddr: macaddr whose handle to remove
+ * @protocol: netlink protocol
*
* Unregister a callback from a netlink monitor.
* The handler function referenced will no longer receive netlink messages.
@@ -570,11 +655,17 @@ error:
* Returns -1 if the file handle was not registered, 0 upon success
*/
int
-virNetlinkEventRemoveClient(int watch, const virMacAddrPtr macaddr)
+virNetlinkEventRemoveClient(int watch, const virMacAddrPtr macaddr,
+ unsigned int protocol)
{
int i;
int ret = -1;
- virNetlinkEventSrvPrivatePtr srv = server;
+ virNetlinkEventSrvPrivatePtr srv = NULL;
+
+ if (protocol >= MAX_LINKS)
+ return -EINVAL;
+
+ srv = server[protocol];
VIR_DEBUG("removing client watch=%d, mac=%p.", watch, macaddr);
@@ -595,7 +686,7 @@ virNetlinkEventRemoveClient(int watch, const virMacAddrPtr macaddr)
VIR_DEBUG("removed client: %d by %s.",
srv->handles[i].watch, watch ? "index" :
"mac");
- virNetlinkEventRemoveClientPrimitive(i);
+ virNetlinkEventRemoveClientPrimitive(i, protocol);
ret = 0;
goto cleanup;
}
@@ -631,7 +722,9 @@ int virNetlinkCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
unsigned char **respbuf ATTRIBUTE_UNUSED,
unsigned int *respbuflen ATTRIBUTE_UNUSED,
uint32_t src_pid ATTRIBUTE_UNUSED,
- uint32_t dst_pid ATTRIBUTE_UNUSED)
+ uint32_t dst_pid ATTRIBUTE_UNUSED,
+ unsigned int protocol ATTRIBUTE_UNUSED,
+ unsigned int groups ATTRIBUTE_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return -1;
@@ -641,7 +734,7 @@ int virNetlinkCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
* stopNetlinkEventServer: stop the monitor to receive netlink
* messages for libvirtd
*/
-int virNetlinkEventServiceStop(void)
+int virNetlinkEventServiceStop(unsigned int protocol ATTRIBUTE_UNUSED)
{
VIR_DEBUG("%s", _(unsupported));
return 0;
@@ -651,7 +744,8 @@ int virNetlinkEventServiceStop(void)
* startNetlinkEventServer: start a monitor to receive netlink
* messages for libvirtd
*/
-int virNetlinkEventServiceStart(void)
+int virNetlinkEventServiceStart(unsigned int protocol ATTRIBUTE_UNUSED,
+ unsigned int groups ATTRIBUTE_UNUSED)
{
VIR_DEBUG("%s", _(unsupported));
return 0;
@@ -661,13 +755,13 @@ int virNetlinkEventServiceStart(void)
* virNetlinkEventServiceIsRunning: returns if the netlink event
* service is running.
*/
-bool virNetlinkEventServiceIsRunning(void)
+bool virNetlinkEventServiceIsRunning(unsigned int protocol ATTRIBUTE_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return 0;
}
-int virNetlinkEventServiceLocalPid(void)
+int virNetlinkEventServiceLocalPid(unsigned int protocol ATTRIBUTE_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return -1;
@@ -681,6 +775,7 @@ int virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB
ATTRIBUTE_UN
virNetlinkEventRemoveCallback removeCB ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED,
const virMacAddrPtr macaddr ATTRIBUTE_UNUSED)
+ unsigned int protocol ATTRIBUTE_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return -1;
@@ -691,6 +786,7 @@ int virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB
ATTRIBUTE_UN
*/
int virNetlinkEventRemoveClient(int watch ATTRIBUTE_UNUSED,
const virMacAddrPtr macaddr ATTRIBUTE_UNUSED)
+ unsigned int protocol ATTRIBUTE_UNUSED)
{
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
return -1;
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 5d8337d..2e18af4 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -41,7 +41,8 @@ void virNetlinkShutdown(void);
int virNetlinkCommand(struct nl_msg *nl_msg,
unsigned char **respbuf, unsigned int *respbuflen,
- uint32_t src_port, uint32_t dst_port);
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups);
typedef void (*virNetlinkEventHandleCallback)(unsigned char *msg, int length, struct
sockaddr_nl *peer, bool *handled, void *opaque);
@@ -50,33 +51,35 @@ typedef void (*virNetlinkEventRemoveCallback)(int watch, const
virMacAddrPtr mac
/**
* stopNetlinkEventServer: stop the monitor to receive netlink messages for libvirtd
*/
-int virNetlinkEventServiceStop(void);
+int virNetlinkEventServiceStop(unsigned int protocol);
/**
* startNetlinkEventServer: start a monitor to receive netlink messages for libvirtd
*/
-int virNetlinkEventServiceStart(void);
+int virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups);
/**
* virNetlinkEventServiceIsRunning: returns if the netlink event service is running.
*/
-bool virNetlinkEventServiceIsRunning(void);
+bool virNetlinkEventServiceIsRunning(unsigned int protocol);
/**
* virNetlinkEventServiceLocalPid: returns nl_pid used to bind() netlink socket
*/
-int virNetlinkEventServiceLocalPid(void);
+int virNetlinkEventServiceLocalPid(unsigned int protocol);
/**
* virNetlinkEventAddClient: register a callback for handling of netlink messages
*/
int virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
virNetlinkEventRemoveCallback removeCB,
- void *opaque, const virMacAddrPtr macaddr);
+ void *opaque, const virMacAddrPtr macaddr,
+ unsigned int protocol);
/**
* virNetlinkEventRemoveClient: unregister a callback from a netlink monitor
*/
-int virNetlinkEventRemoveClient(int watch, const virMacAddrPtr macaddr);
+int virNetlinkEventRemoveClient(int watch, const virMacAddrPtr macaddr,
+ unsigned int protocol);
#endif /* __VIR_NETLINK_H__ */
--
1.7.10.1