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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iEYEABECAAYFAlCsvK0ACgkQpGgxIkP9cwfqxACeOAPgCi+t6skliCgCmvsxU0GZ shkAoJA7K4n6cqCzVz89xixoLWb2WOdg =uoM7 -----END PGP SIGNATURE----- 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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
76e0d67a08
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
What: /sys/class/net/<mesh_iface>/mesh/routing_algo
|
||||
Date: Dec 2011
|
||||
Contact: Marek Lindner <lindner_marek@yahoo.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>
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue