From thaller at redhat.com  Wed Dec  2 03:22:45 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 12:22:45 +0100
Subject: [PATCH 1/3] link: Add AF operation to append attributes to a
 GETLINK message
In-Reply-To: <1448478856-44332-2-git-send-email-dsa@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-2-git-send-email-dsa@cumulusnetworks.com>
Message-ID: <1449055365.13402.2.camel@redhat.com>

On Wed, 2015-11-25 at 11:14 -0800, David Ahern wrote:
> Upcoming bridge patch wants to add IFLA_EXT_MASK attribute to
> RTM_GETLINK
> requests to retrieve VLAN data. Expand request message to a full
> ifinfomsg
> header and call to hook to append attributes if it exists for an
> address
> family.
> 
> Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
> ---
> ?include/netlink-private/route/link/api.h |??4 ++++
> ?lib/route/link.c?????????????????????????| 26
> +++++++++++++++++++++++++-
> ?2 files changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/include/netlink-private/route/link/api.h
> b/include/netlink-private/route/link/api.h
> index 85f83f39539d..2d5665821477 100644
> --- a/include/netlink-private/route/link/api.h
> +++ b/include/netlink-private/route/link/api.h
> @@ -119,6 +119,10 @@ struct rtnl_link_af_ops
> ?	int		??????(*ao_fill_af)(struct rtnl_link *,
> ?					????struct nl_msg *msg, void
> *);
> ?
> +	/** Called for GETLINK message to the kernel. Used to append
> +	?* link address family specific attributes to the request
> message. */
> +	int		??????(*ao_get_af)(struct nl_msg *msg);
> +
> ?	/** Dump address family specific link attributes */
> ?	void		??????(*ao_dump[NL_DUMP_MAX+1])(struct
> rtnl_link *,
> ?							struct
> nl_dump_params *,
> diff --git a/lib/route/link.c b/lib/route/link.c
> index cfe3779f41f4..3cb62df95d6a 100644
> --- a/lib/route/link.c
> +++ b/lib/route/link.c
> @@ -657,8 +657,32 @@ static int link_msg_parser(struct nl_cache_ops
> *ops, struct sockaddr_nl *who,
> ?static int link_request_update(struct nl_cache *cache, struct
> nl_sock *sk)
> ?{
> ?	int family = cache->c_iarg1;
> +	struct ifinfomsg hdr = { .ifi_family = family };
> +	struct rtnl_link_af_ops *ops;
> +	struct nl_msg *msg;
> +	int err;
> +
> +	msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_DUMP);
> +	if (!msg)
> +		return -NLE_NOMEM;
> +
> +	err = -NLE_MSGSIZE;
> +	if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0)
> +		goto nla_put_failure;
> ?
> -	return nl_rtgen_request(sk, RTM_GETLINK, family,
> NLM_F_DUMP);
> +	ops = rtnl_link_af_ops_lookup(family);
> +	if (ops && ops->ao_get_af) {
> +		err = ops->ao_get_af(msg);
> +		if (err)
> +			goto nla_put_failure;
> +	}
> +	err = nl_send_auto(sk, msg);
> +
> +????????return err >= 0 ? 0 : err;

this causes @msg to leak.

How about:

- ? return err >= 0 ? 0 : err;
+ ? if (err >= 0)
+ ? ? ? err = 0;


> +
> +nla_put_failure:
> +	nlmsg_free(msg);
> +	return err;
> ?}
> ?
> ?static void link_dump_line(struct nl_object *obj, struct
> nl_dump_params *p)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/ffbc7d8e/attachment.sig>

From thaller at redhat.com  Wed Dec  2 03:29:16 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 12:29:16 +0100
Subject: [PATCH 2/3] Handle family-based parsing of IFLA_AF_SPEC attribute
In-Reply-To: <1448478856-44332-3-git-send-email-dsa@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-3-git-send-email-dsa@cumulusnetworks.com>
Message-ID: <1449055756.13402.5.camel@redhat.com>

On Wed, 2015-11-25 at 11:14 -0800, David Ahern wrote:
> The encoding of the IFLA_AF_SPEC attribute varies depending on the
> family
> used for the request (RTM_GETLINK) message. For AF_UNSPEC the
> encoding
> has another level of nesting for each address family with the type
> encoded
> first. i.e.,
> ????af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
> ????for each family:
> ????????af = nla_nest_start(skb, af_ops->family)
> ????????af_ops->fill_link_af(skb, dev, ext_filter_mask)
> ????????nest_end
> ????nest_end
> 
> This allows the parser to find the address family by looking at the
> first
> type.
> 
> Whereas AF_BRIDGE encoding is just:
> ????af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
> ????br_fill_ifvlaninfo{_compressed}(skb, vg)
> ????nest_end
> 
> which means the parser can not use the attribute itself to know the
> family
> to which the attribute belongs.
> 
> Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
> ---
> ?lib/route/link.c | 89
> ++++++++++++++++++++++++++++++++++++++++++++++----------
> ?1 file changed, 74 insertions(+), 15 deletions(-)
> 
> 





> 			err = af_ops->ao_parse_af(link, af_attr,
> af_data);
> -				if (err < 0)
> -					goto errout;
> -			}
> -
> +		/* parsing of IFLA_AF_SPEC is dependent on the
> family used
> +		?* in the request message.
> +		?*/
> +		switch(family) {
> +		case AF_BRIDGE:
> +			err = parse_af_spec_bridge(link,
> tb[IFLA_AF_SPEC]);
> +			break;
> +		case AF_UNSPEC:
> +			err = parse_af_spec_unspec(link,
> tb[IFLA_AF_SPEC]);
> +			break;
> +		default:
> +			err = -EINVAL;
> +			NL_DBG(1, "IFLA_AF_SPEC parsing not
> implemented for family %d\n",
> +				family);

isn't it a bit too severe to fail parsing entirely on an unknown
family?

Maybe just print the warning and continue parsing?

Note that usually we also just ignore unknown attributes (which allows
libnl to work also with newer kernels -- mostly).




Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/5bf28373/attachment.sig>

From thaller at redhat.com  Wed Dec  2 05:25:25 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 14:25:25 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
Message-ID: <1449062725.27857.11.camel@redhat.com>

On Wed, 2015-11-25 at 11:14 -0800, David Ahern wrote:
> Add operation for requesting VLAN data for AF_BRIDGE and parsing of
> IFLA_AF_SPEC for AF_BRIDGE. VLANs are saved in a bitmap.
> 
> Also add dumping of vlan info to link list and neigh list.
> For example:
> 
> $ nl-link-list --details --family=bridge
> br1 ether 8e:6e:0e:86:e5:86 master br1
> <broadcast,multicast,up,running,lowerup>
> ????mtu 1500 txqlen 0 weight 0 index 18
> ????mode default carrier down
> ????bridge: pvid 1???all vlans: 1 301-400 601-610???untagged vlans: 1
> bond1 ether 46:ef:e1:c9:46:fe <broadcast,multicast,master>
> ????mtu 1500 txqlen 0 weight 0 index 20
> ????state down mode default carrier down
> ????bridge:
> 
> Signed-off-by: Wilson Kok <wkok at cumulusnetworks.com>
> Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
> ---
> ?include/linux-private/linux/if_bridge.h |??14 +++
> ?include/linux-private/linux/rtnetlink.h |???6 +

when updating the kernel headers, we should copy an entire header
at once so that it is clear from which version it is taken.

Don't bother to do that, I'm just saying, before I merge the patch, I
will update the entire header file not only parts.



>?
> diff --git a/include/netlink/route/link/bridge.h
> b/include/netlink/route/link/bridge.h
> index 16a4505f8b74..5dc6a367595c 100644
> --- a/include/netlink/route/link/bridge.h
> +++ b/include/netlink/route/link/bridge.h
> @@ -19,6 +19,22 @@
> ?extern "C" {
> ?#endif
> ?
> +/* maximum vlan id */
> +#define VLAN_N_VID		4096
> +
> +#define BITS_PER_BYTE		8
> +#define BITS_PER_LONG		(BITS_PER_BYTE *
> sizeof(unsigned long))
> +#define DIV_ROUND_UP(n,d)	(((n) + (d) - 1) / (d))
> +#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_LONG)
> +#define BR_VLAN_BITMAP_LEN	BITS_TO_LONGS(VLAN_N_VID)
> +
> +struct bridge_vlan
> +{
> +	uint16_t????????????????pvid;
> +	unsigned long???????????vlan_bitmap[BR_VLAN_BITMAP_LEN];
> +	unsigned long???????????untagged_bitmap[BR_VLAN_BITMAP_LEN];
> +};
> +

all defines and declarations in public headers should have a distinct
prefix, "rtnl_" for libnl-route-3.so and "nl_" for libnl-3.so.




How about having the type as "uint32_t", instead of "unsigned long".
Leaving it undefined (at using C's long) only makes it more complicated
and I don't think we support an architecture where BITS_PER_BYTES isn't
8 (or uint32_t isn't 32 bits).


Also, the defines aren't really useful in the public API, because it's
clear the Vlan ids range from 0 to 4095. Even if one day that would
change (extremely unlikely), you couldn't just change the define
without breaking ABI. So users using the define don't get any actual
advantage.


How about only:

struct rtnl_bridge_vlan
{
	uint16_t????????????????pvid;
?	uint32_t ? ? ? ? ? ? ? ?vlan_bitmap[4096 / 32];
	uint32_t ? ? ? ? ? ? ? ?untagged_bitmap[4096 / 32];
};






There are the internal utilities set_bit() and clear_bit().
clear_bit() is unused, but it seems they would be useful enough to
expose them in public API like:

int rtnl_bridge_vlan_bitmap_get(const uint32_t *bitmap, uint idx) {
? ? ?return idx < 4096 && ((bitmap[idx / 32] & ((uint32_t) 1 << (idx %
32))));
}

void rtnl_bridge_vlan_bitmap_set(uint32_t *bitmap, uint idx, int is_set) {
     ....
}



Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/fa977610/attachment.sig>

From thaller at redhat.com  Wed Dec  2 06:21:02 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 15:21:02 +0100
Subject: [PATCH 2/2] route/link: handle RTEXT_FILTER_BRVLAN_COMPRESSED
In-Reply-To: <1448552878.7407.61.camel@bisdn.de>
References: <1448552878.7407.61.camel@bisdn.de>
Message-ID: <1449066062.27857.34.camel@redhat.com>

On Thu, 2015-11-26 at 16:47 +0100, Tobias Jungel wrote:
> notifications from the kernel regarding vlan ids are now handled
> ---
> ?lib/route/link.c????????| 12 +++-----
> ?lib/route/link/bridge.c | 82
> ++++++++++++++++++++++++++++++++++++++++++++-----
> ?2 files changed, 78 insertions(+), 16 deletions(-)

Hi Tobias,



before your patch, there were three implementations of ao_af_parse:

  lib/route/link/bridge.c:?????.ao_parse_af?????????????= &bridge_parse_af,
  lib/route/link/inet.c:??.ao_parse_af?????????????= &inet_parse_af,
  lib/route/link/inet6.c: .ao_parse_af?????????????= &inet6_parse_protinfo,

and two callers in?lib/route/link.c:
??parse_af_spec_unspec()
??parse_af_spec_bridge()


with the change:

-????.ao_parse_af?????????????= &bridge_parse_af,
+????.ao_parse_af_full????????= &bridge_parse_af,


parse_af_spec_unspec() can no longer parse AF_BRIDGE as a nested
attribute (AF_BRIDGE can then only be parsed as top-level attribute via
parse_af_spec_bridge()).
Is parsing AF_BRIDGE as nested in parse_af_spec_unspec() not necessary?
I think you have to preserve the original
? .ao_parse_af?????????????= &bridge_parse_af,
too.





Second:


The patch "Handle family-based parsing of IFLA_AF_SPEC attribute"
adds:

[1]
       switch(family) {
????????????????case AF_BRIDGE:
????????????????????????err = parse_af_spec_bridge(link, tb[IFLA_AF_SPEC]);
????????????????????????break;
????????????????case AF_UNSPEC:
????????????????????????err = parse_af_spec_unspec(link, tb[IFLA_AF_SPEC]);
????????????????????????break;

thus making the link_msg_parser() aware of how to parse AF_BRIDGE.



At this point you can do one of two things:

(a) have parse_af_spec_bridge() call directly to bridge_parse_af() without
    the intermediate step of introducing ao_parse_af_full().
    You already *know* that you parse a AF_BRIDGE. There is no point in using
    the virtual function table to invoke the bridge parser.

(b) Or better: change [1] to be actually generic:

???if (tb[IFLA_AF_SPEC]) {
?????????/* parsing of IFLA_AF_SPEC is dependent on the family used
??????????* in the request message.
 ?????????*/
         if (family == AF_UNSPEC)
 ????????????err = parse_af_spec_unspec(link, tb[IFLA_AF_SPEC]);
         else if (af_ops && af_ops->ao_parse_af_full) {
             /* call to ao_parse_af_full, as you did in parse_af_spec_bridge().
                possibly renaming parse_af_spec_bridge() to parse_af_spec_full()
                or better just copy the content of?parse_af_spec_bridge() to here. */
         } else {
             NL_DBG(1, "IFLA_AF_SPEC parsing not implemented for family %d\n",);
         }






Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/cb05e593/attachment.sig>

From tobias.jungel at bisdn.de  Wed Dec  2 07:15:38 2015
From: tobias.jungel at bisdn.de (Tobias Jungel)
Date: Wed, 02 Dec 2015 16:15:38 +0100
Subject: [PATCH 2/2] route/link: handle RTEXT_FILTER_BRVLAN_COMPRESSED
In-Reply-To: <1449066062.27857.34.camel@redhat.com>
References: <1448552878.7407.61.camel@bisdn.de>
 <1449066062.27857.34.camel@redhat.com>
Message-ID: <1449069338.32444.19.camel@bisdn.de>

On Mi, 2015-12-02 at 15:21 +0100, Thomas Haller wrote:
> On Thu, 2015-11-26 at 16:47 +0100, Tobias Jungel wrote:
> > notifications from the kernel regarding vlan ids are now handled
> > ---
> > ?lib/route/link.c????????| 12 +++-----
> > ?lib/route/link/bridge.c | 82
> > ++++++++++++++++++++++++++++++++++++++++++++-----
> > ?2 files changed, 78 insertions(+), 16 deletions(-)
> 
> Hi Tobias,
> 
> 
> 
> before your patch, there were three implementations of ao_af_parse:
> 
> ? lib/route/link/bridge.c:?????.ao_parse_af?????????????=
> &bridge_parse_af,
> ? lib/route/link/inet.c:??.ao_parse_af?????????????= &inet_parse_af,
> ? lib/route/link/inet6.c: .ao_parse_af?????????????=
> &inet6_parse_protinfo,
> 
> and two callers in?lib/route/link.c:
> ??parse_af_spec_unspec()
> ??parse_af_spec_bridge()
> 
> 
> with the change:
> 
> -????.ao_parse_af?????????????= &bridge_parse_af,
> +????.ao_parse_af_full????????= &bridge_parse_af,
> 
> 
> parse_af_spec_unspec() can no longer parse AF_BRIDGE as a nested
> attribute (AF_BRIDGE can then only be parsed as top-level attribute
> via
> parse_af_spec_bridge()).
> Is parsing AF_BRIDGE as nested in parse_af_spec_unspec() not
> necessary?

No, its not necessary. The kernel nests bridge attributes directly in
AF_SPEC.

> I think you have to preserve the original
> ? .ao_parse_af?????????????= &bridge_parse_af,
> too.
> 

No,?bridge_parse_af deals now with all nested attributes.

I had the discussion earlier with David, if we should
overload?ao_parse_af or create separate call in this thread:

http://lists.infradead.org/pipermail/libnl/2015-November/002045.html


> 
> 
> 
> 
> Second:
> 
> 
> The patch "Handle family-based parsing of IFLA_AF_SPEC attribute"
> adds:
> 
> [1]
> ???????switch(family) {
> ????????????????case AF_BRIDGE:
> ????????????????????????err = parse_af_spec_bridge(link,
> tb[IFLA_AF_SPEC]);
> ????????????????????????break;
> ????????????????case AF_UNSPEC:
> ????????????????????????err = parse_af_spec_unspec(link,
> tb[IFLA_AF_SPEC]);
> ????????????????????????break;
> 
> thus making the link_msg_parser() aware of how to parse AF_BRIDGE.
> 
> 
> 
> At this point you can do one of two things:
> 
> (a) have parse_af_spec_bridge() call directly to bridge_parse_af()
> without
> ????the intermediate step of introducing ao_parse_af_full().
> ????You already *know* that you parse a AF_BRIDGE. There is no point
> in using
> ????the virtual function table to invoke the bridge parser.

This implies to expose bridge_parse_af. Is this a good idea?

> 
> (b) Or better: change [1] to be actually generic:
> 
> ???if (tb[IFLA_AF_SPEC]) {
> ?????????/* parsing of IFLA_AF_SPEC is dependent on the family used
> ??????????* in the request message.
> ??????????*/
> ?????????if (family == AF_UNSPEC)
> ?????????????err = parse_af_spec_unspec(link, tb[IFLA_AF_SPEC]);
> ?????????else if (af_ops && af_ops->ao_parse_af_full) {
> ?????????????/* call to ao_parse_af_full, as you did in
> parse_af_spec_bridge().
> ????????????????possibly renaming parse_af_spec_bridge() to
> parse_af_spec_full()
> ????????????????or better just copy the content
> of?parse_af_spec_bridge() to here. */
> ?????????} else {
> ?????????????NL_DBG(1, "IFLA_AF_SPEC parsing not implemented for
> family %d\n",);
> ?????????}

I would rather go for this solution. If there are not any further
issues in using?ao_parse_af_full, I will do this tomorrow.

/tobi

> 
> 
> 
> 
> 
> 
> Thomas


From thaller at redhat.com  Wed Dec  2 07:42:51 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 16:42:51 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
Message-ID: <1449070971.3627.8.camel@redhat.com>

Hi David,


I pushed these 3 patches to upstream branch
https://github.com/thom311/libnl/commit/bridge-vlan
(for easier review).


I added fixup with the things I was talking about.
(untested so far :) )


If we agree on that, I would squash the fixup commits and merge it.
Opinions?



(thanks for all the work so far!!)


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/2b00f01b/attachment.sig>

From dsa at cumulusnetworks.com  Wed Dec  2 09:24:33 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Wed, 2 Dec 2015 09:24:33 -0800
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449070971.3627.8.camel@redhat.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com>
Message-ID: <565F2951.4000204@cumulusnetworks.com>

Hi Thomas:

On 12/2/15 7:42 AM, Thomas Haller wrote:
> Hi David,
>
>
> I pushed these 3 patches to upstream branch
> https://github.com/thom311/libnl/commit/bridge-vlan
> (for easier review).
>
>
> I added fixup with the things I was talking about.
> (untested so far :) )
>
>
> If we agree on that, I would squash the fixup commits and merge it.
> Opinions?

Thanks for the fixups. I'll test these as soon as I can and get back to 
you. Might take a few days.

David


From thaller at redhat.com  Wed Dec  2 10:30:06 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 19:30:06 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <565F2951.4000204@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
Message-ID: <1449081006.3627.32.camel@redhat.com>

On Wed, 2015-12-02 at 09:24 -0800, David Ahern wrote:
> Hi Thomas:
> 
> On 12/2/15 7:42 AM, Thomas Haller wrote:
> > Hi David,
> > 
> > 
> > I pushed these 3 patches to upstream branch
> > https://github.com/thom311/libnl/commit/bridge-vlan
> > (for easier review).
> > 
> > 
> > I added fixup with the things I was talking about.
> > (untested so far :) )
> > 
> > 
> > If we agree on that, I would squash the fixup commits and merge it.
> > Opinions?
> 
> Thanks for the fixups. I'll test these as soon as I can and get back
> to 
> you. Might take a few days.
> 

Hi David, Tobias,

I just reworked the branch again (heavily).

Latest and greatest at:
https://github.com/thom311/libnl/commit/bridge-vlan


Now it contains Tobias' patch and I did the changes I was talking in
the other thread about.

I added your original patches with fixup commits to make it somewhat
clearer what I changed.


(beware: I didn't actually test it).


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/554129a5/attachment.sig>

From thaller at redhat.com  Wed Dec  2 10:32:29 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 02 Dec 2015 19:32:29 +0100
Subject: [PATCH 2/2] route/link: handle RTEXT_FILTER_BRVLAN_COMPRESSED
In-Reply-To: <1449069338.32444.19.camel@bisdn.de>
References: <1448552878.7407.61.camel@bisdn.de>
 <1449066062.27857.34.camel@redhat.com> <1449069338.32444.19.camel@bisdn.de>
Message-ID: <1449081149.3627.35.camel@redhat.com>

On Wed, 2015-12-02 at 16:15 +0100, Tobias Jungel wrote:
> On Mi, 2015-12-02 at 15:21 +0100, Thomas Haller wrote:
> > On Thu, 2015-11-26 at 16:47 +0100, Tobias Jungel wrote:
> > > notifications from the kernel regarding vlan ids are now handled
> > > ---
> > > ?lib/route/link.c????????| 12 +++-----
> > > ?lib/route/link/bridge.c | 82
> > > ++++++++++++++++++++++++++++++++++++++++++++-----
> > > ?2 files changed, 78 insertions(+), 16 deletions(-)
> > 
> > Hi Tobias,
> > 
> > 
> > 
> > before your patch, there were three implementations of ao_af_parse:
> > 
> > ? lib/route/link/bridge.c:?????.ao_parse_af?????????????=
> > &bridge_parse_af,
> > ? lib/route/link/inet.c:??.ao_parse_af?????????????=
> > &inet_parse_af,
> > ? lib/route/link/inet6.c: .ao_parse_af?????????????=
> > &inet6_parse_protinfo,
> > 
> > and two callers in?lib/route/link.c:
> > ??parse_af_spec_unspec()
> > ??parse_af_spec_bridge()
> > 
> > 
> > with the change:
> > 
> > -????.ao_parse_af?????????????= &bridge_parse_af,
> > +????.ao_parse_af_full????????= &bridge_parse_af,
> > 
> > 
> > parse_af_spec_unspec() can no longer parse AF_BRIDGE as a nested
> > attribute (AF_BRIDGE can then only be parsed as top-level attribute
> > via
> > parse_af_spec_bridge()).
> > Is parsing AF_BRIDGE as nested in parse_af_spec_unspec() not
> > necessary?
> 
> No, its not necessary. The kernel nests bridge attributes directly in
> AF_SPEC.


ah, I see.

+????.ao_parse_af?????????????= &bridge_parse_af,

was only recently added (by David's patch). master currently doesn't
parse it at all. Good then.





> 
> > I think you have to preserve the original
> > ? .ao_parse_af?????????????= &bridge_parse_af,
> > too.
> > 
> 
> No,?bridge_parse_af deals now with all nested attributes.
> 
> I had the discussion earlier with David, if we should
> overload?ao_parse_af or create separate call in this thread:
> 
> http://lists.infradead.org/pipermail/libnl/2015-November/002045.html



> > Second:
> > 
> > 
> > The patch "Handle family-based parsing of IFLA_AF_SPEC attribute"
> > adds:
> > 
> > [1]
> > ???????switch(family) {
> > ????????????????case AF_BRIDGE:
> > ????????????????????????err = parse_af_spec_bridge(link,
> > tb[IFLA_AF_SPEC]);
> > ????????????????????????break;
> > ????????????????case AF_UNSPEC:
> > ????????????????????????err = parse_af_spec_unspec(link,
> > tb[IFLA_AF_SPEC]);
> > ????????????????????????break;
> > 
> > thus making the link_msg_parser() aware of how to parse AF_BRIDGE.
> > 
> > 
> > 
> > At this point you can do one of two things:
> > 
> > (a) have parse_af_spec_bridge() call directly to bridge_parse_af()
> > without
> > ????the intermediate step of introducing ao_parse_af_full().
> > ????You already *know* that you parse a AF_BRIDGE. There is no
> > point
> > in using
> > ????the virtual function table to invoke the bridge parser.
> 
> This implies to expose bridge_parse_af. Is this a good idea?


If you'd expose it as internal API via include/netlink-private/ there
wouldn't be a real problem.




> > (b) Or better: change [1] to be actually generic:
> > 
> > ???if (tb[IFLA_AF_SPEC]) {
> > ?????????/* parsing of IFLA_AF_SPEC is dependent on the family used
> > ??????????* in the request message.
> > ??????????*/
> > ?????????if (family == AF_UNSPEC)
> > ?????????????err = parse_af_spec_unspec(link, tb[IFLA_AF_SPEC]);
> > ?????????else if (af_ops && af_ops->ao_parse_af_full) {
> > ?????????????/* call to ao_parse_af_full, as you did in
> > parse_af_spec_bridge().
> > ????????????????possibly renaming parse_af_spec_bridge() to
> > parse_af_spec_full()
> > ????????????????or better just copy the content
> > of?parse_af_spec_bridge() to here. */
> > ?????????} else {
> > ?????????????NL_DBG(1, "IFLA_AF_SPEC parsing not implemented for
> > family %d\n",);
> > ?????????}
> 
> I would rather go for this solution. If there are not any further
> issues in using?ao_parse_af_full, I will do this tomorrow.


I tried to do what I was talking about. It actually applied more to
David's patch then yours. See my other email and
https://github.com/thom311/libnl/commit/bridge-vlan


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151202/58c66bff/attachment.sig>

From mlf.conv at gmail.com  Wed Dec  2 14:03:04 2015
From: mlf.conv at gmail.com (Marek)
Date: Wed, 2 Dec 2015 23:03:04 +0100
Subject: query block devices or disks via libnl / netlink
Message-ID: <CA+sqOsbszvoFpFUfhOJy17ioT1haAY+c1YzL9mbgfWEFGwdE8w@mail.gmail.com>

hi,

i'd like to ask a stupid question, is it possible to query harddrives
or block devices via netlink using libnl?

thanks,

Marek


From thaller at redhat.com  Thu Dec  3 01:43:56 2015
From: thaller at redhat.com (Thomas Haller)
Date: Thu, 03 Dec 2015 10:43:56 +0100
Subject: query block devices or disks via libnl / netlink
In-Reply-To: <CA+sqOsbszvoFpFUfhOJy17ioT1haAY+c1YzL9mbgfWEFGwdE8w@mail.gmail.com>
References: <CA+sqOsbszvoFpFUfhOJy17ioT1haAY+c1YzL9mbgfWEFGwdE8w@mail.gmail.com>
Message-ID: <1449135836.5935.6.camel@redhat.com>

On Wed, 2015-12-02 at 23:03 +0100, Marek wrote:
> i'd like to ask a stupid question, is it possible to query harddrives
> or block devices via netlink using libnl?

Hi Marek,

If you ask, whether kernel supports a netlink family that allows you to
do that, then I don't know. I'd think there is none (?).


If you already know which netlink family you can use to achieve what
you want and whether libnl supports that, then the answer is:

libnl3 consists of a basic parsing library for netlink. You could use
that to help you parsing any kind of netlink protocol.
Then there are separate parts of the library (e.g. libnl-route-3.so),
which can help you handling a specific netlink protocol.


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151203/0d7253fb/attachment.sig>

From tobias.jungel at bisdn.de  Thu Dec  3 08:55:38 2015
From: tobias.jungel at bisdn.de (Tobias Jungel)
Date: Thu, 03 Dec 2015 17:55:38 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449081006.3627.32.camel@redhat.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com>
Message-ID: <1449161738.6080.5.camel@bisdn.de>

On Mi, 2015-12-02 at 19:30 +0100, Thomas Haller wrote:
> On Wed, 2015-12-02 at 09:24 -0800, David Ahern wrote:
> > Hi Thomas:
> > 
> > On 12/2/15 7:42 AM, Thomas Haller wrote:
> > > Hi David,
> > > 
> > > 
> > > I pushed these 3 patches to upstream branch
> > > https://github.com/thom311/libnl/commit/bridge-vlan
> > > (for easier review).
> > > 
> > > 
> > > I added fixup with the things I was talking about.
> > > (untested so far :) )
> > > 
> > > 
> > > If we agree on that, I would squash the fixup commits and merge
> > > it.
> > > Opinions?
> > 
> > Thanks for the fixups. I'll test these as soon as I can and get
> > back
> > to 
> > you. Might take a few days.
> > 
> 
> Hi David, Tobias,
> 
> I just reworked the branch again (heavily).
> 
> Latest and greatest at:
> https://github.com/thom311/libnl/commit/bridge-vlan
> 
> 
> Now it contains Tobias' patch and I did the changes I was talking in
> the other thread about.
> 
> I added your original patches with fixup commits to make it somewhat
> clearer what I changed.
> 
> 
> (beware: I didn't actually test it).
> 
> 
> Thomas


Hi Thomas,

thanks for the work. It looks fine so far besides this one:


You have to either apply this

diff --git a/lib/route/link.c b/lib/route/link.c
index 0338606..21d7d98 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -604,7 +604,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
????????????????/* parsing of IFLA_AF_SPEC is dependent on the family used
?????????????????* in the request message.
?????????????????*/
-???????????????if (af_ops && af_ops->ao_parse_af_full) {
+???????????????if (family == AF_BRIDGE && af_ops && af_ops->ao_parse_af_full) {
????????????????????????err = af_ops->ao_parse_af_full(link,
???????????????????????????????????????????????????????tb[IFLA_AF_SPEC],
???????????????????????????????????????????????????????link->l_af_data[af_ops->ao_family]);


or this patch

diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c
index 51e6e3b..91ebce4 100644
--- a/lib/route/link/bridge.c
+++ b/lib/route/link/bridge.c
@@ -184,7 +184,7 @@ static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full
????????????????????????continue;
?
????????????????if (nla_len(attr) != sizeof(struct bridge_vlan_info))
-???????????????????????return -EINVAL;
+???????????????????????return 0;
?
????????????????vinfo = nla_data(attr);
????????????????if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)


otherwise parsing will fail in case you get a AF_UNSPEC msg.

The second seems way better, unless there is a chance that other AF will interfere with AF_BRIGE parsing.

To test this just run nl-monitor.


/tobi


From thaller at redhat.com  Thu Dec  3 09:27:21 2015
From: thaller at redhat.com (Thomas Haller)
Date: Thu, 03 Dec 2015 18:27:21 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449161738.6080.5.camel@bisdn.de>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com> <1449161738.6080.5.camel@bisdn.de>
Message-ID: <1449163641.5935.11.camel@redhat.com>

On Thu, 2015-12-03 at 17:55 +0100, Tobias Jungel wrote:
> On Mi, 2015-12-02 at 19:30 +0100, Thomas Haller wrote:
> > On Wed, 2015-12-02 at 09:24 -0800, David Ahern wrote:
> > >?

Hi Tobias,



> otherwise parsing will fail in case you get a AF_UNSPEC msg.
> 
> The second seems way better, unless there is a chance that other AF
> will interfere with AF_BRIGE parsing.
> 
> To test this just run nl-monitor.

Thanks for catching this. The problem is that af_ops can be reset
to the ops for?IFLA_INFO_KIND.

I solved it differently, by remembering the correct af_ops:
https://github.com/thom311/libnl/commit/bridge-vlan


OK?


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151203/e677b957/attachment.sig>

From tobias.jungel at bisdn.de  Thu Dec  3 12:25:24 2015
From: tobias.jungel at bisdn.de (Tobias Jungel)
Date: Thu, 03 Dec 2015 21:25:24 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449163641.5935.11.camel@redhat.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com> <1449161738.6080.5.camel@bisdn.de>
 <1449163641.5935.11.camel@redhat.com>
Message-ID: <1449174324.6080.7.camel@bisdn.de>

On Do, 2015-12-03 at 18:27 +0100, Thomas Haller wrote:
> On Thu, 2015-12-03 at 17:55 +0100, Tobias Jungel wrote:
> > On Mi, 2015-12-02 at 19:30 +0100, Thomas Haller wrote:
> > > On Wed, 2015-12-02 at 09:24 -0800, David Ahern wrote:
> > > > ?
> 
> Hi Tobias,
> 
> 
> 
> > otherwise parsing will fail in case you get a AF_UNSPEC msg.
> > 
> > The second seems way better, unless there is a chance that other AF
> > will interfere with AF_BRIGE parsing.
> > 
> > To test this just run nl-monitor.
> 
> Thanks for catching this. The problem is that af_ops can be reset
> to the ops for?IFLA_INFO_KIND.
> 
> I solved it differently, by remembering the correct af_ops:
> https://github.com/thom311/libnl/commit/bridge-vlan
> 
> 
> OK?

That's even better, thanks

/tobi
> 
> 
> Thomas


From dsa at cumulusnetworks.com  Sat Dec  5 12:27:43 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Sat, 5 Dec 2015 13:27:43 -0700
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449081006.3627.32.camel@redhat.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com>
Message-ID: <566348BF.1050007@cumulusnetworks.com>

On 12/2/15 11:30 AM, Thomas Haller wrote:
> Hi David, Tobias,
>
> I just reworked the branch again (heavily).
>
> Latest and greatest at:
> https://github.com/thom311/libnl/commit/bridge-vlan
>
>
> Now it contains Tobias' patch and I did the changes I was talking in
> the other thread about.
>
> I added your original patches with fixup commits to make it somewhat
> clearer what I changed.
>

A couple of comments:
1. since you changed the bitmap from unsigned longs to uint32 the 
__builtin_ffsl should be changed to __builtin_ffs.

2. Why not leave the macros:

+#define BR_VLAN_MAX            4096
+#define BR_VLAN_BITMAP_LEN     (BR_VLAN_MAX / sizeof(uint32_t))

in include/netlink/route/link/bridge.h and avoid magic numbers?

>
> (beware: I didn't actually test it).


I did test it; works fine for me.

Thanks, Thomas.

David


From dsa at cumulusnetworks.com  Sat Dec  5 13:26:44 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Sat, 5 Dec 2015 14:26:44 -0700
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <566348BF.1050007@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com> <566348BF.1050007@cumulusnetworks.com>
Message-ID: <56635694.7020203@cumulusnetworks.com>

On 12/5/15 1:27 PM, David Ahern wrote:
> 2. Why not leave the macros:
>
> +#define BR_VLAN_MAX            4096
> +#define BR_VLAN_BITMAP_LEN     (BR_VLAN_MAX / sizeof(uint32_t))

oops, I meant (BR_VLAN_MAX / (sizeof(uint32_t) * 8))





From thaller at redhat.com  Mon Dec  7 03:25:07 2015
From: thaller at redhat.com (Thomas Haller)
Date: Mon, 07 Dec 2015 12:25:07 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <566348BF.1050007@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com>
 <566348BF.1050007@cumulusnetworks.com>
Message-ID: <1449487507.12236.15.camel@redhat.com>

On Sat, 2015-12-05 at 13:27 -0700, David Ahern wrote:
> On 12/2/15 11:30 AM, Thomas Haller wrote:
> > Hi David, Tobias,
> > 
> > I just reworked the branch again (heavily).
> > 
> > Latest and greatest at:
> > https://github.com/thom311/libnl/commit/bridge-vlan
> > 
> > 
> > Now it contains Tobias' patch and I did the changes I was talking
> > in
> > the other thread about.
> > 
> > I added your original patches with fixup commits to make it
> > somewhat
> > clearer what I changed.
> > 
> 
> A couple of comments:
> 1. since you changed the bitmap from unsigned longs to uint32 the 
> __builtin_ffsl should be changed to __builtin_ffs.

Changed. I think it is always true on supported archs that
sizeof(uint32_t) <= sizeof(int).
I am unsure what happens when casting the unsigned value to "signed
int", but I guess it will still work as expected/correctly.



> 2. Why not leave the macros:
> 
> +#define BR_VLAN_MAX????????????4096
> +#define BR_VLAN_BITMAP_LEN?????(BR_VLAN_MAX / sizeof(uint32_t))

Added back:
+#define RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX 4096
+#define RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN (RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX / 32)

> in include/netlink/route/link/bridge.h and avoid magic numbers?
> 
> > 
> > (beware: I didn't actually test it).
> 
> 
> I did test it; works fine for me.

Thank you.

Merged to master:
https://github.com/thom311/libnl/commit/6555b0df89b1a99cfc32431600cd0a83345274ab



Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151207/0b1819f8/attachment.sig>

From dsa at cumulusnetworks.com  Mon Dec  7 07:01:32 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Mon, 7 Dec 2015 08:01:32 -0700
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <1449487507.12236.15.camel@redhat.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com> <566348BF.1050007@cumulusnetworks.com>
 <1449487507.12236.15.camel@redhat.com>
Message-ID: <56659F4C.9060406@cumulusnetworks.com>

On 12/7/15 4:25 AM, Thomas Haller wrote:
>> A couple of comments:
>> 1. since you changed the bitmap from unsigned longs to uint32 the
>> __builtin_ffsl should be changed to __builtin_ffs.
>
> Changed. I think it is always true on supported archs that
> sizeof(uint32_t) <= sizeof(int).

I thought 'int' was 4 bytes (or at least 4) on all modern processors.


> I am unsure what happens when casting the unsigned value to "signed
> int", but I guess it will still work as expected/correctly.

I don't follow. The prototype is 'int __builtin_ffs (unsigned int x)' so 
should not have unsigned/signed conversions.

David


From thaller at redhat.com  Mon Dec  7 07:15:04 2015
From: thaller at redhat.com (Thomas Haller)
Date: Mon, 07 Dec 2015 16:15:04 +0100
Subject: [PATCH 3/3] bridge: Add support for VLANs
In-Reply-To: <56659F4C.9060406@cumulusnetworks.com>
References: <1448478856-44332-1-git-send-email-dsa@cumulusnetworks.com>
 <1448478856-44332-4-git-send-email-dsa@cumulusnetworks.com>
 <1449070971.3627.8.camel@redhat.com> <565F2951.4000204@cumulusnetworks.com>
 <1449081006.3627.32.camel@redhat.com>
 <566348BF.1050007@cumulusnetworks.com>
 <1449487507.12236.15.camel@redhat.com>
 <56659F4C.9060406@cumulusnetworks.com>
Message-ID: <1449501304.28648.8.camel@redhat.com>

On Mon, 2015-12-07 at 08:01 -0700, David Ahern wrote:
> On 12/7/15 4:25 AM, Thomas Haller wrote:
> > > A couple of comments:
> > > 1. since you changed the bitmap from unsigned longs to uint32 the
> > > __builtin_ffsl should be changed to __builtin_ffs.
> > 
> > Changed. I think it is always true on supported archs that
> > sizeof(uint32_t) <= sizeof(int).
> 
> I thought 'int' was 4 bytes (or at least 4) on all modern processors.

Yes. I agree.




> > I am unsure what happens when casting the unsigned value to "signed
> > int", but I guess it will still work as expected/correctly.
> 
> I don't follow. The prototype is 'int __builtin_ffs (unsigned int x)'
> so 
> should not have unsigned/signed conversions.

I looked at?https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
which says:

? Built-in Function: int __builtin_ffs (int x)

anyway, I think even casting to "signed int" it should work correctly.



Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151207/b9d80a8c/attachment.sig>

From jan.gutter at netronome.com  Tue Dec  8 07:37:31 2015
From: jan.gutter at netronome.com (Jan Gutter)
Date: Tue, 8 Dec 2015 17:37:31 +0200
Subject: nl_recv() and handling truncated messages
Message-ID: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>

Hi,

I've run into a rather interesting problem recently where a weird
interaction between libnl3 and libvirt caused some difficult-to-debug
issues. From libnl3's side, the issue was that a netlink response was
much larger than the pagesize. If anyone's interested, the relevant
function is src/util/virnetlink.c:virNetlinkCommand(). When called in
a system where the number of PCIe Virtual Functions are more than 30
for a given Physical Function, the netlink response is larger than 4k,
meaning that a message is received with MSG_TRUNC set.

virNetlinkCommand() calls lib/nl.c:nl_recv() which in turn calls
recvmsg(). Unfortunately, it seems nl_recv() does not return an error
in this case. From tracing through the code, it seems that it assumes
that recvmsg() will return the actual size of the message. From the
man pages, this seems to be only true if flags have been set to
MSG_TRUNC when it was first called. If not, the rest of the message is
lost and the size of the buffer written to is returned.

nl_recv() works as expected if MSG_PEEK has been set, though, so it's
possible to fix in libvirt by either making the buffer bigger, or
enabling peeking.

However, it would be nice if the error is passed up to the user of libnl3.

There's a couple of options open:
1) Return NLE_MSG_TRUNC when a truncated message is received.
2) Enable MSG_TRUNC for all recvmsg calls and resize the buffer as
needed (meaning that NLE_MSG_TRUNC won't happen, but receive buffer
sizes can grow until realloc fails or a limit is hit...).
3) Make 2) optional (similar to enabling peeking) and return
NLE_MSG_TRUNC if it's not enabled.

I'm really not sure how much software is currently in the wild and
relies on this silent failure.

Jan


From thaller at redhat.com  Wed Dec  9 02:14:06 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 09 Dec 2015 11:14:06 +0100
Subject: nl_recv() and handling truncated messages
In-Reply-To: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
References: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
Message-ID: <1449656046.6382.12.camel@redhat.com>

Hi Jan,


On Tue, 2015-12-08 at 17:37 +0200, Jan Gutter wrote:



> nl_recv() works as expected if MSG_PEEK has been set, though, so it's
> possible to fix in libvirt by either making the buffer bigger, or
> enabling peeking.

using MSG_PEEK requires two syscall to get the data, even if no
truncation happens. Which is why you want to avoid that and why it's
opt-in.




> However, it would be nice if the error is passed up to the user of
> libnl3.
> 
> There's a couple of options open:
> 1) Return NLE_MSG_TRUNC when a truncated message is received.

I don't really understand the problem yet. Are you testing master?

How does this relate to the two recent fixes:
https://github.com/thom311
/libnl/commit/fd9d1da28c9d989f88b6c5edaa352c0https://github.com/thom311
/libnl/commit/bbdcaea9a779885fedc04817dcc1195


> 2) Enable MSG_TRUNC for all recvmsg calls and resize the buffer as
> needed (meaning that NLE_MSG_TRUNC won't happen, but receive buffer
> sizes can grow until realloc fails or a limit is hit...).

With MSG_TRUNC, how can you resize the buffer and recover from the
error? Isn't the message you failed to read (partly) lost?

But this sounds good. How would you do it?


> 3) Make 2) optional (similar to enabling peeking) and return
> NLE_MSG_TRUNC if it's not enabled.

Not sure. Are there any downsides of using (2) that would require to
make it optional?



> I'm really not sure how much software is currently in the wild and
> relies on this silent failure.


ciao,
Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151209/7fb1aa2b/attachment.sig>

From jan.gutter at netronome.com  Wed Dec  9 04:24:26 2015
From: jan.gutter at netronome.com (Jan Gutter)
Date: Wed, 9 Dec 2015 14:24:26 +0200
Subject: nl_recv() and handling truncated messages
In-Reply-To: <1449656046.6382.12.camel@redhat.com>
References: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
 <1449656046.6382.12.camel@redhat.com>
Message-ID: <CALdCBsD07Xky5fjDhbft39UbL4jGEMqeZNZRiYHCg9wh7k5Z4A@mail.gmail.com>

On Wed, Dec 9, 2015 at 12:14 PM, Thomas Haller <thaller at redhat.com> wrote:
> On Tue, 2015-12-08 at 17:37 +0200, Jan Gutter wrote:
>> nl_recv() works as expected if MSG_PEEK has been set, though, so it's
>> possible to fix in libvirt by either making the buffer bigger, or
>> enabling peeking.
>
> using MSG_PEEK requires two syscall to get the data, even if no
> truncation happens. Which is why you want to avoid that and why it's
> opt-in.

Yes, TBD if the performance impact would negatively impact libvirt, I
don't think
it's in fastpath, but I am not sure.

>> However, it would be nice if the error is passed up to the user of
>> libnl3.
>>
>> There's a couple of options open:
>> 1) Return NLE_MSG_TRUNC when a truncated message is received.
>
> I don't really understand the problem yet. Are you testing master?
>
> How does this relate to the two recent fixes:
> https://github.com/thom311/libnl/commit/fd9d1da28c9d989f88b6c5edaa352c0
> https://github.com/thom311/libnl/commit/bbdcaea9a779885fedc04817dcc1195

It has indeed been fixed in master:
http://git.infradead.org/users/tgr/libnl.git/blob_plain/HEAD:/lib/nl.c

I was checking with the older versions in Ubuntu and the docs
generated from v3.2.24-rc1
https://www.infradead.org/~tgr/libnl/doc/api/nl_8c_source.html

I applied the same fix and my test case correctly reports that nl_recv() failed.

>> 2) Enable MSG_TRUNC for all recvmsg calls and resize the buffer as
>> needed (meaning that NLE_MSG_TRUNC won't happen, but receive buffer
>> sizes can grow until realloc fails or a limit is hit...).
>
> With MSG_TRUNC, how can you resize the buffer and recover from the
> error? Isn't the message you failed to read (partly) lost?

Argh, I must have read the man page too optimistically. The idea was
to set MSG_TRUNC (but not MSG_PEEK) in the flags passed to recvmsg,
realloc the receive buffer to the correct size and read the remaining
message. However, it seems the bytes are lost:

recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0\f\33hV\357\213\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
4096}], msg_controllen=0, msg_flags=MSG_TRUNC}, MSG_TRUNC) = 7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"$\0\0\0\2\0\0\0\f\33hV\357\213\0\0\0\0\0\0004\0\0\0\22\0\5\0\f\33hV"...,
7296}], msg_controllen=0, msg_flags=0}, MSG_TRUNC) = 36

vs

recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0[\33hV\f\214\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
4096}], msg_controllen=0, msg_flags=MSG_TRUNC}, MSG_PEEK|MSG_TRUNC) =
7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0[\33hV\f\214\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
7296}], msg_controllen=0, msg_flags=0}, MSG_TRUNC) = 7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"$\0\0\0\2\0\0\0[\33hV\f\214\0\0\0\0\0\0004\0\0\0\22\0\5\0[\33hV"...,
7296}], msg_controllen=0, msg_flags=0}, 0) = 36

> But this sounds good. How would you do it?

It appears the only way to do this is with peeking.

Sorry to have raised the false alarm, that'll teach me to look at the
docs in stead of the code!

Jan


From thaller at redhat.com  Wed Dec  9 05:34:53 2015
From: thaller at redhat.com (Thomas Haller)
Date: Wed, 09 Dec 2015 14:34:53 +0100
Subject: nl_recv() and handling truncated messages
In-Reply-To: <CALdCBsD07Xky5fjDhbft39UbL4jGEMqeZNZRiYHCg9wh7k5Z4A@mail.gmail.com>
References: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
 <1449656046.6382.12.camel@redhat.com>
 <CALdCBsD07Xky5fjDhbft39UbL4jGEMqeZNZRiYHCg9wh7k5Z4A@mail.gmail.com>
Message-ID: <1449668093.32601.9.camel@redhat.com>

On Wed, 2015-12-09 at 14:24 +0200, Jan Gutter wrote:
> On Wed, Dec 9, 2015 at 12:14 PM, Thomas Haller <thaller at redhat.com>
> wrote:
> > On Tue, 2015-12-08 at 17:37 +0200, Jan Gutter wrote:
> > > nl_recv() works as expected if MSG_PEEK has been set, though, so
> > > it's
> > > possible to fix in libvirt by either making the buffer bigger, or
> > > enabling peeking.
> > 
> > using MSG_PEEK requires two syscall to get the data, even if no
> > truncation happens. Which is why you want to avoid that and why
> > it's
> > opt-in.
> 
> Yes, TBD if the performance impact would negatively impact libvirt, I
> don't think
> it's in fastpath, but I am not sure.

Sure, if that would be fine for your application... I meant: it's not
great in general (but might be fine in your case).





> > But this sounds good. How would you do it?
> 
> It appears the only way to do this is with peeking.

Hm yeah. To my understanding, it is not possible with recvmsg() to
obtain the message only if the buffer is large enough.

Without peek, the message gets effectively truncated and lost. With
MSG_PEEK, you have to always call recvmsg() twice.

It would be better to have a opportunistic MSG_PEEK, which reads the
message if possible.


Pretty bad (from recvmsg). Or maybe I am wrong and it is somehow
possible... anybody??




> Sorry to have raised the false alarm, that'll teach me to look at the
> docs in stead of the code!

cool. No problem :) A good idea is to check upstream master branch
first.


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151209/ad16b5ff/attachment.sig>

From jan.gutter at netronome.com  Wed Dec  9 07:01:25 2015
From: jan.gutter at netronome.com (Jan Gutter)
Date: Wed, 9 Dec 2015 17:01:25 +0200
Subject: nl_recv() and handling truncated messages
In-Reply-To: <1449668093.32601.9.camel@redhat.com>
References: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
 <1449656046.6382.12.camel@redhat.com>
 <CALdCBsD07Xky5fjDhbft39UbL4jGEMqeZNZRiYHCg9wh7k5Z4A@mail.gmail.com>
 <1449668093.32601.9.camel@redhat.com>
Message-ID: <CALdCBsBdf8oRyb7FCn6EAqGePWqQ3Q9Fxwgc4EiM_AS=Q=PKUg@mail.gmail.com>

On Wed, Dec 9, 2015 at 3:34 PM, Thomas Haller <thaller at redhat.com> wrote:
> On Wed, 2015-12-09 at 14:24 +0200, Jan Gutter wrote:
>> On Wed, Dec 9, 2015 at 12:14 PM, Thomas Haller <thaller at redhat.com>
>> wrote:
>> > On Tue, 2015-12-08 at 17:37 +0200, Jan Gutter wrote:
>> It appears the only way to do this is with peeking.
>
> Hm yeah. To my understanding, it is not possible with recvmsg() to
> obtain the message only if the buffer is large enough.
>
> Without peek, the message gets effectively truncated and lost. With
> MSG_PEEK, you have to always call recvmsg() twice.
>
> It would be better to have a opportunistic MSG_PEEK, which reads the
> message if possible.
>
> Pretty bad (from recvmsg). Or maybe I am wrong and it is somehow
> possible... anybody??

Closest I got was this from The Holy Tome:
https://books.google.co.za/books?id=ptSC4LpwGA0C&pg=PA594&lpg=PA594&dq=recvmsg+msg_trunc&source=bl&ots=Ks4GRncqUs&sig=pZREA6iKGRxmYzM7HaJBkR8V-o8&hl=en&sa=X&ved=0ahUKEwiQxYewhM_JAhWBPhQKHWq6DHYQ6AEILTAD#v=onepage&q=recvmsg%20msg_trunc&f=false

Paraphrasing Unix Network Programming Vol. 1 (Stevens) Section 22.3
Datagram Truncation

There are three possibilities:

1. Discard bytes and return MSG_TRUNC (Linux recvmsg)
2. Discard bytes and don't tell the app
3. Keep excess bytes and return them on subsequent recvmsg calls

According to the book, POSIX specced 1, but early releases of SVR4 did 3.

Jan


From dsa at cumulusnetworks.com  Wed Dec  9 07:57:09 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Wed, 9 Dec 2015 08:57:09 -0700
Subject: nl_recv() and handling truncated messages
In-Reply-To: <1449668093.32601.9.camel@redhat.com>
References: <CALdCBsCa=JZS4TY8nyyWw2hdf8nEn4r21Z4WWK6SGBaDf66sHg@mail.gmail.com>
 <1449656046.6382.12.camel@redhat.com>
 <CALdCBsD07Xky5fjDhbft39UbL4jGEMqeZNZRiYHCg9wh7k5Z4A@mail.gmail.com>
 <1449668093.32601.9.camel@redhat.com>
Message-ID: <56684F55.40405@cumulusnetworks.com>

On 12/9/15 6:34 AM, Thomas Haller wrote:
>>> > >But this sounds good. How would you do it?
>> >
>> >It appears the only way to do this is with peeking.
> Hm yeah. To my understanding, it is not possible with recvmsg() to
> obtain the message only if the buffer is large enough.
>
> Without peek, the message gets effectively truncated and lost. With
> MSG_PEEK, you have to always call recvmsg() twice.
>
> It would be better to have a opportunistic MSG_PEEK, which reads the
> message if possible.
>
>
> Pretty bad (from recvmsg). Or maybe I am wrong and it is somehow
> possible... anybody??
>

It's not possible with the existing code, but an interesting feature ... 
e.g., add MSG_PEEK_OPPORTUNISTIC flag. If set and skb length is <= user 
buffer length copy the message.



From lenohou at gmail.com  Wed Dec  9 19:22:05 2015
From: lenohou at gmail.com (Leno Hou)
Date: Wed,  9 Dec 2015 22:22:05 -0500
Subject: [PATCH v1][libnl3] lib/nl: Increase default receive socket buffer
 size to 128k
Message-ID: <1449717725-7186-1-git-send-email-lenohou@gmail.com>

From: Leno Hou <houqy at linux.vnet.ibm.com>

This patch set default receive socket buffer size to 128K to solve
nl_recv returned with error: No buffer space available
1. When switching CPUs to offline/online in a system more than 128 cpus
2. When using virsh to destroy domain in a system with more interfaces
3. When NetworkMananger monitoring some uevents,e.g. netlink is changed.

Signed-off-by: Leno Hou <lenohou at gmail.com>
---
 lib/nl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nl.c b/lib/nl.c
index 8fc9ec1..0b9807e 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -122,7 +122,7 @@ int nl_connect(struct nl_sock *sk, int protocol)
 		goto errout;
 	}
 
-	err = nl_socket_set_buffer_size(sk, 0, 0);
+	err = nl_socket_set_buffer_size(sk, 131702, 0);
 	if (err < 0)
 		goto errout;
 
-- 
2.1.0



From thaller at redhat.com  Thu Dec 10 15:26:21 2015
From: thaller at redhat.com (Thomas Haller)
Date: Fri, 11 Dec 2015 00:26:21 +0100
Subject: [PATCH v1][libnl3] lib/nl: Increase default receive socket
 buffer size to 128k
In-Reply-To: <1449717725-7186-1-git-send-email-lenohou@gmail.com>
References: <1449717725-7186-1-git-send-email-lenohou@gmail.com>
Message-ID: <1449789981.9048.23.camel@redhat.com>

On Wed, 2015-12-09 at 22:22 -0500, Leno Hou wrote:
> From: Leno Hou <houqy at linux.vnet.ibm.com>
> 
> This patch set default receive socket buffer size to 128K to solve
> nl_recv returned with error: No buffer space available
> 1. When switching CPUs to offline/online in a system more than 128
> cpus
> 2. When using virsh to destroy domain in a system with more
> interfaces
> 3. When NetworkMananger monitoring some uevents,e.g. netlink is
> changed.

Hi,


Changing the default affects every user. It's not clear to me, that
128k is a better default for everybody.

The user already can change this (either via
nl_socket_set_buffer_size() or directly via ioctl on the file
descriptor).


I tried to figure out why NetworkManager sets the buffer size.
Currently I wasn't able to reproduce a failure related to a smaller
SO_RCVBUF. I'm almost inclined to remove the set_buffer_size() call
from NetworkManager, at least it's not at all clear that this patch is
right.


Can you justify the change better?
Your examples are:
? 1.) affects systems with >128 CPU? Unusual case, I cannot
? ? ? reproduce :)
? 2.) virsh. OK.
? 3.) maybe, but I wonder if NM actually needs this.


Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151211/ab11c67a/attachment.sig>

From dsa at cumulusnetworks.com  Wed Dec 16 13:11:22 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Wed, 16 Dec 2015 13:11:22 -0800
Subject: [PATCH] lib: Update ce-mask to uint64_t
Message-ID: <1450300282-7804-1-git-send-email-dsa@cumulusnetworks.com>

lib/route/link.c already defines 32 attributes which fills the current
uint32_t used for ce_mask. To accommodate more attributes the mask needs
to be expanded. This patch updates the definition to uint64_t and fixes
callers and implementations to consistently use uint64_t data type.

Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
---
 include/netlink-private/netlink.h      | 2 +-
 include/netlink-private/object-api.h   | 8 ++++----
 include/netlink-private/route/tc-api.h | 4 ++--
 include/netlink/object.h               | 2 +-
 lib/fib_lookup/lookup.c                | 4 ++--
 lib/fib_lookup/request.c               | 6 +++---
 lib/genl/family.c                      | 6 +++---
 lib/idiag/idiag_meminfo_obj.c          | 4 ++--
 lib/idiag/idiag_msg_obj.c              | 6 +++---
 lib/idiag/idiag_vegasinfo_obj.c        | 4 ++--
 lib/netfilter/ct_obj.c                 | 6 +++---
 lib/netfilter/exp_obj.c                | 6 +++---
 lib/netfilter/log_obj.c                | 6 +++---
 lib/netfilter/queue_obj.c              | 6 +++---
 lib/object.c                           | 4 ++--
 lib/route/addr.c                       | 6 +++---
 lib/route/link.c                       | 6 +++---
 lib/route/neigh.c                      | 6 +++---
 lib/route/neightbl.c                   | 6 +++---
 lib/route/route_obj.c                  | 7 ++++---
 lib/route/rule.c                       | 6 +++---
 lib/route/tc.c                         | 6 +++---
 lib/xfrm/ae.c                          | 6 ++++--
 lib/xfrm/sa.c                          | 5 +++--
 lib/xfrm/sp.c                          | 5 +++--
 25 files changed, 69 insertions(+), 64 deletions(-)

diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h
index 6d40ea53c578..befd3014afcb 100644
--- a/include/netlink-private/netlink.h
+++ b/include/netlink-private/netlink.h
@@ -71,7 +71,7 @@
 #define NSEC_PER_SEC	1000000000L
 
 struct trans_tbl {
-	int i;
+	uint64_t i;
 	const char *a;
 };
 
diff --git a/include/netlink-private/object-api.h b/include/netlink-private/object-api.h
index f4fd71e576ec..e0971e5706fa 100644
--- a/include/netlink-private/object-api.h
+++ b/include/netlink-private/object-api.h
@@ -189,7 +189,7 @@ extern "C" {
 	struct nl_list_head	ce_list;	\
 	int			ce_msgtype;	\
 	int			ce_flags;	\
-	uint32_t		ce_mask;
+	uint64_t		ce_mask;
 
 struct nl_object
 {
@@ -258,7 +258,7 @@ struct nl_object
  * @endcode
  */
 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
-({	int diff = 0; \
+({	uint64_t diff = 0; \
 	if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
 		diff = ATTR; \
 	diff; })
@@ -333,8 +333,8 @@ struct nl_object_ops
 	 * The function must return a bitmask with the relevant bit
 	 * set for each attribute that mismatches.
 	 */
-	int   (*oo_compare)(struct nl_object *, struct nl_object *,
-			    uint32_t, int);
+	uint64_t (*oo_compare)(struct nl_object *, struct nl_object *,
+			    uint64_t, int);
 
 
 	/**
diff --git a/include/netlink-private/route/tc-api.h b/include/netlink-private/route/tc-api.h
index fbfa2abd8fa2..7158ce5c117b 100644
--- a/include/netlink-private/route/tc-api.h
+++ b/include/netlink-private/route/tc-api.h
@@ -110,9 +110,9 @@ extern void			rtnl_tc_dump_details(struct nl_object *,
 						     struct nl_dump_params *);
 extern void			rtnl_tc_dump_stats(struct nl_object *,
 						   struct nl_dump_params *);
-extern int			rtnl_tc_compare(struct nl_object *,
+extern uint64_t			rtnl_tc_compare(struct nl_object *,
 						struct nl_object *,
-						uint32_t, int);
+						uint64_t, int);
 
 void *                          rtnl_tc_data_peek(struct rtnl_tc *tc);
 extern void *			rtnl_tc_data(struct rtnl_tc *);
diff --git a/include/netlink/object.h b/include/netlink/object.h
index a95feda7b4db..81a1578bb22c 100644
--- a/include/netlink/object.h
+++ b/include/netlink/object.h
@@ -41,7 +41,7 @@ extern void			nl_object_dump(struct nl_object *,
 extern void			nl_object_dump_buf(struct nl_object *, char *, size_t);
 extern int			nl_object_identical(struct nl_object *,
 						    struct nl_object *);
-extern uint32_t			nl_object_diff(struct nl_object *,
+extern uint64_t			nl_object_diff(struct nl_object *,
 					       struct nl_object *);
 extern int			nl_object_match_filter(struct nl_object *,
 						       struct nl_object *);
diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c
index 9b24635240d2..43b6126f376b 100644
--- a/lib/fib_lookup/lookup.c
+++ b/lib/fib_lookup/lookup.c
@@ -141,8 +141,8 @@ static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p)
 	result_dump_line(obj, p);
 }
 
-static int result_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t result_compare(struct nl_object *_a, struct nl_object *_b,
+			uint64_t attrs, int flags)
 {
 	return 0;
 }
diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c
index 1b021b64dba8..5bd49d6fd320 100644
--- a/lib/fib_lookup/request.c
+++ b/lib/fib_lookup/request.c
@@ -53,12 +53,12 @@ static int request_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int request_compare(struct nl_object *_a, struct nl_object *_b,
-			   uint32_t attrs, int flags)
+static uint64_t request_compare(struct nl_object *_a, struct nl_object *_b,
+			   uint64_t attrs, int flags)
 {
 	struct flnl_request *a = (struct flnl_request *) _a;
 	struct flnl_request *b = (struct flnl_request *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/genl/family.c b/lib/genl/family.c
index 9155c8fda9a2..45c3d45e1b3e 100644
--- a/lib/genl/family.c
+++ b/lib/genl/family.c
@@ -147,12 +147,12 @@ static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	family_dump_details(obj, p);
 }
 
-static int family_compare(struct nl_object *_a, struct nl_object *_b,
-			  uint32_t attrs, int flags)
+static uint64_t family_compare(struct nl_object *_a, struct nl_object *_b,
+			  uint64_t attrs, int flags)
 {
 	struct genl_family *a = (struct genl_family *) _a;
 	struct genl_family *b = (struct genl_family *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/idiag/idiag_meminfo_obj.c b/lib/idiag/idiag_meminfo_obj.c
index f07800fdb3c4..1c327bb37832 100644
--- a/lib/idiag/idiag_meminfo_obj.c
+++ b/lib/idiag/idiag_meminfo_obj.c
@@ -81,8 +81,8 @@ void idiagnl_meminfo_set_tmem(struct idiagnl_meminfo *minfo, uint32_t tmem)
 /** @} */
 
 /** @cond SKIP */
-static int idiagnl_meminfo_compare(struct nl_object *_a, struct nl_object *_b,
-                                     uint32_t attrs, int flags)
+static uint64_t idiagnl_meminfo_compare(struct nl_object *_a, struct nl_object *_b,
+                                     uint64_t attrs, int flags)
 {
 	struct idiagnl_meminfo *a = (struct idiagnl_meminfo *) _a;
 	struct idiagnl_meminfo *b = (struct idiagnl_meminfo *) _b;
diff --git a/lib/idiag/idiag_msg_obj.c b/lib/idiag/idiag_msg_obj.c
index d7cf7222049e..beaa9cc49f27 100644
--- a/lib/idiag/idiag_msg_obj.c
+++ b/lib/idiag/idiag_msg_obj.c
@@ -853,12 +853,12 @@ static char *_idiagnl_attrs2str(int attrs, char *buf, size_t len)
 	                   ARRAY_SIZE(idiagnl_attrs));
 }
 
-static int idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
-                           uint32_t attrs, int flags)
+static uint64_t idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
+                                uint64_t attrs, int flags)
 {
 	struct idiagnl_msg *a = (struct idiagnl_msg *) _a;
 	struct idiagnl_msg *b = (struct idiagnl_msg *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
 	diff |= _DIFF(FAMILY,    a->idiag_family != b->idiag_family);
diff --git a/lib/idiag/idiag_vegasinfo_obj.c b/lib/idiag/idiag_vegasinfo_obj.c
index eddd8af0e850..f02eea077b41 100644
--- a/lib/idiag/idiag_vegasinfo_obj.c
+++ b/lib/idiag/idiag_vegasinfo_obj.c
@@ -84,8 +84,8 @@ void idiagnl_vegasinfo_set_minrtt(struct idiagnl_vegasinfo *vinfo, uint32_t
 /** @} */
 
 /** @cond SKIP */
-static int idiagnl_vegasinfo_compare(struct nl_object *_a, struct nl_object *_b,
-                                     uint32_t attrs, int flags)
+static uint64_t idiagnl_vegasinfo_compare(struct nl_object *_a, struct nl_object *_b,
+                                          uint64_t attrs, int flags)
 {
 	struct idiagnl_vegasinfo *a = (struct idiagnl_vegasinfo *) _a;
 	struct idiagnl_vegasinfo *b = (struct idiagnl_vegasinfo *) _b;
diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c
index c8af87023c05..1079ec0a4b07 100644
--- a/lib/netfilter/ct_obj.c
+++ b/lib/netfilter/ct_obj.c
@@ -297,12 +297,12 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p)
 	}
 }
 
-static int ct_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t ct_compare(struct nl_object *_a, struct nl_object *_b,
+			   uint64_t attrs, int flags)
 {
 	struct nfnl_ct *a = (struct nfnl_ct *) _a;
 	struct nfnl_ct *b = (struct nfnl_ct *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
 #define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c
index 591cf45076ad..aef43b73acfa 100644
--- a/lib/netfilter/exp_obj.c
+++ b/lib/netfilter/exp_obj.c
@@ -301,12 +301,12 @@ static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_pro
 	return d;
 }
 
-static int exp_compare(struct nl_object *_a, struct nl_object *_b,
-							uint32_t attrs, int flags)
+static uint64_t exp_compare(struct nl_object *_a, struct nl_object *_b,
+			    uint64_t attrs, int flags)
 {
 	struct nfnl_exp *a = (struct nfnl_exp *) _a;
 	struct nfnl_exp *b = (struct nfnl_exp *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR)
 #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD)
diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c
index 3fdb3472a305..65985d86ee96 100644
--- a/lib/netfilter/log_obj.c
+++ b/lib/netfilter/log_obj.c
@@ -229,12 +229,12 @@ unsigned int nfnl_log_str2flags(const char *name)
 	return __str2flags(name, log_flags, ARRAY_SIZE(log_flags));
 }
 
-static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
-			    uint32_t attrs, int flags)
+static uint64_t nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
+				 uint64_t attrs, int flags)
 {
 	struct nfnl_log *a = (struct nfnl_log *) _a;
 	struct nfnl_log *b = (struct nfnl_log *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NFNL_LOG_DIFF(ATTR, EXPR) \
 	ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c
index 36ed3c53f15c..040bbed4f14b 100644
--- a/lib/netfilter/queue_obj.c
+++ b/lib/netfilter/queue_obj.c
@@ -161,12 +161,12 @@ uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue)
 	return queue->queue_copy_range;
 }
 
-static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
-			      uint32_t attrs, int flags)
+static uint64_t nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
+				   uint64_t attrs, int flags)
 {
 	struct nfnl_queue *a = (struct nfnl_queue *) _a;
 	struct nfnl_queue *b = (struct nfnl_queue *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NFNL_QUEUE_DIFF(ATTR, EXPR) \
 	ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/object.c b/lib/object.c
index cad24e0a9e4d..1c3858eb0c84 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -358,12 +358,12 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b)
  *
  * @return Bitmask describing differences or 0 if they are completely identical.
  */
-uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
+uint64_t nl_object_diff(struct nl_object *a, struct nl_object *b)
 {
 	struct nl_object_ops *ops = obj_ops(a);
 
 	if (ops != obj_ops(b) || ops->oo_compare == NULL)
-		return UINT32_MAX;
+		return UINT64_MAX;
 
 	return ops->oo_compare(a, b, ~0, 0);
 }
diff --git a/lib/route/addr.c b/lib/route/addr.c
index 3bde2bf8b2ec..33df1c86cbf4 100644
--- a/lib/route/addr.c
+++ b/lib/route/addr.c
@@ -429,12 +429,12 @@ static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	addr_dump_details(obj, p);
 }
 
-static int addr_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_addr *a = (struct rtnl_addr *) _a;
 	struct rtnl_addr *b = (struct rtnl_addr *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/link.c b/lib/route/link.c
index d763d973650e..366296a06cd5 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -955,12 +955,12 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int link_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_link *a = (struct rtnl_link *) _a;
 	struct rtnl_link *b = (struct rtnl_link *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index 436d766a6a11..9fdcaca981d5 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -260,12 +260,12 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t neigh_compare(struct nl_object *_a, struct nl_object *_b,
+			      uint64_t attrs, int flags)
 {
 	struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
 	struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c
index f9c9c27759e0..7fd106b93625 100644
--- a/lib/route/neightbl.c
+++ b/lib/route/neightbl.c
@@ -54,12 +54,12 @@ static struct nl_cache_ops rtnl_neightbl_ops;
 static struct nl_object_ops neightbl_obj_ops;
 /** @endcond */
 
-static int neightbl_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t neightbl_compare(struct nl_object *_a, struct nl_object *_b,
+				 uint64_t attrs, int flags)
 {
 	struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a;
 	struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c
index 4063c6f672e8..0f52e00db86e 100644
--- a/lib/route/route_obj.c
+++ b/lib/route/route_obj.c
@@ -343,13 +343,14 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int route_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b,
+			      uint64_t attrs, int flags)
 {
 	struct rtnl_route *a = (struct rtnl_route *) _a;
 	struct rtnl_route *b = (struct rtnl_route *) _b;
 	struct rtnl_nexthop *nh_a, *nh_b;
-	int i, diff = 0, found;
+	int i, found;
+	uint64_t diff = 0;
 
 #define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/rule.c b/lib/route/rule.c
index 357cb1bf60bd..883df812cc3f 100644
--- a/lib/route/rule.c
+++ b/lib/route/rule.c
@@ -245,12 +245,12 @@ static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 
 #define RULE_ATTR_FLAGS		0x0008
 
-static int rule_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_rule *a = (struct rtnl_rule *) _a;
 	struct rtnl_rule *b = (struct rtnl_rule *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/tc.c b/lib/route/tc.c
index 35daf15ae57d..384e85705b1d 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -932,12 +932,12 @@ void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	             tc->tc_stats[RTNL_TC_RATE_PPS]);
 }
 
-int rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
-		    uint32_t attrs, int flags)
+uint64_t rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
+			 uint64_t attrs, int flags)
 {
 	struct rtnl_tc *a = TC_CAST(aobj);
 	struct rtnl_tc *b = TC_CAST(bobj);
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/xfrm/ae.c b/lib/xfrm/ae.c
index 4fe964725b52..bfe481f76eae 100644
--- a/lib/xfrm/ae.c
+++ b/lib/xfrm/ae.c
@@ -181,11 +181,13 @@ static int xfrm_ae_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_ae* a  =   (struct xfrmnl_ae *) _a;
 	struct xfrmnl_ae* b  =   (struct xfrmnl_ae *) _b;
-	int diff = 0, found = 0;
+	uint64_t diff = 0;
+	int found = 0;
 
 #define XFRM_AE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_AE_ATTR_##ATTR, a, b, EXPR)
 	diff |= XFRM_AE_DIFF(DADDR,	nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr));
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index 34d24cf843eb..31c22ba44ef2 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -205,11 +205,12 @@ static int xfrm_sa_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_sa_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_sa_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_sa* a  =   (struct xfrmnl_sa *) _a;
 	struct xfrmnl_sa* b  =   (struct xfrmnl_sa *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 	int found = 0;
 
 #define XFRM_SA_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SA_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/xfrm/sp.c b/lib/xfrm/sp.c
index 943269a6638f..cc2fcb1c60a1 100644
--- a/lib/xfrm/sp.c
+++ b/lib/xfrm/sp.c
@@ -138,12 +138,13 @@ static int xfrm_sp_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_sp_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_sp_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_sp* a  =   (struct xfrmnl_sp *) _a;
 	struct xfrmnl_sp* b  =   (struct xfrmnl_sp *) _b;
 	struct xfrmnl_user_tmpl *tmpl_a, *tmpl_b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define XFRM_SP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SP_ATTR_##ATTR, a, b, EXPR)
 	diff |= XFRM_SP_DIFF(SEL,	xfrmnl_sel_cmp(a->sel, b->sel));
-- 
2.1.4



From rahul.jain at samsung.com  Wed Dec 16 21:03:05 2015
From: rahul.jain at samsung.com (Rahul Jain)
Date: Thu, 17 Dec 2015 10:33:05 +0530
Subject: [PATCH] Potential memory leak in pktloc.c
Message-ID: <1450328585-3325-1-git-send-email-rahul.jain@samsung.com>

From: Amit Khatri <amit.khatri at samsung.com>

In scneario, where file modification time is unchanged, code is returning 0
form read_pktlocs(). It causes memory leak for path variable. 
Memory for this variable is allocated inside build_sysconf_path() 
by asprintf() function.

Signed-off-by: Amit Khatri <amit.khatri at samsung.com>
Signed-off-by: Rahul Jain <rahul.jain at samsung.com>
---
 lib/route/pktloc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c
index 27d63be..75d049e 100644
--- a/lib/route/pktloc.c
+++ b/lib/route/pktloc.c
@@ -101,8 +101,10 @@ static int read_pktlocs(void)
 	/* if stat fails, just try to read the file */
 	if (stat(path, &st) == 0) {
 		/* Don't re-read file if file is unchanged */
-		if (last_read == st.st_mtime)
-			return 0;
+		if (last_read == st.st_mtime) {
+			err = 0;
+			goto errout;
+		}
 	}
 
 	NL_DBG(2, "Reading packet location file \"%s\"\n", path);
-- 
1.9.1



From thaller at redhat.com  Thu Dec 17 23:44:58 2015
From: thaller at redhat.com (Thomas Haller)
Date: Fri, 18 Dec 2015 08:44:58 +0100
Subject: [PATCH] Potential memory leak in pktloc.c
In-Reply-To: <1450328585-3325-1-git-send-email-rahul.jain@samsung.com>
References: <1450328585-3325-1-git-send-email-rahul.jain@samsung.com>
Message-ID: <1450424698.3567.14.camel@redhat.com>

On Thu, 2015-12-17 at 10:33 +0530, Rahul Jain wrote:
> From: Amit Khatri <amit.khatri at samsung.com>
> 
> In scneario, where file modification time is unchanged, code is
> returning 0
> form read_pktlocs(). It causes memory leak for path variable.?
> Memory for this variable is allocated inside build_sysconf_path()?
> by asprintf() function.
> 

merged as:
https://github.com/thom311/libnl/commit/eccca1acfc7242136256185746d93ec7bd10be82


Thank you!
Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151218/05fbde95/attachment.sig>

From thaller at redhat.com  Fri Dec 18 00:16:45 2015
From: thaller at redhat.com (Thomas Haller)
Date: Fri, 18 Dec 2015 09:16:45 +0100
Subject: [PATCH] lib: Update ce-mask to uint64_t
In-Reply-To: <1450300282-7804-1-git-send-email-dsa@cumulusnetworks.com>
References: <1450300282-7804-1-git-send-email-dsa@cumulusnetworks.com>
Message-ID: <1450426605.3567.24.camel@redhat.com>

Hi David,


On Wed, 2015-12-16 at 13:11 -0800, David Ahern wrote:
> lib/route/link.c already defines 32 attributes which fills the
> current
> uint32_t used for ce_mask. To accommodate more attributes the mask
> needs
> to be expanded. This patch updates the definition to uint64_t and
> fixes
> callers and implementations to consistently use uint64_t data type.


> ?extern void *			rtnl_tc_data(struct rtnl_tc *);
> diff --git a/include/netlink/object.h b/include/netlink/object.h
> index a95feda7b4db..81a1578bb22c 100644
> --- a/include/netlink/object.h
> +++ b/include/netlink/object.h
> @@ -41,7 +41,7 @@ extern void			nl_object_dump(s
> truct nl_object *,
> ?extern void			nl_object_dump_buf(struct
> nl_object *, char *, size_t);
> ?extern int			nl_object_identical(struct
> nl_object *,
> ?						????struct nl_object
> *);
> -extern uint32_t			nl_object_diff(struct
> nl_object *,
> +extern uint64_t			nl_object_diff(struct
> nl_object *,
> 

This changes public API. Cannot do that. Maybe add a nl_object_diff64()
-- as ugly as it is...


Too bad we already used:
#define LINK_ATTR_LINK_NETNSID??(1 << 31)

I missed that. Otherwise we could reserve the highest bit for ~there
are some other flags above 32 bit~.


like:

uint32_t nl_object_diff(struct nl_object *obj1, ... obj2)
{
? ? uint64_t diff;

? ? diff = nl_object_diff64 (obj1, obj2);

? ? return (diff & ~((uint64_t 0xFFFFFFFF))
? ? ? ? ? ?? (uint32_t) diff | (1 << 31)
? ? ? ? ? ?: (uint32_t) diff;
}


Maybe we just change LINK_ATTR_LINK_NETNSID to be (1 << 32) and do it
anyway? The actual numeric values of LINK_ATTR_* are anyway private
API.






Otherwise this patch changes ABI for internal API in a somewhat crucial
way. I guess that's OK and no user in the wild depends on that,
right(??)



Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20151218/892707d6/attachment.sig>

From dsa at cumulusnetworks.com  Fri Dec 18 07:24:48 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Fri, 18 Dec 2015 08:24:48 -0700
Subject: [PATCH] lib: Update ce-mask to uint64_t
In-Reply-To: <1450426605.3567.24.camel@redhat.com>
References: <1450300282-7804-1-git-send-email-dsa@cumulusnetworks.com>
 <1450426605.3567.24.camel@redhat.com>
Message-ID: <56742540.7030400@cumulusnetworks.com>

On 12/18/15 1:16 AM, Thomas Haller wrote:
> Hi David,
>
>
> On Wed, 2015-12-16 at 13:11 -0800, David Ahern wrote:
>> lib/route/link.c already defines 32 attributes which fills the
>> current
>> uint32_t used for ce_mask. To accommodate more attributes the mask
>> needs
>> to be expanded. This patch updates the definition to uint64_t and
>> fixes
>> callers and implementations to consistently use uint64_t data type.
>
>
>>   extern void *			rtnl_tc_data(struct rtnl_tc *);
>> diff --git a/include/netlink/object.h b/include/netlink/object.h
>> index a95feda7b4db..81a1578bb22c 100644
>> --- a/include/netlink/object.h
>> +++ b/include/netlink/object.h
>> @@ -41,7 +41,7 @@ extern void			nl_object_dump(s
>> truct nl_object *,
>>   extern void			nl_object_dump_buf(struct
>> nl_object *, char *, size_t);
>>   extern int			nl_object_identical(struct
>> nl_object *,
>>   						    struct nl_object
>> *);
>> -extern uint32_t			nl_object_diff(struct
>> nl_object *,
>> +extern uint64_t			nl_object_diff(struct
>> nl_object *,
>>
>
> This changes public API. Cannot do that. Maybe add a nl_object_diff64()
> -- as ugly as it is...

That crossed my mind but I was not sure how to handle the existing API 
-- a way to indicate that there are more than 32 attributes and a higher 
one differed.

It also struck me as odd that the return is a bitmask with a bit per 
attribute that differed. How can that be used since the attributes are 
hidden inside of the code?

> Too bad we already used:
> #define LINK_ATTR_LINK_NETNSID  (1 << 31)
>
> I missed that. Otherwise we could reserve the highest bit for ~there
> are some other flags above 32 bit~.
>
>
> like:
>
> uint32_t nl_object_diff(struct nl_object *obj1, ... obj2)
> {
>      uint64_t diff;
>
>      diff = nl_object_diff64 (obj1, obj2);
>
>      return (diff & ~((uint64_t 0xFFFFFFFF))
>             ? (uint32_t) diff | (1 << 31)
>             : (uint32_t) diff;
> }
>
>
> Maybe we just change LINK_ATTR_LINK_NETNSID to be (1 << 32) and do it
> anyway? The actual numeric values of LINK_ATTR_* are anyway private
> API.

Ok, that's an idea - mark the high bit as 'other';


>
> Otherwise this patch changes ABI for internal API in a somewhat crucial
> way. I guess that's OK and no user in the wild depends on that,
> right(??)

No way to really know. I'll spin a v2 with the above.




From dsa at cumulusnetworks.com  Fri Dec 18 09:50:03 2015
From: dsa at cumulusnetworks.com (David Ahern)
Date: Fri, 18 Dec 2015 09:50:03 -0800
Subject: [PATCH v2] lib: Update ce-mask to uint64_t
Message-ID: <1450461003-10015-1-git-send-email-dsa@cumulusnetworks.com>

lib/route/link.c already defines 32 attributes which fills the current
uint32_t used for ce_mask. To accommodate more attributes the mask needs
to be expanded. This patch updates the definition to uint64_t.

The nl_object_diff API is maintained for ABI with existing users. A new
nl_object_diff64 API is added for the expanded attribute list. The MSB
of the 32-bit API is used to indicate if higher order attributes had a
mismatch. (Suggested by Thomas).

Signed-off-by: David Ahern <dsa at cumulusnetworks.com>
---
v2
- Thomas' comments
- kept existing nl_object_diff as 32-bit api with high bit indicating
  attribute mismatch in higher order bits
- added nl_object_diff64 for 64-bit mask
 
 include/netlink-private/netlink.h      |  2 +-
 include/netlink-private/object-api.h   | 10 ++++++----
 include/netlink-private/route/tc-api.h |  4 ++--
 include/netlink/object.h               |  2 ++
 lib/fib_lookup/lookup.c                |  4 ++--
 lib/fib_lookup/request.c               |  6 +++---
 lib/genl/family.c                      |  6 +++---
 lib/idiag/idiag_meminfo_obj.c          |  4 ++--
 lib/idiag/idiag_msg_obj.c              |  6 +++---
 lib/idiag/idiag_vegasinfo_obj.c        |  4 ++--
 lib/netfilter/ct_obj.c                 |  6 +++---
 lib/netfilter/exp_obj.c                |  6 +++---
 lib/netfilter/log_obj.c                |  6 +++---
 lib/netfilter/queue_obj.c              |  6 +++---
 lib/object.c                           | 29 +++++++++++++++++++++++++++--
 lib/route/addr.c                       |  6 +++---
 lib/route/link.c                       |  9 +++++----
 lib/route/neigh.c                      |  6 +++---
 lib/route/neightbl.c                   |  6 +++---
 lib/route/route_obj.c                  |  7 ++++---
 lib/route/rule.c                       |  6 +++---
 lib/route/tc.c                         |  6 +++---
 lib/xfrm/ae.c                          |  6 ++++--
 lib/xfrm/sa.c                          |  5 +++--
 lib/xfrm/sp.c                          |  5 +++--
 25 files changed, 99 insertions(+), 64 deletions(-)

diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h
index 6d40ea53c578..befd3014afcb 100644
--- a/include/netlink-private/netlink.h
+++ b/include/netlink-private/netlink.h
@@ -71,7 +71,7 @@
 #define NSEC_PER_SEC	1000000000L
 
 struct trans_tbl {
-	int i;
+	uint64_t i;
 	const char *a;
 };
 
diff --git a/include/netlink-private/object-api.h b/include/netlink-private/object-api.h
index f4fd71e576ec..517e6720f50c 100644
--- a/include/netlink-private/object-api.h
+++ b/include/netlink-private/object-api.h
@@ -126,6 +126,8 @@ extern "C" {
  * #define MY_ATTR_FOO		(1<<0)
  * #define MY_ATTR_BAR		(1<<1)
  *
+ * // Bit 31 for attributes is reserved for 32-bit API.
+ *
  * // When assigning an optional attribute to the object, make sure
  * // to mark its availability.
  * my_obj->foo = 123123;
@@ -189,7 +191,7 @@ extern "C" {
 	struct nl_list_head	ce_list;	\
 	int			ce_msgtype;	\
 	int			ce_flags;	\
-	uint32_t		ce_mask;
+	uint64_t		ce_mask;
 
 struct nl_object
 {
@@ -258,7 +260,7 @@ struct nl_object
  * @endcode
  */
 #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
-({	int diff = 0; \
+({	uint64_t diff = 0; \
 	if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
 		diff = ATTR; \
 	diff; })
@@ -333,8 +335,8 @@ struct nl_object_ops
 	 * The function must return a bitmask with the relevant bit
 	 * set for each attribute that mismatches.
 	 */
-	int   (*oo_compare)(struct nl_object *, struct nl_object *,
-			    uint32_t, int);
+	uint64_t (*oo_compare)(struct nl_object *, struct nl_object *,
+			       uint64_t, int);
 
 
 	/**
diff --git a/include/netlink-private/route/tc-api.h b/include/netlink-private/route/tc-api.h
index fbfa2abd8fa2..7158ce5c117b 100644
--- a/include/netlink-private/route/tc-api.h
+++ b/include/netlink-private/route/tc-api.h
@@ -110,9 +110,9 @@ extern void			rtnl_tc_dump_details(struct nl_object *,
 						     struct nl_dump_params *);
 extern void			rtnl_tc_dump_stats(struct nl_object *,
 						   struct nl_dump_params *);
-extern int			rtnl_tc_compare(struct nl_object *,
+extern uint64_t			rtnl_tc_compare(struct nl_object *,
 						struct nl_object *,
-						uint32_t, int);
+						uint64_t, int);
 
 void *                          rtnl_tc_data_peek(struct rtnl_tc *tc);
 extern void *			rtnl_tc_data(struct rtnl_tc *);
diff --git a/include/netlink/object.h b/include/netlink/object.h
index a95feda7b4db..b0c32c988b1f 100644
--- a/include/netlink/object.h
+++ b/include/netlink/object.h
@@ -43,6 +43,8 @@ extern int			nl_object_identical(struct nl_object *,
 						    struct nl_object *);
 extern uint32_t			nl_object_diff(struct nl_object *,
 					       struct nl_object *);
+extern uint64_t			nl_object_diff64(struct nl_object *,
+						 struct nl_object *);
 extern int			nl_object_match_filter(struct nl_object *,
 						       struct nl_object *);
 extern char *			nl_object_attrs2str(struct nl_object *,
diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c
index 9b24635240d2..43b6126f376b 100644
--- a/lib/fib_lookup/lookup.c
+++ b/lib/fib_lookup/lookup.c
@@ -141,8 +141,8 @@ static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p)
 	result_dump_line(obj, p);
 }
 
-static int result_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t result_compare(struct nl_object *_a, struct nl_object *_b,
+			uint64_t attrs, int flags)
 {
 	return 0;
 }
diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c
index 1b021b64dba8..5bd49d6fd320 100644
--- a/lib/fib_lookup/request.c
+++ b/lib/fib_lookup/request.c
@@ -53,12 +53,12 @@ static int request_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int request_compare(struct nl_object *_a, struct nl_object *_b,
-			   uint32_t attrs, int flags)
+static uint64_t request_compare(struct nl_object *_a, struct nl_object *_b,
+			   uint64_t attrs, int flags)
 {
 	struct flnl_request *a = (struct flnl_request *) _a;
 	struct flnl_request *b = (struct flnl_request *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/genl/family.c b/lib/genl/family.c
index 9155c8fda9a2..45c3d45e1b3e 100644
--- a/lib/genl/family.c
+++ b/lib/genl/family.c
@@ -147,12 +147,12 @@ static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	family_dump_details(obj, p);
 }
 
-static int family_compare(struct nl_object *_a, struct nl_object *_b,
-			  uint32_t attrs, int flags)
+static uint64_t family_compare(struct nl_object *_a, struct nl_object *_b,
+			  uint64_t attrs, int flags)
 {
 	struct genl_family *a = (struct genl_family *) _a;
 	struct genl_family *b = (struct genl_family *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/idiag/idiag_meminfo_obj.c b/lib/idiag/idiag_meminfo_obj.c
index f07800fdb3c4..1c327bb37832 100644
--- a/lib/idiag/idiag_meminfo_obj.c
+++ b/lib/idiag/idiag_meminfo_obj.c
@@ -81,8 +81,8 @@ void idiagnl_meminfo_set_tmem(struct idiagnl_meminfo *minfo, uint32_t tmem)
 /** @} */
 
 /** @cond SKIP */
-static int idiagnl_meminfo_compare(struct nl_object *_a, struct nl_object *_b,
-                                     uint32_t attrs, int flags)
+static uint64_t idiagnl_meminfo_compare(struct nl_object *_a, struct nl_object *_b,
+                                     uint64_t attrs, int flags)
 {
 	struct idiagnl_meminfo *a = (struct idiagnl_meminfo *) _a;
 	struct idiagnl_meminfo *b = (struct idiagnl_meminfo *) _b;
diff --git a/lib/idiag/idiag_msg_obj.c b/lib/idiag/idiag_msg_obj.c
index d7cf7222049e..beaa9cc49f27 100644
--- a/lib/idiag/idiag_msg_obj.c
+++ b/lib/idiag/idiag_msg_obj.c
@@ -853,12 +853,12 @@ static char *_idiagnl_attrs2str(int attrs, char *buf, size_t len)
 	                   ARRAY_SIZE(idiagnl_attrs));
 }
 
-static int idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
-                           uint32_t attrs, int flags)
+static uint64_t idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
+                                uint64_t attrs, int flags)
 {
 	struct idiagnl_msg *a = (struct idiagnl_msg *) _a;
 	struct idiagnl_msg *b = (struct idiagnl_msg *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
 	diff |= _DIFF(FAMILY,    a->idiag_family != b->idiag_family);
diff --git a/lib/idiag/idiag_vegasinfo_obj.c b/lib/idiag/idiag_vegasinfo_obj.c
index eddd8af0e850..f02eea077b41 100644
--- a/lib/idiag/idiag_vegasinfo_obj.c
+++ b/lib/idiag/idiag_vegasinfo_obj.c
@@ -84,8 +84,8 @@ void idiagnl_vegasinfo_set_minrtt(struct idiagnl_vegasinfo *vinfo, uint32_t
 /** @} */
 
 /** @cond SKIP */
-static int idiagnl_vegasinfo_compare(struct nl_object *_a, struct nl_object *_b,
-                                     uint32_t attrs, int flags)
+static uint64_t idiagnl_vegasinfo_compare(struct nl_object *_a, struct nl_object *_b,
+                                          uint64_t attrs, int flags)
 {
 	struct idiagnl_vegasinfo *a = (struct idiagnl_vegasinfo *) _a;
 	struct idiagnl_vegasinfo *b = (struct idiagnl_vegasinfo *) _b;
diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c
index c8af87023c05..1079ec0a4b07 100644
--- a/lib/netfilter/ct_obj.c
+++ b/lib/netfilter/ct_obj.c
@@ -297,12 +297,12 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p)
 	}
 }
 
-static int ct_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t ct_compare(struct nl_object *_a, struct nl_object *_b,
+			   uint64_t attrs, int flags)
 {
 	struct nfnl_ct *a = (struct nfnl_ct *) _a;
 	struct nfnl_ct *b = (struct nfnl_ct *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
 #define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c
index 591cf45076ad..aef43b73acfa 100644
--- a/lib/netfilter/exp_obj.c
+++ b/lib/netfilter/exp_obj.c
@@ -301,12 +301,12 @@ static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_pro
 	return d;
 }
 
-static int exp_compare(struct nl_object *_a, struct nl_object *_b,
-							uint32_t attrs, int flags)
+static uint64_t exp_compare(struct nl_object *_a, struct nl_object *_b,
+			    uint64_t attrs, int flags)
 {
 	struct nfnl_exp *a = (struct nfnl_exp *) _a;
 	struct nfnl_exp *b = (struct nfnl_exp *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR)
 #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD)
diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c
index 3fdb3472a305..65985d86ee96 100644
--- a/lib/netfilter/log_obj.c
+++ b/lib/netfilter/log_obj.c
@@ -229,12 +229,12 @@ unsigned int nfnl_log_str2flags(const char *name)
 	return __str2flags(name, log_flags, ARRAY_SIZE(log_flags));
 }
 
-static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
-			    uint32_t attrs, int flags)
+static uint64_t nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
+				 uint64_t attrs, int flags)
 {
 	struct nfnl_log *a = (struct nfnl_log *) _a;
 	struct nfnl_log *b = (struct nfnl_log *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NFNL_LOG_DIFF(ATTR, EXPR) \
 	ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c
index 36ed3c53f15c..040bbed4f14b 100644
--- a/lib/netfilter/queue_obj.c
+++ b/lib/netfilter/queue_obj.c
@@ -161,12 +161,12 @@ uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue)
 	return queue->queue_copy_range;
 }
 
-static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
-			      uint32_t attrs, int flags)
+static uint64_t nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
+				   uint64_t attrs, int flags)
 {
 	struct nfnl_queue *a = (struct nfnl_queue *) _a;
 	struct nfnl_queue *b = (struct nfnl_queue *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NFNL_QUEUE_DIFF(ATTR, EXPR) \
 	ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/object.c b/lib/object.c
index cad24e0a9e4d..a88ac00357a6 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -358,17 +358,42 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b)
  *
  * @return Bitmask describing differences or 0 if they are completely identical.
  */
-uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
+uint64_t nl_object_diff64(struct nl_object *a, struct nl_object *b)
 {
 	struct nl_object_ops *ops = obj_ops(a);
 
 	if (ops != obj_ops(b) || ops->oo_compare == NULL)
-		return UINT32_MAX;
+		return UINT64_MAX;
 
 	return ops->oo_compare(a, b, ~0, 0);
 }
 
 /**
+ * Compute 32-bit bitmask representing difference in attribute values
+ * @arg a		an object
+ * @arg b		another object of same type
+ *
+ * The bitmask returned is specific to an object type, each bit set represents
+ * an attribute which mismatches in either of the two objects. Unavailability
+ * of an attribute in one object and presence in the other is regarded a
+ * mismatch as well.
+ *
+ * @return Bitmask describing differences or 0 if they are completely identical.
+ *	   32nd bit indicates if higher bits from the 64-bit compare were
+ *	   different.
+ */
+uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
+{
+	uint64_t  diff;
+
+	diff = nl_object_diff64(a, b);
+
+	return (diff & ~((uint64_t) 0xFFFFFFFF))
+		? (uint32_t) diff | (1 << 31)
+		: (uint32_t) diff;
+}
+
+/**
  * Match a filter against an object
  * @arg obj		object to check
  * @arg filter		object of same type acting as filter
diff --git a/lib/route/addr.c b/lib/route/addr.c
index 3bde2bf8b2ec..33df1c86cbf4 100644
--- a/lib/route/addr.c
+++ b/lib/route/addr.c
@@ -429,12 +429,12 @@ static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	addr_dump_details(obj, p);
 }
 
-static int addr_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_addr *a = (struct rtnl_addr *) _a;
 	struct rtnl_addr *b = (struct rtnl_addr *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/link.c b/lib/route/link.c
index d763d973650e..1fa26721bc76 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -61,7 +61,8 @@
 #define LINK_ATTR_PHYS_PORT_ID	(1 << 28)
 #define LINK_ATTR_NS_FD		(1 << 29)
 #define LINK_ATTR_NS_PID	(1 << 30)
-#define LINK_ATTR_LINK_NETNSID  (1 << 31)
+/* 31 used by 32-bit api */
+#define LINK_ATTR_LINK_NETNSID  ((uint64_t) 1 << 32)
 
 static struct nl_cache_ops rtnl_link_ops;
 static struct nl_object_ops link_obj_ops;
@@ -955,12 +956,12 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int link_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_link *a = (struct rtnl_link *) _a;
 	struct rtnl_link *b = (struct rtnl_link *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index 436d766a6a11..9fdcaca981d5 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -260,12 +260,12 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t neigh_compare(struct nl_object *_a, struct nl_object *_b,
+			      uint64_t attrs, int flags)
 {
 	struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
 	struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c
index f9c9c27759e0..7fd106b93625 100644
--- a/lib/route/neightbl.c
+++ b/lib/route/neightbl.c
@@ -54,12 +54,12 @@ static struct nl_cache_ops rtnl_neightbl_ops;
 static struct nl_object_ops neightbl_obj_ops;
 /** @endcond */
 
-static int neightbl_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t neightbl_compare(struct nl_object *_a, struct nl_object *_b,
+				 uint64_t attrs, int flags)
 {
 	struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a;
 	struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c
index 4063c6f672e8..0f52e00db86e 100644
--- a/lib/route/route_obj.c
+++ b/lib/route/route_obj.c
@@ -343,13 +343,14 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey,
 	return;
 }
 
-static int route_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b,
+			      uint64_t attrs, int flags)
 {
 	struct rtnl_route *a = (struct rtnl_route *) _a;
 	struct rtnl_route *b = (struct rtnl_route *) _b;
 	struct rtnl_nexthop *nh_a, *nh_b;
-	int i, diff = 0, found;
+	int i, found;
+	uint64_t diff = 0;
 
 #define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/rule.c b/lib/route/rule.c
index 357cb1bf60bd..883df812cc3f 100644
--- a/lib/route/rule.c
+++ b/lib/route/rule.c
@@ -245,12 +245,12 @@ static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 
 #define RULE_ATTR_FLAGS		0x0008
 
-static int rule_compare(struct nl_object *_a, struct nl_object *_b,
-			uint32_t attrs, int flags)
+static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
+			     uint64_t attrs, int flags)
 {
 	struct rtnl_rule *a = (struct rtnl_rule *) _a;
 	struct rtnl_rule *b = (struct rtnl_rule *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/route/tc.c b/lib/route/tc.c
index 35daf15ae57d..384e85705b1d 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -932,12 +932,12 @@ void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
 	             tc->tc_stats[RTNL_TC_RATE_PPS]);
 }
 
-int rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
-		    uint32_t attrs, int flags)
+uint64_t rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
+			 uint64_t attrs, int flags)
 {
 	struct rtnl_tc *a = TC_CAST(aobj);
 	struct rtnl_tc *b = TC_CAST(bobj);
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
 
diff --git a/lib/xfrm/ae.c b/lib/xfrm/ae.c
index 4fe964725b52..bfe481f76eae 100644
--- a/lib/xfrm/ae.c
+++ b/lib/xfrm/ae.c
@@ -181,11 +181,13 @@ static int xfrm_ae_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_ae* a  =   (struct xfrmnl_ae *) _a;
 	struct xfrmnl_ae* b  =   (struct xfrmnl_ae *) _b;
-	int diff = 0, found = 0;
+	uint64_t diff = 0;
+	int found = 0;
 
 #define XFRM_AE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_AE_ATTR_##ATTR, a, b, EXPR)
 	diff |= XFRM_AE_DIFF(DADDR,	nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr));
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index 34d24cf843eb..31c22ba44ef2 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -205,11 +205,12 @@ static int xfrm_sa_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_sa_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_sa_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_sa* a  =   (struct xfrmnl_sa *) _a;
 	struct xfrmnl_sa* b  =   (struct xfrmnl_sa *) _b;
-	int diff = 0;
+	uint64_t diff = 0;
 	int found = 0;
 
 #define XFRM_SA_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SA_ATTR_##ATTR, a, b, EXPR)
diff --git a/lib/xfrm/sp.c b/lib/xfrm/sp.c
index 943269a6638f..cc2fcb1c60a1 100644
--- a/lib/xfrm/sp.c
+++ b/lib/xfrm/sp.c
@@ -138,12 +138,13 @@ static int xfrm_sp_clone(struct nl_object *_dst, struct nl_object *_src)
 	return 0;
 }
 
-static int xfrm_sp_compare(struct nl_object *_a, struct nl_object *_b, uint32_t attrs, int flags)
+static uint64_t xfrm_sp_compare(struct nl_object *_a, struct nl_object *_b,
+				uint64_t attrs, int flags)
 {
 	struct xfrmnl_sp* a  =   (struct xfrmnl_sp *) _a;
 	struct xfrmnl_sp* b  =   (struct xfrmnl_sp *) _b;
 	struct xfrmnl_user_tmpl *tmpl_a, *tmpl_b;
-	int diff = 0;
+	uint64_t diff = 0;
 
 #define XFRM_SP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SP_ATTR_##ATTR, a, b, EXPR)
 	diff |= XFRM_SP_DIFF(SEL,	xfrmnl_sel_cmp(a->sel, b->sel));
-- 
2.1.4



