Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
authorDavid S. Miller <davem@davemloft.net>
Wed, 21 Nov 2012 20:30:36 +0000 (15:30 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 21 Nov 2012 20:30:36 +0000 (15:30 -0500)
Included changes:
- Increase batman-adv version
- Bridge Loop Avoidance: compute checksum (using crc32) on skb fragments instead
  of linearising it
- sort the sysfs documentation
- some other minor cleanups

Signed-off-by: David S. Miller <davem@davemloft.net>
16 files changed:
Documentation/ABI/testing/sysfs-class-net-batman-adv
Documentation/ABI/testing/sysfs-class-net-mesh
net/batman-adv/Kconfig
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/debugfs.c
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/send.h
net/batman-adv/translation-table.c
net/batman-adv/types.h
net/batman-adv/unicast.c
net/batman-adv/vis.c

index 38dd762def4b8fda48daf66800b93ce2666bd01d..bdc00707c751b955d997aa7ce0c51bd8b0222ca5 100644 (file)
@@ -1,4 +1,10 @@
 
+What:           /sys/class/net/<iface>/batman-adv/iface_status
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Indicates the status of <iface> as it is seen by batman.
+
 What:           /sys/class/net/<iface>/batman-adv/mesh_iface
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -7,8 +13,3 @@ Description:
                 displays the batman mesh interface this <iface>
                 currently is associated with.
 
-What:           /sys/class/net/<iface>/batman-adv/iface_status
-Date:           May 2010
-Contact:        Marek Lindner <lindner_marek@yahoo.de>
-Description:
-                Indicates the status of <iface> as it is seen by batman.
index c81fe89c4c46d4f48e7e3bc8954d587bb9e6d69d..bc41da61608d5dfc22e0c2836aa00c56499c9d98 100644 (file)
@@ -6,6 +6,14 @@ Description:
                 Indicates whether the batman protocol messages of the
                 mesh <mesh_iface> shall be aggregated or not.
 
+What:           /sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:           May 2011
+Contact:        Antonio Quartulli <ordex@autistici.org>
+Description:
+                Indicates whether the data traffic going from a
+                wireless client to another wireless client will be
+                silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/bonding
 Date:           June 2010
 Contact:        Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
@@ -31,14 +39,6 @@ Description:
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
-What:          /sys/class/net/<mesh_iface>/mesh/ap_isolation
-Date:          May 2011
-Contact:       Antonio Quartulli <ordex@autistici.org>
-Description:
-               Indicates whether the data traffic going from a
-               wireless client to another wireless client will be
-               silently dropped.
-
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -60,6 +60,13 @@ Description:
                 Defines the selection criteria this node will use
                 to choose a gateway if gw_mode was set to 'client'.
 
+What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
+Date:           Oct 2010
+Contact:        Linus Lüssing <linus.luessing@web.de>
+Description:
+                Defines the penalty which will be applied to an
+                originator message's tq-field on every hop.
+
 What:           /sys/class/net/<mesh_iface>/mesh/orig_interval
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -67,19 +74,12 @@ Description:
                 Defines the interval in milliseconds in which batman
                 sends its protocol messages.
 
-What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
-Date:           Oct 2010
-Contact:        Linus Lüssing <linus.luessing@web.de>
-Description:
-               Defines the penalty which will be applied to an
-               originator message's tq-field on every hop.
-
-What:          /sys/class/net/<mesh_iface>/mesh/routing_algo
-Date:          Dec 2011
-Contact:       Marek Lindner <lindner_marek@yahoo.de>
+What:           /sys/class/net/<mesh_iface>/mesh/routing_algo
+Date:           Dec 2011
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
 Description:
-               Defines the routing procotol this mesh instance
-               uses to find the optimal paths through the mesh.
+                Defines the routing procotol this mesh instance
+                uses to find the optimal paths through the mesh.
 
 What:           /sys/class/net/<mesh_iface>/mesh/vis_mode
 Date:           May 2010
index 250e0b58109c70544e0599140a9ad72a2f15b719..8d8afb134b3ac016799be9ab43d6fe45f40962bb 100644 (file)
@@ -6,6 +6,7 @@ config BATMAN_ADV
        tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
        depends on NET
        select CRC16
+       select LIBCRC32C
         default n
        help
           B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
index bda8b1710806eef8493956748674a2e0e8ce7a3b..5aebe9327d68c8fd691243f78880c12d69951611 100644 (file)
@@ -77,8 +77,15 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
 {
        const void *data1 = container_of(node, struct batadv_backbone_gw,
                                         hash_entry);
+       const struct batadv_backbone_gw *gw1 = data1, *gw2 = data2;
 
-       return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+       if (!batadv_compare_eth(gw1->orig, gw2->orig))
+               return 0;
+
+       if (gw1->vid != gw2->vid)
+               return 0;
+
+       return 1;
 }
 
 /* compares address and vid of two claims */
@@ -87,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node,
 {
        const void *data1 = container_of(node, struct batadv_claim,
                                         hash_entry);
+       const struct batadv_claim *cl1 = data1, *cl2 = data2;
 
-       return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+       if (!batadv_compare_eth(cl1->addr, cl2->addr))
+               return 0;
+
+       if (cl1->vid != cl2->vid)
+               return 0;
+
+       return 1;
 }
 
 /* free a backbone gw */
@@ -1235,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: encapsulated broadcast frame plus batman header
- * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
+ * @skb: contains the bcast_packet to be checked
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1248,20 +1261,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  * the same host however as this might be intended.
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                                  struct batadv_bcast_packet *bcast_packet,
-                                  int bcast_packet_len)
+                                  struct sk_buff *skb)
 {
-       int i, length, curr, ret = 0;
-       uint8_t *content;
-       uint16_t crc;
+       int i, curr, ret = 0;
+       __be32 crc;
+       struct batadv_bcast_packet *bcast_packet;
        struct batadv_bcast_duplist_entry *entry;
 
-       length = bcast_packet_len - sizeof(*bcast_packet);
-       content = (uint8_t *)bcast_packet;
-       content += sizeof(*bcast_packet);
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
 
        /* calculate the crc ... */
-       crc = crc16(0, content, length);
+       crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
 
        spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
 
index 789cb73bde67acf8f19375d67e8c0ec2322f509f..196d9a0254bcbc6820c5f60f3c53a63638b683c9 100644 (file)
@@ -31,8 +31,7 @@ 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,
-                                  int hdr_size);
+                                  struct sk_buff *skb);
 void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
                                    struct batadv_hard_iface *primary_if,
                                    struct batadv_hard_iface *oldif);
@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 
 static inline int
 batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                              struct batadv_bcast_packet *bcast_packet,
-                              int hdr_size)
+                              struct sk_buff *skb)
 {
        return 0;
 }
index 3f679cb2d0e275de8cd62e050753d21677ece4c1..6f58ddd53bff8d2752c7a59dda1c20e40ec428e0 100644 (file)
@@ -323,7 +323,17 @@ struct batadv_debuginfo batadv_debuginfo_##_name = {       \
                }                                       \
 };
 
+/* the following attributes are general and therefore they will be directly
+ * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
+ */
 static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+
+static struct batadv_debuginfo *batadv_general_debuginfos[] = {
+       &batadv_debuginfo_routing_algos,
+       NULL,
+};
+
+/* The following attributes are per soft interface */
 static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
 static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
 static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
@@ -358,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 
 void batadv_debugfs_init(void)
 {
-       struct batadv_debuginfo *bat_debug;
+       struct batadv_debuginfo **bat_debug;
        struct dentry *file;
 
        batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
@@ -366,17 +376,23 @@ void batadv_debugfs_init(void)
                batadv_debugfs = NULL;
 
        if (!batadv_debugfs)
-               goto out;
+               goto err;
 
-       bat_debug = &batadv_debuginfo_routing_algos;
-       file = debugfs_create_file(bat_debug->attr.name,
-                                  S_IFREG | bat_debug->attr.mode,
-                                  batadv_debugfs, NULL, &bat_debug->fops);
-       if (!file)
-               pr_err("Can't add debugfs file: %s\n", bat_debug->attr.name);
+       for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
+               file = debugfs_create_file(((*bat_debug)->attr).name,
+                                          S_IFREG | ((*bat_debug)->attr).mode,
+                                          batadv_debugfs, NULL,
+                                          &(*bat_debug)->fops);
+               if (!file) {
+                       pr_err("Can't add general debugfs file: %s\n",
+                              ((*bat_debug)->attr).name);
+                       goto err;
+               }
+       }
 
-out:
        return;
+err:
+       debugfs_remove_recursive(batadv_debugfs);
 }
 
 void batadv_debugfs_destroy(void)
index dc33a0c484a4e180f99468f4dec8c2ac2c2d07b6..f65a222b7b83c0d691f859f2eef1ea189ac84e2c 100644 (file)
@@ -17,6 +17,8 @@
  * 02110-1301, USA
  */
 
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
 #include "main.h"
 #include "sysfs.h"
 #include "debugfs.h"
@@ -420,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
        return 0;
 }
 
+/**
+ * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
+ *  the header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to an address in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
+{
+       u32 crc = 0;
+       unsigned int from;
+       unsigned int to = skb->len;
+       struct skb_seq_state st;
+       const u8 *data;
+       unsigned int len;
+       unsigned int consumed = 0;
+
+       from = (unsigned int)(payload_ptr - skb->data);
+
+       skb_prepare_seq_read(skb, from, to, &st);
+       while ((len = skb_seq_read(consumed, &data, &st)) != 0) {
+               crc = crc32c(crc, data, len);
+               consumed += len;
+       }
+       skb_abort_seq_read(&st);
+
+       return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
        struct batadv_algo_ops *bat_algo_ops;
index 8f149bb66817231906029bcb527d73e840da599e..2f85577086a7cf923c6185f84f6efeb3bfb5fe84 100644 (file)
@@ -26,7 +26,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2012.4.0"
+#define BATADV_SOURCE_VERSION "2012.5.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -174,6 +174,7 @@ void batadv_recv_handler_unregister(uint8_t packet_type);
 int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
 
 /**
  * enum batadv_dbg_level - available log levels
index df548ed196d37e5f5e325cd0becfd4818f876b23..1c5454d33f67425c69636160c5bf1182608c75e9 100644 (file)
@@ -173,6 +173,18 @@ struct batadv_icmp_packet_rr {
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
 };
 
+/* All packet headers in front of an ethernet header have to be completely
+ * divisible by 2 but not by 4 to make the payload after the ethernet
+ * header again 4 bytes boundary aligned.
+ *
+ * A packing of 2 is necessary to avoid extra padding at the end of the struct
+ * caused by a structure member which is larger than two bytes. Otherwise
+ * the structure would not fulfill the previously mentioned rule to avoid the
+ * misalignment of the payload after the ethernet header. It may also lead to
+ * leakage of information when the padding it not initialized before sending.
+ */
+#pragma pack(2)
+
 struct batadv_unicast_packet {
        struct batadv_header header;
        uint8_t  ttvn; /* destination translation table version number */
@@ -216,7 +228,9 @@ struct batadv_bcast_packet {
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
         * following ethernet header again 4 bytes boundary aligned
         */
-} __packed;
+};
+
+#pragma pack()
 
 struct batadv_vis_packet {
        struct batadv_header header;
index 78d657264cbfe6227a5b2a2f2c0096a0b4aff55d..1aa1722d01870d69738f6be60a7e7868882cab88 100644 (file)
@@ -285,7 +285,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 {
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        struct batadv_icmp_packet_rr *icmp_packet;
        int ret = NET_RX_DROP;
 
@@ -307,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -322,14 +317,12 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_ECHO_REPLY;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -340,7 +333,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 {
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        struct batadv_icmp_packet *icmp_packet;
        int ret = NET_RX_DROP;
 
@@ -362,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -377,14 +365,12 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -398,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        struct batadv_icmp_packet_rr *icmp_packet;
        struct ethhdr *ethhdr;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        int hdr_size = sizeof(struct batadv_icmp_packet);
        int ret = NET_RX_DROP;
 
@@ -447,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -461,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmp_packet->header.ttl--;
 
        /* route it */
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+               ret = NET_RX_SUCCESS;
 
 out:
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -882,8 +861,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
                           skb->len + ETH_HLEN);
 
        /* route it */
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (neigh_node)
@@ -1217,14 +1196,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
-       /* keep skb linear for crc calculation */
-       if (skb_linearize(skb) < 0)
-               goto out;
-
-       bcast_packet = (struct batadv_bcast_packet *)skb->data;
-
        /* check whether this has been sent by another originator before */
-       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
+       if (batadv_bla_check_bcast_duplist(bat_priv, skb))
                goto out;
 
        /* rebroadcast packet */
index 660d9bf7d219ee3714585059dfe29ddeecdf7301..c7f702376535c32d9de6a01c1e58300668043336 100644 (file)
@@ -78,6 +78,39 @@ send_skb_err:
        return NET_XMIT_DROP;
 }
 
+/**
+ * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
+ * @skb: Packet to be transmitted.
+ * @orig_node: Final destination of the packet.
+ * @recv_if: Interface used when receiving the packet (can be NULL).
+ *
+ * Looks up the best next-hop towards the passed originator and passes the
+ * skb on for preparation of MAC header. If the packet originated from this
+ * host, NULL can be passed as recv_if and no interface alternating is
+ * attempted.
+ *
+ * Returns TRUE on success; FALSE otherwise.
+ */
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+                            struct batadv_orig_node *orig_node,
+                            struct batadv_hard_iface *recv_if)
+{
+       struct batadv_priv *bat_priv = orig_node->bat_priv;
+       struct batadv_neigh_node *neigh_node;
+
+       /* batadv_find_router() increases neigh_nodes refcount if found. */
+       neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
+       if (!neigh_node)
+               return false;
+
+       /* route it */
+       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+
+       batadv_neigh_node_free_ref(neigh_node);
+
+       return true;
+}
+
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
index 643329b787ed125102beb687ad1f18c1b4a0ca8e..0078dece1abcd4cf6784b59cf5441ac150424330 100644 (file)
@@ -23,6 +23,9 @@
 int batadv_send_skb_packet(struct sk_buff *skb,
                           struct batadv_hard_iface *hard_iface,
                           const uint8_t *dst_addr);
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+                            struct batadv_orig_node *orig_node,
+                            struct batadv_hard_iface *recv_if);
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
 int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
                                    const struct sk_buff *skb,
index 582f13405df9286bc752b633ed61a3b9244d545f..22457a7952baae3fc85c3ce43bd14bbeb5acf068 100644 (file)
@@ -911,8 +911,44 @@ out:
        return ret;
 }
 
-/* print all orig nodes who announce the address for this global entry.
- * it is assumed that the caller holds rcu_read_lock();
+/* batadv_transtable_best_orig - Get best originator list entry from tt entry
+ * @tt_global_entry: global translation table entry to be analyzed
+ *
+ * This functon assumes the caller holds rcu_read_lock().
+ * Returns best originator list entry or NULL on errors.
+ */
+static struct batadv_tt_orig_list_entry *
+batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
+{
+       struct batadv_neigh_node *router = NULL;
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
+       int best_tq = 0;
+
+       head = &tt_global_entry->orig_list;
+       hlist_for_each_entry_rcu(orig_entry, node, head, list) {
+               router = batadv_orig_node_get_router(orig_entry->orig_node);
+               if (!router)
+                       continue;
+
+               if (router->tq_avg > best_tq) {
+                       best_entry = orig_entry;
+                       best_tq = router->tq_avg;
+               }
+
+               batadv_neigh_node_free_ref(router);
+       }
+
+       return best_entry;
+}
+
+/* batadv_tt_global_print_entry - print all orig nodes who announce the address
+ * for this global entry
+ * @tt_global_entry: global translation table entry to be printed
+ * @seq: debugfs table seq_file struct
+ *
+ * This functon assumes the caller holds rcu_read_lock().
  */
 static void
 batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
@@ -920,21 +956,37 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
 {
        struct hlist_head *head;
        struct hlist_node *node;
-       struct batadv_tt_orig_list_entry *orig_entry;
+       struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
        struct batadv_tt_common_entry *tt_common_entry;
        uint16_t flags;
        uint8_t last_ttvn;
 
        tt_common_entry = &tt_global_entry->common;
+       flags = tt_common_entry->flags;
+
+       best_entry = batadv_transtable_best_orig(tt_global_entry);
+       if (best_entry) {
+               last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
+               seq_printf(seq, " %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+                          '*', tt_global_entry->common.addr,
+                          best_entry->ttvn, best_entry->orig_node->orig,
+                          last_ttvn,
+                          (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
+                          (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+                          (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
+       }
 
        head = &tt_global_entry->orig_list;
 
        hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-               flags = tt_common_entry->flags;
+               if (best_entry == orig_entry)
+                       continue;
+
                last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
-               seq_printf(seq, " * %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
-                          tt_global_entry->common.addr, orig_entry->ttvn,
-                          orig_entry->orig_node->orig, last_ttvn,
+               seq_printf(seq, " %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+                          '+', tt_global_entry->common.addr,
+                          orig_entry->ttvn, orig_entry->orig_node->orig,
+                          last_ttvn,
                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
@@ -1280,11 +1332,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
        struct batadv_tt_local_entry *tt_local_entry = NULL;
        struct batadv_tt_global_entry *tt_global_entry = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct batadv_tt_orig_list_entry *orig_entry;
-       int best_tq;
+       struct batadv_tt_orig_list_entry *best_entry;
 
        if (src && atomic_read(&bat_priv->ap_isolation)) {
                tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
@@ -1304,25 +1352,15 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
            _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
                goto out;
 
-       best_tq = 0;
-
        rcu_read_lock();
-       head = &tt_global_entry->orig_list;
-       hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-               router = batadv_orig_node_get_router(orig_entry->orig_node);
-               if (!router)
-                       continue;
-
-               if (router->tq_avg > best_tq) {
-                       orig_node = orig_entry->orig_node;
-                       best_tq = router->tq_avg;
-               }
-               batadv_neigh_node_free_ref(router);
-       }
+       best_entry = batadv_transtable_best_orig(tt_global_entry);
        /* found anything? */
+       if (best_entry)
+               orig_node = best_entry->orig_node;
        if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
                orig_node = NULL;
        rcu_read_unlock();
+
 out:
        if (tt_global_entry)
                batadv_tt_global_entry_free_ref(tt_global_entry);
@@ -1604,7 +1642,6 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 {
        struct sk_buff *skb = NULL;
        struct batadv_tt_query_packet *tt_request;
-       struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_hard_iface *primary_if;
        struct batadv_tt_req_node *tt_req_node = NULL;
        int ret = 1;
@@ -1642,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
        if (full_table)
                tt_request->flags |= BATADV_TT_FULL_TABLE;
 
-       neigh_node = batadv_orig_node_get_router(dst_orig_node);
-       if (!neigh_node)
-               goto out;
-
-       batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_REQUEST to %pM via %pM [%c]\n",
-                  dst_orig_node->orig, neigh_node->addr,
-                  (full_table ? 'F' : '.'));
+       batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
+                  dst_orig_node->orig, (full_table ? 'F' : '.'));
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
+       if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
+               ret = 0;
 
 out:
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (ret)
@@ -1678,7 +1707,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 {
        struct batadv_orig_node *req_dst_orig_node;
        struct batadv_orig_node *res_dst_orig_node = NULL;
-       struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_hard_iface *primary_if = NULL;
        uint8_t orig_ttvn, req_ttvn, ttvn;
        int ret = false;
@@ -1704,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
        if (!res_dst_orig_node)
                goto out;
 
-       neigh_node = batadv_orig_node_get_router(res_dst_orig_node);
-       if (!neigh_node)
-               goto out;
-
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if)
                goto out;
@@ -1779,14 +1803,13 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
                tt_response->flags |= BATADV_TT_FULL_TABLE;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
-                  res_dst_orig_node->orig, neigh_node->addr,
-                  req_dst_orig_node->orig, req_ttvn);
+                  "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
+                  res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = true;
+       if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
+               ret = true;
        goto out;
 
 unlock:
@@ -1797,8 +1820,6 @@ out:
                batadv_orig_node_free_ref(res_dst_orig_node);
        if (req_dst_orig_node)
                batadv_orig_node_free_ref(req_dst_orig_node);
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (!ret)
@@ -1812,7 +1833,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                           struct batadv_tt_query_packet *tt_request)
 {
        struct batadv_orig_node *orig_node;
-       struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_hard_iface *primary_if = NULL;
        uint8_t my_ttvn, req_ttvn, ttvn;
        int ret = false;
@@ -1837,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       neigh_node = batadv_orig_node_get_router(orig_node);
-       if (!neigh_node)
-               goto out;
-
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if)
                goto out;
@@ -1904,14 +1920,14 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                tt_response->flags |= BATADV_TT_FULL_TABLE;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_RESPONSE to %pM via %pM [%c]\n",
-                  orig_node->orig, neigh_node->addr,
+                  "Sending TT_RESPONSE to %pM [%c]\n",
+                  orig_node->orig,
                   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = true;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = true;
        goto out;
 
 unlock:
@@ -1919,8 +1935,6 @@ unlock:
 out:
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (!ret)
@@ -2185,7 +2199,6 @@ unlock:
 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
                                 struct batadv_orig_node *orig_node)
 {
-       struct batadv_neigh_node *neigh_node = NULL;
        struct sk_buff *skb = NULL;
        struct batadv_roam_adv_packet *roam_adv_packet;
        int ret = 1;
@@ -2218,23 +2231,17 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
        memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
        memcpy(roam_adv_packet->client, client, ETH_ALEN);
 
-       neigh_node = batadv_orig_node_get_router(orig_node);
-       if (!neigh_node)
-               goto out;
-
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
-                  orig_node->orig, client, neigh_node->addr);
+                  "Sending ROAMING_ADV to %pM (client %pM)\n",
+                  orig_node->orig, client);
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = 0;
 
 out:
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
-       if (ret)
+       if (ret && skb)
                kfree_skb(skb);
        return;
 }
index 7b3d0d7ef06a779f31614371346a2632746b0ae1..ae9ac9aca8c53d5ffd93b015cb6ff779f55c86fe 100644 (file)
@@ -156,7 +156,7 @@ struct batadv_neigh_node {
 #ifdef CONFIG_BATMAN_ADV_BLA
 struct batadv_bcast_duplist_entry {
        uint8_t orig[ETH_ALEN];
-       uint16_t crc;
+       __be32 crc;
        unsigned long entrytime;
 };
 #endif
index c9a1f6523c36e10b93977299f77b4542bcdd3347..10aff49fcf25adb106cefb020309e456d8f04a2f 100644 (file)
@@ -402,7 +402,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
        struct batadv_orig_node *orig_node;
        struct batadv_neigh_node *neigh_node;
        int data_len = skb->len;
-       int ret = 1;
+       int ret = NET_RX_DROP;
        unsigned int dev_mtu;
 
        /* get routing information */
@@ -466,15 +466,15 @@ find_router:
                goto out;
        }
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = 0;
 
 out:
        if (neigh_node)
                batadv_neigh_node_free_ref(neigh_node);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
-       if (ret == 1)
+       if (ret == NET_RX_DROP)
                kfree_skb(skb);
        return ret;
 }
index ad14a6c91d6ad362be83fb749acefd84a9351a5e..0f65a9de5f749719b9b778cd8c989680b0b1eb4d 100644 (file)
@@ -698,15 +698,12 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
                                        struct batadv_vis_info *info)
 {
-       struct batadv_neigh_node *router;
        struct batadv_hashtable *hash = bat_priv->orig_hash;
        struct hlist_node *node;
        struct hlist_head *head;
        struct batadv_orig_node *orig_node;
        struct batadv_vis_packet *packet;
        struct sk_buff *skb;
-       struct batadv_hard_iface *hard_iface;
-       uint8_t dstaddr[ETH_ALEN];
        uint32_t i;
 
 
@@ -722,30 +719,20 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
                        if (!(orig_node->flags & BATADV_VIS_SERVER))
                                continue;
 
-                       router = batadv_orig_node_get_router(orig_node);
-                       if (!router)
-                               continue;
-
                        /* don't send it if we already received the packet from
                         * this node.
                         */
                        if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
-                                                  orig_node->orig)) {
-                               batadv_neigh_node_free_ref(router);
+                                                  orig_node->orig))
                                continue;
-                       }
 
                        memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
-                       hard_iface = router->if_incoming;
-                       memcpy(dstaddr, router->addr, ETH_ALEN);
-
-                       batadv_neigh_node_free_ref(router);
-
                        skb = skb_clone(info->skb_packet, GFP_ATOMIC);
-                       if (skb)
-                               batadv_send_skb_packet(skb, hard_iface,
-                                                      dstaddr);
+                       if (!skb)
+                               continue;
 
+                       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+                               kfree_skb(skb);
                }
                rcu_read_unlock();
        }
@@ -755,7 +742,6 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
                                      struct batadv_vis_info *info)
 {
        struct batadv_orig_node *orig_node;
-       struct batadv_neigh_node *router = NULL;
        struct sk_buff *skb;
        struct batadv_vis_packet *packet;
 
@@ -765,17 +751,14 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
+       skb = skb_clone(info->skb_packet, GFP_ATOMIC);
+       if (!skb)
                goto out;
 
-       skb = skb_clone(info->skb_packet, GFP_ATOMIC);
-       if (skb)
-               batadv_send_skb_packet(skb, router->if_incoming, router->addr);
+       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+               kfree_skb(skb);
 
 out:
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
 }