[systemd-commits] 6 commits - src/libsystemd src/network src/systemd
Tom Gundersen
tomegun at kemper.freedesktop.org
Mon Apr 14 08:57:02 PDT 2014
src/libsystemd/sd-rtnl/rtnl-internal.h | 5 +
src/libsystemd/sd-rtnl/rtnl-message.c | 164 ++++++++++++++++++++++++---------
src/libsystemd/sd-rtnl/sd-rtnl.c | 8 +
src/network/networkd-link.c | 14 +-
src/systemd/sd-rtnl.h | 6 +
5 files changed, 149 insertions(+), 48 deletions(-)
New commits:
commit 3379e257ee06f997ec756cd70008353796457b43
Author: Tom Gundersen <teg at jklm.no>
Date: Mon Apr 14 17:55:47 2014 +0200
networkd: link - make state changing logging a bit less verbose
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 927dbb1..f179af3 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1074,14 +1074,14 @@ static int link_update_flags(Link *link, unsigned flags) {
log_info_link(link, "link is down");
if (flags_added & IFF_LOWER_UP)
- log_info_link(link, "link is lower up");
+ log_debug_link(link, "link is lower up");
else if (flags_removed & IFF_LOWER_UP)
- log_info_link(link, "link is lower down");
+ log_debug_link(link, "link is lower down");
if (flags_added & IFF_RUNNING)
- log_info_link(link, "link is running");
+ log_debug_link(link, "link is running");
else if (flags_removed & IFF_RUNNING)
- log_info_link(link, "link is not running");
+ log_debug_link(link, "link is not running");
if (carrier_gained) {
log_info_link(link, "gained carrier");
commit b9ef681b04644493fca7c1d5611db7169697d26a
Author: Tom Gundersen <teg at jklm.no>
Date: Mon Apr 14 12:42:11 2014 +0200
sd-rtnl: message_addr - allow dumping of messages
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index a93cb0c..1afba8f 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -326,15 +326,17 @@ int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
int r;
assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
- assert_return(index > 0, -EINVAL);
- assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
+ assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
+ index > 0, -EINVAL);
+ assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
+ family == AF_INET || family == AF_INET6, -EINVAL);
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nlmsg_type);
if (r < 0)
return r;
- if (nlmsg_type == RTM_GETADDR && family == AF_INET)
+ if (nlmsg_type == RTM_GETADDR)
(*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
ifa = NLMSG_DATA((*ret)->hdr);
commit a88f77c406ea56160c1e5a4b39eab1de134abe40
Author: Tom Gundersen <teg at jklm.no>
Date: Mon Apr 14 17:20:51 2014 +0200
sd-rtnl: socket_read - use a read buffer
Rather than allocating/freeing memory for each message read, keep a global read buffer
in the rtnl object. Also, rather than using a fixed size, peek at the pending message
header to get the message size and reallocate as necessary.
diff --git a/src/libsystemd/sd-rtnl/rtnl-internal.h b/src/libsystemd/sd-rtnl/rtnl-internal.h
index 2f788d0..6dd65b2 100644
--- a/src/libsystemd/sd-rtnl/rtnl-internal.h
+++ b/src/libsystemd/sd-rtnl/rtnl-internal.h
@@ -72,6 +72,9 @@ struct sd_rtnl {
unsigned wqueue_size;
size_t wqueue_allocated;
+ struct nlmsghdr *rbuffer;
+ size_t rbuffer_allocated;
+
bool processing:1;
uint32_t serial;
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 3a24cb8..a93cb0c 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -997,26 +997,6 @@ int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
return err->error;
}
-static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
- assert(rtnl);
- assert(need);
-
- /* ioctl(rtnl->fd, FIONREAD, &need)
- Does not appear to work on netlink sockets. libnl uses
- MSG_PEEK instead. I don't know if that is worth the
- extra roundtrip.
-
- For now we simply use the maximum message size the kernel
- may use (NLMSG_GOODSIZE), and then realloc to the actual
- size after reading the message (hence avoiding huge memory
- usage in case many small messages are kept around) */
- *need = page_size();
- if (*need > 8192UL)
- *need = 8192UL;
-
- return 0;
-}
-
int rtnl_message_parse(sd_rtnl_message *m,
size_t **rta_offset_tb,
unsigned short *rta_tb_size,
@@ -1082,7 +1062,6 @@ int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
int socket_read_message(sd_rtnl *rtnl) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
sd_rtnl_message *previous = NULL;
- _cleanup_free_ void *buffer = NULL;
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
struct iovec iov = {};
struct msghdr msg = {
@@ -1094,23 +1073,37 @@ int socket_read_message(sd_rtnl *rtnl) {
struct cmsghdr *cmsg;
bool auth = false;
struct nlmsghdr *new_msg;
- size_t need, len;
+ size_t len;
int r, ret = 0;
assert(rtnl);
+ assert(rtnl->rbuffer);
- r = message_receive_need(rtnl, &need);
+ iov.iov_base = rtnl->rbuffer;
+ iov.iov_len = rtnl->rbuffer_allocated;
+
+ /* peek at the pending message header to get the message size */
+ r = recvmsg(rtnl->fd, &msg, MSG_PEEK);
if (r < 0)
- return r;
+ /* no data */
+ return (errno == EAGAIN) ? 0 : -errno;
+ else if (r == 0)
+ /* connection was closed by the kernel */
+ return -ECONNRESET;
+ else if ((size_t)r < sizeof(struct nlmsghdr))
+ return -EIO;
- buffer = malloc0(need);
- if (!buffer)
+ /* make room for the pending message */
+ if (!greedy_realloc((void **)&rtnl->rbuffer,
+ &rtnl->rbuffer_allocated,
+ rtnl->rbuffer->nlmsg_len,
+ sizeof(uint8_t)))
return -ENOMEM;
- iov.iov_base = buffer;
- iov.iov_len = need;
+ iov.iov_base = rtnl->rbuffer;
+ iov.iov_len = rtnl->rbuffer_allocated;
- r = recvmsg(rtnl->fd, &msg, 0);
+ r = recvmsg(rtnl->fd, &msg, MSG_TRUNC);
if (r < 0)
/* no data */
return (errno == EAGAIN) ? 0 : -errno;
@@ -1120,6 +1113,10 @@ int socket_read_message(sd_rtnl *rtnl) {
else
len = (size_t)r;
+ if (len > rtnl->rbuffer_allocated)
+ /* message did not fit in read buffer */
+ return -EIO;
+
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
@@ -1138,7 +1135,7 @@ int socket_read_message(sd_rtnl *rtnl) {
/* not from the kernel, ignore */
return 0;
- for (new_msg = buffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
+ for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
const NLType *nl_type;
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 367f165..e4d436b 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -54,6 +54,12 @@ static int sd_rtnl_new(sd_rtnl **ret) {
if (!GREEDY_REALLOC(rtnl->wqueue, rtnl->wqueue_allocated, 1))
return -ENOMEM;
+ /* We guarantee that the read buffer has at least space for
+ * a message header */
+ if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated,
+ sizeof(struct nlmsghdr), sizeof(uint8_t)))
+ return -ENOMEM;
+
*ret = rtnl;
rtnl = NULL;
@@ -133,6 +139,8 @@ sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) {
sd_rtnl_message_unref(rtnl->wqueue[i]);
free(rtnl->wqueue);
+ free(rtnl->rbuffer);
+
hashmap_free_free(rtnl->reply_callbacks);
prioq_free(rtnl->reply_callbacks_prioq);
commit 1403f45ab61d6f2026a3a7a06b52a536c1b7a3b3
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Apr 13 21:37:53 2014 +0200
sd-rtnl: multi-part message - store as linked-list rather than independent messages
This means the API can stay the same as for single-part messages by simply passing the head message around. Unrefing
the head of the linked list unrefs the whole list.
diff --git a/src/libsystemd/sd-rtnl/rtnl-internal.h b/src/libsystemd/sd-rtnl/rtnl-internal.h
index 9d857ed..2f788d0 100644
--- a/src/libsystemd/sd-rtnl/rtnl-internal.h
+++ b/src/libsystemd/sd-rtnl/rtnl-internal.h
@@ -102,6 +102,8 @@ struct sd_rtnl_message {
size_t *rta_offset_tb[RTNL_CONTAINER_DEPTH];
unsigned short rta_tb_size[RTNL_CONTAINER_DEPTH];
bool sealed:1;
+
+ sd_rtnl_message *next; /* next in a chain of multi-part messages */
};
int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type);
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index fc71ed9..3a24cb8 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -378,6 +378,8 @@ sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
for (i = 0; i <= m->n_containers; i++)
free(m->rta_offset_tb[i]);
+ sd_rtnl_message_unref(m->next);
+
free(m);
}
@@ -1078,6 +1080,8 @@ int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
* On failure, a negative error code is returned.
*/
int socket_read_message(sd_rtnl *rtnl) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
+ sd_rtnl_message *previous = NULL;
_cleanup_free_ void *buffer = NULL;
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
struct iovec iov = {};
@@ -1146,6 +1150,10 @@ int socket_read_message(sd_rtnl *rtnl) {
if (new_msg->nlmsg_type == NLMSG_NOOP)
continue;
+ /* finished reading multi-part message */
+ if (new_msg->nlmsg_type == NLMSG_DONE)
+ break;
+
/* check that we support this message type */
r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
if (r < 0) {
@@ -1173,21 +1181,30 @@ int socket_read_message(sd_rtnl *rtnl) {
if (r < 0)
return r;
- r = rtnl_rqueue_make_room(rtnl);
- if (r < 0)
- return r;
+ if (!first)
+ first = m;
+ else {
+ assert(previous);
- rtnl->rqueue[rtnl->rqueue_size ++] = m;
+ previous->next = m;
+ }
+ previous = m;
m = NULL;
+
ret += new_msg->nlmsg_len;
- /* reached end of multi-part message, or not a multi-part
- message at all */
- if (new_msg->nlmsg_type == NLMSG_DONE ||
- !(new_msg->nlmsg_flags & NLM_F_MULTI))
+ /* not a multi-part message, so stop reading*/
+ if (!(new_msg->nlmsg_flags & NLM_F_MULTI))
break;
}
+ r = rtnl_rqueue_make_room(rtnl);
+ if (r < 0)
+ return r;
+
+ rtnl->rqueue[rtnl->rqueue_size ++] = first;
+ first = NULL;
+
return ret;
}
@@ -1249,3 +1266,9 @@ void rtnl_message_seal(sd_rtnl_message *m) {
m->sealed = true;
}
+
+sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
+ assert_return(m, NULL);
+
+ return m->next;
+}
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index c32c5e2..6fbaee0 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -123,6 +123,8 @@ int sd_rtnl_message_exit_container(sd_rtnl_message *m);
int sd_rtnl_message_rewind(sd_rtnl_message *m);
+sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m);
+
_SD_END_DECLARATIONS;
#endif
commit e00d77ddd598ea6cbc2d512d143e9e4d98e62256
Author: Tom Gundersen <teg at jklm.no>
Date: Mon Apr 14 12:41:13 2014 +0200
sd-rtnl: message_addr - expose a few more getters
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index c9f3487..fc71ed9 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -259,6 +259,66 @@ int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
return 0;
}
+int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
+ struct ifaddrmsg *ifa;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(family, -EINVAL);
+
+ ifa = NLMSG_DATA(m->hdr);
+
+ *family = ifa->ifa_family;
+
+ return 0;
+}
+
+int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
+ struct ifaddrmsg *ifa;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(scope, -EINVAL);
+
+ ifa = NLMSG_DATA(m->hdr);
+
+ *scope = ifa->ifa_scope;
+
+ return 0;
+}
+
+int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
+ struct ifaddrmsg *ifa;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(flags, -EINVAL);
+
+ ifa = NLMSG_DATA(m->hdr);
+
+ *flags = ifa->ifa_flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
+ struct ifaddrmsg *ifa;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(ifindex, -EINVAL);
+
+ ifa = NLMSG_DATA(m->hdr);
+
+ *ifindex = ifa->ifa_index;
+
+ return 0;
+}
+
int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
uint16_t nlmsg_type, int index,
unsigned char family) {
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index f7f7074..c32c5e2 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -84,6 +84,10 @@ int sd_rtnl_message_is_broadcast(sd_rtnl_message *m);
int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope);
int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags);
+int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family);
+int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope);
+int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags);
+int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex);
int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change);
int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type);
commit e9189a1f56e5dd418d13dfcf3a7f5a701884858e
Author: Tom Gundersen <teg at jklm.no>
Date: Sun Apr 13 22:10:34 2014 +0200
networkd: link - ignore missing MAC address from NEWLINK message
The kernel may broadcast such messages, simply discard them.
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 7f81538..927dbb1 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1490,10 +1490,10 @@ int link_update(Link *link, sd_rtnl_message *m) {
PRIu16, link->original_mtu);
}
+ /* The kernel may broadcast NEWLINK messages without the MAC address
+ set, simply ignore them. */
r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
- if (r < 0)
- log_debug_link(link, "Could not get MAC address: %s", strerror(-r));
- else {
+ if (r >= 0) {
if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
More information about the systemd-commits
mailing list