From 3815f36f05f8bc06904777b1eb7f1d22b78bcced Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 29 Jan 2014 21:20:30 +0100 Subject: [PATCH] sd-rtnl: beef up rtnl-util a bit --- src/libsystemd/sd-rtnl/rtnl-internal.h | 27 ++++--- src/libsystemd/sd-rtnl/rtnl-message.c | 99 +++++--------------------- src/libsystemd/sd-rtnl/rtnl-util.c | 72 +++++++++++++++++++ src/libsystemd/sd-rtnl/rtnl-util.h | 10 +++ src/libsystemd/sd-rtnl/sd-rtnl.c | 14 ++-- src/libsystemd/sd-rtnl/test-rtnl.c | 5 +- 6 files changed, 125 insertions(+), 102 deletions(-) diff --git a/src/libsystemd/sd-rtnl/rtnl-internal.h b/src/libsystemd/sd-rtnl/rtnl-internal.h index 5dc66ac9d..4bfcb836d 100644 --- a/src/libsystemd/sd-rtnl/rtnl-internal.h +++ b/src/libsystemd/sd-rtnl/rtnl-internal.h @@ -29,6 +29,13 @@ #include "sd-rtnl.h" +#define RTNL_DEFAULT_TIMEOUT ((usec_t) (10 * USEC_PER_SEC)) + +#define RTNL_WQUEUE_MAX 1024 +#define RTNL_RQUEUE_MAX 64*1024 + +#define RTNL_CONTAINER_DEPTH 32 + struct reply_callback { sd_rtnl_message_handler_t callback; void *userdata; @@ -78,20 +85,18 @@ struct sd_rtnl { sd_event *event; }; -#define RTNL_DEFAULT_TIMEOUT ((usec_t) (10 * USEC_PER_SEC)) - -#define RTNL_WQUEUE_MAX 1024 -#define RTNL_RQUEUE_MAX 64*1024 +struct sd_rtnl_message { + RefCount n_ref; -#define RTNL_CONTAINER_DEPTH 32 + struct nlmsghdr *hdr; + size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */ + unsigned n_containers; /* number of containers */ + size_t next_rta_offset; /* offset from hdr to next rta */ -int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret); -uint32_t message_get_serial(sd_rtnl_message *m); -int message_seal(sd_rtnl *nl, sd_rtnl_message *m); + bool sealed:1; +}; -bool message_type_is_link(uint16_t type); -bool message_type_is_addr(uint16_t type); -bool message_type_is_route(uint16_t type); +int message_new(sd_rtnl_message **ret, size_t initial_size); int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m); int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret); diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c index 85c59bfed..87ad68234 100644 --- a/src/libsystemd/sd-rtnl/rtnl-message.c +++ b/src/libsystemd/sd-rtnl/rtnl-message.c @@ -29,25 +29,15 @@ #include "refcnt.h" #include "sd-rtnl.h" +#include "rtnl-util.h" #include "rtnl-internal.h" -struct sd_rtnl_message { - RefCount n_ref; - - struct nlmsghdr *hdr; - size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */ - unsigned n_containers; /* number of containers */ - size_t next_rta_offset; /* offset from hdr to next rta */ - - bool sealed:1; -}; - #define GET_CONTAINER(m, i) (i < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL) #define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset)) #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; -static int message_new(sd_rtnl_message **ret, size_t initial_size) { +int message_new(sd_rtnl_message **ret, size_t initial_size) { sd_rtnl_message *m; assert_return(ret, -EINVAL); @@ -73,67 +63,12 @@ static int message_new(sd_rtnl_message **ret, size_t initial_size) { return 0; } -int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) { - struct nlmsgerr *err; - int r; - - assert(error <= 0); - - r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr))); - if (r < 0) - return r; - - (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); - (*ret)->hdr->nlmsg_type = NLMSG_ERROR; - (*ret)->hdr->nlmsg_seq = serial; - - err = NLMSG_DATA((*ret)->hdr); - - err->error = error; - - return 0; -} - -bool message_type_is_route(uint16_t type) { - switch (type) { - case RTM_NEWROUTE: - case RTM_GETROUTE: - case RTM_DELROUTE: - return true; - default: - return false; - } -} - -bool message_type_is_link(uint16_t type) { - switch (type) { - case RTM_NEWLINK: - case RTM_SETLINK: - case RTM_GETLINK: - case RTM_DELLINK: - return true; - default: - return false; - } -} - -bool message_type_is_addr(uint16_t type) { - switch (type) { - case RTM_NEWADDR: - case RTM_GETADDR: - case RTM_DELADDR: - return true; - default: - return false; - } -} - int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); rtm = NLMSG_DATA(m->hdr); @@ -151,7 +86,7 @@ int sd_rtnl_message_route_new(uint16_t nlmsg_type, unsigned char rtm_family, struct rtmsg *rtm; int r; - assert_return(message_type_is_route(nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL); assert_return(ret, -EINVAL); @@ -182,7 +117,7 @@ int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); ifi = NLMSG_DATA(m->hdr); @@ -200,7 +135,7 @@ int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); ifi = NLMSG_DATA(m->hdr); @@ -213,7 +148,7 @@ int sd_rtnl_message_link_new(uint16_t nlmsg_type, int index, sd_rtnl_message **r struct ifinfomsg *ifi; int r; - assert_return(message_type_is_link(nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL); assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL); assert_return(ret, -EINVAL); @@ -241,7 +176,7 @@ int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixl assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); @@ -259,7 +194,7 @@ int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); @@ -273,7 +208,7 @@ int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); @@ -287,7 +222,7 @@ int sd_rtnl_message_addr_new(uint16_t nlmsg_type, int index, unsigned char famil struct ifaddrmsg *ifa; int r; - assert_return(message_type_is_addr(nlmsg_type), -EINVAL); + 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(ret, -EINVAL); @@ -343,7 +278,7 @@ int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(ifindex, -EINVAL); ifi = NLMSG_DATA(m->hdr); @@ -358,7 +293,7 @@ int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(flags, -EINVAL); ifi = NLMSG_DATA(m->hdr); @@ -726,7 +661,7 @@ int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) { sd_rtnl_message_get_type(m, &rtm_type); - if (message_type_is_link(rtm_type)) { + if (rtnl_message_type_is_link(rtm_type)) { if ((type == IFLA_LINKINFO && m->n_containers == 0) || (type == IFLA_INFO_DATA && m->n_containers == 1 && GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)) @@ -778,7 +713,7 @@ int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) *type = NEXT_RTA(m)->rta_type; - if (message_type_is_link(rtm_type) && + if (rtnl_message_type_is_link(rtm_type) && ((m->n_containers == 0 && NEXT_RTA(m)->rta_type == IFLA_LINKINFO) || (m->n_containers == 1 && @@ -805,7 +740,7 @@ int sd_rtnl_message_exit_container(sd_rtnl_message *m) { return 0; } -uint32_t message_get_serial(sd_rtnl_message *m) { +uint32_t rtnl_message_get_serial(sd_rtnl_message *m) { assert(m); assert(m->hdr); @@ -826,7 +761,7 @@ int sd_rtnl_message_get_errno(sd_rtnl_message *m) { return err->error; } -int message_seal(sd_rtnl *nl, sd_rtnl_message *m) { +int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) { int r; assert(m); diff --git a/src/libsystemd/sd-rtnl/rtnl-util.c b/src/libsystemd/sd-rtnl/rtnl-util.c index dfc0050de..29250c90a 100644 --- a/src/libsystemd/sd-rtnl/rtnl-util.c +++ b/src/libsystemd/sd-rtnl/rtnl-util.c @@ -25,6 +25,7 @@ #include "sd-rtnl.h" #include "rtnl-util.h" +#include "rtnl-internal.h" int rtnl_set_link_name(sd_rtnl *rtnl, int ifindex, const char *name) { _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message = NULL; @@ -98,3 +99,74 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias, return 0; } + +int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) { + struct nlmsgerr *err; + int r; + + assert(error <= 0); + + r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr))); + if (r < 0) + return r; + + (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); + (*ret)->hdr->nlmsg_type = NLMSG_ERROR; + (*ret)->hdr->nlmsg_seq = serial; + + err = NLMSG_DATA((*ret)->hdr); + + err->error = error; + + return 0; +} + +bool rtnl_message_type_is_route(uint16_t type) { + switch (type) { + case RTM_NEWROUTE: + case RTM_GETROUTE: + case RTM_DELROUTE: + return true; + default: + return false; + } +} + +bool rtnl_message_type_is_link(uint16_t type) { + switch (type) { + case RTM_NEWLINK: + case RTM_SETLINK: + case RTM_GETLINK: + case RTM_DELLINK: + return true; + default: + return false; + } +} + +bool rtnl_message_type_is_addr(uint16_t type) { + switch (type) { + case RTM_NEWADDR: + case RTM_GETADDR: + case RTM_DELADDR: + return true; + default: + return false; + } +} + +int rtnl_message_link_get_ifname(sd_rtnl_message *message, const char **ret) { + unsigned short type; + void *name; + + assert(rtnl_message_type_is_link(message->hdr->nlmsg_type)); + + while (sd_rtnl_message_read(message, &type, &name)) { + if (type == IFLA_IFNAME) { + *ret = name; + return 0; + } + } + + return -ENOENT; +} diff --git a/src/libsystemd/sd-rtnl/rtnl-util.h b/src/libsystemd/sd-rtnl/rtnl-util.h index 013002dd6..d590ca74d 100644 --- a/src/libsystemd/sd-rtnl/rtnl-util.h +++ b/src/libsystemd/sd-rtnl/rtnl-util.h @@ -26,9 +26,19 @@ #include "util.h" #include "sd-rtnl.h" +int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret); +uint32_t rtnl_message_get_serial(sd_rtnl_message *m); +int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m); + +bool rtnl_message_type_is_link(uint16_t type); +bool rtnl_message_type_is_addr(uint16_t type); +bool rtnl_message_type_is_route(uint16_t type); + int rtnl_set_link_name(sd_rtnl *rtnl, int ifindex, const char *name); int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu); +int rtnl_message_link_get_ifname(sd_rtnl_message *m, const char **ret); + DEFINE_TRIVIAL_CLEANUP_FUNC(sd_rtnl*, sd_rtnl_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_rtnl_message*, sd_rtnl_message_unref); diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 08b82ab2a..04fcb3d00 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -150,7 +150,7 @@ int sd_rtnl_send(sd_rtnl *nl, assert_return(!rtnl_pid_changed(nl), -ECHILD); assert_return(message, -EINVAL); - r = message_seal(nl, message); + r = rtnl_message_seal(nl, message); if (r < 0) return r; @@ -181,7 +181,7 @@ int sd_rtnl_send(sd_rtnl *nl, } if (serial) - *serial = message_get_serial(message); + *serial = rtnl_message_get_serial(message); return 1; } @@ -256,7 +256,7 @@ static int process_timeout(sd_rtnl *rtnl) { if (c->timeout > n) return 0; - r = message_new_synthetic_error(-ETIMEDOUT, c->serial, &m); + r = rtnl_message_new_synthetic_error(-ETIMEDOUT, c->serial, &m); if (r < 0) return r; @@ -277,7 +277,7 @@ static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) { assert(rtnl); assert(m); - serial = message_get_serial(m); + serial = rtnl_message_get_serial(m); c = hashmap_remove(rtnl->reply_callbacks, &serial); if (!c) return 0; @@ -580,7 +580,7 @@ int sd_rtnl_call(sd_rtnl *nl, if (r < 0) return r; if (incoming) { - uint32_t received_serial = message_get_serial(incoming); + uint32_t received_serial = rtnl_message_get_serial(incoming); if (received_serial == serial) { r = sd_rtnl_message_get_errno(incoming); @@ -833,7 +833,9 @@ int sd_rtnl_add_match(sd_rtnl *rtnl, assert_return(rtnl, -EINVAL); assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); - assert_return(message_type_is_link(type) || message_type_is_addr(type) || message_type_is_route(type), -ENOTSUP); + assert_return(rtnl_message_type_is_link(type) || + rtnl_message_type_is_addr(type) || + rtnl_message_type_is_route(type), -ENOTSUP); c = new0(struct match_callback, 1); if (!c) diff --git a/src/libsystemd/sd-rtnl/test-rtnl.c b/src/libsystemd/sd-rtnl/test-rtnl.c index ec6b29438..15e42b68f 100644 --- a/src/libsystemd/sd-rtnl/test-rtnl.c +++ b/src/libsystemd/sd-rtnl/test-rtnl.c @@ -27,7 +27,6 @@ #include "sd-rtnl.h" #include "socket-util.h" #include "rtnl-util.h" -#include "rtnl-internal.h" #include "event-util.h" static void test_link_configure(sd_rtnl *rtnl, int ifindex) { @@ -86,7 +85,7 @@ static void test_route(void) { return; } - assert(message_seal(NULL, req) >= 0); + assert(rtnl_message_seal(NULL, req) >= 0); assert(sd_rtnl_message_read(req, &type, &data) > 0); assert(type == RTA_GATEWAY); @@ -227,7 +226,7 @@ static void test_container(void) { assert(sd_rtnl_message_close_container(m) >= 0); assert(sd_rtnl_message_close_container(m) == -EINVAL); - assert(message_seal(NULL, m) >= 0); + assert(rtnl_message_seal(NULL, m) >= 0); assert(sd_rtnl_message_read(m, &type, &data) >= 0); assert(type == IFLA_LINKINFO); -- 2.30.2