Commit 76e0d67a authored by David S. Miller's avatar David S. Miller

Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge

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: default avatarDavid S. Miller <davem@davemloft.net>
parents de4594a5 e022b956
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 What: /sys/class/net/<iface>/batman-adv/mesh_iface
Date: May 2010 Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de> Contact: Marek Lindner <lindner_marek@yahoo.de>
...@@ -7,8 +13,3 @@ Description: ...@@ -7,8 +13,3 @@ Description:
displays the batman mesh interface this <iface> displays the batman mesh interface this <iface>
currently is associated with. 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.
...@@ -6,6 +6,14 @@ Description: ...@@ -6,6 +6,14 @@ Description:
Indicates whether the batman protocol messages of the Indicates whether the batman protocol messages of the
mesh <mesh_iface> shall be aggregated or not. 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 What: /sys/class/net/<mesh_iface>/mesh/bonding
Date: June 2010 Date: June 2010
Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
...@@ -31,14 +39,6 @@ Description: ...@@ -31,14 +39,6 @@ Description:
mesh will be fragmented or silently discarded if the mesh will be fragmented or silently discarded if the
packet size exceeds the outgoing interface MTU. 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 What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
Date: October 2010 Date: October 2010
Contact: Marek Lindner <lindner_marek@yahoo.de> Contact: Marek Lindner <lindner_marek@yahoo.de>
...@@ -60,13 +60,6 @@ Description: ...@@ -60,13 +60,6 @@ Description:
Defines the selection criteria this node will use Defines the selection criteria this node will use
to choose a gateway if gw_mode was set to 'client'. to choose a gateway if gw_mode was set to 'client'.
What: /sys/class/net/<mesh_iface>/mesh/orig_interval
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Defines the interval in milliseconds in which batman
sends its protocol messages.
What: /sys/class/net/<mesh_iface>/mesh/hop_penalty What: /sys/class/net/<mesh_iface>/mesh/hop_penalty
Date: Oct 2010 Date: Oct 2010
Contact: Linus Lüssing <linus.luessing@web.de> Contact: Linus Lüssing <linus.luessing@web.de>
...@@ -74,6 +67,13 @@ Description: ...@@ -74,6 +67,13 @@ Description:
Defines the penalty which will be applied to an Defines the penalty which will be applied to an
originator message's tq-field on every hop. 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>
Description:
Defines the interval in milliseconds in which batman
sends its protocol messages.
What: /sys/class/net/<mesh_iface>/mesh/routing_algo What: /sys/class/net/<mesh_iface>/mesh/routing_algo
Date: Dec 2011 Date: Dec 2011
Contact: Marek Lindner <lindner_marek@yahoo.de> Contact: Marek Lindner <lindner_marek@yahoo.de>
......
...@@ -6,6 +6,7 @@ config BATMAN_ADV ...@@ -6,6 +6,7 @@ config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol" tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET depends on NET
select CRC16 select CRC16
select LIBCRC32C
default n default n
help help
B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
......
...@@ -77,8 +77,15 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node, ...@@ -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, const void *data1 = container_of(node, struct batadv_backbone_gw,
hash_entry); 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 */ /* compares address and vid of two claims */
...@@ -87,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node, ...@@ -87,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node,
{ {
const void *data1 = container_of(node, struct batadv_claim, const void *data1 = container_of(node, struct batadv_claim,
hash_entry); hash_entry);
const struct batadv_claim *cl1 = data1, *cl2 = data2;
if (!batadv_compare_eth(cl1->addr, cl2->addr))
return 0;
if (cl1->vid != cl2->vid)
return 0;
return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0); return 1;
} }
/* free a backbone gw */ /* free a backbone gw */
...@@ -1235,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv) ...@@ -1235,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
/** /**
* batadv_bla_check_bcast_duplist * batadv_bla_check_bcast_duplist
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @bcast_packet: encapsulated broadcast frame plus batman header * @skb: contains the bcast_packet to be checked
* @bcast_packet_len: length of encapsulated broadcast frame plus batman header
* *
* check if it is on our broadcast list. Another gateway might * check if it is on our broadcast list. Another gateway might
* have sent the same packet because it is connected to the same backbone, * 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) ...@@ -1248,20 +1261,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
* the same host however as this might be intended. * the same host however as this might be intended.
*/ */
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
struct batadv_bcast_packet *bcast_packet, struct sk_buff *skb)
int bcast_packet_len)
{ {
int i, length, curr, ret = 0; int i, curr, ret = 0;
uint8_t *content; __be32 crc;
uint16_t crc; struct batadv_bcast_packet *bcast_packet;
struct batadv_bcast_duplist_entry *entry; struct batadv_bcast_duplist_entry *entry;
length = bcast_packet_len - sizeof(*bcast_packet); bcast_packet = (struct batadv_bcast_packet *)skb->data;
content = (uint8_t *)bcast_packet;
content += sizeof(*bcast_packet);
/* calculate the crc ... */ /* 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); spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
......
...@@ -31,8 +31,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, ...@@ -31,8 +31,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
void *offset); void *offset);
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig); 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, int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
struct batadv_bcast_packet *bcast_packet, struct sk_buff *skb);
int hdr_size);
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if, struct batadv_hard_iface *primary_if,
struct batadv_hard_iface *oldif); struct batadv_hard_iface *oldif);
...@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, ...@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
static inline int static inline int
batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
struct batadv_bcast_packet *bcast_packet, struct sk_buff *skb)
int hdr_size)
{ {
return 0; return 0;
} }
......
...@@ -323,7 +323,17 @@ struct batadv_debuginfo batadv_debuginfo_##_name = { \ ...@@ -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 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(originators, S_IRUGO, batadv_originators_open);
static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
static BATADV_DEBUGINFO(transtable_global, S_IRUGO, static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
...@@ -358,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { ...@@ -358,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
void batadv_debugfs_init(void) void batadv_debugfs_init(void)
{ {
struct batadv_debuginfo *bat_debug; struct batadv_debuginfo **bat_debug;
struct dentry *file; struct dentry *file;
batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL); batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
...@@ -366,17 +376,23 @@ void batadv_debugfs_init(void) ...@@ -366,17 +376,23 @@ void batadv_debugfs_init(void)
batadv_debugfs = NULL; batadv_debugfs = NULL;
if (!batadv_debugfs) if (!batadv_debugfs)
goto out; goto err;
bat_debug = &batadv_debuginfo_routing_algos; for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
file = debugfs_create_file(bat_debug->attr.name, file = debugfs_create_file(((*bat_debug)->attr).name,
S_IFREG | bat_debug->attr.mode, S_IFREG | ((*bat_debug)->attr).mode,
batadv_debugfs, NULL, &bat_debug->fops); batadv_debugfs, NULL,
if (!file) &(*bat_debug)->fops);
pr_err("Can't add debugfs file: %s\n", bat_debug->attr.name); if (!file) {
pr_err("Can't add general debugfs file: %s\n",
((*bat_debug)->attr).name);
goto err;
}
}
out:
return; return;
err:
debugfs_remove_recursive(batadv_debugfs);
} }
void batadv_debugfs_destroy(void) void batadv_debugfs_destroy(void)
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* 02110-1301, USA * 02110-1301, USA
*/ */
#include <linux/crc32c.h>
#include <linux/highmem.h>
#include "main.h" #include "main.h"
#include "sysfs.h" #include "sysfs.h"
#include "debugfs.h" #include "debugfs.h"
...@@ -420,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset) ...@@ -420,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
return 0; 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) static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
{ {
struct batadv_algo_ops *bat_algo_ops; struct batadv_algo_ops *bat_algo_ops;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv" #define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION #ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2012.4.0" #define BATADV_SOURCE_VERSION "2012.5.0"
#endif #endif
/* B.A.T.M.A.N. parameters */ /* B.A.T.M.A.N. parameters */
...@@ -174,6 +174,7 @@ void batadv_recv_handler_unregister(uint8_t packet_type); ...@@ -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_register(struct batadv_algo_ops *bat_algo_ops);
int batadv_algo_select(struct batadv_priv *bat_priv, char *name); int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); 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 * enum batadv_dbg_level - available log levels
......
...@@ -173,6 +173,18 @@ struct batadv_icmp_packet_rr { ...@@ -173,6 +173,18 @@ struct batadv_icmp_packet_rr {
uint8_t rr[BATADV_RR_LEN][ETH_ALEN]; 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_unicast_packet {
struct batadv_header header; struct batadv_header header;
uint8_t ttvn; /* destination translation table version number */ uint8_t ttvn; /* destination translation table version number */
...@@ -216,7 +228,9 @@ struct batadv_bcast_packet { ...@@ -216,7 +228,9 @@ struct batadv_bcast_packet {
/* "4 bytes boundary + 2 bytes" long to make the payload after the /* "4 bytes boundary + 2 bytes" long to make the payload after the
* following ethernet header again 4 bytes boundary aligned * following ethernet header again 4 bytes boundary aligned
*/ */
} __packed; };
#pragma pack()
struct batadv_vis_packet { struct batadv_vis_packet {
struct batadv_header header; struct batadv_header header;
......
...@@ -285,7 +285,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, ...@@ -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_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL; struct batadv_orig_node *orig_node = NULL;
struct batadv_neigh_node *router = NULL;
struct batadv_icmp_packet_rr *icmp_packet; struct batadv_icmp_packet_rr *icmp_packet;
int ret = NET_RX_DROP; int ret = NET_RX_DROP;
...@@ -307,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, ...@@ -307,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
if (!orig_node) if (!orig_node)
goto out; 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. */ /* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0) if (skb_cow(skb, ETH_HLEN) < 0)
goto out; goto out;
...@@ -322,14 +317,12 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, ...@@ -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->msg_type = BATADV_ECHO_REPLY;
icmp_packet->header.ttl = BATADV_TTL; icmp_packet->header.ttl = BATADV_TTL;
batadv_send_skb_packet(skb, router->if_incoming, router->addr); if (batadv_send_skb_to_orig(skb, orig_node, NULL))
ret = NET_RX_SUCCESS; ret = NET_RX_SUCCESS;
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
if (router)
batadv_neigh_node_free_ref(router);
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
return ret; return ret;
...@@ -340,7 +333,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, ...@@ -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_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL; struct batadv_orig_node *orig_node = NULL;
struct batadv_neigh_node *router = NULL;
struct batadv_icmp_packet *icmp_packet; struct batadv_icmp_packet *icmp_packet;
int ret = NET_RX_DROP; int ret = NET_RX_DROP;
...@@ -362,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, ...@@ -362,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
if (!orig_node) if (!orig_node)
goto out; 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. */ /* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0) if (skb_cow(skb, ETH_HLEN) < 0)
goto out; goto out;
...@@ -377,14 +365,12 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, ...@@ -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->msg_type = BATADV_TTL_EXCEEDED;
icmp_packet->header.ttl = BATADV_TTL; icmp_packet->header.ttl = BATADV_TTL;
batadv_send_skb_packet(skb, router->if_incoming, router->addr); if (batadv_send_skb_to_orig(skb, orig_node, NULL))
ret = NET_RX_SUCCESS; ret = NET_RX_SUCCESS;
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
if (router)
batadv_neigh_node_free_ref(router);
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
return ret; return ret;
...@@ -398,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, ...@@ -398,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct batadv_icmp_packet_rr *icmp_packet; struct batadv_icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct batadv_orig_node *orig_node = NULL; struct batadv_orig_node *orig_node = NULL;
struct batadv_neigh_node *router = NULL;
int hdr_size = sizeof(struct batadv_icmp_packet); int hdr_size = sizeof(struct batadv_icmp_packet);
int ret = NET_RX_DROP; int ret = NET_RX_DROP;
...@@ -447,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, ...@@ -447,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
if (!orig_node) if (!orig_node)
goto out; 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. */ /* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0) if (skb_cow(skb, ETH_HLEN) < 0)
goto out; goto out;
...@@ -461,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, ...@@ -461,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet->header.ttl--; icmp_packet->header.ttl--;
/* route it */ /* route it */
batadv_send_skb_packet(skb, router->if_incoming, router->addr); if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
ret = NET_RX_SUCCESS; ret = NET_RX_SUCCESS;
out: out:
if (router)
batadv_neigh_node_free_ref(router);
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
return ret; return ret;
...@@ -882,7 +861,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, ...@@ -882,7 +861,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
skb->len + ETH_HLEN); skb->len + ETH_HLEN);
/* route it */ /* route it */
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
ret = NET_RX_SUCCESS; ret = NET_RX_SUCCESS;
out: out:
...@@ -1217,14 +1196,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, ...@@ -1217,14 +1196,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
spin_unlock_bh(&orig_node->bcast_seqno_lock); 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 */ /* 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; goto out;
/* rebroadcast packet */ /* rebroadcast packet */
......
...@@ -78,6 +78,39 @@ int batadv_send_skb_packet(struct sk_buff *skb, ...@@ -78,6 +78,39 @@ int batadv_send_skb_packet(struct sk_buff *skb,
return NET_XMIT_DROP; 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) void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
{ {
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
int batadv_send_skb_packet(struct sk_buff *skb, int batadv_send_skb_packet(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface, struct batadv_hard_iface *hard_iface,
const uint8_t *dst_addr); 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); void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb, const struct sk_buff *skb,
......
...@@ -911,8 +911,44 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -911,8 +911,44 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
return ret; return ret;
} }
/* print all orig nodes who announce the address for this global entry. /* batadv_transtable_best_orig - Get best originator list entry from tt entry
* it is assumed that the caller holds rcu_read_lock(); * @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 static void
batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, 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, ...@@ -920,21 +956,37 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
{ {
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node; 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; struct batadv_tt_common_entry *tt_common_entry;
uint16_t flags; uint16_t flags;
uint8_t last_ttvn; uint8_t last_ttvn;
tt_common_entry = &tt_global_entry->common; 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; head = &tt_global_entry->orig_list;
hlist_for_each_entry_rcu(orig_entry, node, head, 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); last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n", seq_printf(seq, " %c %pM (%3u) via %pM (%3u) [%c%c%c]\n",
tt_global_entry->common.addr, orig_entry->ttvn, '+', tt_global_entry->common.addr,
orig_entry->orig_node->orig, last_ttvn, orig_entry->ttvn, orig_entry->orig_node->orig,
last_ttvn,
(flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
(flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
(flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
...@@ -1280,11 +1332,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, ...@@ -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_local_entry *tt_local_entry = NULL;
struct batadv_tt_global_entry *tt_global_entry = NULL; struct batadv_tt_global_entry *tt_global_entry = NULL;
struct batadv_orig_node *orig_node = NULL; struct batadv_orig_node *orig_node = NULL;
struct batadv_neigh_node *router = NULL; struct batadv_tt_orig_list_entry *best_entry;
struct hlist_head *head;
struct hlist_node *node;
struct batadv_tt_orig_list_entry *orig_entry;
int best_tq;
if (src && atomic_read(&bat_priv->ap_isolation)) { if (src && atomic_read(&bat_priv->ap_isolation)) {
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); 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, ...@@ -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)) _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
goto out; goto out;
best_tq = 0;
rcu_read_lock(); rcu_read_lock();
head = &tt_global_entry->orig_list; best_entry = batadv_transtable_best_orig(tt_global_entry);
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);
}
/* found anything? */ /* found anything? */
if (best_entry)
orig_node = best_entry->orig_node;
if (orig_node && !atomic_inc_not_zero(&orig_node->refcount)) if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
orig_node = NULL; orig_node = NULL;
rcu_read_unlock(); rcu_read_unlock();
out: out:
if (tt_global_entry) if (tt_global_entry)
batadv_tt_global_entry_free_ref(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, ...@@ -1604,7 +1642,6 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
{ {
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct batadv_tt_query_packet *tt_request; struct batadv_tt_query_packet *tt_request;
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
struct batadv_tt_req_node *tt_req_node = NULL; struct batadv_tt_req_node *tt_req_node = NULL;
int ret = 1; int ret = 1;
...@@ -1642,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv, ...@@ -1642,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (full_table) if (full_table)
tt_request->flags |= BATADV_TT_FULL_TABLE; tt_request->flags |= BATADV_TT_FULL_TABLE;
neigh_node = batadv_orig_node_get_router(dst_orig_node); batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
if (!neigh_node) dst_orig_node->orig, (full_table ? 'F' : '.'));
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_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
ret = 0; ret = 0;
out: out:
if (neigh_node)
batadv_neigh_node_free_ref(neigh_node);
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
if (ret) if (ret)
...@@ -1678,7 +1707,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, ...@@ -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 *req_dst_orig_node;
struct batadv_orig_node *res_dst_orig_node = NULL; struct batadv_orig_node *res_dst_orig_node = NULL;
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *primary_if = NULL; struct batadv_hard_iface *primary_if = NULL;
uint8_t orig_ttvn, req_ttvn, ttvn; uint8_t orig_ttvn, req_ttvn, ttvn;
int ret = false; int ret = false;
...@@ -1704,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, ...@@ -1704,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
if (!res_dst_orig_node) if (!res_dst_orig_node)
goto out; 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); primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if) if (!primary_if)
goto out; goto out;
...@@ -1779,13 +1803,12 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, ...@@ -1779,13 +1803,12 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
tt_response->flags |= BATADV_TT_FULL_TABLE; tt_response->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv, batadv_dbg(BATADV_DBG_TT, bat_priv,
"Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n", "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
res_dst_orig_node->orig, neigh_node->addr, res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
req_dst_orig_node->orig, req_ttvn);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
ret = true; ret = true;
goto out; goto out;
...@@ -1797,8 +1820,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, ...@@ -1797,8 +1820,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
batadv_orig_node_free_ref(res_dst_orig_node); batadv_orig_node_free_ref(res_dst_orig_node);
if (req_dst_orig_node) if (req_dst_orig_node)
batadv_orig_node_free_ref(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) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
if (!ret) if (!ret)
...@@ -1812,7 +1833,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, ...@@ -1812,7 +1833,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_request) struct batadv_tt_query_packet *tt_request)
{ {
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *primary_if = NULL; struct batadv_hard_iface *primary_if = NULL;
uint8_t my_ttvn, req_ttvn, ttvn; uint8_t my_ttvn, req_ttvn, ttvn;
int ret = false; int ret = false;
...@@ -1837,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, ...@@ -1837,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
if (!orig_node) if (!orig_node)
goto out; 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); primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if) if (!primary_if)
goto out; goto out;
...@@ -1904,13 +1920,13 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, ...@@ -1904,13 +1920,13 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
tt_response->flags |= BATADV_TT_FULL_TABLE; tt_response->flags |= BATADV_TT_FULL_TABLE;
batadv_dbg(BATADV_DBG_TT, bat_priv, batadv_dbg(BATADV_DBG_TT, bat_priv,
"Sending TT_RESPONSE to %pM via %pM [%c]\n", "Sending TT_RESPONSE to %pM [%c]\n",
orig_node->orig, neigh_node->addr, orig_node->orig,
(tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, orig_node, NULL))
ret = true; ret = true;
goto out; goto out;
...@@ -1919,8 +1935,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, ...@@ -1919,8 +1935,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
out: out:
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
if (neigh_node)
batadv_neigh_node_free_ref(neigh_node);
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
if (!ret) if (!ret)
...@@ -2185,7 +2199,6 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, ...@@ -2185,7 +2199,6 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
struct batadv_orig_node *orig_node) struct batadv_orig_node *orig_node)
{ {
struct batadv_neigh_node *neigh_node = NULL;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct batadv_roam_adv_packet *roam_adv_packet; struct batadv_roam_adv_packet *roam_adv_packet;
int ret = 1; int ret = 1;
...@@ -2218,23 +2231,17 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, ...@@ -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->dst, orig_node->orig, ETH_ALEN);
memcpy(roam_adv_packet->client, client, 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, batadv_dbg(BATADV_DBG_TT, bat_priv,
"Sending ROAMING_ADV to %pM (client %pM) via %pM\n", "Sending ROAMING_ADV to %pM (client %pM)\n",
orig_node->orig, client, neigh_node->addr); orig_node->orig, client);
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, orig_node, NULL))
ret = 0; ret = 0;
out: out:
if (neigh_node) if (ret && skb)
batadv_neigh_node_free_ref(neigh_node);
if (ret)
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
......
...@@ -156,7 +156,7 @@ struct batadv_neigh_node { ...@@ -156,7 +156,7 @@ struct batadv_neigh_node {
#ifdef CONFIG_BATMAN_ADV_BLA #ifdef CONFIG_BATMAN_ADV_BLA
struct batadv_bcast_duplist_entry { struct batadv_bcast_duplist_entry {
uint8_t orig[ETH_ALEN]; uint8_t orig[ETH_ALEN];
uint16_t crc; __be32 crc;
unsigned long entrytime; unsigned long entrytime;
}; };
#endif #endif
......
...@@ -402,7 +402,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, ...@@ -402,7 +402,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
struct batadv_neigh_node *neigh_node; struct batadv_neigh_node *neigh_node;
int data_len = skb->len; int data_len = skb->len;
int ret = 1; int ret = NET_RX_DROP;
unsigned int dev_mtu; unsigned int dev_mtu;
/* get routing information */ /* get routing information */
...@@ -466,7 +466,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, ...@@ -466,7 +466,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
goto out; goto out;
} }
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); if (batadv_send_skb_to_orig(skb, orig_node, NULL))
ret = 0; ret = 0;
out: out:
...@@ -474,7 +474,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, ...@@ -474,7 +474,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
batadv_neigh_node_free_ref(neigh_node); batadv_neigh_node_free_ref(neigh_node);
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
if (ret == 1) if (ret == NET_RX_DROP)
kfree_skb(skb); kfree_skb(skb);
return ret; return ret;
} }
...@@ -698,15 +698,12 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv) ...@@ -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, static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
struct batadv_vis_info *info) struct batadv_vis_info *info)
{ {
struct batadv_neigh_node *router;
struct batadv_hashtable *hash = bat_priv->orig_hash; struct batadv_hashtable *hash = bat_priv->orig_hash;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
struct batadv_vis_packet *packet; struct batadv_vis_packet *packet;
struct sk_buff *skb; struct sk_buff *skb;
struct batadv_hard_iface *hard_iface;
uint8_t dstaddr[ETH_ALEN];
uint32_t i; uint32_t i;
...@@ -722,30 +719,20 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv, ...@@ -722,30 +719,20 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
if (!(orig_node->flags & BATADV_VIS_SERVER)) if (!(orig_node->flags & BATADV_VIS_SERVER))
continue; continue;
router = batadv_orig_node_get_router(orig_node);
if (!router)
continue;
/* don't send it if we already received the packet from /* don't send it if we already received the packet from
* this node. * this node.
*/ */
if (batadv_recv_list_is_in(bat_priv, &info->recv_list, if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
orig_node->orig)) { orig_node->orig))
batadv_neigh_node_free_ref(router);
continue; continue;
}
memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); 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); skb = skb_clone(info->skb_packet, GFP_ATOMIC);
if (skb) if (!skb)
batadv_send_skb_packet(skb, hard_iface, continue;
dstaddr);
if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
kfree_skb(skb);
} }
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -755,7 +742,6 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv, ...@@ -755,7 +742,6 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
struct batadv_vis_info *info) struct batadv_vis_info *info)
{ {
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
struct batadv_neigh_node *router = NULL;
struct sk_buff *skb; struct sk_buff *skb;
struct batadv_vis_packet *packet; struct batadv_vis_packet *packet;
...@@ -765,17 +751,14 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv, ...@@ -765,17 +751,14 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
if (!orig_node) if (!orig_node)
goto out; goto out;
router = batadv_orig_node_get_router(orig_node); skb = skb_clone(info->skb_packet, GFP_ATOMIC);
if (!router) if (!skb)
goto out; goto out;
skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
if (skb) kfree_skb(skb);
batadv_send_skb_packet(skb, router->if_incoming, router->addr);
out: out:
if (router)
batadv_neigh_node_free_ref(router);
if (orig_node) if (orig_node)
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment