This patch implements the de-aggregation and reception of
broadcast aggregation packets, which areintroduced through
the new BATADV_BCAST_AGGR packet type.

It enables us to receive aggregation packets consisting of any
batman packet type with a broadcast ethernet destination.

Signed-off-by: Linus Lüssing <linus.luess...@c0d3.blue>
---
 Makefile                        |   3 +
 gen-compat-autoconf.sh          |   1 +
 net/batman-adv/Makefile         |   1 +
 net/batman-adv/aggregation.c    | 177 ++++++++++++++++++++++++++++++++++++++++
 net/batman-adv/aggregation.h    |  51 ++++++++++++
 net/batman-adv/main.c           |   9 ++
 net/batman-adv/packet.h         |  18 ++++
 net/batman-adv/routing.c        |  61 ++++++++++++++
 net/batman-adv/routing.h        |   2 +
 net/batman-adv/soft-interface.c |   6 ++
 net/batman-adv/tvlv.c           |  13 ++-
 net/batman-adv/types.h          |  38 +++++++++
 12 files changed, 378 insertions(+), 2 deletions(-)
 create mode 100644 net/batman-adv/aggregation.c
 create mode 100644 net/batman-adv/aggregation.h

diff --git a/Makefile b/Makefile
index 1eb6821..6b9d565 100644
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,8 @@ export CONFIG_BATMAN_ADV_DAT=y
 export CONFIG_BATMAN_ADV_NC=n
 # B.A.T.M.A.N. multicast optimizations:
 export CONFIG_BATMAN_ADV_MCAST=y
+# B.A.T.M.A.N. generic broadcast aggregation:
+export CONFIG_BATMAN_ADV_AGGR=y
 # B.A.T.M.A.N. V routing algorithm (experimental):
 export CONFIG_BATMAN_ADV_BATMAN_V=n
 
@@ -83,6 +85,7 @@ BUILD_FLAGS := \
        CONFIG_BATMAN_ADV_DAT=$(CONFIG_BATMAN_ADV_DAT) \
        CONFIG_BATMAN_ADV_NC=$(CONFIG_BATMAN_ADV_NC) \
        CONFIG_BATMAN_ADV_MCAST=$(CONFIG_BATMAN_ADV_MCAST) \
+       CONFIG_BATMAN_ADV_AGGR=$(CONFIG_BATMAN_ADV_AGGR) \
        CONFIG_BATMAN_ADV_BATMAN_V=$(CONFIG_BATMAN_ADV_BATMAN_V) \
        INSTALL_MOD_DIR=updates/
 
diff --git a/gen-compat-autoconf.sh b/gen-compat-autoconf.sh
index cf36e55..c835a6d 100755
--- a/gen-compat-autoconf.sh
+++ b/gen-compat-autoconf.sh
@@ -41,6 +41,7 @@ gen_config 'CONFIG_BATMAN_ADV_DEBUG' 
${CONFIG_BATMAN_ADV_DEBUG:="n"} >> "${TMP}"
 gen_config 'CONFIG_BATMAN_ADV_BLA' ${CONFIG_BATMAN_ADV_BLA:="y"} >> "${TMP}"
 gen_config 'CONFIG_BATMAN_ADV_DAT' ${CONFIG_BATMAN_ADV_DAT:="y"} >> "${TMP}"
 gen_config 'CONFIG_BATMAN_ADV_MCAST' ${CONFIG_BATMAN_ADV_MCAST:="y"} >> 
"${TMP}"
+gen_config 'CONFIG_BATMAN_ADV_AGGR' ${CONFIG_BATMAN_ADV_AGGR:="y"} >> "${TMP}"
 gen_config 'CONFIG_BATMAN_ADV_NC' ${CONFIG_BATMAN_ADV_NC:="n"} >> "${TMP}"
 gen_config 'CONFIG_BATMAN_ADV_BATMAN_V' ${CONFIG_BATMAN_ADV_BATMAN_V:="n"} >> 
"${TMP}"
 
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 915987b..00f3e92 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -17,6 +17,7 @@
 #
 
 obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
+batman-adv-$(CONFIG_BATMAN_ADV_AGGR) += aggregation.o
 batman-adv-y += bat_algo.o
 batman-adv-y += bat_iv_ogm.o
 batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v.o
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
new file mode 100644
index 0000000..f8b40d1
--- /dev/null
+++ b/net/batman-adv/aggregation.c
@@ -0,0 +1,177 @@
+/* Copyright (C) 2016  B.A.T.M.A.N. contributors:
+ *
+ * Linus Lüssing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aggregation.h"
+#include "main.h"
+
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "tvlv.h"
+
+/**
+ * batadv_aggr_add_counter_rx - update aggregation rx statistics
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the skb to count
+ *
+ * Updates statistics for received aggregation packets with the given skb.
+ */
+void batadv_aggr_add_counter_rx(struct batadv_priv *bat_priv,
+                               struct sk_buff *skb)
+{
+       batadv_inc_counter(bat_priv, BATADV_CNT_AGGR_RX);
+       batadv_add_counter(bat_priv, BATADV_CNT_AGGR_RX_BYTES,
+                          skb->len + ETH_HLEN);
+}
+
+/**
+ * batadv_aggr_put_ethhdr - append a mac header to skb
+ * @skb: the packet to append to
+ * @h_source: the ethernet source address to set
+ *
+ * Appends a mac header to the given skb with the ethernet source address
+ * set to the provided h_source and the ethernet destination address to
+ * a broadcast one. Furthermore, sets the ethernet type to ETH_P_BATMAN.
+ *
+ * Also sets the skb mac header pointer to the beginning of the appended mac
+ * header.
+ */
+static void batadv_aggr_put_ethhdr(struct sk_buff *skb, unsigned char 
*h_source)
+{
+       struct ethhdr *ethhdr;
+
+       skb_reset_mac_header(skb);
+
+       ethhdr = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+       ethhdr->h_proto = htons(ETH_P_BATMAN);
+       ether_addr_copy(ethhdr->h_source, h_source);
+       ether_addr_copy(ethhdr->h_dest, batadv_broadcast_addr);
+}
+
+/**
+ * batadv_aggr_put_batadv - append batman header and data to skb
+ * @skb: the packet to append to
+ * @data: the data to append after the batman header
+ * @data_len: the length of the data to append
+ * @packet_type: the packet type to set in the batman header
+ *
+ * First appends a batman header consisting of the given packet type and the
+ * compatibility version to the given skb. Then copies the given data behind
+ * this minimal batman header in the skb.
+ *
+ * Also sets the skb network header pointer to the beginning of the batman
+ * header.
+ */
+static void batadv_aggr_put_batadv(struct sk_buff *skb, void *data,
+                                  u16 data_len, u8 packet_type)
+{
+       u8 version = BATADV_COMPAT_VERSION;
+       u8 *pos;
+
+       skb_reset_network_header(skb);
+       skb_reset_mac_len(skb);
+
+       pos = (u8 *)skb_put(skb, sizeof(packet_type));
+       *pos = packet_type;
+       pos = (u8 *)skb_put(skb, sizeof(version));
+       *pos = version;
+
+       pos = (u8 *)skb_put(skb, data_len);
+       memcpy(pos, data, data_len);
+}
+
+/**
+ * batadv_aggr_tvlv_handler - process incoming aggregation tvlv container
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tvlv_value: tvlv buffer containing an aggregated packet
+ * @tvlv_value_len: length of the aggregated packet
+ * @ctx: handler specific context information
+ *  (here: recv_if, h_source and packet type of aggregated packet)
+ *
+ * De-aggregates the given, specific broadcast packet and transparently
+ * forwards it for broadcast packet reception.
+ *
+ * Return: NET_RX_SUCCESS on success, NET_RX_DROP otherwise.
+ */
+static int batadv_aggr_tvlv_handler(struct batadv_priv *bat_priv,
+                                   void *tvlv_value, u16 tvlv_value_len,
+                                   void *ctx)
+{
+       struct batadv_aggr_ctx *aggr_ctx = ctx;
+       struct batadv_hard_iface *recv_if = aggr_ctx->recv_if;
+       struct sk_buff *skb;
+       unsigned int size;
+       u8 version = BATADV_COMPAT_VERSION;
+       u8 packet_type = aggr_ctx->handler.tvlv_type;
+
+       /* disallow aggr-in-aggr-in-... to avoid stack overflows */
+       if (packet_type == BATADV_BCAST_AGGR)
+               return NET_RX_DROP;
+
+       size = NET_IP_ALIGN + ETH_HLEN;
+       size += sizeof(packet_type) + sizeof(version);
+       size += tvlv_value_len;
+
+       skb = dev_alloc_skb(size);
+       if (!skb)
+               return NET_RX_DROP;
+
+       skb_reserve(skb, NET_IP_ALIGN);
+       batadv_aggr_put_ethhdr(skb, aggr_ctx->h_source);
+       skb_pull(skb, ETH_HLEN);
+       batadv_aggr_put_batadv(skb, tvlv_value, tvlv_value_len, packet_type);
+
+       skb->protocol = htons(ETH_P_BATMAN);
+       skb->dev = recv_if->net_dev;
+
+       batadv_inc_counter(bat_priv, BATADV_CNT_AGGR_PARTS_RX);
+       batadv_add_counter(bat_priv, BATADV_CNT_AGGR_PARTS_RX_BYTES,
+                          skb->len + ETH_HLEN);
+
+       return batadv_batman_skb_recv(skb, recv_if->net_dev,
+                                     &recv_if->batman_adv_ptype, NULL);
+}
+
+/**
+ * batadv_aggr_mesh_init - initialise the generic aggregation engine
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Return: 0 on success or a negative error code in case of failure
+ */
+int batadv_aggr_mesh_init(struct batadv_priv *bat_priv)
+{
+       batadv_tvlv_handler_register2(bat_priv, batadv_aggr_tvlv_handler,
+                                     BATADV_BCAST_AGGR, BATADV_TVLV_ANY, 1,
+                                     BATADV_TVLV_HANDLER_MORECTX);
+       batadv_tvlv_container_register(bat_priv, BATADV_TVLV_AGGR, 1, NULL, 0);
+
+       return 0;
+}
+
+/**
+ * batadv_mcast_free - shutdown the generic aggregation engine
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_aggr_mesh_free(struct batadv_priv *bat_priv)
+{
+       batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_AGGR, 1);
+       batadv_tvlv_handler_unregister2(bat_priv, BATADV_BCAST_AGGR,
+                                       BATADV_TVLV_ANY, 1);
+}
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
new file mode 100644
index 0000000..5b577e6
--- /dev/null
+++ b/net/batman-adv/aggregation.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2016  B.A.T.M.A.N. contributors:
+ *
+ * Linus Lüssing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
+#define _NET_BATMAN_ADV_AGGREGATION_H_
+
+#include "main.h"
+
+struct sk_buff;
+
+#ifdef CONFIG_BATMAN_ADV_AGGR
+
+void batadv_aggr_add_counter_rx(struct batadv_priv *bat_priv,
+                               struct sk_buff *skb);
+
+int batadv_aggr_mesh_init(struct batadv_priv *bat_priv);
+void batadv_aggr_mesh_free(struct batadv_priv *bat_priv);
+
+#else
+
+static inline void batadv_aggr_add_counter_rx(struct batadv_priv *bat_priv,
+                                             struct sk_buff *skb)
+{
+}
+
+static inline int batadv_aggr_mesh_init(struct batadv_priv *bat_priv)
+{
+       return 0;
+}
+
+static inline void batadv_aggr_mesh_free(struct batadv_priv *bat_priv)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_AGGR */
+
+#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 5efe40b..6ea29c5 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -47,6 +47,7 @@
 #include <net/rtnetlink.h>
 #include <uapi/linux/batman_adv.h>
 
+#include "aggregation.h"
 #include "bat_algo.h"
 #include "bat_iv_ogm.h"
 #include "bat_v.h"
@@ -180,6 +181,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
        INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
        INIT_HLIST_HEAD(&bat_priv->tp_list);
 
+       ret = batadv_aggr_mesh_init(bat_priv);
+       if (ret < 0)
+               goto err;
+
        ret = batadv_v_mesh_init(bat_priv);
        if (ret < 0)
                goto err;
@@ -227,6 +232,7 @@ void batadv_mesh_free(struct net_device *soft_iface)
 
        batadv_gw_node_free(bat_priv);
 
+       batadv_aggr_mesh_free(bat_priv);
        batadv_v_mesh_free(bat_priv);
        batadv_nc_mesh_free(bat_priv);
        batadv_dat_free(bat_priv);
@@ -508,6 +514,7 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10);
        BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18);
        BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20);
+       BUILD_BUG_ON(sizeof(struct batadv_aggr_packet) != 4);
        BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14);
        BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46);
        BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20);
@@ -531,6 +538,8 @@ static void batadv_recv_handler_init(void)
        batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
        /* Fragmented packets */
        batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_frag_packet;
+       /* Aggregation packets */
+       batadv_rx_handler[BATADV_BCAST_AGGR] = batadv_recv_aggr_packet;
 }
 
 int
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 4de324f..c2c20fd 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -31,6 +31,7 @@
  * @BATADV_CODED: network coded packets
  * @BATADV_ELP: echo location packets for B.A.T.M.A.N. V
  * @BATADV_OGM2: originator messages for B.A.T.M.A.N. V
+ * @BATADV_AGGR: broadcast aggregation packets
  *
  * @BATADV_UNICAST: unicast packets carrying unicast payload traffic
  * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
@@ -47,6 +48,7 @@ enum batadv_packettype {
        BATADV_CODED            = 0x02,
        BATADV_ELP              = 0x03,
        BATADV_OGM2             = 0x04,
+       BATADV_BCAST_AGGR       = 0x05,
        /* 0x40 - 0x7f: unicast */
 #define BATADV_UNICAST_MIN     0x40
        BATADV_UNICAST          = 0x40,
@@ -154,6 +156,8 @@ enum batadv_bla_claimframe {
  * @BATADV_TVLV_TT: translation table tvlv
  * @BATADV_TVLV_ROAM: roaming advertisement tvlv
  * @BATADV_TVLV_MCAST: multicast capability tvlv
+ * @BATADV_TVLV_AGGR: generic broadcast aggregation capability tvlv
+ * @BATADV_ANYTYPE: internal place holder for TVLV handlers, not for the "wire"
  */
 enum batadv_tvlv_type {
        BATADV_TVLV_GW          = 0x01,
@@ -162,6 +166,8 @@ enum batadv_tvlv_type {
        BATADV_TVLV_TT          = 0x04,
        BATADV_TVLV_ROAM        = 0x05,
        BATADV_TVLV_MCAST       = 0x06,
+       BATADV_TVLV_AGGR        = 0x07,
+       BATADV_TVLV_ANY         = 0xff,
 };
 
 /**
@@ -468,6 +474,18 @@ struct batadv_frag_packet {
 };
 
 /**
+ * struct batadv_aggr_packet - aggregation packet for broadcast packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @tvlv_len: length of tvlv data following the aggregation header
+ */
+struct batadv_aggr_packet {
+       u8     packet_type;
+       u8     version;  /* batman version field */
+       __be16 tvlv_len;
+};
+
+/**
  * struct batadv_bcast_packet - broadcast packet for network payload
  * @packet_type: batman-adv packet type, part of the general header
  * @version: batman-adv protocol version, part of the genereal header
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 7fd740b..b74779b 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -34,6 +34,7 @@
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
+#include "aggregation.h"
 #include "bitarray.h"
 #include "bridge_loop_avoidance.h"
 #include "distributed-arp-table.h"
@@ -1136,6 +1137,66 @@ free_skb:
        return ret;
 }
 
+/**
+ * batadv_recv_aggr_get_tvlv_len - get tvlv_len of an aggregation packet
+ * @skb: the aggregation packet to parse
+ *
+ * Return: Length of the tvlv data of the given skb on success,
+ * -EINVAL otherwise (i.e. packet is too short).
+ */
+static int batadv_recv_aggr_get_tvlv_len(struct sk_buff *skb)
+{
+       unsigned int tvlv_len_offset;
+       __be16 *tvlv_len, tvlv_len_buff;
+
+       tvlv_len_offset = offsetof(struct batadv_aggr_packet, tvlv_len);
+       tvlv_len = skb_header_pointer(skb, tvlv_len_offset,
+                                     sizeof(tvlv_len_buff), &tvlv_len_buff);
+
+       if (!tvlv_len)
+               return -EINVAL;
+
+       return ntohs(*tvlv_len);
+}
+
+/**
+ * batadv_recv_aggr_packet - process received aggregation packet
+ * @skb: the aggregation packet to process
+ * @recv_if: interface that the skb is received on
+ *
+ * This function de-aggregates broadcast packets from the given
+ * aggregation packet.
+ *
+ * Frees/consumes the provided skb.
+ *
+ * Return: NET_RX_SUCCESS on success, NET_RX_DROP otherwise.
+ */
+int batadv_recv_aggr_packet(struct sk_buff *skb,
+                           struct batadv_hard_iface *recv_if)
+{
+       struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+       struct batadv_aggr_ctx aggr_ctx;
+       unsigned int tvlv_offset = sizeof(struct batadv_aggr_packet);
+       int tvlv_len, ret;
+
+       aggr_ctx.recv_if = recv_if;
+       aggr_ctx.h_source = eth_hdr(skb)->h_source;
+       tvlv_len = batadv_recv_aggr_get_tvlv_len(skb);
+
+       if (tvlv_len < 0) {
+               kfree_skb(skb);
+               return NET_RX_DROP;
+       }
+
+       batadv_aggr_add_counter_rx(bat_priv, skb);
+
+       ret = batadv_tvlv_containers_process2(bat_priv, skb, BATADV_BCAST_AGGR,
+                                             tvlv_offset, tvlv_len, &aggr_ctx);
+
+       consume_skb(skb);
+       return ret;
+}
+
 int batadv_recv_bcast_packet(struct sk_buff *skb,
                             struct batadv_hard_iface *recv_if)
 {
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 5ede16c..7e9225a 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -37,6 +37,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
                               struct batadv_hard_iface *recv_if);
 int batadv_recv_frag_packet(struct sk_buff *skb,
                            struct batadv_hard_iface *iface);
+int batadv_recv_aggr_packet(struct sk_buff *skb,
+                           struct batadv_hard_iface *recv_if);
 int batadv_recv_bcast_packet(struct sk_buff *skb,
                             struct batadv_hard_iface *recv_if);
 int batadv_recv_tt_query(struct sk_buff *skb,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 5d099b2..1b0ef7e 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -1149,6 +1149,12 @@ static const struct {
        { "frag_rx_bytes" },
        { "frag_fwd" },
        { "frag_fwd_bytes" },
+#ifdef CONFIG_BATMAN_ADV_AGGR
+       { "aggr_rx" },
+       { "aggr_rx_bytes" },
+       { "aggr_parts_rx" },
+       { "aggr_parts_rx_bytes" },
+#endif
        { "tt_request_tx" },
        { "tt_request_rx" },
        { "tt_response_tx" },
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index 4259993..b505640 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -88,10 +88,12 @@ batadv_tvlv_handler_get(struct batadv_priv *bat_priv, int 
packet_type,
                if (tvlv_handler_tmp->packet_type != packet_type)
                        continue;
 
-               if (tvlv_handler_tmp->tvlv_type != tvlv_type)
+               if (tvlv_handler_tmp->tvlv_type != BATADV_TVLV_ANY &&
+                   tvlv_handler_tmp->tvlv_type != tvlv_type)
                        continue;
 
-               if (tvlv_handler_tmp->tvlv_version != tvlv_version)
+               if (tvlv_handler_tmp->tvlv_type != BATADV_TVLV_ANY &&
+                   tvlv_handler_tmp->tvlv_version != tvlv_version)
                        continue;
 
                if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount))
@@ -431,6 +433,7 @@ static int batadv_tvlv_call_handler2(struct batadv_priv 
*bat_priv,
                                     u8 tvlv_version, void *tvlv_value,
                                     u16 tvlv_value_len, void *ctx)
 {
+       struct batadv_tvlv_handler_ctx *handler_ctx;
        struct batadv_tvlv_handler *tvlv_handler;
        int ret;
 
@@ -439,6 +442,12 @@ static int batadv_tvlv_call_handler2(struct batadv_priv 
*bat_priv,
        if (!tvlv_handler)
                return NET_RX_DROP;
 
+       if (tvlv_handler->flags & BATADV_TVLV_HANDLER_MORECTX) {
+               handler_ctx = (struct batadv_tvlv_handler_ctx *)ctx;
+               handler_ctx->tvlv_type = tvlv_type;
+               handler_ctx->tvlv_version = tvlv_version;
+       }
+
        ret = tvlv_handler->handler(bat_priv, tvlv_value, tvlv_value_len, ctx);
        tvlv_handler->flags |= BATADV_TVLV_HANDLER_CALLED;
 
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index d189860..0e25f01 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -575,6 +575,10 @@ struct batadv_bcast_duplist_entry {
  * @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter
  * @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter
  * @BATADV_CNT_FRAG_FWD_BYTES: forwarded fragment traffic bytes counter
+ * @BATADV_CNT_AGGR_RX: received aggregation traffic packet count
+ * @BATADV_CNT_AGGR_RX_BYTES: received aggregation traffic bytes counter
+ * @BATADV_CNT_AGGR_PARTS_RX: received aggregated traffic packet counter
+ * @BATADV_CNT_AGGR_PARTS_RX_BYTES: received aggregated bytes counter
  * @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter
  * @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter
  * @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter
@@ -618,6 +622,12 @@ enum batadv_counters {
        BATADV_CNT_FRAG_RX_BYTES,
        BATADV_CNT_FRAG_FWD,
        BATADV_CNT_FRAG_FWD_BYTES,
+#ifdef CONFIG_BATMAN_ADV_AGGR
+       BATADV_CNT_AGGR_RX,
+       BATADV_CNT_AGGR_RX_BYTES,
+       BATADV_CNT_AGGR_PARTS_RX,
+       BATADV_CNT_AGGR_PARTS_RX_BYTES,
+#endif
        BATADV_CNT_TT_REQUEST_TX,
        BATADV_CNT_TT_REQUEST_RX,
        BATADV_CNT_TT_RESPONSE_TX,
@@ -1648,16 +1658,44 @@ struct batadv_tvlv_handler {
 };
 
 /**
+ * struct batadv_tvlv_handler_ctx - handler meta information
+ * @tvlv_type: type of the processed tvlv
+ * @tvlv_version: version of the processed tvlv
+ *
+ * This structure is provided to a tvlv handler if the
+ * BATADV_TVLV_HANDLER_MORECTX flag was set during registration.
+ */
+struct batadv_tvlv_handler_ctx {
+       u8 tvlv_type;
+       u8 tvlv_version;
+};
+
+/**
+ * struct batadv_aggr_ctx - aggregation tvlv context
+ * @handler: information regarding the tvlv handler itself
+ * @recv_if: interface the packet was received from
+ * @h_source: ethernet address of the neighbor the packet was received from
+ */
+struct batadv_aggr_ctx {
+       struct batadv_tvlv_handler_ctx handler;
+       struct batadv_hard_iface *recv_if;
+       unsigned char *h_source;
+};
+
+/**
  * enum batadv_tvlv_handler_flags - tvlv handler flags definitions
  * @BATADV_TVLV_HANDLER_CIFNOTFND: tvlv processing function will call
  *  this handler even if its type was not found (with no data)
  * @BATADV_TVLV_HANDLER_CALLED: internal tvlv handling flag - the API marks
  *  a handler as being called, so it won't be called if the
  *  BATADV_TVLV_HANDLER_CIFNOTFND flag was set
+ * @BATADV_TVLV_HANDLER_MORECTX: tvlv processing function will be provided with
+ *  handler specific context (e.g. tvlv type and version)
  */
 enum batadv_tvlv_handler_flags {
        BATADV_TVLV_HANDLER_CIFNOTFND = BIT(1),
        BATADV_TVLV_HANDLER_CALLED = BIT(2),
+       BATADV_TVLV_HANDLER_MORECTX = BIT(3),
 };
 
 /**
-- 
2.1.4

Reply via email to