All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcel Holtmann <marcel@holtmann.org>
To: ell@lists.01.org
Subject: Re: [PATCH 2/4] genl: Add a message builder API to help creating complex nl messages
Date: Wed, 18 Mar 2015 10:24:15 -0700	[thread overview]
Message-ID: <2ABAC5E1-9C53-4599-9740-316A32C15557@holtmann.org> (raw)
In-Reply-To: <1425986070-8808-3-git-send-email-tomasz.bursztyka@linux.intel.com>

[-- Attachment #1: Type: text/plain, Size: 5732 bytes --]

Hi Tomasz,

> ---
> ell/genl.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ell/genl.h |  18 +++++++++
> 2 files changed, 152 insertions(+)
> 
> diff --git a/ell/genl.c b/ell/genl.c
> index 90c0864..c49c363 100644
> --- a/ell/genl.c
> +++ b/ell/genl.c
> @@ -34,6 +34,7 @@
> #include "io.h"
> #include "netlink-private.h"
> #include "genl.h"
> +#include "genl-private.h"
> #include "private.h"
> 
> struct l_genl {
> @@ -114,6 +115,12 @@ struct l_genl_family {
> 	unsigned int nlctrl_cmd;
> };
> 
> +struct l_genl_msg_builder {
> +	struct l_genl_msg *message;
> +	struct l_queue *nests;
> +	struct nlattr *last_nested;
> +};
> +
> static void destroy_request(void *data)
> {
> 	struct genl_request *request = data;
> @@ -642,6 +649,16 @@ LIB_EXPORT struct l_genl_msg *l_genl_msg_new_sized(uint8_t cmd, uint32_t size)
> 	return msg_alloc(cmd, 0x00, size);
> }
> 
> +const void *_genl_msg_get_as_raw_data(struct l_genl_msg *msg, uint32_t *len)
> +{
> +	if (!msg)
> +		return NULL;
> +
> +	*len = msg->len;
> +
> +	return msg->data;
> +}
> +
> LIB_EXPORT struct l_genl_msg *l_genl_msg_ref(struct l_genl_msg *msg)
> {
> 	if (unlikely(!msg))
> @@ -1252,3 +1269,120 @@ LIB_EXPORT bool l_genl_family_unregister(struct l_genl_family *family,
> 
> 	return true;
> }
> +
> +LIB_EXPORT struct l_genl_msg_builder *l_genl_msg_builder_new(
> +						struct l_genl_msg *message)
> +{
> +	struct l_genl_msg_builder *ret;
> +
> +	if (unlikely(!message))
> +		return NULL;
> +
> +	ret = l_new(struct l_genl_msg_builder, 1);
> +	ret->message = l_genl_msg_ref(message);
> +
> +	return ret;
> +}
> +
> +static inline void builder_message_realign(struct l_genl_msg_builder *builder)
> +{
> +	if (!builder->last_nested)
> +		return;
> +
> +	if (!builder->nests)
> +		builder->message->len = NLA_ALIGN(builder->message->len);
> +
> +	builder->last_nested = NULL;
> +}
> +
> +LIB_EXPORT bool l_genl_msg_builder_append_attribute(
> +					struct l_genl_msg_builder *builder,
> +					uint16_t type, uint16_t len,
> +					const void *data)
> +{
> +	if (unlikely(!builder))
> +		return false;
> +
> +	builder_message_realign(builder);
> +
> +	return l_genl_msg_append_attr(builder->message, type, len, data);
> +}
> +
> +LIB_EXPORT bool l_genl_msg_builder_enter_nested(
> +					struct l_genl_msg_builder *builder,
> +					uint16_t type)
> +{
> +	struct nlattr *nla;
> +
> +	if (unlikely(!builder))
> +		return false;
> +
> +	if (!builder->nests) {
> +		builder->nests = l_queue_new();
> +		if (!builder->nests)
> +			return false;
> +	}

do we really need a queue here? Can we not just store the latest offset. Also how do you do nested of nested attributes?

> +
> +	builder_message_realign(builder);
> +
> +	nla = builder->message->data + builder->message->len;
> +	nla->nla_len = NLA_HDRLEN;
> +	nla->nla_type = type;
> +
> +	if (!l_genl_msg_append_attr(builder->message, type, 0, NULL))
> +		return false;
> +
> +	return l_queue_push_head(builder->nests, nla);
> +}
> +
> +LIB_EXPORT bool l_genl_msg_builder_leave_nested(
> +					struct l_genl_msg_builder *builder)
> +{
> +	struct nlattr *nla;
> +	uint32_t len;
> +
> +	if (unlikely(!builder) || unlikely(!builder->nests))
> +		return false;
> +
> +	nla = l_queue_pop_head(builder->nests);
> +	if (!nla)
> +		return false;
> +
> +	if (l_queue_isempty(builder->nests)) {
> +		l_queue_destroy(builder->nests, NULL);
> +		builder->nests = NULL;
> +	}
> +
> +	// In case nothing has been appended into the nested attribute
> +	// it could try to be smart and revert the message back and return true

this is not our comment style. Please respect the coding style.

> +	len = builder->message->len - ((void *)nla - builder->message->data);
> +	if (len <= NLA_HDRLEN)
> +		return false;
> +
> +	nla->nla_len = len;
> +
> +	builder->last_nested = nla;
> +
> +	return true;
> +}
> +
> +LIB_EXPORT void l_genl_msg_builder_destroy(struct l_genl_msg_builder *builder)
> +{
> +	if (unlikely(!builder))
> +		return;
> +
> +	l_queue_destroy(builder->nests, NULL);
> +	l_genl_msg_unref(builder->message);
> +	l_free(builder);
> +}
> +
> +LIB_EXPORT struct l_genl_msg *l_genl_msg_builder_finalize(
> +					struct l_genl_msg_builder *builder)
> +{
> +	if (unlikely(!builder) || unlikely(builder->nests))
> +		return NULL;
> +
> +	builder_message_realign(builder);
> +
> +	return builder->message;
> +}
> diff --git a/ell/genl.h b/ell/genl.h
> index c628b8c..a31db1c 100644
> --- a/ell/genl.h
> +++ b/ell/genl.h
> @@ -112,6 +112,24 @@ unsigned int l_genl_family_register(struct l_genl_family *family,
> 				void *user_data, l_genl_destroy_func_t destroy);
> bool l_genl_family_unregister(struct l_genl_family *family, unsigned int id);
> 
> +struct l_genl_msg_builder;
> +
> +struct l_genl_msg_builder *l_genl_msg_builder_new(struct l_genl_msg *msg);
> +
> +bool l_genl_msg_builder_append_attribute(struct l_genl_msg_builder *builder,
> +						uint16_t type, uint16_t len,
> +						const void *data);
> +
> +bool l_genl_msg_builder_enter_nested(struct l_genl_msg_builder *builder,
> +								uint16_t type);
> +
> +bool l_genl_msg_builder_leave_nested(struct l_genl_msg_builder *builder);
> +
> +void l_genl_msg_builder_destroy(struct l_genl_msg_builder *builder);
> +
> +struct l_genl_msg *l_genl_msg_builder_finalize(
> +					struct l_genl_msg_builder *builder);

So I saw that l_dbus_message_builder does a similar thing. We give in a message to start from and then we get that message back out when finalizing it. Has anything changed in between or why are we doing this?

Regards

Marcel


  reply	other threads:[~2015-03-18 17:24 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-10 11:14 [PATCH v2 0/4] Improve genl with a message builder Tomasz Bursztyka
2015-03-10 11:14 ` [PATCH 1/4] genl: Normilize functions exports and parameters check as it should Tomasz Bursztyka
2015-03-11  5:03   ` Denis Kenzior
2015-03-10 11:14 ` [PATCH 2/4] genl: Add a message builder API to help creating complex nl messages Tomasz Bursztyka
2015-03-18 17:24   ` Marcel Holtmann [this message]
2015-03-20  8:51     ` Tomasz Bursztyka
2015-03-24  8:12       ` Tomasz Bursztyka
2015-03-10 11:14 ` [PATCH 3/4] genl: Add a function to grab the message's raw data for unit purpose Tomasz Bursztyka
2015-03-10 11:14 ` [PATCH 4/4] unit: Add a message builder unit test for genl Tomasz Bursztyka
2015-03-18 17:24   ` Marcel Holtmann
2015-03-20 22:41   ` Marcel Holtmann
2015-03-24  6:55     ` Tomasz Bursztyka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2ABAC5E1-9C53-4599-9740-316A32C15557@holtmann.org \
    --to=marcel@holtmann.org \
    --cc=ell@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.