In a second step I am converting the netlink send/receive function to
use libnl.
I tested this with 802.1Qbg profiles and my test server and did not see
a regression.
Caveat: The online documentation of libnl talks about nl_socket_alloc()
but the header file provides nl_handle_alloc() -- this could be a hint
to a possible problem between libnl versions...
http://www.infradead.org/~tgr/libnl/doc/group__socket.html
versus
http://libnl.sourcearchive.com/documentation/1.1/group__socket_gf903c9ea0...
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/util/macvtap.c | 89
++++++++++++++++++-----------------------------------
1 file changed, 31 insertions(+), 58 deletions(-)
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -82,22 +82,6 @@ enum virVirtualPortOp {
};
-static int nlOpen(void)
-{
- int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0)
- virReportSystemError(errno,
- "%s",_("cannot open netlink socket"));
- return fd;
-}
-
-
-static void nlClose(int fd)
-{
- close(fd);
-}
-
-
/**
* nlComm:
* @nlmsg: pointer to netlink message
@@ -111,8 +95,8 @@ static void nlClose(int fd)
* buffer will be returned.
*/
static
-int nlComm(struct nlmsghdr *nlmsg,
- char **respbuf, unsigned int *respbuflen,
+int nlComm(struct nl_msg *nl_msg,
+ unsigned char **respbuf, unsigned int *respbuflen,
int nl_pid)
{
int rc = 0;
@@ -121,24 +105,29 @@ int nlComm(struct nlmsghdr *nlmsg,
.nl_pid = nl_pid,
.nl_groups = 0,
};
- int rcvChunkSize = 1024; // expecting less than that
- int rcvoffset = 0;
ssize_t nbytes;
struct timeval tv = {
.tv_sec = NETLINK_ACK_TIMEOUT_S,
};
fd_set readfds;
- int fd = nlOpen();
+ int fd;
int n;
+ struct nl_handle *nlhandle = nl_handle_alloc();
+ struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
- if (fd < 0)
+ if (!nlhandle)
return -1;
+ if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) {
+ rc = -1;
+ goto err_exit;
+ }
+
+ nlmsg_set_dst(nl_msg, &nladdr);
+
nlmsg->nlmsg_pid = getpid();
- nlmsg->nlmsg_flags |= NLM_F_ACK;
- nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len, 0,
- (struct sockaddr *)&nladdr, sizeof(nladdr));
+ nbytes = nl_send_auto_complete(nlhandle, nl_msg);
if (nbytes < 0) {
virReportSystemError(errno,
"%s", _("cannot send to netlink
socket"));
@@ -146,6 +135,8 @@ int nlComm(struct nlmsghdr *nlmsg,
goto err_exit;
}
+ fd = nl_socket_get_fd(nlhandle);
+
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
@@ -161,28 +152,9 @@ int nlComm(struct nlmsghdr *nlmsg,
goto err_exit;
}
- while (1) {
- if (VIR_REALLOC_N(*respbuf, rcvoffset+rcvChunkSize) < 0) {
- virReportOOMError();
- rc = -1;
- goto err_exit;
- }
-
- socklen_t addrlen = sizeof(nladdr);
- nbytes = recvfrom(fd, &((*respbuf)[rcvoffset]), rcvChunkSize, 0,
- (struct sockaddr *)&nladdr, &addrlen);
- if (nbytes < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
- virReportSystemError(errno, "%s",
- _("error receiving from netlink socket"));
- rc = -1;
- goto err_exit;
- }
- rcvoffset += nbytes;
- break;
- }
- *respbuflen = rcvoffset;
+ *respbuflen = nl_recv(nlhandle, &nladdr, respbuf, NULL);
+ if (*respbuflen <= 0)
+ rc = -1;
err_exit:
if (rc == -1) {
@@ -191,7 +163,8 @@ err_exit:
*respbuflen = 0;
}
- nlClose(fd);
+ nl_handle_destroy(nlhandle);
+
return rc;
}
@@ -211,7 +184,7 @@ link_add(const char *type,
struct nlmsgerr *err;
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
int ifindex;
- char *recvbuf = NULL;
+ unsigned char *recvbuf = NULL;
unsigned int recvbuflen;
struct nl_msg *nl_msg;
struct nlattr *linkinfo, *info_data;
@@ -260,7 +233,7 @@ link_add(const char *type,
nla_nest_end(nl_msg, linkinfo);
- if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, 0) < 0) {
+ if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) {
rc = -1;
goto err_exit;
}
@@ -332,7 +305,7 @@ link_del(const char *ifname)
struct nlmsghdr *resp;
struct nlmsgerr *err;
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
- char *recvbuf = NULL;
+ unsigned char *recvbuf = NULL;
unsigned int recvbuflen;
struct nl_msg *nl_msg;
@@ -349,7 +322,7 @@ link_del(const char *ifname)
if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
goto buffer_too_small;
- if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, 0) < 0) {
+ if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) {
rc = -1;
goto err_exit;
}
@@ -746,7 +719,7 @@ getLldpadPid(void) {
static int
link_dump(bool nltarget_kernel, const char *ifname, int ifindex,
- struct nlattr **tb, char **recvbuf)
+ struct nlattr **tb, unsigned char **recvbuf)
{
int rc = 0;
struct nlmsghdr *resp;
@@ -783,7 +756,7 @@ link_dump(bool nltarget_kernel, const ch
}
}
- if (nlComm(nlmsg_hdr(nl_msg), recvbuf, &recvbuflen, pid) < 0) {
+ if (nlComm(nl_msg, recvbuf, &recvbuflen, pid) < 0) {
rc = -1;
goto err_exit;
}
@@ -869,7 +842,7 @@ ifaceGetNthParent(int ifindex, const cha
{
int rc;
struct nlattr *tb[IFLA_MAX + 1] = { NULL, };
- char *recvbuf = NULL;
+ unsigned char *recvbuf = NULL;
bool end = false;
unsigned int i = 0;
@@ -1029,7 +1002,7 @@ doPortProfileOpSetLink(bool nltarget_ker
.ifi_family = AF_UNSPEC,
.ifi_index = ifindex,
};
- char *recvbuf = NULL;
+ unsigned char *recvbuf = NULL;
unsigned int recvbuflen = 0;
uint32_t pid = 0;
struct nl_msg *nl_msg;
@@ -1140,7 +1113,7 @@ doPortProfileOpSetLink(bool nltarget_ker
}
}
- if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, pid) < 0) {
+ if (nlComm(nl_msg, &recvbuf, &recvbuflen, pid) < 0) {
rc = -1;
goto err_exit;
}
@@ -1208,7 +1181,7 @@ doPortProfileOpCommon(bool nltarget_kern
uint8_t op)
{
int rc;
- char *recvbuf = NULL;
+ unsigned char *recvbuf = NULL;
struct nlattr *tb[IFLA_MAX + 1] = { NULL , };
int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC;
uint16_t status = 0;