Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Alex Bergmann @ 2012-08-23 11:58 UTC (permalink / raw)
  To: H.K. Jerry Chu; +Cc: davem, netdev, linux-kernel
In-Reply-To: <CAFbMe2M7ekc94bQk7vTS1LhScPd49VZ-zKOCUXhqwxXtL-nkuA@mail.gmail.com>

On 08/22/2012 06:41 PM, H.K. Jerry Chu wrote:
> On Tue, Aug 21, 2012 at 4:29 PM, Alex Bergmann <alex@linlab.net
> <mailto:alex@linlab.net>> wrote:
>
>     Hi David,
>
>     I'm not 100% sure, but it looks like I found an RFC mismatch with the
>     current default values of the TCP implementation.
>
>     Alex
>
>      From 8b854a525eb45f64ad29dfab16f9d9f681e84495 Mon Sep 17 00:00:00 2001
>     From: Alexander Bergmann <alex@linlab.net <mailto:alex@linlab.net>>
>     Date: Wed, 22 Aug 2012 00:29:08 +0200
>     Subject: [PATCH 1/1] tcp: Wrong timeout for SYN segments
>
>     Commit 9ad7c049 changed the initRTO from 3secs to 1sec in accordance to
>     RFC6298 (former RFC2988bis). This introduced a gap with RFC1122 that
>     defines a minimum retransmission window for SYN segments of at least
>     180secs.
>
>     Prior to 9ad7c049 the timeout was defined with 189secs. Now we have only
>     a timeout of 63secs.
>
>              ((2 << 5) - 1) * 3 secs = 189 secs
>              ((2 << 5) - 1) * 1 secs = 63 secs
>
>     To fulfill the MUST constraint in RFC1122 section 4.2.3.5 about R2 for
>     SYN segments, the values of TCP_SYN_RETRIES and TCP_SYNACK_RETRIES must
>     be changed to 7 reties.
>
>              ((2 << 7) - 1) * 1 secs = 255 secs
>
>     This would result in an ETIMEDOUT of 4 minutes 15 seconds.
>
>
> This issue occurred to me right after I submitted the patch for RFC6298.
> I did not commit any more change because RFC compliance aside, 180secs
> just seem like eternity in the Internet age.
>
> (See my past post on this at
> http://marc.info/?l=linux-netdev&m=130759078118866&w=2)

Okay, I missed that post during my search about the current situation.

Thanks,
Alex


> Jerry
>
>
>     Signed-off-by: Alexander Bergmann <alex@linlab.net
>     <mailto:alex@linlab.net>>
>     ---
>       include/net/tcp.h |    4 ++--
>       1 files changed, 2 insertions(+), 2 deletions(-)
>
>     diff --git a/include/net/tcp.h b/include/net/tcp.h
>     index 1f000ff..7eaae19 100644
>     --- a/include/net/tcp.h
>     +++ b/include/net/tcp.h
>     @@ -98,10 +98,10 @@ extern void tcp_time_wait(struct sock *sk, int
>     state, int timeo);
>                                       * 15 is ~13-30min depending on RTO.
>                                       */
>
>     -#define TCP_SYN_RETRIES         5      /* number of times to retry
>     active opening a
>     +#define TCP_SYN_RETRIES         7      /* number of times to retry
>     active opening a
>                                       * connection: ~180sec is RFC
>     minimum   */
>
>     -#define TCP_SYNACK_RETRIES 5   /* number of times to retry passive
>     opening a
>     +#define TCP_SYNACK_RETRIES 7   /* number of times to retry passive
>     opening a
>                                       * connection: ~180sec is RFC
>     minimum   */
>
>       #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy
>     TIME-WAIT
>     --
>     1.7.8.6
>
>     --
>     To unsubscribe from this list: send the line "unsubscribe netdev" in
>     the body of a message to majordomo@vger.kernel.org
>     <mailto:majordomo@vger.kernel.org>
>     More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>


-- 
|. _ | _ |_   _  _ _|_
||| ||(_||_).| |(/_ |
email/sip/xmpp: alex@linlab.net
phone/enum: +49 2871 2355378

^ permalink raw reply

* [PATCH] netlink: fix possible spoofing from non-root processes
From: pablo @ 2012-08-23 12:09 UTC (permalink / raw)
  To: netdev; +Cc: davem

From: Pablo Neira Ayuso <pablo@netfilter.org>

Non-root user-space processes can send Netlink messages to other
processes that are well-known for being subscribed to Netlink
asynchronous notifications. This allows ilegitimate non-root
process to send forged messages to Netlink subscribers.

The userspace process usually verifies the legitimate origin in
two ways:

a) Socket credentials. If UID != 0, then the message comes from
   some ilegitimate process and the message needs to be dropped.

b) Netlink portID. In general, portID == 0 means that the origin
   of the messages comes from the kernel. Thus, discarding any
   message not coming from the kernel.

However, ctnetlink sets the portID in event messages that has
been triggered by some user-space process, eg. conntrack utility.
So other processes subscribed to ctnetlink events, eg. conntrackd,
know that the event was triggered by some user-space action.

Neither of the two ways to discard ilegitimate messages coming
from non-root processes can help for ctnetlink.

This patch adds capability validation in case that dst_pid is set
in netlink_sendmsg(). This approach is aggressive since existing
applications using any Netlink bus to deliver messages between
two user-space processes will break. Note that the exception is
NETLINK_USERSOCK, since it is reserved for netlink-to-netlink
userspace communication.

Still, if anyone wants that his Netlink bus allows netlink-to-netlink
userspace, then they can set NL_NONROOT_SEND. However, by default,
I don't think it makes sense to allow to use NETLINK_ROUTE to
communicate two processes that are sending no matter what information
that is not related to link/neighbouring/routing. They should be using
NETLINK_USERSOCK instead for that.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netlink/af_netlink.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5463969..998dd18 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1373,7 +1373,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		dst_pid = addr->nl_pid;
 		dst_group = ffs(addr->nl_groups);
 		err =  -EPERM;
-		if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
+		if ((dst_group || dst_pid) &&
+		    !netlink_capable(sock, NL_NONROOT_SEND))
 			goto out;
 	} else {
 		dst_pid = nlk->dst_pid;
@@ -2147,6 +2148,7 @@ static void __init netlink_add_usersock_entry(void)
 	rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
 	nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
 	nl_table[NETLINK_USERSOCK].registered = 1;
+	nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND;
 
 	netlink_table_ungrab();
 }
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v2] libceph: Fix sparse warning
From: Iulius Curt @ 2012-08-23 12:14 UTC (permalink / raw)
  To: sage; +Cc: davem, ceph-devel, netdev, dbaluta, Iulius Curt, Iulius Curt

From: Iulius Curt <iulius.curt@gmail.com>

Make ceph_monc_do_poolop() static to remove the following sparse warning:
 * net/ceph/mon_client.c:616:5: warning: symbol 'ceph_monc_do_poolop' was not
   declared. Should it be static?
Also drops the 'ceph_monc_' prefix, now being a private function.

Signed-off-by: Iulius Curt <icurt@ixiacom.com>
---
v1 ---> v2
 * drop the 'ceph_monc_' prefix
---
 net/ceph/mon_client.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 105d533..84ce495 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -613,7 +613,7 @@ bad:
 /*
  * Do a synchronous pool op.
  */
-int ceph_monc_do_poolop(struct ceph_mon_client *monc, u32 op,
+static int do_poolop(struct ceph_mon_client *monc, u32 op,
 			u32 pool, u64 snapid,
 			char *buf, int len)
 {
@@ -663,7 +663,7 @@ out:
 int ceph_monc_create_snapid(struct ceph_mon_client *monc,
 			    u32 pool, u64 *snapid)
 {
-	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
+	return do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
 				   pool, 0, (char *)snapid, sizeof(*snapid));

 }
@@ -672,7 +672,7 @@ EXPORT_SYMBOL(ceph_monc_create_snapid);
 int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
 			    u32 pool, u64 snapid)
 {
-	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
+	return do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
 				   pool, snapid, 0, 0);

 }
--
1.7.9.5


^ permalink raw reply related

* Re: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Eric Dumazet @ 2012-08-23 12:15 UTC (permalink / raw)
  To: Alex Bergmann; +Cc: H.K. Jerry Chu, davem, netdev, linux-kernel
In-Reply-To: <50361AEA.6010807@linlab.net>

On Thu, 2012-08-23 at 13:58 +0200, Alex Bergmann wrote:
> On 08/22/2012 06:41 PM, H.K. Jerry Chu wrote:

> > This issue occurred to me right after I submitted the patch for RFC6298.
> > I did not commit any more change because RFC compliance aside, 180secs
> > just seem like eternity in the Internet age.
> >
> > (See my past post on this at
> > http://marc.info/?l=linux-netdev&m=130759078118866&w=2)
> 
> Okay, I missed that post during my search about the current situation.

I would suggest to increase TCP_SYN_RETRIES from 5 to 6.

180 secs is eternity, but 31 secs is too small.

Can you repost a v2, only changing TCP_SYN_RETRIES ?

^ permalink raw reply

* [PATCH net-next V3 0/2] Add rtnl_link_ops support to IPoIB
From: Or Gerlitz @ 2012-08-23 12:15 UTC (permalink / raw)
  To: davem; +Cc: roland, netdev, Or Gerlitz

This is about adding rtnl_link_ops to IPoIB, primarly addressing feedback 
from Dave on a similar patch that was part of the eIPoIB submission.

Also added the releated iproute2 patch, for the sake of the review and 
testing, e.g example usages: 

$ ip link add link ib0 name ib0.1 type ipoib 
$ ip link add link ib0 name ib0.8001 type ipoib pkey 0x8001

and the obvious

$ link delete dev ib0.8001
$ link delete dev ib0.1

Changes from V2:
 - removed the notion of user defined index per child, since we can do well w.o it 
 - for that end, make (an internal to ipoib) distrinction between legacy childs created 
   through the old sysfs way to childs created using rtnl link ops

Changes from V1: 
 - applied feedback from Dave Miller to avoid using sysfs
 - added rtnl_link_ops support in ipoib and use them to add/delete childs

Or Gerlitz (1):
  IB/ipoib: Add rtnl_link_ops support

 Documentation/infiniband/ipoib.txt           |    3 +
 drivers/infiniband/ulp/ipoib/Makefile        |    3 +-
 drivers/infiniband/ulp/ipoib/ipoib.h         |   13 +++
 drivers/infiniband/ulp/ipoib/ipoib_main.c    |   25 ++++-
 drivers/infiniband/ulp/ipoib/ipoib_netlink.c |  122 ++++++++++++++++++++++++++
 drivers/infiniband/ulp/ipoib/ipoib_vlan.c    |  102 ++++++++++++----------
 6 files changed, 217 insertions(+), 51 deletions(-)
 create mode 100644 drivers/infiniband/ulp/ipoib/ipoib_netlink.c

^ permalink raw reply

* [PATCH iproute2 2/2] iplink: added support for ipoib rtnl link ops
From: Or Gerlitz @ 2012-08-23 12:15 UTC (permalink / raw)
  To: davem; +Cc: roland, netdev, Or Gerlitz
In-Reply-To: <1345724119-32110-1-git-send-email-ogerlitz@mellanox.com>

Added basic support to create/delete IPoIB child devices,
where the user can optionally specify the IB PKEY (Partition Key)
to be used by the newly created device. If nothing is provided,
the child will use the same pkey as the parent.

Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 include/linux/if_link.h |    9 ++++++
 ip/Makefile             |    2 +-
 ip/iplink.c             |    2 +-
 ip/iplink_ipoib.c       |   73 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+), 2 deletions(-)
 create mode 100644 ip/iplink_ipoib.c

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 46f03db..7e64aa7 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -384,4 +384,13 @@ struct ifla_port_vsi {
 	__u8 pad[3];
 };
 
+/* IPoIB section */
+enum {
+	IFLA_IPOIB_UNSPEC,
+	IFLA_IPOIB_CHILD_PKEY,
+	__IFLA_IPOIB_MAX
+};
+
+#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/ip/Makefile b/ip/Makefile
index 6a518f8..ba2e2e6 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -3,7 +3,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
-    iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o
+    iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o iplink_ipoib.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink.c b/ip/iplink.c
index 4111871..7451aa0 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -83,7 +83,7 @@ void iplink_usage(void)
 
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "\n");
-		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can | bridge }\n");
+		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can | bridge | ipoib }\n");
 	}
 	exit(-1);
 }
diff --git a/ip/iplink_ipoib.c b/ip/iplink_ipoib.c
new file mode 100644
index 0000000..7dea357
--- /dev/null
+++ b/ip/iplink_ipoib.c
@@ -0,0 +1,73 @@
+/*
+ * iplink_ipoib.c	IPoIB device support
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Or Gerlitz <ogerlitz@mellanox.com> 
+ *		copied iflink_vlan.c authored by Patrick McHardy <kaber@trash.net>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/if_link.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+static void explain(void)
+{
+	fprintf(stderr,
+		"Usage: ... ipoib [pkey PKEY]\n"
+		"\n"
+		"PKEY  := 0x8001-0xffff\n"
+	);
+}
+
+static int ipoib_parse_opt(struct link_util *lu, int argc, char **argv,
+			  struct nlmsghdr *n)
+{
+	__u16 pkey;
+
+	while (argc > 0) {
+		if (matches(*argv, "pkey") == 0) {
+			NEXT_ARG();
+			if (get_u16(&pkey, *argv, 0))
+				invarg("pkey is invalid", *argv);
+			addattr_l(n, 1024, IFLA_IPOIB_CHILD_PKEY, &pkey, 2);
+		} else if (matches(*argv, "help") == 0) {
+			explain();
+			return -1;
+		} else {
+			fprintf(stderr, "ipoib: what is \"%s\"?\n", *argv);
+			explain();
+			return -1;
+		}
+		argc--, argv++;
+	}
+
+	return 0;
+}
+
+static void ipoib_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+{
+	if (!tb)
+		return;
+
+	if (!tb[IFLA_IPOIB_CHILD_PKEY] ||
+	    RTA_PAYLOAD(tb[IFLA_IPOIB_CHILD_PKEY]) < sizeof(__u16))
+		return;
+
+	fprintf(f, "pkey  %.4x ", rta_getattr_u16(tb[IFLA_IPOIB_CHILD_PKEY]));
+}
+
+struct link_util ipoib_link_util = {
+	.id		= "ipoib",
+	.maxattr	= IFLA_IPOIB_MAX,
+	.parse_opt	= ipoib_parse_opt,
+	.print_opt	= ipoib_print_opt,
+};
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH v8] bonding: support for IPv6 transmit hashing
From: Jeremy Brookman @ 2012-08-23 12:23 UTC (permalink / raw)
  To: John Eaglesham; +Cc: netdev
In-Reply-To: <2e01d8f94c42c61af9886683a4c35caf6816bc3d.1345615999.git.linux@8192.net>

Thanks for getting this in John.  Apologies for my earlier reply,
where I hadn't spotted this revision of the patch; it looks like the
comments I made have been addressed, and all is well.

Thanks again,

Jeremy

On Wed, Aug 22, 2012 at 7:43 AM, John Eaglesham <linux@8192.net> wrote:
> From: John Eaglesham <linux@8192.net>
>
> Currently the "bonding" driver does not support load balancing outgoing
> traffic in LACP mode for IPv6 traffic. IPv4 (and TCP or UDP over IPv4)
> are currently supported; this patch adds transmit hashing for IPv6 (and
> TCP or UDP over IPv6), bringing IPv6 up to par with IPv4 support in the
> bonding driver. In addition, bounds checking has been added to all
> transmit hashing functions.
>
> The algorithm chosen (xor'ing the bottom three quads of the source and
> destination addresses together, then xor'ing each byte of that result into
> the bottom byte, finally xor'ing with the last bytes of the MAC addresses)
> was selected after testing almost 400,000 unique IPv6 addresses harvested
> from server logs. This algorithm had the most even distribution for both
> big- and little-endian architectures while still using few instructions. Its
> behavior also attempts to closely match that of the IPv4 algorithm.
>
> The IPv6 flow label was intentionally not included in the hash as it appears
> to be unset in the vast majority of IPv6 traffic sampled, and the current
> algorithm not using the flow label already offers a very even distribution.
>
> Fragmented IPv6 packets are handled the same way as fragmented IPv4 packets,
> ie, they are not balanced based on layer 4 information. Additionally,
> IPv6 packets with intermediate headers are not balanced based on layer
> 4 information. In practice these intermediate headers are not common and
> this should not cause any problems, and the alternative (a packet-parsing
> loop and look-up table) seemed slow and complicated for little gain.
>
> Tested-by: John Eaglesham <linux@8192.net>
> Signed-off-by: John Eaglesham <linux@8192.net>
>
> ---
>
> Changes:
> v2)
>         * Clarify description
>         * Add bounds checking to more functions
>         * All functions call bond_xmit_hash_policy_l2 rather than re-
>           implement the same logic.
> v3)
>         * Patch against net-next.
>         * Style corrections.
> v4)
>         * Correct indenting.
> v5)
>         * Squash documentation and code patches into one.
> v6)
>         * Modify IPv6 hash to behave more like the IPv4 hash, update
>           documentation with modified algorithm.
>         * Clean up formatting.
>         * Move all variable declaration to the top of the function.
>         * Minor change to IPv6 layer 4 hash to match IPv4 hash behavior
>           (mix all hashed address bits together rather than just the
>           bottom 24 bits).
> v7)
>         * Improve bounds checking code (handle truncated IPv6 header,
>           removed goto, fewer if statements).
>         * Re-write pseudocode in documentation to match actual code more
>           closely.
>         * Correct indenting, align parentheses, wrap code at <= 80 columns
>           (based on Jay's changes).
> v8)
>         * Correct patch submission format.
>
>  Documentation/networking/bonding.txt | 30 ++++++++++--
>  drivers/net/bonding/bond_main.c      | 89 +++++++++++++++++++++++++-----------
>  2 files changed, 88 insertions(+), 31 deletions(-)
>
> diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
> index 6b1c711..10a015c 100644
> --- a/Documentation/networking/bonding.txt
> +++ b/Documentation/networking/bonding.txt
> @@ -752,12 +752,22 @@ xmit_hash_policy
>                 protocol information to generate the hash.
>
>                 Uses XOR of hardware MAC addresses and IP addresses to
> -               generate the hash.  The formula is
> +               generate the hash.  The IPv4 formula is
>
>                 (((source IP XOR dest IP) AND 0xffff) XOR
>                         ( source MAC XOR destination MAC ))
>                                 modulo slave count
>
> +               The IPv6 formula is
> +
> +               hash = (source ip quad 2 XOR dest IP quad 2) XOR
> +                      (source ip quad 3 XOR dest IP quad 3) XOR
> +                      (source ip quad 4 XOR dest IP quad 4)
> +
> +               (((hash >> 24) XOR (hash >> 16) XOR (hash >> 8) XOR hash)
> +                       XOR (source MAC XOR destination MAC))
> +                               modulo slave count
> +
>                 This algorithm will place all traffic to a particular
>                 network peer on the same slave.  For non-IP traffic,
>                 the formula is the same as for the layer2 transmit
> @@ -778,19 +788,29 @@ xmit_hash_policy
>                 slaves, although a single connection will not span
>                 multiple slaves.
>
> -               The formula for unfragmented TCP and UDP packets is
> +               The formula for unfragmented IPv4 TCP and UDP packets is
>
>                 ((source port XOR dest port) XOR
>                          ((source IP XOR dest IP) AND 0xffff)
>                                 modulo slave count
>
> -               For fragmented TCP or UDP packets and all other IP
> -               protocol traffic, the source and destination port
> +               The formula for unfragmented IPv6 TCP and UDP packets is
> +
> +               hash = (source port XOR dest port) XOR
> +                      ((source ip quad 2 XOR dest IP quad 2) XOR
> +                       (source ip quad 3 XOR dest IP quad 3) XOR
> +                       (source ip quad 4 XOR dest IP quad 4))
> +
> +               ((hash >> 24) XOR (hash >> 16) XOR (hash >> 8) XOR hash)
> +                       modulo slave count
> +
> +               For fragmented TCP or UDP packets and all other IPv4 and
> +               IPv6 protocol traffic, the source and destination port
>                 information is omitted.  For non-IP traffic, the
>                 formula is the same as for the layer2 transmit hash
>                 policy.
>
> -               This policy is intended to mimic the behavior of
> +               The IPv4 policy is intended to mimic the behavior of
>                 certain switches, notably Cisco switches with PFC2 as
>                 well as some Foundry and IBM products.
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index d95fbc3..4221e57 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -3354,56 +3354,93 @@ static struct notifier_block bond_netdev_notifier = {
>  /*---------------------------- Hashing Policies -----------------------------*/
>
>  /*
> + * Hash for the output device based upon layer 2 data
> + */
> +static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
> +{
> +       struct ethhdr *data = (struct ethhdr *)skb->data;
> +
> +       if (skb_headlen(skb) >= offsetof(struct ethhdr, h_proto))
> +               return (data->h_dest[5] ^ data->h_source[5]) % count;
> +
> +       return 0;
> +}
> +
> +/*
>   * Hash for the output device based upon layer 2 and layer 3 data. If
> - * the packet is not IP mimic bond_xmit_hash_policy_l2()
> + * the packet is not IP, fall back on bond_xmit_hash_policy_l2()
>   */
>  static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
>  {
>         struct ethhdr *data = (struct ethhdr *)skb->data;
> -       struct iphdr *iph = ip_hdr(skb);
> -
> -       if (skb->protocol == htons(ETH_P_IP)) {
> +       struct iphdr *iph;
> +       struct ipv6hdr *ipv6h;
> +       u32 v6hash;
> +       __be32 *s, *d;
> +
> +       if (skb->protocol == htons(ETH_P_IP) &&
> +           skb_network_header_len(skb) >= sizeof(*iph)) {
> +               iph = ip_hdr(skb);
>                 return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
>                         (data->h_dest[5] ^ data->h_source[5])) % count;
> +       } else if (skb->protocol == htons(ETH_P_IPV6) &&
> +                  skb_network_header_len(skb) >= sizeof(*ipv6h)) {
> +               ipv6h = ipv6_hdr(skb);
> +               s = &ipv6h->saddr.s6_addr32[0];
> +               d = &ipv6h->daddr.s6_addr32[0];
> +               v6hash = (s[1] ^ d[1]) ^ (s[2] ^ d[2]) ^ (s[3] ^ d[3]);
> +               v6hash ^= (v6hash >> 24) ^ (v6hash >> 16) ^ (v6hash >> 8);
> +               return (v6hash ^ data->h_dest[5] ^ data->h_source[5]) % count;
>         }
>
> -       return (data->h_dest[5] ^ data->h_source[5]) % count;
> +       return bond_xmit_hash_policy_l2(skb, count);
>  }
>
>  /*
>   * Hash for the output device based upon layer 3 and layer 4 data. If
>   * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
> - * altogether not IP, mimic bond_xmit_hash_policy_l2()
> + * altogether not IP, fall back on bond_xmit_hash_policy_l2()
>   */
>  static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
>  {
> -       struct ethhdr *data = (struct ethhdr *)skb->data;
> -       struct iphdr *iph = ip_hdr(skb);
> -       __be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
> -       int layer4_xor = 0;
> -
> -       if (skb->protocol == htons(ETH_P_IP)) {
> +       u32 layer4_xor = 0;
> +       struct iphdr *iph;
> +       struct ipv6hdr *ipv6h;
> +       __be32 *s, *d;
> +       __be16 *layer4hdr;
> +
> +       if (skb->protocol == htons(ETH_P_IP) &&
> +           skb_network_header_len(skb) >= sizeof(*iph)) {
> +               iph = ip_hdr(skb);
>                 if (!ip_is_fragment(iph) &&
>                     (iph->protocol == IPPROTO_TCP ||
> -                    iph->protocol == IPPROTO_UDP)) {
> -                       layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
> +                    iph->protocol == IPPROTO_UDP) &&
> +                   (skb_headlen(skb) - skb_network_offset(skb) >=
> +                    iph->ihl * sizeof(u32) + sizeof(*layer4hdr) * 2)) {
> +                       layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
> +                       layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
>                 }
>                 return (layer4_xor ^
>                         ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
> -
> +       } else if (skb->protocol == htons(ETH_P_IPV6) &&
> +                  skb_network_header_len(skb) >= sizeof(*ipv6h)) {
> +               ipv6h = ipv6_hdr(skb);
> +               if ((ipv6h->nexthdr == IPPROTO_TCP ||
> +                    ipv6h->nexthdr == IPPROTO_UDP) &&
> +                   (skb_headlen(skb) - skb_network_offset(skb) >=
> +                    sizeof(*ipv6h) + sizeof(*layer4hdr) * 2)) {
> +                       layer4hdr = (__be16 *)(ipv6h + 1);
> +                       layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
> +               }
> +               s = &ipv6h->saddr.s6_addr32[0];
> +               d = &ipv6h->daddr.s6_addr32[0];
> +               layer4_xor ^= (s[1] ^ d[1]) ^ (s[2] ^ d[2]) ^ (s[3] ^ d[3]);
> +               layer4_xor ^= (layer4_xor >> 24) ^ (layer4_xor >> 16) ^
> +                              (layer4_xor >> 8);
> +               return layer4_xor % count;
>         }
>
> -       return (data->h_dest[5] ^ data->h_source[5]) % count;
> -}
> -
> -/*
> - * Hash for the output device based upon layer 2 data
> - */
> -static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
> -{
> -       struct ethhdr *data = (struct ethhdr *)skb->data;
> -
> -       return (data->h_dest[5] ^ data->h_source[5]) % count;
> +       return bond_xmit_hash_policy_l2(skb, count);
>  }
>
>  /*-------------------------- Device entry points ----------------------------*/
> --
> 1.7.11
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: David Laight @ 2012-08-23 12:35 UTC (permalink / raw)
  To: Eric Dumazet, Alex Bergmann; +Cc: H.K. Jerry Chu, davem, netdev, linux-kernel
In-Reply-To: <1345724123.5904.756.camel@edumazet-glaptop>

> I would suggest to increase TCP_SYN_RETRIES from 5 to 6.
> 
> 180 secs is eternity, but 31 secs is too small.

Wasn't the intention of the long delay to allow a system
acting as a router to reboot?
I suspect that is why it (and some other TCP timers)
are in minutes.

	David


^ permalink raw reply

* Re: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Alex Bergmann @ 2012-08-23 12:37 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: H.K. Jerry Chu, davem, netdev, linux-kernel
In-Reply-To: <1345724123.5904.756.camel@edumazet-glaptop>

On 08/23/2012 02:15 PM, Eric Dumazet wrote:
> On Thu, 2012-08-23 at 13:58 +0200, Alex Bergmann wrote:
>> On 08/22/2012 06:41 PM, H.K. Jerry Chu wrote:
> 
>>> This issue occurred to me right after I submitted the patch for RFC6298.
>>> I did not commit any more change because RFC compliance aside, 180secs
>>> just seem like eternity in the Internet age.
>>>
>>> (See my past post on this at
>>> http://marc.info/?l=linux-netdev&m=130759078118866&w=2)
>>
>> Okay, I missed that post during my search about the current situation.
> 
> I would suggest to increase TCP_SYN_RETRIES from 5 to 6.
> 
> 180 secs is eternity, but 31 secs is too small.
> 
> Can you repost a v2, only changing TCP_SYN_RETRIES ?

I hope the description is good enough.

Alex


>From be551f82499112e4775b6d579d58967510b6d492 Mon Sep 17 00:00:00 2001
From: Alexander Bergmann <alex@linlab.net>
Date: Thu, 23 Aug 2012 14:33:35 +0200
Subject: [PATCH 1/1] tcp: Increase timeout for SYN segments

Commit 9ad7c049 changed the initRTO from 3secs to 1sec in accordance to
RFC6298 (former RFC2988bis). This reduced the time till the last SYN
retransmission packet gets sent from 93secs to 31secs.

RFC1122 is stating that the retransmission should be done for at least 3
minutes, but this seems to be quite high.[1]

This patch increases the value of TCP_SYN_RETRIES to the value of 6,
providing a retransmission window of 63secs.

[1] RFC 1122 - 4.2.3.5 TCP Connection Failures

Signed-off-by: Alexander Bergmann <alex@linlab.net>
---
 include/net/tcp.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 1f000ff..f309e93 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -98,7 +98,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
                                 * 15 is ~13-30min depending on RTO.
                                 */
 
-#define TCP_SYN_RETRIES         5      /* number of times to retry active opening a
+#define TCP_SYN_RETRIES         6      /* number of times to retry active opening a
                                 * connection: ~180sec is RFC minimum   */
 
 #define TCP_SYNACK_RETRIES 5   /* number of times to retry passive opening a
-- 
1.7.8.6

^ permalink raw reply related

* [PATCH net-next V3 1/2] IB/ipoib: Add rtnl_link_ops support
From: Or Gerlitz @ 2012-08-23 12:15 UTC (permalink / raw)
  To: davem; +Cc: roland, netdev, Or Gerlitz, Erez Shitrit
In-Reply-To: <1345724119-32110-1-git-send-email-ogerlitz@mellanox.com>

Add rtnl_link_ops to IPoIB, with the first usage being child device
create/delete through them. Childs devices are now either legacy ones,
created/deleted through the ipoib sysfs entries, or RTNL ones.

Adding support for RTNL childs involved refactoring of ipoib_vlan_add
which is now used by both the sysfs and the link_ops code.

Also, added ndo_uninit entry to support calling unregister_netdevice_queue
from the rtnl dellink entry. This required removal of calls to
ipoib_dev_cleanup from the driver in flows which use unregister_netdevice,
since the networking core will invoke ipoib_uninit which does exactly that.

Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 Documentation/infiniband/ipoib.txt           |    3 +
 drivers/infiniband/ulp/ipoib/Makefile        |    3 +-
 drivers/infiniband/ulp/ipoib/ipoib.h         |   13 +++
 drivers/infiniband/ulp/ipoib/ipoib_main.c    |   25 ++++-
 drivers/infiniband/ulp/ipoib/ipoib_netlink.c |  122 ++++++++++++++++++++++++++
 drivers/infiniband/ulp/ipoib/ipoib_vlan.c    |  102 ++++++++++++----------
 6 files changed, 217 insertions(+), 51 deletions(-)
 create mode 100644 drivers/infiniband/ulp/ipoib/ipoib_netlink.c

diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 64eeb55..f2cfe26 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -24,6 +24,9 @@ Partitions and P_Keys
   The P_Key for any interface is given by the "pkey" file, and the
   main interface for a subinterface is in "parent."
 
+  Child interface create/delete can also be done using IPoIB's
+  rtnl_link_ops, where childs created using either way behave the same.
+
 Datagram vs Connected modes
 
   The IPoIB driver supports two modes of operation: datagram and
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
index 3090100..e5430dd 100644
--- a/drivers/infiniband/ulp/ipoib/Makefile
+++ b/drivers/infiniband/ulp/ipoib/Makefile
@@ -5,7 +5,8 @@ ib_ipoib-y					:= ipoib_main.o \
 						   ipoib_multicast.o \
 						   ipoib_verbs.o \
 						   ipoib_vlan.o \
-						   ipoib_ethtool.o
+						   ipoib_ethtool.o \
+						   ipoib_netlink.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM)		+= ipoib_cm.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG)	+= ipoib_fs.o
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index ca43901..381f51b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -104,6 +104,10 @@ enum {
 
 	MAX_SEND_CQE		  = 16,
 	IPOIB_CM_COPYBREAK	  = 256,
+
+	IPOIB_NON_CHILD		  = 0,
+	IPOIB_LEGACY_CHILD	  = 1,
+	IPOIB_RTNL_CHILD	  = 2,
 };
 
 #define	IPOIB_OP_RECV   (1ul << 31)
@@ -350,6 +354,7 @@ struct ipoib_dev_priv {
 	struct net_device *parent;
 	struct list_head child_intfs;
 	struct list_head list;
+	int    child_type;
 
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
 	struct ipoib_cm_dev_priv cm;
@@ -509,6 +514,14 @@ void ipoib_event(struct ib_event_handler *handler,
 int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey);
 int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
 
+int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
+		     u16 pkey, int child_type);
+
+int  __init ipoib_netlink_init(void);
+void __exit ipoib_netlink_fini(void);
+
+void ipoib_setup(struct net_device *dev);
+
 void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
 void ipoib_drain_cq(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 3e2085a..b3e9709 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -173,6 +173,11 @@ static int ipoib_stop(struct net_device *dev)
 	return 0;
 }
 
+static void ipoib_uninit(struct net_device *dev)
+{
+	ipoib_dev_cleanup(dev);
+}
+
 static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -1262,6 +1267,9 @@ out:
 void ipoib_dev_cleanup(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv;
+	LIST_HEAD(head);
+
+	ASSERT_RTNL();
 
 	ipoib_delete_debug_files(dev);
 
@@ -1270,10 +1278,9 @@ void ipoib_dev_cleanup(struct net_device *dev)
 		/* Stop GC on child */
 		set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags);
 		cancel_delayed_work(&cpriv->neigh_reap_task);
-		unregister_netdev(cpriv->dev);
-		ipoib_dev_cleanup(cpriv->dev);
-		free_netdev(cpriv->dev);
+		unregister_netdevice_queue(cpriv->dev, &head);
 	}
+	unregister_netdevice_many(&head);
 
 	ipoib_ib_dev_cleanup(dev);
 
@@ -1291,6 +1298,7 @@ static const struct header_ops ipoib_header_ops = {
 };
 
 static const struct net_device_ops ipoib_netdev_ops = {
+	.ndo_uninit		 = ipoib_uninit,
 	.ndo_open		 = ipoib_open,
 	.ndo_stop		 = ipoib_stop,
 	.ndo_change_mtu		 = ipoib_change_mtu,
@@ -1300,7 +1308,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
 	.ndo_set_rx_mode	 = ipoib_set_mcast_list,
 };
 
-static void ipoib_setup(struct net_device *dev)
+void ipoib_setup(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -1662,7 +1670,6 @@ static void ipoib_remove_one(struct ib_device *device)
 		flush_workqueue(ipoib_workqueue);
 
 		unregister_netdev(priv->dev);
-		ipoib_dev_cleanup(priv->dev);
 		free_netdev(priv->dev);
 	}
 
@@ -1714,8 +1721,15 @@ static int __init ipoib_init_module(void)
 	if (ret)
 		goto err_sa;
 
+	ret = ipoib_netlink_init();
+	if (ret)
+		goto err_client;
+
 	return 0;
 
+err_client:
+	ib_unregister_client(&ipoib_client);
+
 err_sa:
 	ib_sa_unregister_client(&ipoib_sa_client);
 	destroy_workqueue(ipoib_workqueue);
@@ -1728,6 +1742,7 @@ err_fs:
 
 static void __exit ipoib_cleanup_module(void)
 {
+	ipoib_netlink_fini();
 	ib_unregister_client(&ipoib_client);
 	ib_sa_unregister_client(&ipoib_sa_client);
 	ipoib_unregister_debugfs();
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
new file mode 100644
index 0000000..18d6ac9
--- /dev/null
+++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. -  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <net/rtnetlink.h>
+#include "ipoib.h"
+
+enum {
+	IFLA_IPOIB_UNSPEC,
+	IFLA_IPOIB_CHILD_PKEY,
+	__IFLA_IPOIB_MAX
+};
+
+#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
+
+static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = {
+	[IFLA_IPOIB_CHILD_PKEY]		= { .type = NLA_U16 },
+};
+
+static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
+			       struct nlattr *tb[], struct nlattr *data[])
+{
+	struct net_device *pdev;
+	struct ipoib_dev_priv *ppriv;
+	u16 child_pkey;
+	int err;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+	if (!pdev)
+		return -ENODEV;
+
+	ppriv = netdev_priv(pdev);
+
+	if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
+		ipoib_warn(ppriv, "child creation disallowed for child devices\n");
+		return -EINVAL;
+	}
+
+	if (!data || !data[IFLA_IPOIB_CHILD_PKEY]) {
+		ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
+		child_pkey  = ppriv->pkey;
+	} else
+		child_pkey  = nla_get_u16(data[IFLA_IPOIB_CHILD_PKEY]);
+
+	err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);
+
+	return err;
+}
+
+static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head *head)
+{
+	struct ipoib_dev_priv *priv, *ppriv;
+
+	priv = netdev_priv(dev);
+	ppriv = netdev_priv(priv->parent);
+
+	mutex_lock(&ppriv->vlan_mutex);
+	unregister_netdevice_queue(dev, head);
+	list_del(&priv->list);
+	mutex_unlock(&ppriv->vlan_mutex);
+}
+
+static size_t ipoib_get_size(const struct net_device *dev)
+{
+	return nla_total_size(2);	/* IFLA_IPOIB_CHILD_PKEY */
+}
+
+static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
+	.kind		= "ipoib",
+	.maxtype	= IFLA_IPOIB_MAX,
+	.policy		= ipoib_policy,
+	.priv_size	= sizeof(struct ipoib_dev_priv),
+	.setup		= ipoib_setup,
+	.newlink	= ipoib_new_child_link,
+	.dellink	= ipoib_unregister_child_dev,
+	.get_size	= ipoib_get_size,
+};
+
+int __init ipoib_netlink_init(void)
+{
+	return rtnl_link_register(&ipoib_link_ops);
+}
+
+void __exit ipoib_netlink_fini(void)
+{
+	rtnl_link_unregister(&ipoib_link_ops);
+}
+
+MODULE_ALIAS_RTNL_LINK("ipoib");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d7e9740..238bbf9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -49,47 +49,11 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr,
 }
 static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
 
-int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
+		     u16 pkey, int type)
 {
-	struct ipoib_dev_priv *ppriv, *priv;
-	char intf_name[IFNAMSIZ];
 	int result;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	ppriv = netdev_priv(pdev);
-
-	if (!rtnl_trylock())
-		return restart_syscall();
-	mutex_lock(&ppriv->vlan_mutex);
-
-	/*
-	 * First ensure this isn't a duplicate. We check the parent device and
-	 * then all of the child interfaces to make sure the Pkey doesn't match.
-	 */
-	if (ppriv->pkey == pkey) {
-		result = -ENOTUNIQ;
-		priv = NULL;
-		goto err;
-	}
-
-	list_for_each_entry(priv, &ppriv->child_intfs, list) {
-		if (priv->pkey == pkey) {
-			result = -ENOTUNIQ;
-			priv = NULL;
-			goto err;
-		}
-	}
-
-	snprintf(intf_name, sizeof intf_name, "%s.%04x",
-		 ppriv->dev->name, pkey);
-	priv = ipoib_intf_alloc(intf_name);
-	if (!priv) {
-		result = -ENOMEM;
-		goto err;
-	}
-
 	priv->max_ib_mtu = ppriv->max_ib_mtu;
 	/* MTU will be reset when mcast join happens */
 	priv->dev->mtu   = IPOIB_UD_MTU(priv->max_ib_mtu);
@@ -134,14 +98,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 	if (device_create_file(&priv->dev->dev, &dev_attr_parent))
 		goto sysfs_failed;
 
+	priv->child_type = type;
 	list_add_tail(&priv->list, &ppriv->child_intfs);
 
-	mutex_unlock(&ppriv->vlan_mutex);
-	rtnl_unlock();
-
 	return 0;
 
 sysfs_failed:
+	result = -ENOMEM;
 	ipoib_delete_debug_files(priv->dev);
 	unregister_netdevice(priv->dev);
 
@@ -149,11 +112,60 @@ register_failed:
 	ipoib_dev_cleanup(priv->dev);
 
 err:
+	return result;
+}
+
+int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+{
+	struct ipoib_dev_priv *ppriv, *priv;
+	char intf_name[IFNAMSIZ];
+	struct ipoib_dev_priv *tpriv;
+	int result;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	ppriv = netdev_priv(pdev);
+
+	snprintf(intf_name, sizeof intf_name, "%s.%04x",
+		 ppriv->dev->name, pkey);
+	priv = ipoib_intf_alloc(intf_name);
+	if (!priv)
+		return -ENOMEM;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	mutex_lock(&ppriv->vlan_mutex);
+
+	/*
+	 * First ensure this isn't a duplicate. We check the parent device and
+	 * then all of the legacy child interfaces to make sure the Pkey
+	 * doesn't match.
+	 */
+	if (ppriv->pkey == pkey) {
+		result = -ENOTUNIQ;
+		goto out;
+	}
+
+	list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
+		if (tpriv->pkey == pkey &&
+		    tpriv->child_type == IPOIB_LEGACY_CHILD) {
+			result = -ENOTUNIQ;
+			goto out;
+		}
+	}
+
+	result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
+
+out:
 	mutex_unlock(&ppriv->vlan_mutex);
-	rtnl_unlock();
-	if (priv)
+
+	if (result)
 		free_netdev(priv->dev);
 
+	rtnl_unlock();
+
 	return result;
 }
 
@@ -171,9 +183,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 		return restart_syscall();
 	mutex_lock(&ppriv->vlan_mutex);
 	list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
-		if (priv->pkey == pkey) {
+		if (priv->pkey == pkey &&
+		    priv->child_type == IPOIB_LEGACY_CHILD) {
 			unregister_netdevice(priv->dev);
-			ipoib_dev_cleanup(priv->dev);
 			list_del(&priv->list);
 			dev = priv->dev;
 			break;
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Eric Dumazet @ 2012-08-23 12:49 UTC (permalink / raw)
  To: Alex Bergmann; +Cc: H.K. Jerry Chu, davem, netdev, linux-kernel
In-Reply-To: <50362407.9070805@linlab.net>

On Thu, 2012-08-23 at 14:37 +0200, Alex Bergmann wrote:

> 
> From be551f82499112e4775b6d579d58967510b6d492 Mon Sep 17 00:00:00 2001
> From: Alexander Bergmann <alex@linlab.net>
> Date: Thu, 23 Aug 2012 14:33:35 +0200
> Subject: [PATCH 1/1] tcp: Increase timeout for SYN segments
> 
> Commit 9ad7c049 changed the initRTO from 3secs to 1sec in accordance to
> RFC6298 (former RFC2988bis). This reduced the time till the last SYN
> retransmission packet gets sent from 93secs to 31secs.
> 
> RFC1122 is stating that the retransmission should be done for at least 3
> minutes, but this seems to be quite high.[1]
> 
> This patch increases the value of TCP_SYN_RETRIES to the value of 6,
> providing a retransmission window of 63secs.
> 
> [1] RFC 1122 - 4.2.3.5 TCP Connection Failures
> 
> Signed-off-by: Alexander Bergmann <alex@linlab.net>
> ---
>  include/net/tcp.h |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 1f000ff..f309e93 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -98,7 +98,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
>                                  * 15 is ~13-30min depending on RTO.
>                                  */
>  
> -#define TCP_SYN_RETRIES         5      /* number of times to retry active opening a
> +#define TCP_SYN_RETRIES         6      /* number of times to retry active opening a
>                                  * connection: ~180sec is RFC minimum   */
>  
>  #define TCP_SYNACK_RETRIES 5   /* number of times to retry passive opening a

Acked-by: Eric Dumazet <edumazet@google.com>

A change of the comment might be good, to help future readers.

^ permalink raw reply

* Re: [PATCH 2/3] ipvs: Fix faulty IPv6 extension header handling in IPVS
From: Jesper Dangaard Brouer @ 2012-08-23 12:50 UTC (permalink / raw)
  To: Julian Anastasov
  Cc: netdev, Patrick McHardy, Hans Schillstrom, lvs-devel,
	Simon Horman, Wensong Zhang, netfilter-devel
In-Reply-To: <alpine.LFD.2.00.1208211558410.2149@ja.ssi.bg>


On Tue, 2012-08-21 at 17:14 +0300, Julian Anastasov wrote:
> On Mon, 20 Aug 2012, Jesper Dangaard Brouer wrote:
> 
> > Based on patch from: Hans Schillstrom
> > 
> > IPv6 headers must be processed in order of appearance,
> > neither can it be assumed that Upper layer headers is first.
> > If anything else than L4 is the first header IPVS will throw it.
> > 
> > IPVS will write SNAT & DNAT modifications at a fixed pos which
> > will corrupt the message. Proper header position must be found
> > before writing modifying packet.
> > 
> > This patch contains a lot of API changes.  This is done, to avoid
> > the costly scan of finding the IPv6 headers, via ipv6_find_hdr().
> > Finding the IPv6 headers is done as early as possible, and passed
> > on as a pointer "struct ip_vs_iphdr *" to the affected functions.
> > 
> > Notice, I have choosen, not to change the API of function
> > pointer "(*schedule)" (in struct ip_vs_scheduler) as it can be
> > used by external schedulers, via {un,}register_ip_vs_scheduler.
> > Only 4 out of 10 schedulers use info from ip_vs_iphdr*, and when
> > they do, they are only interested in iph->{s,d}addr.
> > 
> > This patch depends on commit 84018f55a:
> >  "netfilter: ip6_tables: add flags parameter to ipv6_find_hdr()"
> > 
> > This also adds a dependency to ip6_tables.
> > 
> > Hans left some questions in ip_vs_pe_sip.c, which I'm uncertain about.
> > 
> > Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> > Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
> 
> 	Patch 1 looks ok, following are some small comments
> for patch 2 and 3.
> 
> > +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> > +#include <linux/netfilter_ipv6/ip6_tables.h>
> > +#endif
> 
> 	There is already #if IS_ENABLED(CONFIG_IPV6) that
> can replace #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

Okay.

> 	It seems we need IS_ENABLED for many places:
> CONFIG_NF_CONNTRACK, CONFIG_NF_DEFRAG_IPV6

Wondering if we should keep these cleanup changes to a separate patch.


> > @@ -958,34 +943,26 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
> >  	}
> >  
> >  	/* Now find the contained IP header */
> > -	offset += sizeof(_icmph);
> > -	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
> > -	if (cih == NULL)
> > -		return NF_ACCEPT; /* The packet looks wrong, ignore */
> > +	ipvsh->len += sizeof(_icmph);
> > +	ip6 = skb_header_pointer(skb, ipvsh->len, sizeof(_ip6), &_ip6);
> 
> 	ip6 is not checked here for NULL or we rely on
> ipv6_find_hdr checks?

Good catch, I'll re-add the NULL pointer check.



> > @@ -1506,39 +1464,43 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
> >  	}
> >  
> >  	/* Now find the contained IP header */
> > -	offset += sizeof(_icmph);
> > -	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
> > -	if (cih == NULL)
> > -		return NF_ACCEPT; /* The packet looks wrong, ignore */
> > +	ciph.len = iph->len + sizeof(_icmph);
> > +	ciph.flags = 0;
> > +	ciph.fragoffs = 0;
> > +	ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs,
> > +				      &ciph.flags);

(notice that &ciph.len can get updated by ipv6_find_hdr())

> > +	ciph.saddr = iph->saddr;	/* con_in_get() handles reverse order */
> > +	ciph.daddr = iph->daddr;
> 
> 	The ciph initialization looks dangerous if one day
> we add new field into the header.
> 
> 	Can we use ciph = (struct ip_vs_iphdr) { .XXX = val, ... },
> in such case we have to call ipv6_find_hdr out of (after)
> this initialization? Of course, we will write twice to
> small fields such as protocol, len, fragoffs, flags

I'm not sure I follow/understand.


> 	Also ipv6_find_hdr looks a bit noisy for missing header,
> can it be a problem for the inner IPv6 header in ICMP messages?

I can see, that I don't handle the error cases of missing headers, from
a call to ipv6_find_hdr() ... I guess I need to check if the return
value "protocol" is negative.  But I'm not sure if it matters in this
case (Hans?)


> 	In patch 3 ip_vs_in_icmp_v6 initializes ciph in the
> same way. It will be difficult to audit the code later
> considering the large number of places where iph is used.

I'm not sure what you want me to do?


> >  	net = skb_net(skb);
> > -	pd = ip_vs_proto_data_get(net, cih->nexthdr);
> > +	pd = ip_vs_proto_data_get(net, ciph.protocol);
> >  	if (!pd)
> >  		return NF_ACCEPT;
> >  	pp = pd->pp;
> >  
> > -	/* Is the embedded protocol header present? */
> > -	/* TODO: we don't support fragmentation at the moment anyways */
> > -	if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
> > +	/* Is the embedded protocol header present?
> > +	 * If it's the second or later fragment we don't know what it is
> > +	 * i.e. just let it through.
> > +	 */
> > +	if (ciph.fragoffs)
> >  		return NF_ACCEPT;
> >  
> > +	offset = ciph.len;
> >  	IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
> >  		      "Checking incoming ICMPv6 for");
> >  
> > -	offset += sizeof(struct ipv6hdr);
> > -
> > -	ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
> >  	/* The embedded headers contain source and dest in reverse order */
> > -	cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
> > +	cp = pp->conn_in_get(AF_INET6, skb, &ciph, 1);
> >  	if (!cp)
> >  		return NF_ACCEPT;
> >  
> >  	/* do the statistics and put it back */
> >  	ip_vs_in_stats(cp, skb);
> > -	if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr ||
> > -	    IPPROTO_SCTP == cih->nexthdr)
> > -		offset += 2 * sizeof(__u16);
> > -	verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum);
> > +	if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol ||
> > +	    IPPROTO_SCTP == ciph.protocol)
> > +		offset = ciph.len + (2 * sizeof(__u16));
> 
> 	Still in the same func, above code is correct but
> patch 3 changes it back to wrong state (offs_ciph = ciph.len).

Don't think its a "bug" in patch3, it might be a "bug" in this patch.
Because &ciph.len gets updated earlier by ipv6_find_hdr()... but I'm
starting to get confused.
Perhaps we should move these changes to ip_vs_in_icmp_v6() into the same
patch?

> > +
> > +	verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum, &ciph);
> >  
> >  	__ip_vs_conn_put(cp);
> 
> > diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
> > index 1aa5cac..bb28b4f 100644
> > --- a/net/netfilter/ipvs/ip_vs_pe_sip.c
> > +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
> > @@ -68,26 +68,37 @@ static int get_callid(const char *dptr, unsigned int dataoff,
> >  static int
> >  ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
> >  {
> > +	struct sk_buff *reasm = skb_nfct_reasm(skb);
> >  	struct ip_vs_iphdr iph;
> >  	unsigned int dataoff, datalen, matchoff, matchlen;
> >  	const char *dptr;
> >  	int retc;
> >  
> > -	ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
> > +	ip_vs_fill_iph_skb(p->af, skb, &iph);
> 
> 	May be skb_linearize is bad for IPv6? IIRC,
> ip_vs_pe_sip.c needs access just to read the Call-ID.
> For IPv4 it was simple to use skb_linearize, may be
> the logic should be improved to read the values even
> from non-linear data. May be there is already some
> example code for this. For IPv6 I'm not sure what
> kind are the problems here, may be it depends if
> we try to call skb_linearize for reasm packet?

I'm not able to answer these questions, my self...
 

> > -
> > -	if ((retc=skb_linearize(skb)) < 0)
> > +	/*
> > +	 * todo: Check if this will mess-up the reasm skb !!! /HS
> > +	 */
> > +	retc = skb_linearize(reasm);
> > +	if (retc < 0)
> >  		return retc;
> > -	dptr = skb->data + dataoff;
> > -	datalen = skb->len - dataoff;
> > +	dptr = reasm->data + dataoff;
> > +	datalen = reasm->len - dataoff;
> >  
> >  	if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
> >  		return -EINVAL;
> 
> 	There are recents changes for IPv6 from Patrick McHardy:
> 
> http://marc.info/?l=netfilter-devel&m=134543406303402&w=2
> http://marc.info/?l=netfilter-devel&m=134543407803412&w=2
> 
> 	In this context, may be soon we will modify ip_vs_ftp to
> support IPv6. It is possible to work with present FTP helper
> in netfilter. Does it mean that we will see only reassembled
> packets when conntrack is running? No original fragments.

Yes, it seems that we will *only* see the reassembled packet (no
original fragments) after Patricks patches.  BUT *only* when loading the
module nf_conntrack_ipv6.


> Are we prepared to work in both ways (originals+reasm and
> just reasm) ?

As mentioned in another thread, no. But only because the reassembled
packet will be dropped due to the MTU check. After this is fixed, the
ipvs code seems to work. (Notice, this is both without and with my/these
patches)


> - For patch 3 in Kconfig do we need 'select NF_DEFRAG_IPV6' ?

Yes, but it is still possible not to load the module nf_defrag_ipv6.

When not loading, nf_defrag_ipv6, these patches have no effect, and no
fragments are passed through.


> 	Basicly, I'm concerned what will happen when we
> start to mangle the protocol payloads (FTP). For now
> we are safe by touching only addresses and ports. May be
> we have to synchronize these changes with the work from
> Patrick.

Yes, I think we should take Patrick's work into account.

My biggest concern is, that depending on which modules (nf_defrag_ipv6
only, or also nf_conntrack_ipv6) are loaded, different code paths are
used (to support IPv6 fragments for IPVS).
This will be hard to understand, from a user perspective.  And also
difficult for us, when users report bugs...

Is loading nf_conntrack_ipv6 considered a big performance problem/issue
for IPVS?
(Can we tell people, to enable conntrack for frag support?)


-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Sr. Network Kernel Developer at Red Hat
  Author of http://www.iptv-analyzer.org
  LinkedIn: http://www.linkedin.com/in/brouer



^ permalink raw reply

* RE: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Eric Dumazet @ 2012-08-23 12:51 UTC (permalink / raw)
  To: David Laight; +Cc: Alex Bergmann, H.K. Jerry Chu, davem, netdev, linux-kernel
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B6FC3@saturn3.aculab.com>

On Thu, 2012-08-23 at 13:35 +0100, David Laight wrote:
> > I would suggest to increase TCP_SYN_RETRIES from 5 to 6.
> > 
> > 180 secs is eternity, but 31 secs is too small.
> 
> Wasn't the intention of the long delay to allow a system
> acting as a router to reboot?
> I suspect that is why it (and some other TCP timers)
> are in minutes.

One could argue that if an application really wants to connect to a
peer, it should probably handle failures and retries.

But for unaware (basic ?) applications, the 3 -> 1 change reduced by a 3
factor the timeout. So a transient network failure has now more
chance to impact them.

Not all applications run inside a browser or under human control...

^ permalink raw reply

* [PATCH net-next] packet: fix broken build.
From: Rami Rosen @ 2012-08-23 12:55 UTC (permalink / raw)
  To: davem@davemloft.net, netdev@vger.kernel.org
  Cc: xemul@parallels.com, edumazet@google.com

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

This patch fixes a broken build due to a missing header: 
...
  CC      net/ipv4/proc.o
In file included from include/net/net_namespace.h:15,
                 from net/ipv4/proc.c:35:
include/net/netns/packet.h:11: error: field 'sklist_lock' has incomplete type
...

The lock of netns_packet has been replaced by a recent patch to be a mutex instead of a spinlock, 
but we need to replace the header file to be linux/mutex.h instead of linux/spinlock.h as well.

See commit 0fa7fa98dbcc2789409ed24e885485e645803d7f:
packet: Protect packet sk list with mutex (v2) patch, 

Signed-off-by: Rami Rosen <rosenr@marvell.com>

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 348 bytes --]

diff --git a/include/net/netns/packet.h b/include/net/netns/packet.h
index 4780b08..17ec2b9 100644
--- a/include/net/netns/packet.h
+++ b/include/net/netns/packet.h
@@ -5,7 +5,7 @@
 #define __NETNS_PACKET_H__
 
 #include <linux/rculist.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 
 struct netns_packet {
 	struct mutex		sklist_lock;

^ permalink raw reply related

* pull request: batman-adv 2012-08-23
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r

Hello David,

this is our set of changes intended for net-next/linux-3.7.
It is mostly composed by style fixes and cleanups. Other than that you have a
patch introducing a new table in debugfs (backbone gateways table for the Bridge
Loop Avoidance) and a new mechanism for the TranslationTable component. The
latter allows mesh nodes to immediately detect new clients joining the network,
without waiting for any periodic advertisement.

Thank you,
	Antonio




The following changes since commit 0fa7fa98dbcc2789409ed24e885485e645803d7f:

  packet: Protect packet sk list with mutex (v2) (2012-08-22 22:58:27 -0700)

are available in the git repository at:

  git://git.open-mesh.org/linux-merge.git tags/batman-adv-for-davem

for you to fetch changes up to fa4f0afcf40361bf67ed3abd520a5fbe12d11166:

  batman-adv: Start new development cycle (2012-08-23 14:20:23 +0200)

----------------------------------------------------------------
Included changes:
- a set of codestyle rearrangements/fixes
- new feature to early detect new joining (mesh-unaware) clients
- a minor fix for the gw-feature
- substitution of shift operations with the BIT() macro
- reorganization of the main batman-adv structure (struct batadv_priv)
- some more (very) minor cleanups and fixes

----------------------------------------------------------------
Antonio Quartulli (5):
      batman-adv: move function arguments on one line
      batman-adv: add reference counting for type batadv_tt_orig_list_entry
      batman-adv: fix typos in comments
      batman-adv: detect not yet announced clients
      batman-adv: change interface_rx to get orig node

Jonathan Corbet (1):
      batman-adv: remove a misleading comment

Marek Lindner (1):
      batman-adv: convert remaining packet counters to per_cpu_ptr() infrastructure

Martin Hundebøll (2):
      batman-adv: Move batadv_check_unicast_packet()
      batman-adv: Drop tt queries with foreign dest

Simon Wunderlich (4):
      batman-adv: Add the backbone gateway list to debugfs
      batman-adv: correct comments in bridge loop avoidance
      batman-adv: rename bridge loop avoidance claim types
      batman-adv: check batadv_orig_hash_add_if() return code

Sven Eckelmann (5):
      batman-adv: Split batadv_priv in sub-structures for features
      batman-adv: Use BIT(x) macro to calculate bit positions
      batman-adv: Don't break statements after assignment operator
      batman-adv: Reduce accumulated length of simple statements
      batman-adv: Start new development cycle

 Documentation/networking/batman-adv.txt |    7 +-
 net/batman-adv/bat_iv_ogm.c             |   96 ++++---
 net/batman-adv/bridge_loop_avoidance.c  |  214 ++++++++++------
 net/batman-adv/bridge_loop_avoidance.h  |   11 +-
 net/batman-adv/debugfs.c                |   12 +
 net/batman-adv/gateway_client.c         |   53 ++--
 net/batman-adv/hard-interface.c         |   13 +-
 net/batman-adv/main.c                   |   27 +-
 net/batman-adv/main.h                   |   29 +--
 net/batman-adv/packet.h                 |   35 +--
 net/batman-adv/routing.c                |   85 +++----
 net/batman-adv/send.c                   |    8 +-
 net/batman-adv/soft-interface.c         |   79 +++---
 net/batman-adv/soft-interface.h         |    5 +-
 net/batman-adv/translation-table.c      |  416 +++++++++++++++++++------------
 net/batman-adv/translation-table.h      |    4 +-
 net/batman-adv/types.h                  |  120 +++++----
 net/batman-adv/unicast.c                |   16 +-
 net/batman-adv/vis.c                    |  144 +++++------
 net/batman-adv/vis.h                    |    2 +-
 20 files changed, 818 insertions(+), 558 deletions(-)

^ permalink raw reply

* [PATCH 03/18] batman-adv: correct comments in bridge loop avoidance
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Simon Wunderlich
In-Reply-To: <1345727427-20805-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

From: Simon Wunderlich <simon.wunderlich-Y4E02TeZ33kaBlGTGt4zH4SGEyLTKazZ@public.gmane.org>

Signed-off-by: Simon Wunderlich <siwu-MaAgPAbsBIVS8oHt8HbXEIQuADTiUCJX@public.gmane.org>
Signed-off-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
---
 net/batman-adv/bridge_loop_avoidance.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 7e60466..5f1ad80 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -281,7 +281,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 			 NULL,
 			 /* Ethernet SRC/HW SRC:  originator mac */
 			 primary_if->net_dev->dev_addr,
-			 /* HW DST: FF:43:05:XX:00:00
+			 /* HW DST: FF:43:05:XX:YY:YY
 			  * with XX   = claim type
 			  * and YY:YY = group id
 			  */
@@ -323,7 +323,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 		break;
 	case BATADV_CLAIM_TYPE_REQUEST:
 		/* request frame
-		 * set HW SRC to the special mac containg the crc
+		 * set HW SRC and header destination to the receiving backbone
+		 * gws mac
 		 */
 		memcpy(hw_src, mac, ETH_ALEN);
 		memcpy(ethhdr->h_dest, mac, ETH_ALEN);
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 01/18] batman-adv: move function arguments on one line
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/bridge_loop_avoidance.h |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 563cfbf..3f0dfa2 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -41,8 +41,7 @@ void batadv_bla_free(struct batadv_priv *bat_priv);
 #else /* ifdef CONFIG_BATMAN_ADV_BLA */
 
 static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
-				struct sk_buff *skb, short vid,
-				bool is_bcast)
+				struct sk_buff *skb, short vid, bool is_bcast)
 {
 	return 0;
 }
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 02/18] batman-adv: Add the backbone gateway list to debugfs
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
	Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>

This is especially useful if there are no claims yet, but we still want
to know which gateways are using bridge loop avoidance in the network.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 Documentation/networking/batman-adv.txt |    7 ++--
 net/batman-adv/bridge_loop_avoidance.c  |   65 +++++++++++++++++++++++++++++++
 net/batman-adv/bridge_loop_avoidance.h  |    8 ++++
 net/batman-adv/debugfs.c                |   12 ++++++
 4 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 8f3ae4a..a173d2a 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -75,9 +75,10 @@ folder:
 
 There is a special folder for debugging information:
 
-#  ls /sys/kernel/debug/batman_adv/bat0/
-# bla_claim_table    log                socket             transtable_local
-# gateways           originators        transtable_global  vis_data
+# ls /sys/kernel/debug/batman_adv/bat0/
+# bla_backbone_table  log                 transtable_global
+# bla_claim_table     originators         transtable_local
+# gateways            socket              vis_data
 
 Some of the files contain all sort of status information  regard-
 ing  the  mesh  network.  For  example, you can view the table of
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 6705d35..7e60466 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1616,3 +1616,68 @@ out:
 		batadv_hardif_free_ref(primary_if);
 	return ret;
 }
+
+int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
+{
+	struct net_device *net_dev = (struct net_device *)seq->private;
+	struct batadv_priv *bat_priv = netdev_priv(net_dev);
+	struct batadv_hashtable *hash = bat_priv->backbone_hash;
+	struct batadv_backbone_gw *backbone_gw;
+	struct batadv_hard_iface *primary_if;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	int secs, msecs;
+	uint32_t i;
+	bool is_own;
+	int ret = 0;
+	uint8_t *primary_addr;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if) {
+		ret = seq_printf(seq,
+				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
+				 net_dev->name);
+		goto out;
+	}
+
+	if (primary_if->if_status != BATADV_IF_ACTIVE) {
+		ret = seq_printf(seq,
+				 "BATMAN mesh %s disabled - primary interface not active\n",
+				 net_dev->name);
+		goto out;
+	}
+
+	primary_addr = primary_if->net_dev->dev_addr;
+	seq_printf(seq,
+		   "Backbones announced for the mesh %s (orig %pM, group id %04x)\n",
+		   net_dev->name, primary_addr,
+		   ntohs(bat_priv->claim_dest.group));
+	seq_printf(seq, "   %-17s    %-5s %-9s (%-4s)\n",
+		   "Originator", "VID", "last seen", "CRC");
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
+			msecs = jiffies_to_msecs(jiffies -
+						 backbone_gw->lasttime);
+			secs = msecs / 1000;
+			msecs = msecs % 1000;
+
+			is_own = batadv_compare_eth(backbone_gw->orig,
+						    primary_addr);
+			if (is_own)
+				continue;
+
+			seq_printf(seq,
+				   " * %pM on % 5d % 4i.%03is (%04x)\n",
+				   backbone_gw->orig, backbone_gw->vid,
+				   secs, msecs, backbone_gw->crc);
+		}
+		rcu_read_unlock();
+	}
+out:
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	return ret;
+}
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 3f0dfa2..789cb73 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -27,6 +27,8 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
 int batadv_bla_is_backbone_gw(struct sk_buff *skb,
 			      struct batadv_orig_node *orig_node, int hdr_size);
 int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
+					     void *offset);
 int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 				   struct batadv_bcast_packet *bcast_packet,
@@ -65,6 +67,12 @@ static inline int batadv_bla_claim_table_seq_print_text(struct seq_file *seq,
 	return 0;
 }
 
+static inline int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
+							   void *offset)
+{
+	return 0;
+}
+
 static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 						 uint8_t *orig)
 {
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 34fbb16..391d4fb 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -267,6 +267,15 @@ static int batadv_bla_claim_table_open(struct inode *inode, struct file *file)
 	return single_open(file, batadv_bla_claim_table_seq_print_text,
 			   net_dev);
 }
+
+static int batadv_bla_backbone_table_open(struct inode *inode,
+					  struct file *file)
+{
+	struct net_device *net_dev = (struct net_device *)inode->i_private;
+	return single_open(file, batadv_bla_backbone_table_seq_print_text,
+			   net_dev);
+}
+
 #endif
 
 static int batadv_transtable_local_open(struct inode *inode, struct file *file)
@@ -305,6 +314,8 @@ static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
 			batadv_transtable_global_open);
 #ifdef CONFIG_BATMAN_ADV_BLA
 static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
+static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
+			batadv_bla_backbone_table_open);
 #endif
 static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
 			batadv_transtable_local_open);
@@ -316,6 +327,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 	&batadv_debuginfo_transtable_global,
 #ifdef CONFIG_BATMAN_ADV_BLA
 	&batadv_debuginfo_bla_claim_table,
+	&batadv_debuginfo_bla_backbone_table,
 #endif
 	&batadv_debuginfo_transtable_local,
 	&batadv_debuginfo_vis_data,
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 04/18] batman-adv: rename bridge loop avoidance claim types
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
	Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>

for consistency reasons within the code and with the documentation,
we should always call it "claim" and "unclaim".

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/bridge_loop_avoidance.c |   18 +++++++++---------
 net/batman-adv/packet.h                |    4 ++--
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 5f1ad80..84dd841 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -295,7 +295,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 
 	/* now we pretend that the client would have sent this ... */
 	switch (claimtype) {
-	case BATADV_CLAIM_TYPE_ADD:
+	case BATADV_CLAIM_TYPE_CLAIM:
 		/* normal claim frame
 		 * set Ethernet SRC to the clients mac
 		 */
@@ -303,7 +303,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 		batadv_dbg(BATADV_DBG_BLA, bat_priv,
 			   "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
 		break;
-	case BATADV_CLAIM_TYPE_DEL:
+	case BATADV_CLAIM_TYPE_UNCLAIM:
 		/* unclaim frame
 		 * set HW SRC to the clients mac
 		 */
@@ -468,7 +468,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
 				continue;
 
 			batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
-					      BATADV_CLAIM_TYPE_ADD);
+					      BATADV_CLAIM_TYPE_CLAIM);
 		}
 		rcu_read_unlock();
 	}
@@ -703,7 +703,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
 	if (primary_if && batadv_compare_eth(backbone_addr,
 					     primary_if->net_dev->dev_addr))
 		batadv_bla_send_claim(bat_priv, claim_addr, vid,
-				      BATADV_CLAIM_TYPE_DEL);
+				      BATADV_CLAIM_TYPE_UNCLAIM);
 
 	backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
 
@@ -739,7 +739,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
 	batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
 	if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
 		batadv_bla_send_claim(bat_priv, claim_addr, vid,
-				      BATADV_CLAIM_TYPE_ADD);
+				      BATADV_CLAIM_TYPE_CLAIM);
 
 	/* TODO: we could call something like tt_local_del() here. */
 
@@ -784,12 +784,12 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
 	 * otherwise assume it is in the hw_src
 	 */
 	switch (bla_dst->type) {
-	case BATADV_CLAIM_TYPE_ADD:
+	case BATADV_CLAIM_TYPE_CLAIM:
 		backbone_addr = hw_src;
 		break;
 	case BATADV_CLAIM_TYPE_REQUEST:
 	case BATADV_CLAIM_TYPE_ANNOUNCE:
-	case BATADV_CLAIM_TYPE_DEL:
+	case BATADV_CLAIM_TYPE_UNCLAIM:
 		backbone_addr = ethhdr->h_source;
 		break;
 	default:
@@ -905,12 +905,12 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
 
 	/* check for the different types of claim frames ... */
 	switch (bla_dst->type) {
-	case BATADV_CLAIM_TYPE_ADD:
+	case BATADV_CLAIM_TYPE_CLAIM:
 		if (batadv_handle_claim(bat_priv, primary_if, hw_src,
 					ethhdr->h_source, vid))
 			return 1;
 		break;
-	case BATADV_CLAIM_TYPE_DEL:
+	case BATADV_CLAIM_TYPE_UNCLAIM:
 		if (batadv_handle_unclaim(bat_priv, primary_if,
 					  ethhdr->h_source, hw_src, vid))
 			return 1;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 8d3e55a..65d66e4 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -92,8 +92,8 @@ enum batadv_tt_client_flags {
 
 /* claim frame types for the bridge loop avoidance */
 enum batadv_bla_claimframe {
-	BATADV_CLAIM_TYPE_ADD		= 0x00,
-	BATADV_CLAIM_TYPE_DEL		= 0x01,
+	BATADV_CLAIM_TYPE_CLAIM		= 0x00,
+	BATADV_CLAIM_TYPE_UNCLAIM	= 0x01,
 	BATADV_CLAIM_TYPE_ANNOUNCE	= 0x02,
 	BATADV_CLAIM_TYPE_REQUEST	= 0x03,
 };
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 05/18] batman-adv: convert remaining packet counters to per_cpu_ptr() infrastructure
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Marek Lindner <lindner_marek@yahoo.de>

Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/bridge_loop_avoidance.c |    5 ++--
 net/batman-adv/soft-interface.c        |   51 +++++++++++++++++++++-----------
 net/batman-adv/types.h                 |    5 ++++
 3 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 84dd841..c9732ac 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -340,8 +340,9 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 
 	skb_reset_mac_header(skb);
 	skb->protocol = eth_type_trans(skb, soft_iface);
-	bat_priv->stats.rx_packets++;
-	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
+	batadv_inc_counter(bat_priv, BATADV_CNT_RX);
+	batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
+			   skb->len + ETH_HLEN);
 	soft_iface->last_rx = jiffies;
 
 	netif_rx(skb);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 109ea2a..2b3842b 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -93,7 +93,14 @@ static int batadv_interface_release(struct net_device *dev)
 static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
 {
 	struct batadv_priv *bat_priv = netdev_priv(dev);
-	return &bat_priv->stats;
+	struct net_device_stats *stats = &bat_priv->stats;
+
+	stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX);
+	stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES);
+	stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED);
+	stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX);
+	stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES);
+	return stats;
 }
 
 static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
@@ -246,14 +253,14 @@ static int batadv_interface_tx(struct sk_buff *skb,
 			goto dropped_freed;
 	}
 
-	bat_priv->stats.tx_packets++;
-	bat_priv->stats.tx_bytes += data_len;
+	batadv_inc_counter(bat_priv, BATADV_CNT_TX);
+	batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len);
 	goto end;
 
 dropped:
 	kfree_skb(skb);
 dropped_freed:
-	bat_priv->stats.tx_dropped++;
+	batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED);
 end:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
@@ -308,8 +315,9 @@ void batadv_interface_rx(struct net_device *soft_iface,
 
 	/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
 
-	bat_priv->stats.rx_packets++;
-	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
+	batadv_inc_counter(bat_priv, BATADV_CNT_RX);
+	batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
+			   skb->len + ETH_HLEN);
 
 	soft_iface->last_rx = jiffies;
 
@@ -379,15 +387,22 @@ struct net_device *batadv_softif_create(const char *name)
 	if (!soft_iface)
 		goto out;
 
+	bat_priv = netdev_priv(soft_iface);
+
+	/* batadv_interface_stats() needs to be available as soon as
+	 * register_netdevice() has been called
+	 */
+	bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
+	if (!bat_priv->bat_counters)
+		goto free_soft_iface;
+
 	ret = register_netdevice(soft_iface);
 	if (ret < 0) {
 		pr_err("Unable to register the batman interface '%s': %i\n",
 		       name, ret);
-		goto free_soft_iface;
+		goto free_bat_counters;
 	}
 
-	bat_priv = netdev_priv(soft_iface);
-
 	atomic_set(&bat_priv->aggregated_ogms, 1);
 	atomic_set(&bat_priv->bonding, 0);
 	atomic_set(&bat_priv->bridge_loop_avoidance, 0);
@@ -417,17 +432,13 @@ struct net_device *batadv_softif_create(const char *name)
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
 
-	bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
-	if (!bat_priv->bat_counters)
-		goto unreg_soft_iface;
-
 	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
 	if (ret < 0)
-		goto free_bat_counters;
+		goto unreg_soft_iface;
 
 	ret = batadv_sysfs_add_meshif(soft_iface);
 	if (ret < 0)
-		goto free_bat_counters;
+		goto unreg_soft_iface;
 
 	ret = batadv_debugfs_add_meshif(soft_iface);
 	if (ret < 0)
@@ -443,12 +454,13 @@ unreg_debugfs:
 	batadv_debugfs_del_meshif(soft_iface);
 unreg_sysfs:
 	batadv_sysfs_del_meshif(soft_iface);
-free_bat_counters:
-	free_percpu(bat_priv->bat_counters);
 unreg_soft_iface:
+	free_percpu(bat_priv->bat_counters);
 	unregister_netdevice(soft_iface);
 	return NULL;
 
+free_bat_counters:
+	free_percpu(bat_priv->bat_counters);
 free_soft_iface:
 	free_netdev(soft_iface);
 out:
@@ -518,6 +530,11 @@ static u32 batadv_get_link(struct net_device *dev)
 static const struct {
 	const char name[ETH_GSTRING_LEN];
 } batadv_counters_strings[] = {
+	{ "tx" },
+	{ "tx_bytes" },
+	{ "tx_dropped" },
+	{ "rx" },
+	{ "rx_bytes" },
 	{ "forward" },
 	{ "forward_bytes" },
 	{ "mgmt_tx" },
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 12635fd..7812b6e 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -145,6 +145,11 @@ struct batadv_bcast_duplist_entry {
 #endif
 
 enum batadv_counters {
+	BATADV_CNT_TX,
+	BATADV_CNT_TX_BYTES,
+	BATADV_CNT_TX_DROPPED,
+	BATADV_CNT_RX,
+	BATADV_CNT_RX_BYTES,
 	BATADV_CNT_FORWARD,
 	BATADV_CNT_FORWARD_BYTES,
 	BATADV_CNT_MGMT_TX,
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 06/18] batman-adv: remove a misleading comment
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Jonathan Corbet, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Jonathan Corbet <corbet@lwn.net>

As much as I'm happy to see LWN links sprinkled through the kernel by the
dozen, this one in particular reflects a very old state of reality; the
associated comment is now incorrect.  So just delete it.

Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/main.c |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 13c88b2..2a1f243 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -58,9 +58,6 @@ static int __init batadv_init(void)
 
 	batadv_iv_init();
 
-	/* the name should not be longer than 10 chars - see
-	 * http://lwn.net/Articles/23634/
-	 */
 	batadv_event_workqueue = create_singlethread_workqueue("bat_events");
 
 	if (!batadv_event_workqueue)
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 07/18] batman-adv: add reference counting for type batadv_tt_orig_list_entry
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

The batadv_tt_orig_list_entry structure didn't have any refcounting mechanism so
far. This patch introduces it and makes the structure being usable in much more
complex context.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/translation-table.c |   77 +++++++++++++++++++++++++-----------
 net/batman-adv/types.h             |    1 +
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 99dd8f7..eb8490e 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -152,6 +152,8 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
 static void
 batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
 {
+	if (!atomic_dec_and_test(&orig_entry->refcount))
+		return;
 	/* to avoid race conditions, immediately decrease the tt counter */
 	atomic_dec(&orig_entry->orig_node->tt_size);
 	call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
@@ -625,50 +627,82 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
 	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
 }
 
+/* retrieves the orig_tt_list_entry belonging to orig_node from the
+ * batadv_tt_global_entry list
+ *
+ * returns it with an increased refcounter, NULL if not found
+ */
+static struct batadv_tt_orig_list_entry *
+batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
+				 const struct batadv_orig_node *orig_node)
+{
+	struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
+	const struct hlist_head *head;
+	struct hlist_node *node;
+
+	rcu_read_lock();
+	head = &entry->orig_list;
+	hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
+		if (tmp_orig_entry->orig_node != orig_node)
+			continue;
+		if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
+			continue;
+
+		orig_entry = tmp_orig_entry;
+		break;
+	}
+	rcu_read_unlock();
+
+	return orig_entry;
+}
+
 /* find out if an orig_node is already in the list of a tt_global_entry.
- * returns 1 if found, 0 otherwise
+ * returns true if found, false otherwise
  */
 static bool
 batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
 				const struct batadv_orig_node *orig_node)
 {
-	struct batadv_tt_orig_list_entry *tmp_orig_entry;
-	const struct hlist_head *head;
-	struct hlist_node *node;
+	struct batadv_tt_orig_list_entry *orig_entry;
 	bool found = false;
 
-	rcu_read_lock();
-	head = &entry->orig_list;
-	hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
-		if (tmp_orig_entry->orig_node == orig_node) {
-			found = true;
-			break;
-		}
+	orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
+	if (orig_entry) {
+		found = true;
+		batadv_tt_orig_list_entry_free_ref(orig_entry);
 	}
-	rcu_read_unlock();
+
 	return found;
 }
 
 static void
-batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
+batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
 				struct batadv_orig_node *orig_node, int ttvn)
 {
 	struct batadv_tt_orig_list_entry *orig_entry;
 
+	orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
+	if (orig_entry)
+		goto out;
+
 	orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
 	if (!orig_entry)
-		return;
+		goto out;
 
 	INIT_HLIST_NODE(&orig_entry->list);
 	atomic_inc(&orig_node->refcount);
 	atomic_inc(&orig_node->tt_size);
 	orig_entry->orig_node = orig_node;
 	orig_entry->ttvn = ttvn;
+	atomic_set(&orig_entry->refcount, 2);
 
-	spin_lock_bh(&tt_global_entry->list_lock);
+	spin_lock_bh(&tt_global->list_lock);
 	hlist_add_head_rcu(&orig_entry->list,
-			   &tt_global_entry->orig_list);
-	spin_unlock_bh(&tt_global_entry->list_lock);
+			   &tt_global->orig_list);
+	spin_unlock_bh(&tt_global->list_lock);
+out:
+	if (orig_entry)
+		batadv_tt_orig_list_entry_free_ref(orig_entry);
 }
 
 /* caller must hold orig_node refcount */
@@ -709,9 +743,6 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 			batadv_tt_global_entry_free_ref(tt_global_entry);
 			goto out_remove;
 		}
-
-		batadv_tt_global_add_orig_entry(tt_global_entry, orig_node,
-						ttvn);
 	} else {
 		/* there is already a global entry, use this one. */
 
@@ -728,11 +759,9 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 			tt_global_entry->roam_at = 0;
 		}
 
-		if (!batadv_tt_global_entry_has_orig(tt_global_entry,
-						     orig_node))
-			batadv_tt_global_add_orig_entry(tt_global_entry,
-							orig_node, ttvn);
 	}
+	/* add the new orig_entry (if needed) */
+	batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Creating new global tt entry: %pM (via %pM)\n",
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 7812b6e..664ef81 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -282,6 +282,7 @@ struct batadv_tt_global_entry {
 struct batadv_tt_orig_list_entry {
 	struct batadv_orig_node *orig_node;
 	uint8_t ttvn;
+	atomic_t refcount;
 	struct rcu_head rcu;
 	struct hlist_node list;
 };
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 08/18] batman-adv: fix typos in comments
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

the word millisecond is misspelled in several comments. This patch fixes it.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/main.h |    8 ++++----
 net/batman-adv/vis.h  |    2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 5d8fa07..4dfeae5 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -41,13 +41,13 @@
  * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE
  */
 #define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */
-#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in miliseconds */
-#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in miliseconds */
+#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
+#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
 /* sliding packet range of received originator messages in sequence numbers
  * (should be a multiple of our word size)
  */
 #define BATADV_TQ_LOCAL_WINDOW_SIZE 64
-/* miliseconds we have to keep pending tt_req */
+/* milliseconds we have to keep pending tt_req */
 #define BATADV_TT_REQUEST_TIMEOUT 3000
 
 #define BATADV_TQ_GLOBAL_WINDOW_SIZE 5
@@ -59,7 +59,7 @@
 #define BATADV_TT_OGM_APPEND_MAX 3
 
 /* Time in which a client can roam at most ROAMING_MAX_COUNT times in
- * miliseconds
+ * milliseconds
  */
 #define BATADV_ROAMING_MAX_TIME 20000
 #define BATADV_ROAMING_MAX_COUNT 5
diff --git a/net/batman-adv/vis.h b/net/batman-adv/vis.h
index 84e716e..873282f 100644
--- a/net/batman-adv/vis.h
+++ b/net/batman-adv/vis.h
@@ -20,7 +20,7 @@
 #ifndef _NET_BATMAN_ADV_VIS_H_
 #define _NET_BATMAN_ADV_VIS_H_
 
-/* timeout of vis packets in miliseconds */
+/* timeout of vis packets in milliseconds */
 #define BATADV_VIS_TIMEOUT		200000
 
 int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 09/18] batman-adv: check batadv_orig_hash_add_if() return code
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich,
	Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>

If this call fails, some of the orig_nodes spaces may have been
resized for the increased number of interface, and some may not.
If we would just continue with the larger number of interfaces,
this would lead to access to not allocated memory later.

We better check the return code, and don't add the interface if
no memory is available. OTOH, keeping some of the orig_nodes
with too much memory allocated should hurt no one (except for
a few too many bytes allocated).

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/hard-interface.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 282bf6e..2c5a247 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -313,7 +313,13 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 	hard_iface->if_num = bat_priv->num_ifaces;
 	bat_priv->num_ifaces++;
 	hard_iface->if_status = BATADV_IF_INACTIVE;
-	batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
+	ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
+	if (ret < 0) {
+		bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
+		bat_priv->num_ifaces--;
+		hard_iface->if_status = BATADV_IF_NOT_IN_USE;
+		goto err_dev;
+	}
 
 	hard_iface->batman_adv_ptype.type = ethertype;
 	hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
-- 
1.7.9.4

^ permalink raw reply related

* [PATCH 10/18] batman-adv: Split batadv_priv in sub-structures for features
From: Antonio Quartulli @ 2012-08-23 13:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1345727427-20805-1-git-send-email-ordex@autistici.org>

From: Sven Eckelmann <sven@narfation.org>

The structure batadv_priv grows everytime a new feature is introduced. It gets
hard to find the parts of the struct that belongs to a specific feature. This
becomes even harder by the fact that not every feature uses a prefix in the
member name.

The variables for bridge loop avoidence, gateway handling, translation table
and visualization server are moved into separate structs that are included in
the bat_priv main struct.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 net/batman-adv/bat_iv_ogm.c            |    4 +-
 net/batman-adv/bridge_loop_avoidance.c |  115 +++++++++---------
 net/batman-adv/gateway_client.c        |   32 ++---
 net/batman-adv/hard-interface.c        |    5 +-
 net/batman-adv/main.c                  |   24 ++--
 net/batman-adv/routing.c               |    6 +-
 net/batman-adv/soft-interface.c        |   17 +--
 net/batman-adv/translation-table.c     |  208 ++++++++++++++++----------------
 net/batman-adv/types.h                 |  113 ++++++++++-------
 net/batman-adv/vis.c                   |  130 ++++++++++----------
 10 files changed, 343 insertions(+), 311 deletions(-)

diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e877af8..eb507c9 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -603,8 +603,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 			htonl((uint32_t)atomic_read(&hard_iface->seqno));
 	atomic_inc(&hard_iface->seqno);
 
-	batadv_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn);
-	batadv_ogm_packet->tt_crc = htons(bat_priv->tt_crc);
+	batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
+	batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
 	if (tt_num_changes >= 0)
 		batadv_ogm_packet->tt_num_changes = tt_num_changes;
 
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index c9732ac..ad18017 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -133,7 +133,7 @@ static void batadv_claim_free_ref(struct batadv_claim *claim)
 static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
 						   struct batadv_claim *data)
 {
-	struct batadv_hashtable *hash = bat_priv->claim_hash;
+	struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct batadv_claim *claim;
@@ -174,7 +174,7 @@ static struct batadv_backbone_gw *
 batadv_backbone_hash_find(struct batadv_priv *bat_priv,
 			  uint8_t *addr, short vid)
 {
-	struct batadv_hashtable *hash = bat_priv->backbone_hash;
+	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct batadv_backbone_gw search_entry, *backbone_gw;
@@ -218,7 +218,7 @@ batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw)
 	int i;
 	spinlock_t *list_lock;	/* protects write access to the hash lists */
 
-	hash = backbone_gw->bat_priv->claim_hash;
+	hash = backbone_gw->bat_priv->bla.claim_hash;
 	if (!hash)
 		return;
 
@@ -265,7 +265,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 	if (!primary_if)
 		return;
 
-	memcpy(&local_claim_dest, &bat_priv->claim_dest,
+	memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
 	       sizeof(local_claim_dest));
 	local_claim_dest.type = claimtype;
 
@@ -391,7 +391,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 	/* one for the hash, one for returning */
 	atomic_set(&entry->refcount, 2);
 
-	hash_added = batadv_hash_add(bat_priv->backbone_hash,
+	hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
 				     batadv_compare_backbone_gw,
 				     batadv_choose_backbone_gw, entry,
 				     &entry->hash_entry);
@@ -458,7 +458,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
 	if (!backbone_gw)
 		return;
 
-	hash = bat_priv->claim_hash;
+	hash = bat_priv->bla.claim_hash;
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
@@ -499,7 +499,7 @@ static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw)
 
 	/* no local broadcasts should be sent or received, for now. */
 	if (!atomic_read(&backbone_gw->request_sent)) {
-		atomic_inc(&backbone_gw->bat_priv->bla_num_requests);
+		atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
 		atomic_set(&backbone_gw->request_sent, 1);
 	}
 }
@@ -559,7 +559,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
 		batadv_dbg(BATADV_DBG_BLA, bat_priv,
 			   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
 			   mac, vid);
-		hash_added = batadv_hash_add(bat_priv->claim_hash,
+		hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
 					     batadv_compare_claim,
 					     batadv_choose_claim, claim,
 					     &claim->hash_entry);
@@ -612,7 +612,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
 	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
 		   mac, vid);
 
-	batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim,
+	batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
 			   batadv_choose_claim, claim);
 	batadv_claim_free_ref(claim); /* reference from the hash is gone */
 
@@ -659,7 +659,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
 		 * we can allow traffic again.
 		 */
 		if (atomic_read(&backbone_gw->request_sent)) {
-			atomic_dec(&backbone_gw->bat_priv->bla_num_requests);
+			atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
 			atomic_set(&backbone_gw->request_sent, 0);
 		}
 	}
@@ -774,7 +774,7 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
 	struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
 
 	bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
-	bla_dst_own = &bat_priv->claim_dest;
+	bla_dst_own = &bat_priv->bla.claim_dest;
 
 	/* check if it is a claim packet in general */
 	if (memcmp(bla_dst->magic, bla_dst_own->magic,
@@ -947,7 +947,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 	spinlock_t *list_lock;	/* protects write access to the hash lists */
 	int i;
 
-	hash = bat_priv->backbone_hash;
+	hash = bat_priv->bla.backbone_hash;
 	if (!hash)
 		return;
 
@@ -971,7 +971,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 purge_now:
 			/* don't wait for the pending request anymore */
 			if (atomic_read(&backbone_gw->request_sent))
-				atomic_dec(&bat_priv->bla_num_requests);
+				atomic_dec(&bat_priv->bla.num_requests);
 
 			batadv_bla_del_backbone_claims(backbone_gw);
 
@@ -1001,7 +1001,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
 	struct batadv_hashtable *hash;
 	int i;
 
-	hash = bat_priv->claim_hash;
+	hash = bat_priv->bla.claim_hash;
 	if (!hash)
 		return;
 
@@ -1048,11 +1048,12 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 	struct hlist_node *node;
 	struct hlist_head *head;
 	struct batadv_hashtable *hash;
+	__be16 group;
 	int i;
 
 	/* reset bridge loop avoidance group id */
-	bat_priv->claim_dest.group =
-		htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
+	group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
+	bat_priv->bla.claim_dest.group = group;
 
 	if (!oldif) {
 		batadv_bla_purge_claims(bat_priv, NULL, 1);
@@ -1060,7 +1061,7 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 		return;
 	}
 
-	hash = bat_priv->backbone_hash;
+	hash = bat_priv->bla.backbone_hash;
 	if (!hash)
 		return;
 
@@ -1090,8 +1091,8 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 /* (re)start the timer */
 static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
 {
-	INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work);
-	queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work,
+	INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
+	queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
 			   msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
 }
 
@@ -1104,6 +1105,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 	struct delayed_work *delayed_work =
 		container_of(work, struct delayed_work, work);
 	struct batadv_priv *bat_priv;
+	struct batadv_priv_bla *priv_bla;
 	struct hlist_node *node;
 	struct hlist_head *head;
 	struct batadv_backbone_gw *backbone_gw;
@@ -1111,7 +1113,8 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 	struct batadv_hard_iface *primary_if;
 	int i;
 
-	bat_priv = container_of(delayed_work, struct batadv_priv, bla_work);
+	priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
+	bat_priv = container_of(priv_bla, struct batadv_priv, bla);
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (!primary_if)
 		goto out;
@@ -1122,7 +1125,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
 		goto out;
 
-	hash = bat_priv->backbone_hash;
+	hash = bat_priv->bla.backbone_hash;
 	if (!hash)
 		goto out;
 
@@ -1162,40 +1165,41 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 	int i;
 	uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
 	struct batadv_hard_iface *primary_if;
+	uint16_t crc;
+	unsigned long entrytime;
 
 	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 
 	/* setting claim destination address */
-	memcpy(&bat_priv->claim_dest.magic, claim_dest, 3);
-	bat_priv->claim_dest.type = 0;
+	memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
+	bat_priv->bla.claim_dest.type = 0;
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (primary_if) {
-		bat_priv->claim_dest.group =
-			htons(crc16(0, primary_if->net_dev->dev_addr,
-				    ETH_ALEN));
+		crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
+		bat_priv->bla.claim_dest.group = htons(crc);
 		batadv_hardif_free_ref(primary_if);
 	} else {
-		bat_priv->claim_dest.group = 0; /* will be set later */
+		bat_priv->bla.claim_dest.group = 0; /* will be set later */
 	}
 
 	/* initialize the duplicate list */
+	entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
 	for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
-		bat_priv->bcast_duplist[i].entrytime =
-			jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
-	bat_priv->bcast_duplist_curr = 0;
+		bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
+	bat_priv->bla.bcast_duplist_curr = 0;
 
-	if (bat_priv->claim_hash)
+	if (bat_priv->bla.claim_hash)
 		return 0;
 
-	bat_priv->claim_hash = batadv_hash_new(128);
-	bat_priv->backbone_hash = batadv_hash_new(32);
+	bat_priv->bla.claim_hash = batadv_hash_new(128);
+	bat_priv->bla.backbone_hash = batadv_hash_new(32);
 
-	if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
+	if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash)
 		return -ENOMEM;
 
-	batadv_hash_set_lock_class(bat_priv->claim_hash,
+	batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
 				   &batadv_claim_hash_lock_class_key);
-	batadv_hash_set_lock_class(bat_priv->backbone_hash,
+	batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
 				   &batadv_backbone_hash_lock_class_key);
 
 	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
@@ -1236,8 +1240,9 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 	crc = crc16(0, content, length);
 
 	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
-		curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE;
-		entry = &bat_priv->bcast_duplist[curr];
+		curr = (bat_priv->bla.bcast_duplist_curr + i);
+		curr %= BATADV_DUPLIST_SIZE;
+		entry = &bat_priv->bla.bcast_duplist[curr];
 
 		/* we can stop searching if the entry is too old ;
 		 * later entries will be even older
@@ -1258,13 +1263,13 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 		return 1;
 	}
 	/* not found, add a new entry (overwrite the oldest entry) */
-	curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
+	curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
 	curr %= BATADV_DUPLIST_SIZE;
-	entry = &bat_priv->bcast_duplist[curr];
+	entry = &bat_priv->bla.bcast_duplist[curr];
 	entry->crc = crc;
 	entry->entrytime = jiffies;
 	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
-	bat_priv->bcast_duplist_curr = curr;
+	bat_priv->bla.bcast_duplist_curr = curr;
 
 	/* allow it, its the first occurence. */
 	return 0;
@@ -1281,7 +1286,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
  */
 int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
 {
-	struct batadv_hashtable *hash = bat_priv->backbone_hash;
+	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct batadv_backbone_gw *backbone_gw;
@@ -1361,18 +1366,18 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
 {
 	struct batadv_hard_iface *primary_if;
 
-	cancel_delayed_work_sync(&bat_priv->bla_work);
+	cancel_delayed_work_sync(&bat_priv->bla.work);
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 
-	if (bat_priv->claim_hash) {
+	if (bat_priv->bla.claim_hash) {
 		batadv_bla_purge_claims(bat_priv, primary_if, 1);
-		batadv_hash_destroy(bat_priv->claim_hash);
-		bat_priv->claim_hash = NULL;
+		batadv_hash_destroy(bat_priv->bla.claim_hash);
+		bat_priv->bla.claim_hash = NULL;
 	}
-	if (bat_priv->backbone_hash) {
+	if (bat_priv->bla.backbone_hash) {
 		batadv_bla_purge_backbone_gw(bat_priv, 1);
-		batadv_hash_destroy(bat_priv->backbone_hash);
-		bat_priv->backbone_hash = NULL;
+		batadv_hash_destroy(bat_priv->bla.backbone_hash);
+		bat_priv->bla.backbone_hash = NULL;
 	}
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
@@ -1411,7 +1416,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
 		goto allow;
 
 
-	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
+	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
 		/* don't allow broadcasts while requests are in flight */
 		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
 			goto handled;
@@ -1510,7 +1515,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
-	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
+	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
 		/* don't allow broadcasts while requests are in flight */
 		if (is_multicast_ether_addr(ethhdr->h_dest))
 			goto handled;
@@ -1566,7 +1571,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 {
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct batadv_priv *bat_priv = netdev_priv(net_dev);
-	struct batadv_hashtable *hash = bat_priv->claim_hash;
+	struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
 	struct batadv_claim *claim;
 	struct batadv_hard_iface *primary_if;
 	struct hlist_node *node;
@@ -1595,7 +1600,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 	seq_printf(seq,
 		   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
 		   net_dev->name, primary_addr,
-		   ntohs(bat_priv->claim_dest.group));
+		   ntohs(bat_priv->bla.claim_dest.group));
 	seq_printf(seq, "   %-17s    %-5s    %-17s [o] (%-4s)\n",
 		   "Client", "VID", "Originator", "CRC");
 	for (i = 0; i < hash->size; i++) {
@@ -1623,7 +1628,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 {
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct batadv_priv *bat_priv = netdev_priv(net_dev);
-	struct batadv_hashtable *hash = bat_priv->backbone_hash;
+	struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 	struct batadv_backbone_gw *backbone_gw;
 	struct batadv_hard_iface *primary_if;
 	struct hlist_node *node;
@@ -1653,7 +1658,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 	seq_printf(seq,
 		   "Backbones announced for the mesh %s (orig %pM, group id %04x)\n",
 		   net_dev->name, primary_addr,
-		   ntohs(bat_priv->claim_dest.group));
+		   ntohs(bat_priv->bla.claim_dest.group));
 	seq_printf(seq, "   %-17s    %-5s %-9s (%-4s)\n",
 		   "Originator", "VID", "last seen", "CRC");
 	for (i = 0; i < hash->size; i++) {
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index fc866f2..eef7cc7 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -48,7 +48,7 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
 	struct batadv_gw_node *gw_node;
 
 	rcu_read_lock();
-	gw_node = rcu_dereference(bat_priv->curr_gw);
+	gw_node = rcu_dereference(bat_priv->gw.curr_gw);
 	if (!gw_node)
 		goto out;
 
@@ -91,23 +91,23 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,
 {
 	struct batadv_gw_node *curr_gw_node;
 
-	spin_lock_bh(&bat_priv->gw_list_lock);
+	spin_lock_bh(&bat_priv->gw.list_lock);
 
 	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
 		new_gw_node = NULL;
 
-	curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1);
-	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
+	curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1);
+	rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node);
 
 	if (curr_gw_node)
 		batadv_gw_node_free_ref(curr_gw_node);
 
-	spin_unlock_bh(&bat_priv->gw_list_lock);
+	spin_unlock_bh(&bat_priv->gw.list_lock);
 }
 
 void batadv_gw_deselect(struct batadv_priv *bat_priv)
 {
-	atomic_set(&bat_priv->gw_reselect, 1);
+	atomic_set(&bat_priv->gw.reselect, 1);
 }
 
 static struct batadv_gw_node *
@@ -122,7 +122,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 	struct batadv_orig_node *orig_node;
 
 	rcu_read_lock();
-	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
+	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 		if (gw_node->deleted)
 			continue;
 
@@ -202,7 +202,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
 
 	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 
-	if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect) && curr_gw)
+	if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw)
 		goto out;
 
 	next_gw = batadv_gw_get_best_gw_node(bat_priv);
@@ -321,9 +321,9 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
 	gw_node->orig_node = orig_node;
 	atomic_set(&gw_node->refcount, 1);
 
-	spin_lock_bh(&bat_priv->gw_list_lock);
-	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
-	spin_unlock_bh(&bat_priv->gw_list_lock);
+	spin_lock_bh(&bat_priv->gw.list_lock);
+	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
+	spin_unlock_bh(&bat_priv->gw.list_lock);
 
 	batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up);
 	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -350,7 +350,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
 	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 
 	rcu_read_lock();
-	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
+	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 		if (gw_node->orig_node != orig_node)
 			continue;
 
@@ -404,10 +404,10 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
 
 	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 
-	spin_lock_bh(&bat_priv->gw_list_lock);
+	spin_lock_bh(&bat_priv->gw.list_lock);
 
 	hlist_for_each_entry_safe(gw_node, node, node_tmp,
-				  &bat_priv->gw_list, list) {
+				  &bat_priv->gw.list, list) {
 		if (((!gw_node->deleted) ||
 		     (time_before(jiffies, gw_node->deleted + timeout))) &&
 		    atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE)
@@ -420,7 +420,7 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
 		batadv_gw_node_free_ref(gw_node);
 	}
 
-	spin_unlock_bh(&bat_priv->gw_list_lock);
+	spin_unlock_bh(&bat_priv->gw.list_lock);
 
 	/* gw_deselect() needs to acquire the gw_list_lock */
 	if (do_deselect)
@@ -496,7 +496,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 		   primary_if->net_dev->dev_addr, net_dev->name);
 
 	rcu_read_lock();
-	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
+	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 		if (gw_node->deleted)
 			continue;
 
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 2c5a247..d112fd6 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -103,13 +103,14 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
 {
 	struct batadv_vis_packet *vis_packet;
 	struct batadv_hard_iface *primary_if;
+	struct sk_buff *skb;
 
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (!primary_if)
 		goto out;
 
-	vis_packet = (struct batadv_vis_packet *)
-				bat_priv->my_vis_info->skb_packet->data;
+	skb = bat_priv->vis.my_info->skb_packet;
+	vis_packet = (struct batadv_vis_packet *)skb->data;
 	memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
 	memcpy(vis_packet->sender_orig,
 	       primary_if->net_dev->dev_addr, ETH_ALEN);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 2a1f243..b4aa470 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -94,20 +94,20 @@ int batadv_mesh_init(struct net_device *soft_iface)
 
 	spin_lock_init(&bat_priv->forw_bat_list_lock);
 	spin_lock_init(&bat_priv->forw_bcast_list_lock);
-	spin_lock_init(&bat_priv->tt_changes_list_lock);
-	spin_lock_init(&bat_priv->tt_req_list_lock);
-	spin_lock_init(&bat_priv->tt_roam_list_lock);
-	spin_lock_init(&bat_priv->tt_buff_lock);
-	spin_lock_init(&bat_priv->gw_list_lock);
-	spin_lock_init(&bat_priv->vis_hash_lock);
-	spin_lock_init(&bat_priv->vis_list_lock);
+	spin_lock_init(&bat_priv->tt.changes_list_lock);
+	spin_lock_init(&bat_priv->tt.req_list_lock);
+	spin_lock_init(&bat_priv->tt.roam_list_lock);
+	spin_lock_init(&bat_priv->tt.last_changeset_lock);
+	spin_lock_init(&bat_priv->gw.list_lock);
+	spin_lock_init(&bat_priv->vis.hash_lock);
+	spin_lock_init(&bat_priv->vis.list_lock);
 
 	INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
 	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
-	INIT_HLIST_HEAD(&bat_priv->gw_list);
-	INIT_LIST_HEAD(&bat_priv->tt_changes_list);
-	INIT_LIST_HEAD(&bat_priv->tt_req_list);
-	INIT_LIST_HEAD(&bat_priv->tt_roam_list);
+	INIT_HLIST_HEAD(&bat_priv->gw.list);
+	INIT_LIST_HEAD(&bat_priv->tt.changes_list);
+	INIT_LIST_HEAD(&bat_priv->tt.req_list);
+	INIT_LIST_HEAD(&bat_priv->tt.roam_list);
 
 	ret = batadv_originator_init(bat_priv);
 	if (ret < 0)
@@ -128,7 +128,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	if (ret < 0)
 		goto err;
 
-	atomic_set(&bat_priv->gw_reselect, 0);
+	atomic_set(&bat_priv->gw.reselect, 0);
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 
 	return 0;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index bc2b88b..d5edee7 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -721,7 +721,7 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 	 * been incremented yet. This flag will make me check all the incoming
 	 * packets for the correct destination.
 	 */
-	bat_priv->tt_poss_change = true;
+	bat_priv->tt.poss_change = true;
 
 	batadv_orig_node_free_ref(orig_node);
 out:
@@ -947,8 +947,8 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
 	unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
 	if (batadv_is_my_mac(unicast_packet->dest)) {
-		tt_poss_change = bat_priv->tt_poss_change;
-		curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+		tt_poss_change = bat_priv->tt.poss_change;
+		curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 	} else {
 		orig_node = batadv_orig_hash_find(bat_priv,
 						  unicast_packet->dest);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 2b3842b..6d44625 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -420,14 +420,15 @@ struct net_device *batadv_softif_create(const char *name)
 
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 	atomic_set(&bat_priv->bcast_seqno, 1);
-	atomic_set(&bat_priv->ttvn, 0);
-	atomic_set(&bat_priv->tt_local_changes, 0);
-	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
-	atomic_set(&bat_priv->bla_num_requests, 0);
-
-	bat_priv->tt_buff = NULL;
-	bat_priv->tt_buff_len = 0;
-	bat_priv->tt_poss_change = false;
+	atomic_set(&bat_priv->tt.vn, 0);
+	atomic_set(&bat_priv->tt.local_changes, 0);
+	atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
+#ifdef CONFIG_BATMAN_ADV_BLA
+	atomic_set(&bat_priv->bla.num_requests, 0);
+#endif
+	bat_priv->tt.last_changeset = NULL;
+	bat_priv->tt.last_changeset_len = 0;
+	bat_priv->tt.poss_change = false;
 
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index eb8490e..b01049a 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -46,8 +46,8 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 
 static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
 {
-	INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge);
-	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work,
+	INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
+	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
 			   msecs_to_jiffies(5000));
 }
 
@@ -88,7 +88,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
 	struct batadv_tt_common_entry *tt_common_entry;
 	struct batadv_tt_local_entry *tt_local_entry = NULL;
 
-	tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data);
+	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
 	if (tt_common_entry)
 		tt_local_entry = container_of(tt_common_entry,
 					      struct batadv_tt_local_entry,
@@ -102,7 +102,7 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
 	struct batadv_tt_common_entry *tt_common_entry;
 	struct batadv_tt_global_entry *tt_global_entry = NULL;
 
-	tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data);
+	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
 	if (tt_common_entry)
 		tt_global_entry = container_of(tt_common_entry,
 					       struct batadv_tt_global_entry,
@@ -177,8 +177,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
 	del_op_requested = flags & BATADV_TT_CLIENT_DEL;
 
 	/* check for ADD+DEL or DEL+ADD events */
-	spin_lock_bh(&bat_priv->tt_changes_list_lock);
-	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+	spin_lock_bh(&bat_priv->tt.changes_list_lock);
+	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 				 list) {
 		if (!batadv_compare_eth(entry->change.addr, addr))
 			continue;
@@ -205,15 +205,15 @@ del:
 	}
 
 	/* track the change in the OGMinterval list */
-	list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
+	list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
 
 unlock:
-	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 
 	if (event_removed)
-		atomic_dec(&bat_priv->tt_local_changes);
+		atomic_dec(&bat_priv->tt.local_changes);
 	else
-		atomic_inc(&bat_priv->tt_local_changes);
+		atomic_inc(&bat_priv->tt.local_changes);
 }
 
 int batadv_tt_len(int changes_num)
@@ -223,12 +223,12 @@ int batadv_tt_len(int changes_num)
 
 static int batadv_tt_local_init(struct batadv_priv *bat_priv)
 {
-	if (bat_priv->tt_local_hash)
+	if (bat_priv->tt.local_hash)
 		return 0;
 
-	bat_priv->tt_local_hash = batadv_hash_new(1024);
+	bat_priv->tt.local_hash = batadv_hash_new(1024);
 
-	if (!bat_priv->tt_local_hash)
+	if (!bat_priv->tt.local_hash)
 		return -ENOMEM;
 
 	return 0;
@@ -260,7 +260,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
-		   (uint8_t)atomic_read(&bat_priv->ttvn));
+		   (uint8_t)atomic_read(&bat_priv->tt.vn));
 
 	memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
 	tt_local_entry->common.flags = BATADV_NO_FLAGS;
@@ -279,7 +279,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 	 */
 	tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
 
-	hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt,
+	hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
 				     batadv_choose_orig,
 				     &tt_local_entry->common,
 				     &tt_local_entry->common.hash_entry);
@@ -350,7 +350,7 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 
 	req_len = min_packet_len;
-	req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes));
+	req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
 
 	/* if we have too many changes for one packet don't send any
 	 * and wait for the tt table request which will be fragmented
@@ -383,10 +383,10 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
 	if (new_len > 0)
 		tot_changes = new_len / batadv_tt_len(1);
 
-	spin_lock_bh(&bat_priv->tt_changes_list_lock);
-	atomic_set(&bat_priv->tt_local_changes, 0);
+	spin_lock_bh(&bat_priv->tt.changes_list_lock);
+	atomic_set(&bat_priv->tt.local_changes, 0);
 
-	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 				 list) {
 		if (count < tot_changes) {
 			memcpy(tt_buff + batadv_tt_len(count),
@@ -396,25 +396,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
 		list_del(&entry->list);
 		kfree(entry);
 	}
-	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 
 	/* Keep the buffer for possible tt_request */
-	spin_lock_bh(&bat_priv->tt_buff_lock);
-	kfree(bat_priv->tt_buff);
-	bat_priv->tt_buff_len = 0;
-	bat_priv->tt_buff = NULL;
+	spin_lock_bh(&bat_priv->tt.last_changeset_lock);
+	kfree(bat_priv->tt.last_changeset);
+	bat_priv->tt.last_changeset_len = 0;
+	bat_priv->tt.last_changeset = NULL;
 	/* check whether this new OGM has no changes due to size problems */
 	if (new_len > 0) {
 		/* if kmalloc() fails we will reply with the full table
 		 * instead of providing the diff
 		 */
-		bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC);
-		if (bat_priv->tt_buff) {
-			memcpy(bat_priv->tt_buff, tt_buff, new_len);
-			bat_priv->tt_buff_len = new_len;
+		bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC);
+		if (bat_priv->tt.last_changeset) {
+			memcpy(bat_priv->tt.last_changeset, tt_buff, new_len);
+			bat_priv->tt.last_changeset_len = new_len;
 		}
 	}
-	spin_unlock_bh(&bat_priv->tt_buff_lock);
+	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 
 	return count;
 }
@@ -423,7 +423,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 {
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct batadv_priv *bat_priv = netdev_priv(net_dev);
-	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 	struct batadv_tt_common_entry *tt_common_entry;
 	struct batadv_hard_iface *primary_if;
 	struct hlist_node *node;
@@ -448,7 +448,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 
 	seq_printf(seq,
 		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
-		   net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
+		   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -546,7 +546,7 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
 
 static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
 {
-	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 	struct hlist_head *head;
 	spinlock_t *list_lock; /* protects write access to the hash lists */
 	uint32_t i;
@@ -572,10 +572,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
 	struct hlist_head *head;
 	uint32_t i;
 
-	if (!bat_priv->tt_local_hash)
+	if (!bat_priv->tt.local_hash)
 		return;
 
-	hash = bat_priv->tt_local_hash;
+	hash = bat_priv->tt.local_hash;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -595,17 +595,17 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
 
 	batadv_hash_destroy(hash);
 
-	bat_priv->tt_local_hash = NULL;
+	bat_priv->tt.local_hash = NULL;
 }
 
 static int batadv_tt_global_init(struct batadv_priv *bat_priv)
 {
-	if (bat_priv->tt_global_hash)
+	if (bat_priv->tt.global_hash)
 		return 0;
 
-	bat_priv->tt_global_hash = batadv_hash_new(1024);
+	bat_priv->tt.global_hash = batadv_hash_new(1024);
 
-	if (!bat_priv->tt_global_hash)
+	if (!bat_priv->tt.global_hash)
 		return -ENOMEM;
 
 	return 0;
@@ -615,16 +615,16 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
 {
 	struct batadv_tt_change_node *entry, *safe;
 
-	spin_lock_bh(&bat_priv->tt_changes_list_lock);
+	spin_lock_bh(&bat_priv->tt.changes_list_lock);
 
-	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 				 list) {
 		list_del(&entry->list);
 		kfree(entry);
 	}
 
-	atomic_set(&bat_priv->tt_local_changes, 0);
-	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+	atomic_set(&bat_priv->tt.local_changes, 0);
+	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 }
 
 /* retrieves the orig_tt_list_entry belonging to orig_node from the
@@ -733,7 +733,7 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 		INIT_HLIST_HEAD(&tt_global_entry->orig_list);
 		spin_lock_init(&tt_global_entry->list_lock);
 
-		hash_added = batadv_hash_add(bat_priv->tt_global_hash,
+		hash_added = batadv_hash_add(bat_priv->tt.global_hash,
 					     batadv_compare_tt,
 					     batadv_choose_orig, common,
 					     &common->hash_entry);
@@ -812,7 +812,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
 {
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct batadv_priv *bat_priv = netdev_priv(net_dev);
-	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 	struct batadv_tt_common_entry *tt_common_entry;
 	struct batadv_tt_global_entry *tt_global;
 	struct batadv_hard_iface *primary_if;
@@ -913,7 +913,7 @@ batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
 		   "Deleting global tt entry %pM: %s\n",
 		   tt_global_entry->common.addr, message);
 
-	batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt,
+	batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
 			   batadv_choose_orig, tt_global_entry->common.addr);
 	batadv_tt_global_entry_free_ref(tt_global_entry);
 
@@ -1024,7 +1024,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
 	struct batadv_tt_global_entry *tt_global;
 	struct batadv_tt_common_entry *tt_common_entry;
 	uint32_t i;
-	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 	struct hlist_node *node, *safe;
 	struct hlist_head *head;
 	spinlock_t *list_lock; /* protects write access to the hash lists */
@@ -1088,7 +1088,7 @@ static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv,
 
 static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv)
 {
-	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 	struct hlist_head *head;
 	spinlock_t *list_lock; /* protects write access to the hash lists */
 	uint32_t i;
@@ -1114,10 +1114,10 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 	struct hlist_head *head;
 	uint32_t i;
 
-	if (!bat_priv->tt_global_hash)
+	if (!bat_priv->tt.global_hash)
 		return;
 
-	hash = bat_priv->tt_global_hash;
+	hash = bat_priv->tt.global_hash;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -1137,7 +1137,7 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 
 	batadv_hash_destroy(hash);
 
-	bat_priv->tt_global_hash = NULL;
+	bat_priv->tt.global_hash = NULL;
 }
 
 static bool
@@ -1216,7 +1216,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
 				     struct batadv_orig_node *orig_node)
 {
 	uint16_t total = 0, total_one;
-	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 	struct batadv_tt_common_entry *tt_common;
 	struct batadv_tt_global_entry *tt_global;
 	struct hlist_node *node;
@@ -1263,7 +1263,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
 static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
 {
 	uint16_t total = 0, total_one;
-	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 	struct batadv_tt_common_entry *tt_common;
 	struct hlist_node *node;
 	struct hlist_head *head;
@@ -1296,14 +1296,14 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
 {
 	struct batadv_tt_req_node *node, *safe;
 
-	spin_lock_bh(&bat_priv->tt_req_list_lock);
+	spin_lock_bh(&bat_priv->tt.req_list_lock);
 
-	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 		list_del(&node->list);
 		kfree(node);
 	}
 
-	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+	spin_unlock_bh(&bat_priv->tt.req_list_lock);
 }
 
 static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
@@ -1333,15 +1333,15 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
 {
 	struct batadv_tt_req_node *node, *safe;
 
-	spin_lock_bh(&bat_priv->tt_req_list_lock);
-	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+	spin_lock_bh(&bat_priv->tt.req_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 		if (batadv_has_timed_out(node->issued_at,
 					 BATADV_TT_REQUEST_TIMEOUT)) {
 			list_del(&node->list);
 			kfree(node);
 		}
 	}
-	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+	spin_unlock_bh(&bat_priv->tt.req_list_lock);
 }
 
 /* returns the pointer to the new tt_req_node struct if no request
@@ -1353,8 +1353,8 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
 {
 	struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
 
-	spin_lock_bh(&bat_priv->tt_req_list_lock);
-	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
+	spin_lock_bh(&bat_priv->tt.req_list_lock);
+	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
 		if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
 		    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
 					  BATADV_TT_REQUEST_TIMEOUT))
@@ -1368,9 +1368,9 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
 	memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
 	tt_req_node->issued_at = jiffies;
 
-	list_add(&tt_req_node->list, &bat_priv->tt_req_list);
+	list_add(&tt_req_node->list, &bat_priv->tt.req_list);
 unlock:
-	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+	spin_unlock_bh(&bat_priv->tt.req_list_lock);
 	return tt_req_node;
 }
 
@@ -1536,9 +1536,9 @@ out:
 	if (ret)
 		kfree_skb(skb);
 	if (ret && tt_req_node) {
-		spin_lock_bh(&bat_priv->tt_req_list_lock);
+		spin_lock_bh(&bat_priv->tt.req_list_lock);
 		list_del(&tt_req_node->list);
-		spin_unlock_bh(&bat_priv->tt_req_list_lock);
+		spin_unlock_bh(&bat_priv->tt.req_list_lock);
 		kfree(tt_req_node);
 	}
 	return ret;
@@ -1629,7 +1629,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 		ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
 
 		skb = batadv_tt_response_fill_table(tt_len, ttvn,
-						    bat_priv->tt_global_hash,
+						    bat_priv->tt.global_hash,
 						    primary_if,
 						    batadv_tt_global_valid,
 						    req_dst_orig_node);
@@ -1700,7 +1700,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 
 
-	my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+	my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 	req_ttvn = tt_request->ttvn;
 
 	orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
@@ -1719,7 +1719,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 	 * is too big send the whole local translation table
 	 */
 	if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
-	    !bat_priv->tt_buff)
+	    !bat_priv->tt.last_changeset)
 		full_table = true;
 	else
 		full_table = false;
@@ -1728,8 +1728,8 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 	 * I'll send only one packet with as much TT entries as I can
 	 */
 	if (!full_table) {
-		spin_lock_bh(&bat_priv->tt_buff_lock);
-		tt_len = bat_priv->tt_buff_len;
+		spin_lock_bh(&bat_priv->tt.last_changeset_lock);
+		tt_len = bat_priv->tt.last_changeset_len;
 		tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
 		len = sizeof(*tt_response) + tt_len;
@@ -1744,16 +1744,16 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 		tt_response->tt_data = htons(tt_tot);
 
 		tt_buff = skb->data + sizeof(*tt_response);
-		memcpy(tt_buff, bat_priv->tt_buff,
-		       bat_priv->tt_buff_len);
-		spin_unlock_bh(&bat_priv->tt_buff_lock);
+		memcpy(tt_buff, bat_priv->tt.last_changeset,
+		       bat_priv->tt.last_changeset_len);
+		spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 	} else {
-		tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt);
+		tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
 		tt_len *= sizeof(struct batadv_tt_change);
-		ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+		ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 
 		skb = batadv_tt_response_fill_table(tt_len, ttvn,
-						    bat_priv->tt_local_hash,
+						    bat_priv->tt.local_hash,
 						    primary_if,
 						    batadv_tt_local_valid_entry,
 						    NULL);
@@ -1785,7 +1785,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 	goto out;
 
 unlock:
-	spin_unlock_bh(&bat_priv->tt_buff_lock);
+	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 out:
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
@@ -1938,14 +1938,14 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
 	}
 
 	/* Delete the tt_req_node from pending tt_requests list */
-	spin_lock_bh(&bat_priv->tt_req_list_lock);
-	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+	spin_lock_bh(&bat_priv->tt.req_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 		if (!batadv_compare_eth(node->addr, tt_response->src))
 			continue;
 		list_del(&node->list);
 		kfree(node);
 	}
-	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+	spin_unlock_bh(&bat_priv->tt.req_list_lock);
 
 	/* Recalculate the CRC for this orig_node and store it */
 	orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
@@ -1979,22 +1979,22 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
 {
 	struct batadv_tt_roam_node *node, *safe;
 
-	spin_lock_bh(&bat_priv->tt_roam_list_lock);
+	spin_lock_bh(&bat_priv->tt.roam_list_lock);
 
-	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
 		list_del(&node->list);
 		kfree(node);
 	}
 
-	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 }
 
 static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
 {
 	struct batadv_tt_roam_node *node, *safe;
 
-	spin_lock_bh(&bat_priv->tt_roam_list_lock);
-	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+	spin_lock_bh(&bat_priv->tt.roam_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
 		if (!batadv_has_timed_out(node->first_time,
 					  BATADV_ROAMING_MAX_TIME))
 			continue;
@@ -2002,7 +2002,7 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
 		list_del(&node->list);
 		kfree(node);
 	}
-	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 }
 
 /* This function checks whether the client already reached the
@@ -2017,11 +2017,11 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
 	struct batadv_tt_roam_node *tt_roam_node;
 	bool ret = false;
 
-	spin_lock_bh(&bat_priv->tt_roam_list_lock);
+	spin_lock_bh(&bat_priv->tt.roam_list_lock);
 	/* The new tt_req will be issued only if I'm not waiting for a
 	 * reply from the same orig_node yet
 	 */
-	list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
+	list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
 		if (!batadv_compare_eth(tt_roam_node->addr, client))
 			continue;
 
@@ -2046,12 +2046,12 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
 			   BATADV_ROAMING_MAX_COUNT - 1);
 		memcpy(tt_roam_node->addr, client, ETH_ALEN);
 
-		list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
+		list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
 		ret = true;
 	}
 
 unlock:
-	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 	return ret;
 }
 
@@ -2115,10 +2115,12 @@ out:
 static void batadv_tt_purge(struct work_struct *work)
 {
 	struct delayed_work *delayed_work;
+	struct batadv_priv_tt *priv_tt;
 	struct batadv_priv *bat_priv;
 
 	delayed_work = container_of(work, struct delayed_work, work);
-	bat_priv = container_of(delayed_work, struct batadv_priv, tt_work);
+	priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
+	bat_priv = container_of(priv_tt, struct batadv_priv, tt);
 
 	batadv_tt_local_purge(bat_priv);
 	batadv_tt_global_roam_purge(bat_priv);
@@ -2130,7 +2132,7 @@ static void batadv_tt_purge(struct work_struct *work)
 
 void batadv_tt_free(struct batadv_priv *bat_priv)
 {
-	cancel_delayed_work_sync(&bat_priv->tt_work);
+	cancel_delayed_work_sync(&bat_priv->tt.work);
 
 	batadv_tt_local_table_free(bat_priv);
 	batadv_tt_global_table_free(bat_priv);
@@ -2138,7 +2140,7 @@ void batadv_tt_free(struct batadv_priv *bat_priv)
 	batadv_tt_changes_list_free(bat_priv);
 	batadv_tt_roam_list_free(bat_priv);
 
-	kfree(bat_priv->tt_buff);
+	kfree(bat_priv->tt.last_changeset);
 }
 
 /* This function will enable or disable the specified flags for all the entries
@@ -2182,7 +2184,7 @@ out:
 /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
 static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 {
-	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
+	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 	struct batadv_tt_common_entry *tt_common;
 	struct batadv_tt_local_entry *tt_local;
 	struct hlist_node *node, *node_tmp;
@@ -2207,7 +2209,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 				   "Deleting local tt entry (%pM): pending\n",
 				   tt_common->addr);
 
-			atomic_dec(&bat_priv->num_local_tt);
+			atomic_dec(&bat_priv->tt.local_entry_num);
 			hlist_del_rcu(node);
 			tt_local = container_of(tt_common,
 						struct batadv_tt_local_entry,
@@ -2225,26 +2227,26 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
 {
 	uint16_t changed_num = 0;
 
-	if (atomic_read(&bat_priv->tt_local_changes) < 1)
+	if (atomic_read(&bat_priv->tt.local_changes) < 1)
 		return -ENOENT;
 
-	changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash,
+	changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
 					  BATADV_TT_CLIENT_NEW, false);
 
 	/* all reset entries have to be counted as local entries */
-	atomic_add(changed_num, &bat_priv->num_local_tt);
+	atomic_add(changed_num, &bat_priv->tt.local_entry_num);
 	batadv_tt_local_purge_pending_clients(bat_priv);
-	bat_priv->tt_crc = batadv_tt_local_crc(bat_priv);
+	bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
 
 	/* Increment the TTVN only once per OGM interval */
-	atomic_inc(&bat_priv->ttvn);
+	atomic_inc(&bat_priv->tt.vn);
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Local changes committed, updating to ttvn %u\n",
-		   (uint8_t)atomic_read(&bat_priv->ttvn));
-	bat_priv->tt_poss_change = false;
+		   (uint8_t)atomic_read(&bat_priv->tt.vn));
+	bat_priv->tt.poss_change = false;
 
 	/* reset the sending counter */
-	atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
+	atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
 
 	return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
 					   packet_buff_len, packet_min_len);
@@ -2264,7 +2266,7 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
 
 	/* if the changes have been sent often enough */
 	if ((tt_num_changes < 0) &&
-	    (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
+	    (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
 		batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 					      packet_min_len, packet_min_len);
 		tt_num_changes = 0;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 664ef81..97c4978 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -165,6 +165,67 @@ enum batadv_counters {
 	BATADV_CNT_NUM,
 };
 
+/**
+ * struct batadv_priv_tt - per mesh interface translation table data
+ * @vn: translation table version number
+ * @local_changes: changes registered in an originator interval
+ * @poss_change: Detect an ongoing roaming phase. If true, then this node
+ *  received a roaming_adv and has to inspect every packet directed to it to
+ *  check whether it still is the true destination or not. This flag will be
+ *  reset to false as soon as the this node's ttvn is increased
+ * @changes_list: tracks tt local changes within an originator interval
+ * @req_list: list of pending tt_requests
+ * @local_crc: Checksum of the local table, recomputed before sending a new OGM
+ */
+struct batadv_priv_tt {
+	atomic_t vn;
+	atomic_t ogm_append_cnt;
+	atomic_t local_changes;
+	bool poss_change;
+	struct list_head changes_list;
+	struct batadv_hashtable *local_hash;
+	struct batadv_hashtable *global_hash;
+	struct list_head req_list;
+	struct list_head roam_list;
+	spinlock_t changes_list_lock; /* protects changes */
+	spinlock_t req_list_lock; /* protects req_list */
+	spinlock_t roam_list_lock; /* protects roam_list */
+	atomic_t local_entry_num;
+	uint16_t local_crc;
+	unsigned char *last_changeset;
+	int16_t last_changeset_len;
+	spinlock_t last_changeset_lock; /* protects last_changeset */
+	struct delayed_work work;
+};
+
+#ifdef CONFIG_BATMAN_ADV_BLA
+struct batadv_priv_bla {
+	atomic_t num_requests; /* number of bla requests in flight */
+	struct batadv_hashtable *claim_hash;
+	struct batadv_hashtable *backbone_hash;
+	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
+	int bcast_duplist_curr;
+	struct batadv_bla_claim_dst claim_dest;
+	struct delayed_work work;
+};
+#endif
+
+struct batadv_priv_gw {
+	struct hlist_head list;
+	spinlock_t list_lock; /* protects gw_list and curr_gw */
+	struct batadv_gw_node __rcu *curr_gw;  /* rcu protected pointer */
+	atomic_t reselect;
+};
+
+struct batadv_priv_vis {
+	struct list_head send_list;
+	struct batadv_hashtable *hash;
+	spinlock_t hash_lock; /* protects hash */
+	spinlock_t list_lock; /* protects info::recv_list */
+	struct delayed_work work;
+	struct batadv_vis_info *my_info;
+};
+
 struct batadv_priv {
 	atomic_t mesh_state;
 	struct net_device_stats stats;
@@ -184,64 +245,24 @@ struct batadv_priv {
 	atomic_t bcast_seqno;
 	atomic_t bcast_queue_left;
 	atomic_t batman_queue_left;
-	atomic_t ttvn; /* translation table version number */
-	atomic_t tt_ogm_append_cnt;
-	atomic_t tt_local_changes; /* changes registered in a OGM interval */
-	atomic_t bla_num_requests; /* number of bla requests in flight */
-	/* The tt_poss_change flag is used to detect an ongoing roaming phase.
-	 * If true, then I received a Roaming_adv and I have to inspect every
-	 * packet directed to me to check whether I am still the true
-	 * destination or not. This flag will be reset to false as soon as I
-	 * increase my TTVN
-	 */
-	bool tt_poss_change;
 	char num_ifaces;
 	struct batadv_debug_log *debug_log;
 	struct kobject *mesh_obj;
 	struct dentry *debug_dir;
 	struct hlist_head forw_bat_list;
 	struct hlist_head forw_bcast_list;
-	struct hlist_head gw_list;
-	struct list_head tt_changes_list; /* tracks changes in a OGM int */
-	struct list_head vis_send_list;
 	struct batadv_hashtable *orig_hash;
-	struct batadv_hashtable *tt_local_hash;
-	struct batadv_hashtable *tt_global_hash;
-#ifdef CONFIG_BATMAN_ADV_BLA
-	struct batadv_hashtable *claim_hash;
-	struct batadv_hashtable *backbone_hash;
-#endif
-	struct list_head tt_req_list; /* list of pending tt_requests */
-	struct list_head tt_roam_list;
-	struct batadv_hashtable *vis_hash;
-#ifdef CONFIG_BATMAN_ADV_BLA
-	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
-	int bcast_duplist_curr;
-	struct batadv_bla_claim_dst claim_dest;
-#endif
 	spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
 	spinlock_t forw_bcast_list_lock; /* protects  */
-	spinlock_t tt_changes_list_lock; /* protects tt_changes */
-	spinlock_t tt_req_list_lock; /* protects tt_req_list */
-	spinlock_t tt_roam_list_lock; /* protects tt_roam_list */
-	spinlock_t gw_list_lock; /* protects gw_list and curr_gw */
-	spinlock_t vis_hash_lock; /* protects vis_hash */
-	spinlock_t vis_list_lock; /* protects vis_info::recv_list */
-	atomic_t num_local_tt;
-	/* Checksum of the local table, recomputed before sending a new OGM */
-	uint16_t tt_crc;
-	unsigned char *tt_buff;
-	int16_t tt_buff_len;
-	spinlock_t tt_buff_lock; /* protects tt_buff */
-	struct delayed_work tt_work;
 	struct delayed_work orig_work;
-	struct delayed_work vis_work;
-	struct delayed_work bla_work;
-	struct batadv_gw_node __rcu *curr_gw;  /* rcu protected pointer */
-	atomic_t gw_reselect;
 	struct batadv_hard_iface __rcu *primary_if;  /* rcu protected pointer */
-	struct batadv_vis_info *my_vis_info;
 	struct batadv_algo_ops *bat_algo_ops;
+#ifdef CONFIG_BATMAN_ADV_BLA
+	struct batadv_priv_bla bla;
+#endif
+	struct batadv_priv_gw gw;
+	struct batadv_priv_tt tt;
+	struct batadv_priv_vis vis;
 };
 
 struct batadv_socket_client {
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 2a2ea06..4608c1b2 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -41,13 +41,13 @@ static void batadv_free_info(struct kref *ref)
 	bat_priv = info->bat_priv;
 
 	list_del_init(&info->send_list);
-	spin_lock_bh(&bat_priv->vis_list_lock);
+	spin_lock_bh(&bat_priv->vis.list_lock);
 	list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
 		list_del(&entry->list);
 		kfree(entry);
 	}
 
-	spin_unlock_bh(&bat_priv->vis_list_lock);
+	spin_unlock_bh(&bat_priv->vis.list_lock);
 	kfree_skb(info->skb_packet);
 	kfree(info);
 }
@@ -94,7 +94,7 @@ static uint32_t batadv_vis_info_choose(const void *data, uint32_t size)
 static struct batadv_vis_info *
 batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
 {
-	struct batadv_hashtable *hash = bat_priv->vis_hash;
+	struct batadv_hashtable *hash = bat_priv->vis.hash;
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
@@ -252,7 +252,7 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 	struct hlist_head *head;
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct batadv_priv *bat_priv = netdev_priv(net_dev);
-	struct batadv_hashtable *hash = bat_priv->vis_hash;
+	struct batadv_hashtable *hash = bat_priv->vis.hash;
 	uint32_t i;
 	int ret = 0;
 	int vis_server = atomic_read(&bat_priv->vis_mode);
@@ -264,12 +264,12 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 	if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
 		goto out;
 
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 		batadv_vis_seq_print_text_bucket(seq, head);
 	}
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 
 out:
 	if (primary_if)
@@ -285,7 +285,7 @@ static void batadv_send_list_add(struct batadv_priv *bat_priv,
 {
 	if (list_empty(&info->send_list)) {
 		kref_get(&info->refcount);
-		list_add_tail(&info->send_list, &bat_priv->vis_send_list);
+		list_add_tail(&info->send_list, &bat_priv->vis.send_list);
 	}
 }
 
@@ -311,9 +311,9 @@ static void batadv_recv_list_add(struct batadv_priv *bat_priv,
 		return;
 
 	memcpy(entry->mac, mac, ETH_ALEN);
-	spin_lock_bh(&bat_priv->vis_list_lock);
+	spin_lock_bh(&bat_priv->vis.list_lock);
 	list_add_tail(&entry->list, recv_list);
-	spin_unlock_bh(&bat_priv->vis_list_lock);
+	spin_unlock_bh(&bat_priv->vis.list_lock);
 }
 
 /* returns 1 if this mac is in the recv_list */
@@ -323,14 +323,14 @@ static int batadv_recv_list_is_in(struct batadv_priv *bat_priv,
 {
 	const struct batadv_recvlist_node *entry;
 
-	spin_lock_bh(&bat_priv->vis_list_lock);
+	spin_lock_bh(&bat_priv->vis.list_lock);
 	list_for_each_entry(entry, recv_list, list) {
 		if (batadv_compare_eth(entry->mac, mac)) {
-			spin_unlock_bh(&bat_priv->vis_list_lock);
+			spin_unlock_bh(&bat_priv->vis.list_lock);
 			return 1;
 		}
 	}
-	spin_unlock_bh(&bat_priv->vis_list_lock);
+	spin_unlock_bh(&bat_priv->vis.list_lock);
 	return 0;
 }
 
@@ -354,7 +354,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 
 	*is_new = 0;
 	/* sanity check */
-	if (!bat_priv->vis_hash)
+	if (!bat_priv->vis.hash)
 		return NULL;
 
 	/* see if the packet is already in vis_hash */
@@ -385,7 +385,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 			}
 		}
 		/* remove old entry */
-		batadv_hash_remove(bat_priv->vis_hash, batadv_vis_info_cmp,
+		batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp,
 				   batadv_vis_info_choose, old_info);
 		batadv_send_list_del(old_info);
 		kref_put(&old_info->refcount, batadv_free_info);
@@ -426,7 +426,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 	batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
 
 	/* try to add it */
-	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
+	hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
 				     batadv_vis_info_choose, info,
 				     &info->hash_entry);
 	if (hash_added != 0) {
@@ -449,7 +449,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
 
 	make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
 
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 				 &is_new, make_broadcast);
 	if (!info)
@@ -461,7 +461,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
 	if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
 		batadv_send_list_add(bat_priv, info);
 end:
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 }
 
 /* handle an incoming client update packet and schedule forward if needed. */
@@ -484,7 +484,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
 	    batadv_is_my_mac(vis_packet->target_orig))
 		are_target = 1;
 
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 				 &is_new, are_target);
 
@@ -505,7 +505,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
 	}
 
 end:
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 }
 
 /* Walk the originators and find the VIS server with the best tq. Set the packet
@@ -574,7 +574,7 @@ static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
 	struct hlist_head *head;
 	struct batadv_orig_node *orig_node;
 	struct batadv_neigh_node *router;
-	struct batadv_vis_info *info = bat_priv->my_vis_info;
+	struct batadv_vis_info *info = bat_priv->vis.my_info;
 	struct batadv_vis_packet *packet;
 	struct batadv_vis_info_entry *entry;
 	struct batadv_tt_common_entry *tt_common_entry;
@@ -636,7 +636,7 @@ next:
 		rcu_read_unlock();
 	}
 
-	hash = bat_priv->tt_local_hash;
+	hash = bat_priv->tt.local_hash;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -671,7 +671,7 @@ unlock:
 static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 {
 	uint32_t i;
-	struct batadv_hashtable *hash = bat_priv->vis_hash;
+	struct batadv_hashtable *hash = bat_priv->vis.hash;
 	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
 	struct batadv_vis_info *info;
@@ -682,7 +682,7 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 		hlist_for_each_entry_safe(info, node, node_tmp,
 					  head, hash_entry) {
 			/* never purge own data. */
-			if (info == bat_priv->my_vis_info)
+			if (info == bat_priv->vis.my_info)
 				continue;
 
 			if (batadv_has_timed_out(info->first_seen,
@@ -817,31 +817,33 @@ static void batadv_send_vis_packets(struct work_struct *work)
 	struct delayed_work *delayed_work =
 		container_of(work, struct delayed_work, work);
 	struct batadv_priv *bat_priv;
+	struct batadv_priv_vis *priv_vis;
 	struct batadv_vis_info *info;
 
-	bat_priv = container_of(delayed_work, struct batadv_priv, vis_work);
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	priv_vis = container_of(delayed_work, struct batadv_priv_vis, work);
+	bat_priv = container_of(priv_vis, struct batadv_priv, vis);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 	batadv_purge_vis_packets(bat_priv);
 
 	if (batadv_generate_vis_packet(bat_priv) == 0) {
 		/* schedule if generation was successful */
-		batadv_send_list_add(bat_priv, bat_priv->my_vis_info);
+		batadv_send_list_add(bat_priv, bat_priv->vis.my_info);
 	}
 
-	while (!list_empty(&bat_priv->vis_send_list)) {
-		info = list_first_entry(&bat_priv->vis_send_list,
+	while (!list_empty(&bat_priv->vis.send_list)) {
+		info = list_first_entry(&bat_priv->vis.send_list,
 					typeof(*info), send_list);
 
 		kref_get(&info->refcount);
-		spin_unlock_bh(&bat_priv->vis_hash_lock);
+		spin_unlock_bh(&bat_priv->vis.hash_lock);
 
 		batadv_send_vis_packet(bat_priv, info);
 
-		spin_lock_bh(&bat_priv->vis_hash_lock);
+		spin_lock_bh(&bat_priv->vis.hash_lock);
 		batadv_send_list_del(info);
 		kref_put(&info->refcount, batadv_free_info);
 	}
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 	batadv_start_vis_timer(bat_priv);
 }
 
@@ -856,37 +858,37 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
 	unsigned long first_seen;
 	struct sk_buff *tmp_skb;
 
-	if (bat_priv->vis_hash)
+	if (bat_priv->vis.hash)
 		return 0;
 
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 
-	bat_priv->vis_hash = batadv_hash_new(256);
-	if (!bat_priv->vis_hash) {
+	bat_priv->vis.hash = batadv_hash_new(256);
+	if (!bat_priv->vis.hash) {
 		pr_err("Can't initialize vis_hash\n");
 		goto err;
 	}
 
-	bat_priv->my_vis_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
-	if (!bat_priv->my_vis_info)
+	bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
+	if (!bat_priv->vis.my_info)
 		goto err;
 
 	len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
-	bat_priv->my_vis_info->skb_packet = dev_alloc_skb(len);
-	if (!bat_priv->my_vis_info->skb_packet)
+	bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
+	if (!bat_priv->vis.my_info->skb_packet)
 		goto free_info;
 
-	skb_reserve(bat_priv->my_vis_info->skb_packet, ETH_HLEN);
-	tmp_skb = bat_priv->my_vis_info->skb_packet;
+	skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
+	tmp_skb = bat_priv->vis.my_info->skb_packet;
 	packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
 
 	/* prefill the vis info */
 	first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
-	bat_priv->my_vis_info->first_seen = first_seen;
-	INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list);
-	INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list);
-	kref_init(&bat_priv->my_vis_info->refcount);
-	bat_priv->my_vis_info->bat_priv = bat_priv;
+	bat_priv->vis.my_info->first_seen = first_seen;
+	INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list);
+	INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list);
+	kref_init(&bat_priv->vis.my_info->refcount);
+	bat_priv->vis.my_info->bat_priv = bat_priv;
 	packet->header.version = BATADV_COMPAT_VERSION;
 	packet->header.packet_type = BATADV_VIS;
 	packet->header.ttl = BATADV_TTL;
@@ -894,28 +896,28 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
 	packet->reserved = 0;
 	packet->entries = 0;
 
-	INIT_LIST_HEAD(&bat_priv->vis_send_list);
+	INIT_LIST_HEAD(&bat_priv->vis.send_list);
 
-	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
+	hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
 				     batadv_vis_info_choose,
-				     bat_priv->my_vis_info,
-				     &bat_priv->my_vis_info->hash_entry);
+				     bat_priv->vis.my_info,
+				     &bat_priv->vis.my_info->hash_entry);
 	if (hash_added != 0) {
 		pr_err("Can't add own vis packet into hash\n");
 		/* not in hash, need to remove it manually. */
-		kref_put(&bat_priv->my_vis_info->refcount, batadv_free_info);
+		kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info);
 		goto err;
 	}
 
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 	batadv_start_vis_timer(bat_priv);
 	return 0;
 
 free_info:
-	kfree(bat_priv->my_vis_info);
-	bat_priv->my_vis_info = NULL;
+	kfree(bat_priv->vis.my_info);
+	bat_priv->vis.my_info = NULL;
 err:
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 	batadv_vis_quit(bat_priv);
 	return -ENOMEM;
 }
@@ -933,23 +935,23 @@ static void batadv_free_info_ref(struct hlist_node *node, void *arg)
 /* shutdown vis-server */
 void batadv_vis_quit(struct batadv_priv *bat_priv)
 {
-	if (!bat_priv->vis_hash)
+	if (!bat_priv->vis.hash)
 		return;
 
-	cancel_delayed_work_sync(&bat_priv->vis_work);
+	cancel_delayed_work_sync(&bat_priv->vis.work);
 
-	spin_lock_bh(&bat_priv->vis_hash_lock);
+	spin_lock_bh(&bat_priv->vis.hash_lock);
 	/* properly remove, kill timers ... */
-	batadv_hash_delete(bat_priv->vis_hash, batadv_free_info_ref, NULL);
-	bat_priv->vis_hash = NULL;
-	bat_priv->my_vis_info = NULL;
-	spin_unlock_bh(&bat_priv->vis_hash_lock);
+	batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL);
+	bat_priv->vis.hash = NULL;
+	bat_priv->vis.my_info = NULL;
+	spin_unlock_bh(&bat_priv->vis.hash_lock);
 }
 
 /* schedule packets for (re)transmission */
 static void batadv_start_vis_timer(struct batadv_priv *bat_priv)
 {
-	INIT_DELAYED_WORK(&bat_priv->vis_work, batadv_send_vis_packets);
-	queue_delayed_work(batadv_event_workqueue, &bat_priv->vis_work,
+	INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets);
+	queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
 			   msecs_to_jiffies(BATADV_VIS_INTERVAL));
 }
-- 
1.7.9.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox