[ovs-dev] [QoS v2 13/17] netlink: Improve support for nested Netlink attributes.

Justin Pettit jpettit at nicira.com
Wed Jun 9 22:20:15 UTC 2010


Looks good.

--Justin


On Jun 8, 2010, at 1:41 PM, Ben Pfaff wrote:

> Fairly often it happens that nested Netlink attributes must themselves
> contain Netlink attributes.  In such a case, nlmsg_put_nested() is not so
> convenient, because it requires the contents to be pre-assembled and then
> copied into place.  This commit introduces a new interface that instead
> allows the nested attributes to be assembled in-place.  As a demonstration,
> it updates nl_msg_put_nested() to use this new interface.
> ---
> lib/netlink.c |   34 ++++++++++++++++++++++++++++------
> lib/netlink.h |   14 +++++++++-----
> 2 files changed, 37 insertions(+), 11 deletions(-)
> 
> diff --git a/lib/netlink.c b/lib/netlink.c
> index 6eee028..bde66b3 100644
> --- a/lib/netlink.c
> +++ b/lib/netlink.c
> @@ -811,15 +811,37 @@ nl_msg_put_string(struct ofpbuf *msg, uint16_t type, const char *value)
>     nl_msg_put_unspec(msg, type, value, strlen(value) + 1);
> }
> 
> -/* Appends a Netlink attribute of the given 'type' and the given buffered
> - * netlink message in 'nested_msg' to 'msg'.  The nlmsg_len field in
> - * 'nested_msg' is finalized to match 'nested_msg->size'. */
> +/* Adds the header for nested Netlink attributes to 'msg', with the specified
> + * 'type', and returns the header's offset within 'msg'.  The caller should add
> + * the content for the nested Netlink attribute to 'msg' (e.g. using the other
> + * nl_msg_*() functions), and then pass the returned offset to
> + * nl_msg_end_nested() to finish up the nested attributes. */
> +size_t
> +nl_msg_start_nested(struct ofpbuf *msg, uint16_t type)
> +{
> +    size_t offset = msg->size;
> +    nl_msg_put_unspec(msg, type, NULL, 0);
> +    return offset;
> +}
> +
> +/* Finalizes a nested Netlink attribute in 'msg'.  'offset' should be the value
> + * returned by nl_msg_start_nested(). */
> +void
> +nl_msg_end_nested(struct ofpbuf *msg, size_t offset)
> +{
> +    struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr);
> +    attr->nla_len = msg->size - offset;
> +}
> +
> +/* Appends a nested Netlink attribute of the given 'type', with the 'size'
> + * bytes of content starting at 'data', to 'msg'. */
> void
> nl_msg_put_nested(struct ofpbuf *msg,
> -                  uint16_t type, struct ofpbuf *nested_msg)
> +                  uint16_t type, const void *data, size_t size)
> {
> -    nl_msg_nlmsghdr(nested_msg)->nlmsg_len = nested_msg->size;
> -    nl_msg_put_unspec(msg, type, nested_msg->data, nested_msg->size);
> +    size_t offset = nl_msg_start_nested(msg, type);
> +    nl_msg_put(msg, data, size);
> +    nl_msg_end_nested(msg, offset);
> }
> 
> /* If 'buffer' begins with a valid "struct nlmsghdr", pulls the header and its
> diff --git a/lib/netlink.h b/lib/netlink.h
> index 13f1459..9cb1f81 100644
> --- a/lib/netlink.h
> +++ b/lib/netlink.h
> @@ -52,10 +52,10 @@ void nl_sock_wait(const struct nl_sock *, short int events);
> 
> /* Table dumping. */
> struct nl_dump {
> -    uint32_t seq;
> -    struct nl_sock *sock;
> -    int status;
> -    struct ofpbuf *buffer;
> +    struct nl_sock *sock;       /* Socket being dumped. */
> +    uint32_t seq;               /* Expected nlmsg_seq for replies. */
> +    struct ofpbuf *buffer;      /* Receive buffer currently being iterated. */
> +    int status;                 /* 0=OK, EOF=done, or positive errno value. */
> };
> 
> void nl_dump_start(struct nl_dump *, struct nl_sock *,
> @@ -89,7 +89,11 @@ void nl_msg_put_u16(struct ofpbuf *, uint16_t type, uint16_t value);
> void nl_msg_put_u32(struct ofpbuf *, uint16_t type, uint32_t value);
> void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value);
> void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value);
> -void nl_msg_put_nested(struct ofpbuf *, uint16_t type, struct ofpbuf *);
> +
> +size_t nl_msg_start_nested(struct ofpbuf *, uint16_t type);
> +void nl_msg_end_nested(struct ofpbuf *, size_t offset);
> +void nl_msg_put_nested(struct ofpbuf *, uint16_t type,
> +                       const void *data, size_t size);
> 
> /* Separating buffers into individual messages. */
> struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg);
> -- 
> 1.7.1
> 
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev_openvswitch.org





More information about the dev mailing list