Included changes:
- remove useless skb size check in batadv_interface_rx - basic netns support introduced by Andrew Lunn: - prevent virtual interface from changing netns by setting NETIF_F_NETNS_LOCAL - create virtual interface within the netns of the first hard-interface - introduce detection of complex bridge loops and report event to the user (via udev) when the Bridge Loop Avoidance mechanism can't prevent them - minor reference counting bugfixes for the hard_iface object that couldn't make it via the net tree - use kref_get() instead of kref_get_unless_zero() to make reference counting bug more visible - use batadv_compare_eth() all over the code when possible instead of plain memcmp() - minor code cleanup and style adjustments -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJXMjUdAAoJEJ4aZjxxc6bKhDsP/i3rRwoppaDK3gxuDkXqrqOj AYhMJYulcizK2PPCzj24bZSttwcKDNWpjR67rBgXY02NpqSsW+qYFnCm+KokzgC0 3NGV+lC6oCwzowP3FJtW06BCNOybnbR84Fw6JCRL5P4mKoGnhn4jAOIYlYnk4K7z ByhEallLD84h5oo2Td8i06QzxzaO6lkYaLrAVBQnd+Cs27foxjMOO0gasyCvUkl7 Jsm2n0NSEN6SYv0smLhiPHx9oF66MBAxNRVS6dL/6Ko/vSHNy1AGQgx0SztlHzCQ K6JCpOZn5CExvKZUMXQXOrSkpdjIxVh+EGnGBAGyNswqBg49Y3K45FqNz4b+R0Pg ckPzc7UAo8z+ZHzPz4mzx/596sw9xG4jLS6aHkjwet7kLXj/ShP//HqGwfHTeeOY w4a2ers6ByCq2PwKYz34s/sDvC2+p++ZdyJF+qOjJpNjbH1B+mDId8M1f9H/9rvF //EZhCcdlpqLIxvQKDMADQRpcwTbAPglsBuHs/1Sk1zjRK1NDRPw+46pUUQOb8ND ydAs0JVUOgSKHZT+3b5l85poRYpp8gX8nVrvF2DNJBqmBTvSkAbZpNPiSy6fNWQV he3Q9RndqQq2OPffG1ijte7G1m9J8lCh7Nzl6Ee6vGsw4GzzkKIx9qHHCtXhYpOE kdg5ttgUK5sfgjsn3ANp =CB1D -----END PGP SIGNATURE----- Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge Antonio Quartulli says: ==================== Included changes: - remove useless skb size check in batadv_interface_rx - basic netns support introduced by Andrew Lunn: - prevent virtual interface from changing netns by setting NETIF_F_NETNS_LOCAL - create virtual interface within the netns of the first hard-interface - introduce detection of complex bridge loops and report event to the user (via udev) when the Bridge Loop Avoidance mechanism can't prevent them - minor reference counting bugfixes for the hard_iface object that couldn't make it via the net tree - use kref_get() instead of kref_get_unless_zero() to make reference counting bug more visible - use batadv_compare_eth() all over the code when possible instead of plain memcmp() - minor code cleanup and style adjustments ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
cf88585b1d
@ -681,18 +681,12 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
unsigned char *skb_buff;
|
||||
unsigned int skb_size;
|
||||
|
||||
if (!kref_get_unless_zero(&if_incoming->refcount))
|
||||
return;
|
||||
|
||||
if (!kref_get_unless_zero(&if_outgoing->refcount))
|
||||
goto out_free_incoming;
|
||||
|
||||
/* own packet should always be scheduled */
|
||||
if (!own_packet) {
|
||||
if (!batadv_atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"batman packet queue full\n");
|
||||
goto out_free_outgoing;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,6 +712,8 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
forw_packet_aggr->packet_len = packet_len;
|
||||
memcpy(skb_buff, packet_buff, packet_len);
|
||||
|
||||
kref_get(&if_incoming->refcount);
|
||||
kref_get(&if_outgoing->refcount);
|
||||
forw_packet_aggr->own = own_packet;
|
||||
forw_packet_aggr->if_incoming = if_incoming;
|
||||
forw_packet_aggr->if_outgoing = if_outgoing;
|
||||
@ -747,10 +743,6 @@ out_free_forw_packet:
|
||||
out_nomem:
|
||||
if (!own_packet)
|
||||
atomic_inc(&bat_priv->batman_queue_left);
|
||||
out_free_outgoing:
|
||||
batadv_hardif_put(if_outgoing);
|
||||
out_free_incoming:
|
||||
batadv_hardif_put(if_incoming);
|
||||
}
|
||||
|
||||
/* aggregate a new packet into the existing ogm packet */
|
||||
@ -987,9 +979,15 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
list_for_each_entry_rcu(tmp_hard_iface, &batadv_hardif_list, list) {
|
||||
if (tmp_hard_iface->soft_iface != hard_iface->soft_iface)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&tmp_hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
batadv_iv_ogm_queue_add(bat_priv, *ogm_buff,
|
||||
*ogm_buff_len, hard_iface,
|
||||
tmp_hard_iface, 1, send_time);
|
||||
|
||||
batadv_hardif_put(tmp_hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -1170,13 +1168,13 @@ out:
|
||||
* @if_incoming: interface where the packet was received
|
||||
* @if_outgoing: interface for which the retransmission should be considered
|
||||
*
|
||||
* Return: 1 if the link can be considered bidirectional, 0 otherwise
|
||||
* Return: true if the link can be considered bidirectional, false otherwise
|
||||
*/
|
||||
static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
||||
struct batadv_orig_node *orig_neigh_node,
|
||||
struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
||||
struct batadv_orig_node *orig_neigh_node,
|
||||
struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
|
||||
struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node;
|
||||
@ -1184,9 +1182,10 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
||||
u8 total_count;
|
||||
u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
|
||||
unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
|
||||
int tq_asym_penalty, inv_asym_penalty, if_num, ret = 0;
|
||||
int tq_asym_penalty, inv_asym_penalty, if_num;
|
||||
unsigned int combined_tq;
|
||||
int tq_iface_penalty;
|
||||
bool ret = false;
|
||||
|
||||
/* find corresponding one hop neighbor */
|
||||
rcu_read_lock();
|
||||
@ -1298,7 +1297,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
||||
* consider it bidirectional
|
||||
*/
|
||||
if (batadv_ogm_packet->tq >= BATADV_TQ_TOTAL_BIDRECT_LIMIT)
|
||||
ret = 1;
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
if (neigh_node)
|
||||
@ -1327,9 +1326,9 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
||||
struct batadv_orig_ifinfo *orig_ifinfo = NULL;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
int is_dup;
|
||||
bool is_dup;
|
||||
s32 seq_diff;
|
||||
int need_update = 0;
|
||||
bool need_update = false;
|
||||
int set_mark;
|
||||
enum batadv_dup_status ret = BATADV_NO_DUP;
|
||||
u32 seqno = ntohl(batadv_ogm_packet->seqno);
|
||||
@ -1439,7 +1438,7 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
|
||||
struct sk_buff *skb_priv;
|
||||
struct ethhdr *ethhdr;
|
||||
u8 *prev_sender;
|
||||
int is_bidirect;
|
||||
bool is_bidirect;
|
||||
|
||||
/* create a private copy of the skb, as some functions change tq value
|
||||
* and/or flags.
|
||||
@ -1767,8 +1766,13 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
||||
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,
|
||||
if_incoming, hard_iface);
|
||||
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/random.h>
|
||||
@ -176,6 +177,9 @@ static void batadv_v_ogm_send(struct work_struct *work)
|
||||
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
|
||||
ogm_packet->orig, ntohl(ogm_packet->seqno),
|
||||
@ -185,10 +189,13 @@ static void batadv_v_ogm_send(struct work_struct *work)
|
||||
|
||||
/* this skb gets consumed by batadv_v_ogm_send_to_if() */
|
||||
skb_tmp = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!skb_tmp)
|
||||
if (!skb_tmp) {
|
||||
batadv_hardif_put(hard_iface);
|
||||
break;
|
||||
}
|
||||
|
||||
batadv_v_ogm_send_to_if(skb_tmp, hard_iface);
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -704,9 +711,14 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
||||
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
|
||||
orig_node, neigh_node,
|
||||
if_incoming, hard_iface);
|
||||
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
|
@ -38,11 +38,11 @@ static void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n)
|
||||
* the last sequence number
|
||||
* @set_mark: whether this packet should be marked in seq_bits
|
||||
*
|
||||
* Return: 1 if the window was moved (either new or very old),
|
||||
* 0 if the window was not moved/shifted.
|
||||
* Return: true if the window was moved (either new or very old),
|
||||
* false if the window was not moved/shifted.
|
||||
*/
|
||||
int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
int set_mark)
|
||||
bool batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
|
||||
s32 seq_num_diff, int set_mark)
|
||||
{
|
||||
struct batadv_priv *bat_priv = priv;
|
||||
|
||||
@ -52,7 +52,7 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
if (seq_num_diff <= 0 && seq_num_diff > -BATADV_TQ_LOCAL_WINDOW_SIZE) {
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, -seq_num_diff);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* sequence number is slightly newer, so we shift the window and
|
||||
@ -63,7 +63,7 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, 0);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* sequence number is much newer, probably missed a lot of packets */
|
||||
@ -75,7 +75,7 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, 0);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* received a much older packet. The other host either restarted
|
||||
@ -94,5 +94,5 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, 0);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
@ -31,17 +32,17 @@
|
||||
* @last_seqno: latest sequence number in seq_bits
|
||||
* @curr_seqno: sequence number to test for
|
||||
*
|
||||
* Return: 1 if the corresponding bit in the given seq_bits indicates true
|
||||
* and curr_seqno is within range of last_seqno. Otherwise returns 0.
|
||||
* Return: true if the corresponding bit in the given seq_bits indicates true
|
||||
* and curr_seqno is within range of last_seqno. Otherwise returns false.
|
||||
*/
|
||||
static inline int batadv_test_bit(const unsigned long *seq_bits,
|
||||
u32 last_seqno, u32 curr_seqno)
|
||||
static inline bool batadv_test_bit(const unsigned long *seq_bits,
|
||||
u32 last_seqno, u32 curr_seqno)
|
||||
{
|
||||
s32 diff;
|
||||
|
||||
diff = last_seqno - curr_seqno;
|
||||
if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE)
|
||||
return 0;
|
||||
return false;
|
||||
return test_bit(diff, seq_bits) != 0;
|
||||
}
|
||||
|
||||
@ -55,7 +56,7 @@ static inline void batadv_set_bit(unsigned long *seq_bits, s32 n)
|
||||
set_bit(n, seq_bits); /* turn the position on */
|
||||
}
|
||||
|
||||
int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff,
|
||||
int set_mark);
|
||||
bool batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
|
||||
s32 seq_num_diff, int set_mark);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "hash.h"
|
||||
#include "originator.h"
|
||||
#include "packet.h"
|
||||
#include "sysfs.h"
|
||||
#include "translation-table.h"
|
||||
|
||||
static const u8 batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
|
||||
@ -100,10 +101,10 @@ static inline u32 batadv_choose_backbone_gw(const void *data, u32 size)
|
||||
* @node: list node of the first entry to compare
|
||||
* @data2: pointer to the second backbone gateway
|
||||
*
|
||||
* Return: 1 if the backbones have the same data, 0 otherwise
|
||||
* Return: true if the backbones have the same data, false otherwise
|
||||
*/
|
||||
static int batadv_compare_backbone_gw(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
static bool batadv_compare_backbone_gw(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
{
|
||||
const void *data1 = container_of(node, struct batadv_bla_backbone_gw,
|
||||
hash_entry);
|
||||
@ -111,12 +112,12 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
|
||||
const struct batadv_bla_backbone_gw *gw2 = data2;
|
||||
|
||||
if (!batadv_compare_eth(gw1->orig, gw2->orig))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (gw1->vid != gw2->vid)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,10 +125,10 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
|
||||
* @node: list node of the first entry to compare
|
||||
* @data2: pointer to the second claims
|
||||
*
|
||||
* Return: 1 if the claim have the same data, 0 otherwise
|
||||
* Return: true if the claim have the same data, 0 otherwise
|
||||
*/
|
||||
static int batadv_compare_claim(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
static bool batadv_compare_claim(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
{
|
||||
const void *data1 = container_of(node, struct batadv_bla_claim,
|
||||
hash_entry);
|
||||
@ -135,12 +136,12 @@ static int batadv_compare_claim(const struct hlist_node *node,
|
||||
const struct batadv_bla_claim *cl2 = data2;
|
||||
|
||||
if (!batadv_compare_eth(cl1->addr, cl2->addr))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (cl1->vid != cl2->vid)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -407,6 +408,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
|
||||
ethhdr->h_source, ethhdr->h_dest,
|
||||
BATADV_PRINT_VID(vid));
|
||||
break;
|
||||
case BATADV_CLAIM_TYPE_LOOPDETECT:
|
||||
ether_addr_copy(ethhdr->h_source, mac);
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv,
|
||||
"bla_send_claim(): LOOPDETECT of %pM to %pM on vid %d\n",
|
||||
ethhdr->h_source, ethhdr->h_dest,
|
||||
BATADV_PRINT_VID(vid));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (vid & BATADV_VLAN_HAS_TAG)
|
||||
@ -426,6 +435,36 @@ out:
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_loopdetect_report - worker for reporting the loop
|
||||
* @work: work queue item
|
||||
*
|
||||
* Throws an uevent, as the loopdetect check function can't do that itself
|
||||
* since the kernel may sleep while throwing uevents.
|
||||
*/
|
||||
static void batadv_bla_loopdetect_report(struct work_struct *work)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_priv *bat_priv;
|
||||
char vid_str[6] = { '\0' };
|
||||
|
||||
backbone_gw = container_of(work, struct batadv_bla_backbone_gw,
|
||||
report_work);
|
||||
bat_priv = backbone_gw->bat_priv;
|
||||
|
||||
batadv_info(bat_priv->soft_iface,
|
||||
"Possible loop on VLAN %d detected which can't be handled by BLA - please check your network setup!\n",
|
||||
BATADV_PRINT_VID(backbone_gw->vid));
|
||||
snprintf(vid_str, sizeof(vid_str), "%d",
|
||||
BATADV_PRINT_VID(backbone_gw->vid));
|
||||
vid_str[sizeof(vid_str) - 1] = 0;
|
||||
|
||||
batadv_throw_uevent(bat_priv, BATADV_UEV_BLA, BATADV_UEV_LOOPDETECT,
|
||||
vid_str);
|
||||
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_get_backbone_gw - finds or creates a backbone gateway
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
@ -464,6 +503,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
|
||||
atomic_set(&entry->request_sent, 0);
|
||||
atomic_set(&entry->wait_periods, 0);
|
||||
ether_addr_copy(entry->orig, orig);
|
||||
INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
|
||||
|
||||
/* one for the hash, one for returning */
|
||||
kref_init(&entry->refcount);
|
||||
@ -735,22 +775,22 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
|
||||
* @backbone_addr: originator address of the sender (Ethernet source MAC)
|
||||
* @vid: the VLAN ID of the frame
|
||||
*
|
||||
* Return: 1 if handled
|
||||
* Return: true if handled
|
||||
*/
|
||||
static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
||||
u8 *backbone_addr, unsigned short vid)
|
||||
static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
||||
u8 *backbone_addr, unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
u16 backbone_crc, crc;
|
||||
|
||||
if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
|
||||
false);
|
||||
|
||||
if (unlikely(!backbone_gw))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* handle as ANNOUNCE frame */
|
||||
backbone_gw->lasttime = jiffies;
|
||||
@ -783,7 +823,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
||||
}
|
||||
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -794,29 +834,29 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
||||
* @ethhdr: ethernet header of a packet
|
||||
* @vid: the VLAN ID of the frame
|
||||
*
|
||||
* Return: 1 if handled
|
||||
* Return: true if handled
|
||||
*/
|
||||
static int batadv_handle_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, struct ethhdr *ethhdr,
|
||||
unsigned short vid)
|
||||
static bool batadv_handle_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, struct ethhdr *ethhdr,
|
||||
unsigned short vid)
|
||||
{
|
||||
/* check for REQUEST frame */
|
||||
if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* sanity check, this should not happen on a normal switch,
|
||||
* we ignore it in this case.
|
||||
*/
|
||||
if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv,
|
||||
"handle_request(): REQUEST vid %d (sent by %pM)...\n",
|
||||
BATADV_PRINT_VID(vid), ethhdr->h_source);
|
||||
|
||||
batadv_bla_answer_request(bat_priv, primary_if, vid);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -827,12 +867,12 @@ static int batadv_handle_request(struct batadv_priv *bat_priv,
|
||||
* @claim_addr: Client to be unclaimed (ARP sender HW MAC)
|
||||
* @vid: the VLAN ID of the frame
|
||||
*
|
||||
* Return: 1 if handled
|
||||
* Return: true if handled
|
||||
*/
|
||||
static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, u8 *claim_addr,
|
||||
unsigned short vid)
|
||||
static bool batadv_handle_unclaim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, u8 *claim_addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
|
||||
@ -845,7 +885,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
|
||||
backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
|
||||
|
||||
if (!backbone_gw)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* this must be an UNCLAIM frame */
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv,
|
||||
@ -854,7 +894,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
|
||||
|
||||
batadv_bla_del_claim(bat_priv, claim_addr, vid);
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -865,12 +905,12 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
|
||||
* @claim_addr: client mac address to be claimed (ARP sender HW MAC)
|
||||
* @vid: the VLAN ID of the frame
|
||||
*
|
||||
* Return: 1 if handled
|
||||
* Return: true if handled
|
||||
*/
|
||||
static int batadv_handle_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, u8 *claim_addr,
|
||||
unsigned short vid)
|
||||
static bool batadv_handle_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
u8 *backbone_addr, u8 *claim_addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
|
||||
@ -880,7 +920,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
|
||||
false);
|
||||
|
||||
if (unlikely(!backbone_gw))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* this must be a CLAIM frame */
|
||||
batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
|
||||
@ -891,7 +931,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
|
||||
/* TODO: we could call something like tt_local_del() here. */
|
||||
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -975,12 +1015,12 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
|
||||
* @primary_if: the primary hard interface of this batman soft interface
|
||||
* @skb: the frame to be checked
|
||||
*
|
||||
* Return: 1 if it was a claim frame, otherwise return 0 to
|
||||
* Return: true if it was a claim frame, otherwise return false to
|
||||
* tell the callee that it can use the frame on its own.
|
||||
*/
|
||||
static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
struct sk_buff *skb)
|
||||
static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
|
||||
u8 *hw_src, *hw_dst;
|
||||
@ -1011,7 +1051,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
vhdr = skb_header_pointer(skb, headlen, VLAN_HLEN,
|
||||
&vhdr_buf);
|
||||
if (!vhdr)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
proto = vhdr->h_vlan_encapsulated_proto;
|
||||
headlen += VLAN_HLEN;
|
||||
@ -1020,12 +1060,12 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
}
|
||||
|
||||
if (proto != htons(ETH_P_ARP))
|
||||
return 0; /* not a claim frame */
|
||||
return false; /* not a claim frame */
|
||||
|
||||
/* this must be a ARP frame. check if it is a claim. */
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* pskb_may_pull() may have modified the pointers, get ethhdr again */
|
||||
ethhdr = eth_hdr(skb);
|
||||
@ -1035,13 +1075,13 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
* IP information
|
||||
*/
|
||||
if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
|
||||
return 0;
|
||||
return false;
|
||||
if (arphdr->ar_pro != htons(ETH_P_IP))
|
||||
return 0;
|
||||
return false;
|
||||
if (arphdr->ar_hln != ETH_ALEN)
|
||||
return 0;
|
||||
return false;
|
||||
if (arphdr->ar_pln != 4)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
hw_src = (u8 *)arphdr + sizeof(struct arphdr);
|
||||
hw_dst = hw_src + ETH_ALEN + 4;
|
||||
@ -1051,14 +1091,18 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
/* check if it is a claim frame in general */
|
||||
if (memcmp(bla_dst->magic, bla_dst_own->magic,
|
||||
sizeof(bla_dst->magic)) != 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* check if there is a claim frame encapsulated deeper in (QinQ) and
|
||||
* drop that, as this is not supported by BLA but should also not be
|
||||
* sent via the mesh.
|
||||
*/
|
||||
if (vlan_depth > 1)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* Let the loopdetect frames on the mesh in any case. */
|
||||
if (bla_dst->type == BATADV_CLAIM_TYPE_LOOPDETECT)
|
||||
return 0;
|
||||
|
||||
/* check if it is a claim frame. */
|
||||
ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
|
||||
@ -1070,7 +1114,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
hw_dst);
|
||||
|
||||
if (ret < 2)
|
||||
return ret;
|
||||
return !!ret;
|
||||
|
||||
/* become a backbone gw ourselves on this vlan if not happened yet */
|
||||
batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
|
||||
@ -1080,30 +1124,30 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
case BATADV_CLAIM_TYPE_CLAIM:
|
||||
if (batadv_handle_claim(bat_priv, primary_if, hw_src,
|
||||
ethhdr->h_source, vid))
|
||||
return 1;
|
||||
return true;
|
||||
break;
|
||||
case BATADV_CLAIM_TYPE_UNCLAIM:
|
||||
if (batadv_handle_unclaim(bat_priv, primary_if,
|
||||
ethhdr->h_source, hw_src, vid))
|
||||
return 1;
|
||||
return true;
|
||||
break;
|
||||
|
||||
case BATADV_CLAIM_TYPE_ANNOUNCE:
|
||||
if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
|
||||
vid))
|
||||
return 1;
|
||||
return true;
|
||||
break;
|
||||
case BATADV_CLAIM_TYPE_REQUEST:
|
||||
if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
|
||||
vid))
|
||||
return 1;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv,
|
||||
"bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
|
||||
ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src, hw_dst);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1264,6 +1308,26 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_send_loopdetect - send a loopdetect frame
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @backbone_gw: the backbone gateway for which a loop should be detected
|
||||
*
|
||||
* To detect loops that the bridge loop avoidance can't handle, send a loop
|
||||
* detection packet on the backbone. Unlike other BLA frames, this frame will
|
||||
* be allowed on the mesh by other nodes. If it is received on the mesh, this
|
||||
* indicates that there is a loop.
|
||||
*/
|
||||
static void
|
||||
batadv_bla_send_loopdetect(struct batadv_priv *bat_priv,
|
||||
struct batadv_bla_backbone_gw *backbone_gw)
|
||||
{
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv, "Send loopdetect frame for vid %d\n",
|
||||
backbone_gw->vid);
|
||||
batadv_bla_send_claim(bat_priv, bat_priv->bla.loopdetect_addr,
|
||||
backbone_gw->vid, BATADV_CLAIM_TYPE_LOOPDETECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_status_update - purge bla interfaces if necessary
|
||||
* @net_dev: the soft interface net device
|
||||
@ -1301,6 +1365,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_hashtable *hash;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
bool send_loopdetect = false;
|
||||
int i;
|
||||
|
||||
delayed_work = to_delayed_work(work);
|
||||
@ -1316,6 +1381,22 @@ static void batadv_bla_periodic_work(struct work_struct *work)
|
||||
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
|
||||
goto out;
|
||||
|
||||
if (atomic_dec_and_test(&bat_priv->bla.loopdetect_next)) {
|
||||
/* set a new random mac address for the next bridge loop
|
||||
* detection frames. Set the locally administered bit to avoid
|
||||
* collisions with users mac addresses.
|
||||
*/
|
||||
random_ether_addr(bat_priv->bla.loopdetect_addr);
|
||||
bat_priv->bla.loopdetect_addr[0] = 0xba;
|
||||
bat_priv->bla.loopdetect_addr[1] = 0xbe;
|
||||
bat_priv->bla.loopdetect_lasttime = jiffies;
|
||||
atomic_set(&bat_priv->bla.loopdetect_next,
|
||||
BATADV_BLA_LOOPDETECT_PERIODS);
|
||||
|
||||
/* mark for sending loop detect on all VLANs */
|
||||
send_loopdetect = true;
|
||||
}
|
||||
|
||||
hash = bat_priv->bla.backbone_hash;
|
||||
if (!hash)
|
||||
goto out;
|
||||
@ -1332,6 +1413,9 @@ static void batadv_bla_periodic_work(struct work_struct *work)
|
||||
backbone_gw->lasttime = jiffies;
|
||||
|
||||
batadv_bla_send_announce(bat_priv, backbone_gw);
|
||||
if (send_loopdetect)
|
||||
batadv_bla_send_loopdetect(bat_priv,
|
||||
backbone_gw);
|
||||
|
||||
/* request_sent is only set after creation to avoid
|
||||
* problems when we are not yet known as backbone gw
|
||||
@ -1405,6 +1489,9 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
|
||||
bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
|
||||
bat_priv->bla.bcast_duplist_curr = 0;
|
||||
|
||||
atomic_set(&bat_priv->bla.loopdetect_next,
|
||||
BATADV_BLA_LOOPDETECT_PERIODS);
|
||||
|
||||
if (bat_priv->bla.claim_hash)
|
||||
return 0;
|
||||
|
||||
@ -1442,15 +1529,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
|
||||
* sent by another host, drop it. We allow equal packets from
|
||||
* the same host however as this might be intended.
|
||||
*
|
||||
* Return: 1 if a packet is in the duplicate list, 0 otherwise.
|
||||
* Return: true if a packet is in the duplicate list, false otherwise.
|
||||
*/
|
||||
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int i, curr, ret = 0;
|
||||
int i, curr;
|
||||
__be32 crc;
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
struct batadv_bcast_duplist_entry *entry;
|
||||
bool ret = false;
|
||||
|
||||
bcast_packet = (struct batadv_bcast_packet *)skb->data;
|
||||
|
||||
@ -1478,9 +1566,9 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
continue;
|
||||
|
||||
/* this entry seems to match: same crc, not too old,
|
||||
* and from another gw. therefore return 1 to forbid it.
|
||||
* and from another gw. therefore return true to forbid it.
|
||||
*/
|
||||
ret = 1;
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
/* not found, add a new entry (overwrite the oldest entry)
|
||||
@ -1546,21 +1634,21 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
|
||||
* @orig_node: the orig_node of the frame
|
||||
* @hdr_size: maximum length of the frame
|
||||
*
|
||||
* Return: 1 if the orig_node is also a gateway on the soft interface, otherwise
|
||||
* it returns 0.
|
||||
* Return: true if the orig_node is also a gateway on the soft interface,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node, int hdr_size)
|
||||
bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node, int hdr_size)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
unsigned short vid;
|
||||
|
||||
if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* first, find out the vid. */
|
||||
if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
vid = batadv_get_vid(skb, hdr_size);
|
||||
|
||||
@ -1568,10 +1656,10 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
|
||||
orig_node->orig, vid);
|
||||
if (!backbone_gw)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1601,6 +1689,55 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_loopdetect_check - check and handle a detected loop
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @skb: the packet to check
|
||||
* @primary_if: interface where the request came on
|
||||
* @vid: the VLAN ID of the frame
|
||||
*
|
||||
* Checks if this packet is a loop detect frame which has been sent by us,
|
||||
* throw an uevent and log the event if that is the case.
|
||||
*
|
||||
* Return: true if it is a loop detect frame which is to be dropped, false
|
||||
* otherwise.
|
||||
*/
|
||||
static bool
|
||||
batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct ethhdr *ethhdr;
|
||||
|
||||
ethhdr = eth_hdr(skb);
|
||||
|
||||
/* Only check for the MAC address and skip more checks here for
|
||||
* performance reasons - this function is on the hotpath, after all.
|
||||
*/
|
||||
if (!batadv_compare_eth(ethhdr->h_source,
|
||||
bat_priv->bla.loopdetect_addr))
|
||||
return false;
|
||||
|
||||
/* If the packet came too late, don't forward it on the mesh
|
||||
* but don't consider that as loop. It might be a coincidence.
|
||||
*/
|
||||
if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
|
||||
BATADV_BLA_LOOPDETECT_TIMEOUT))
|
||||
return true;
|
||||
|
||||
backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
|
||||
primary_if->net_dev->dev_addr,
|
||||
vid, true);
|
||||
if (unlikely(!backbone_gw))
|
||||
return true;
|
||||
|
||||
queue_work(batadv_event_workqueue, &backbone_gw->report_work);
|
||||
/* backbone_gw is unreferenced in the report work function function */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_bla_rx - check packets coming from the mesh.
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
@ -1614,16 +1751,16 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
|
||||
*
|
||||
* in these cases, the skb is further handled by this function
|
||||
*
|
||||
* Return: 1 if handled, otherwise it returns 0 and the caller shall further
|
||||
* process the skb.
|
||||
* Return: true if handled, otherwise it returns false and the caller shall
|
||||
* further process the skb.
|
||||
*/
|
||||
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, bool is_bcast)
|
||||
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, bool is_bcast)
|
||||
{
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_bla_claim search_claim, *claim = NULL;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
int ret;
|
||||
bool ret;
|
||||
|
||||
ethhdr = eth_hdr(skb);
|
||||
|
||||
@ -1634,6 +1771,9 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
|
||||
goto allow;
|
||||
|
||||
if (batadv_bla_loopdetect_check(bat_priv, skb, primary_if, vid))
|
||||
goto handled;
|
||||
|
||||
if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
|
||||
/* don't allow broadcasts while requests are in flight */
|
||||
if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
|
||||
@ -1682,12 +1822,12 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
}
|
||||
allow:
|
||||
batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
|
||||
ret = 0;
|
||||
ret = false;
|
||||
goto out;
|
||||
|
||||
handled:
|
||||
kfree_skb(skb);
|
||||
ret = 1;
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
if (primary_if)
|
||||
@ -1711,16 +1851,16 @@ out:
|
||||
*
|
||||
* This call might reallocate skb data.
|
||||
*
|
||||
* Return: 1 if handled, otherwise it returns 0 and the caller shall further
|
||||
* process the skb.
|
||||
* Return: true if handled, otherwise it returns false and the caller shall
|
||||
* further process the skb.
|
||||
*/
|
||||
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid)
|
||||
bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_bla_claim search_claim, *claim = NULL;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
int ret = 0;
|
||||
bool ret = false;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
@ -1774,10 +1914,10 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
}
|
||||
allow:
|
||||
batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
|
||||
ret = 0;
|
||||
ret = false;
|
||||
goto out;
|
||||
handled:
|
||||
ret = 1;
|
||||
ret = true;
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_put(primary_if);
|
||||
|
@ -27,19 +27,20 @@ struct seq_file;
|
||||
struct sk_buff;
|
||||
|
||||
#ifdef CONFIG_BATMAN_ADV_BLA
|
||||
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, bool is_bcast);
|
||||
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid);
|
||||
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node, int hdr_size);
|
||||
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, bool is_bcast);
|
||||
bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid);
|
||||
bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node,
|
||||
int hdr_size);
|
||||
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
|
||||
int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
|
||||
void *offset);
|
||||
bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
|
||||
unsigned short vid);
|
||||
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb);
|
||||
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
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);
|
||||
@ -50,24 +51,24 @@ void batadv_bla_free(struct batadv_priv *bat_priv);
|
||||
#define BATADV_BLA_CRC_INIT 0
|
||||
#else /* ifdef CONFIG_BATMAN_ADV_BLA */
|
||||
|
||||
static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, unsigned short vid,
|
||||
bool is_bcast)
|
||||
static inline bool batadv_bla_rx(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, unsigned short vid,
|
||||
bool is_bcast)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int batadv_bla_tx(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, unsigned short vid)
|
||||
static inline bool batadv_bla_tx(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, unsigned short vid)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node,
|
||||
int hdr_size)
|
||||
static inline bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node,
|
||||
int hdr_size)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int batadv_bla_claim_table_seq_print_text(struct seq_file *seq,
|
||||
@ -88,11 +89,11 @@ static inline bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline bool
|
||||
batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -134,7 +134,7 @@ static int batadv_log_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int batadv_log_empty(struct batadv_priv_debug_log *debug_log)
|
||||
static bool batadv_log_empty(struct batadv_priv_debug_log *debug_log)
|
||||
{
|
||||
return !(debug_log->log_start - debug_log->log_end);
|
||||
}
|
||||
|
@ -165,14 +165,14 @@ static void batadv_dat_purge(struct work_struct *work)
|
||||
* @node: node in the local table
|
||||
* @data2: second object to compare the node to
|
||||
*
|
||||
* Return: 1 if the two entries are the same, 0 otherwise.
|
||||
* Return: true if the two entries are the same, false otherwise.
|
||||
*/
|
||||
static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
|
||||
static bool batadv_compare_dat(const struct hlist_node *node, const void *data2)
|
||||
{
|
||||
const void *data1 = container_of(node, struct batadv_dat_entry,
|
||||
hash_entry);
|
||||
|
||||
return memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0;
|
||||
return memcmp(data1, data2, sizeof(__be32)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,8 +135,8 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,
|
||||
|
||||
spin_lock_bh(&bat_priv->gw.list_lock);
|
||||
|
||||
if (new_gw_node && !kref_get_unless_zero(&new_gw_node->refcount))
|
||||
new_gw_node = NULL;
|
||||
if (new_gw_node)
|
||||
kref_get(&new_gw_node->refcount);
|
||||
|
||||
curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1);
|
||||
rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node);
|
||||
@ -440,15 +440,11 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
|
||||
if (gateway->bandwidth_down == 0)
|
||||
return;
|
||||
|
||||
if (!kref_get_unless_zero(&orig_node->refcount))
|
||||
return;
|
||||
|
||||
gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
|
||||
if (!gw_node) {
|
||||
batadv_orig_node_put(orig_node);
|
||||
if (!gw_node)
|
||||
return;
|
||||
}
|
||||
|
||||
kref_get(&orig_node->refcount);
|
||||
INIT_HLIST_NODE(&gw_node->list);
|
||||
gw_node->orig_node = orig_node;
|
||||
gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
#include "bridge_loop_avoidance.h"
|
||||
#include "debugfs.h"
|
||||
@ -121,6 +120,7 @@ static bool batadv_mutual_parents(const struct net_device *dev1,
|
||||
static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
|
||||
{
|
||||
struct net_device *parent_dev;
|
||||
struct net *net = dev_net(net_dev);
|
||||
bool ret;
|
||||
|
||||
/* check if this is a batman-adv mesh interface */
|
||||
@ -133,7 +133,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
|
||||
return false;
|
||||
|
||||
/* recurse over the parent device */
|
||||
parent_dev = __dev_get_by_index(&init_net, dev_get_iflink(net_dev));
|
||||
parent_dev = __dev_get_by_index(net, dev_get_iflink(net_dev));
|
||||
/* if we got a NULL parent_dev there is something broken.. */
|
||||
if (WARN(!parent_dev, "Cannot find parent device"))
|
||||
return false;
|
||||
@ -146,22 +146,22 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int batadv_is_valid_iface(const struct net_device *net_dev)
|
||||
static bool batadv_is_valid_iface(const struct net_device *net_dev)
|
||||
{
|
||||
if (net_dev->flags & IFF_LOOPBACK)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (net_dev->type != ARPHRD_ETHER)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (net_dev->addr_len != ETH_ALEN)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* no batman over batman */
|
||||
if (batadv_is_on_batman_iface(net_dev))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,8 +236,8 @@ static void batadv_primary_if_select(struct batadv_priv *bat_priv,
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (new_hard_iface && !kref_get_unless_zero(&new_hard_iface->refcount))
|
||||
new_hard_iface = NULL;
|
||||
if (new_hard_iface)
|
||||
kref_get(&new_hard_iface->refcount);
|
||||
|
||||
curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
|
||||
rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
|
||||
@ -456,7 +456,7 @@ static int batadv_master_del_slave(struct batadv_hard_iface *slave,
|
||||
}
|
||||
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
const char *iface_name)
|
||||
struct net *net, const char *iface_name)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
struct net_device *soft_iface, *master;
|
||||
@ -467,13 +467,12 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
goto out;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
goto out;
|
||||
kref_get(&hard_iface->refcount);
|
||||
|
||||
soft_iface = dev_get_by_name(&init_net, iface_name);
|
||||
soft_iface = dev_get_by_name(net, iface_name);
|
||||
|
||||
if (!soft_iface) {
|
||||
soft_iface = batadv_softif_create(iface_name);
|
||||
soft_iface = batadv_softif_create(net, iface_name);
|
||||
|
||||
if (!soft_iface) {
|
||||
ret = -ENOMEM;
|
||||
@ -522,6 +521,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
goto err_upper;
|
||||
}
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
hard_iface->batman_adv_ptype.type = ethertype;
|
||||
hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
|
||||
hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
|
||||
@ -583,6 +583,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
||||
batadv_info(hard_iface->soft_iface, "Removing interface: %s\n",
|
||||
hard_iface->net_dev->name);
|
||||
dev_remove_pack(&hard_iface->batman_adv_ptype);
|
||||
batadv_hardif_put(hard_iface);
|
||||
|
||||
bat_priv->num_ifaces--;
|
||||
batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
|
||||
@ -652,8 +653,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
ret = batadv_is_valid_iface(net_dev);
|
||||
if (ret != 1)
|
||||
if (!batadv_is_valid_iface(net_dev))
|
||||
goto out;
|
||||
|
||||
dev_hold(net_dev);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
struct net_device;
|
||||
struct net;
|
||||
|
||||
enum batadv_hard_if_state {
|
||||
BATADV_IF_NOT_IN_USE,
|
||||
@ -55,7 +56,7 @@ bool batadv_is_wifi_iface(int ifindex);
|
||||
struct batadv_hard_iface*
|
||||
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
const char *iface_name);
|
||||
struct net *net, const char *iface_name);
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
||||
enum batadv_hard_if_cleanup autodel);
|
||||
void batadv_hardif_remove_interfaces(void);
|
||||
|
@ -32,10 +32,10 @@ struct lock_class_key;
|
||||
/* callback to a compare function. should compare 2 element datas for their
|
||||
* keys
|
||||
*
|
||||
* Return: 0 if same and not 0 if not same
|
||||
* Return: true if same and false if not same
|
||||
*/
|
||||
typedef int (*batadv_hashdata_compare_cb)(const struct hlist_node *,
|
||||
const void *);
|
||||
typedef bool (*batadv_hashdata_compare_cb)(const struct hlist_node *,
|
||||
const void *);
|
||||
|
||||
/* the hashfunction
|
||||
*
|
||||
|
@ -401,11 +401,19 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
hard_iface = container_of(ptype, struct batadv_hard_iface,
|
||||
batman_adv_ptype);
|
||||
|
||||
/* Prevent processing a packet received on an interface which is getting
|
||||
* shut down otherwise the packet may trigger de-reference errors
|
||||
* further down in the receive path.
|
||||
*/
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
goto err_out;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
|
||||
/* skb was released by skb_share_check() */
|
||||
if (!skb)
|
||||
goto err_out;
|
||||
goto err_put;
|
||||
|
||||
/* packet should hold at least type and version */
|
||||
if (unlikely(!pskb_may_pull(skb, 2)))
|
||||
@ -448,6 +456,8 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
if (ret == NET_RX_DROP)
|
||||
kfree_skb(skb);
|
||||
|
||||
batadv_hardif_put(hard_iface);
|
||||
|
||||
/* return NET_RX_SUCCESS in any case as we
|
||||
* most probably dropped the packet for
|
||||
* routing-logical reasons.
|
||||
@ -456,6 +466,8 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
err_free:
|
||||
kfree_skb(skb);
|
||||
err_put:
|
||||
batadv_hardif_put(hard_iface);
|
||||
err_out:
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
@ -736,9 +748,7 @@ batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
|
||||
if (tvlv_tmp->tvlv_hdr.version != version)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&tvlv_tmp->refcount))
|
||||
continue;
|
||||
|
||||
kref_get(&tvlv_tmp->refcount);
|
||||
tvlv = tvlv_tmp;
|
||||
break;
|
||||
}
|
||||
|
@ -120,6 +120,8 @@
|
||||
#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 6)
|
||||
#define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10)
|
||||
#define BATADV_BLA_WAIT_PERIODS 3
|
||||
#define BATADV_BLA_LOOPDETECT_PERIODS 6
|
||||
#define BATADV_BLA_LOOPDETECT_TIMEOUT 3000 /* 3 seconds */
|
||||
|
||||
#define BATADV_DUPLIST_SIZE 16
|
||||
#define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */
|
||||
@ -142,10 +144,12 @@ enum batadv_uev_action {
|
||||
BATADV_UEV_ADD = 0,
|
||||
BATADV_UEV_DEL,
|
||||
BATADV_UEV_CHANGE,
|
||||
BATADV_UEV_LOOPDETECT,
|
||||
};
|
||||
|
||||
enum batadv_uev_type {
|
||||
BATADV_UEV_GW = 0,
|
||||
BATADV_UEV_BLA,
|
||||
};
|
||||
|
||||
#define BATADV_GW_THRESHOLD 50
|
||||
@ -288,7 +292,7 @@ static inline void _batadv_dbg(int type __always_unused,
|
||||
*
|
||||
* note: can't use ether_addr_equal() as it requires aligned memory
|
||||
*
|
||||
* Return: 1 if they are the same ethernet addr
|
||||
* Return: true if they are the same ethernet addr
|
||||
*/
|
||||
static inline bool batadv_compare_eth(const void *data1, const void *data2)
|
||||
{
|
||||
|
@ -510,10 +510,10 @@ static u32 batadv_nc_hash_choose(const void *data, u32 size)
|
||||
* @node: node in the local table
|
||||
* @data2: second object to compare the node to
|
||||
*
|
||||
* Return: 1 if the two entry are the same, 0 otherwise
|
||||
* Return: true if the two entry are the same, false otherwise
|
||||
*/
|
||||
static int batadv_nc_hash_compare(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
static bool batadv_nc_hash_compare(const struct hlist_node *node,
|
||||
const void *data2)
|
||||
{
|
||||
const struct batadv_nc_path *nc_path1, *nc_path2;
|
||||
|
||||
@ -521,15 +521,13 @@ static int batadv_nc_hash_compare(const struct hlist_node *node,
|
||||
nc_path2 = data2;
|
||||
|
||||
/* Return 1 if the two keys are identical */
|
||||
if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop,
|
||||
sizeof(nc_path1->prev_hop)) != 0)
|
||||
return 0;
|
||||
if (!batadv_compare_eth(nc_path1->prev_hop, nc_path2->prev_hop))
|
||||
return false;
|
||||
|
||||
if (memcmp(nc_path1->next_hop, nc_path2->next_hop,
|
||||
sizeof(nc_path1->next_hop)) != 0)
|
||||
return 0;
|
||||
if (!batadv_compare_eth(nc_path1->next_hop, nc_path2->next_hop))
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -856,8 +854,7 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
|
||||
if (!nc_node)
|
||||
return NULL;
|
||||
|
||||
if (!kref_get_unless_zero(&orig_neigh_node->refcount))
|
||||
goto free;
|
||||
kref_get(&orig_neigh_node->refcount);
|
||||
|
||||
/* Initialize nc_node */
|
||||
INIT_LIST_HEAD(&nc_node->list);
|
||||
@ -884,10 +881,6 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
|
||||
spin_unlock_bh(lock);
|
||||
|
||||
return nc_node;
|
||||
|
||||
free:
|
||||
kfree(nc_node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,9 +54,9 @@ static void batadv_purge_orig(struct work_struct *work);
|
||||
* @node: node in the local table
|
||||
* @data2: second object to compare the node to
|
||||
*
|
||||
* Return: 1 if they are the same originator
|
||||
* Return: true if they are the same originator
|
||||
*/
|
||||
int batadv_compare_orig(const struct hlist_node *node, const void *data2)
|
||||
bool batadv_compare_orig(const struct hlist_node *node, const void *data2)
|
||||
{
|
||||
const void *data1 = container_of(node, struct batadv_orig_node,
|
||||
hash_entry);
|
||||
@ -374,12 +374,8 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
|
||||
if (!orig_ifinfo)
|
||||
goto out;
|
||||
|
||||
if (if_outgoing != BATADV_IF_DEFAULT &&
|
||||
!kref_get_unless_zero(&if_outgoing->refcount)) {
|
||||
kfree(orig_ifinfo);
|
||||
orig_ifinfo = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (if_outgoing != BATADV_IF_DEFAULT)
|
||||
kref_get(&if_outgoing->refcount);
|
||||
|
||||
reset_time = jiffies - 1;
|
||||
reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
|
||||
@ -455,11 +451,8 @@ batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
|
||||
if (!neigh_ifinfo)
|
||||
goto out;
|
||||
|
||||
if (if_outgoing && !kref_get_unless_zero(&if_outgoing->refcount)) {
|
||||
kfree(neigh_ifinfo);
|
||||
neigh_ifinfo = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (if_outgoing)
|
||||
kref_get(&if_outgoing->refcount);
|
||||
|
||||
INIT_HLIST_NODE(&neigh_ifinfo->list);
|
||||
kref_init(&neigh_ifinfo->refcount);
|
||||
@ -532,15 +525,11 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
|
||||
if (hardif_neigh)
|
||||
goto out;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
goto out;
|
||||
|
||||
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC);
|
||||
if (!hardif_neigh) {
|
||||
batadv_hardif_put(hard_iface);
|
||||
if (!hardif_neigh)
|
||||
goto out;
|
||||
}
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
INIT_HLIST_NODE(&hardif_neigh->list);
|
||||
ether_addr_copy(hardif_neigh->addr, neigh_addr);
|
||||
hardif_neigh->if_incoming = hard_iface;
|
||||
@ -643,16 +632,11 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
|
||||
if (!neigh_node)
|
||||
goto out;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount)) {
|
||||
kfree(neigh_node);
|
||||
neigh_node = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_HLIST_NODE(&neigh_node->list);
|
||||
INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
|
||||
spin_lock_init(&neigh_node->ifinfo_lock);
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
ether_addr_copy(neigh_node->addr, neigh_addr);
|
||||
neigh_node->if_incoming = hard_iface;
|
||||
neigh_node->orig_node = orig_node;
|
||||
@ -1160,6 +1144,9 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
if (hard_iface->soft_iface != bat_priv->soft_iface)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
best_neigh_node = batadv_find_best_neighbor(bat_priv,
|
||||
orig_node,
|
||||
hard_iface);
|
||||
@ -1167,6 +1154,8 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
best_neigh_node);
|
||||
if (best_neigh_node)
|
||||
batadv_neigh_node_put(best_neigh_node);
|
||||
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
struct seq_file;
|
||||
|
||||
int batadv_compare_orig(const struct hlist_node *node, const void *data2);
|
||||
bool batadv_compare_orig(const struct hlist_node *node, const void *data2);
|
||||
int batadv_originator_init(struct batadv_priv *bat_priv);
|
||||
void batadv_originator_free(struct batadv_priv *bat_priv);
|
||||
void batadv_purge_orig_ref(struct batadv_priv *bat_priv);
|
||||
|
@ -175,6 +175,7 @@ enum batadv_bla_claimframe {
|
||||
BATADV_CLAIM_TYPE_UNCLAIM = 0x01,
|
||||
BATADV_CLAIM_TYPE_ANNOUNCE = 0x02,
|
||||
BATADV_CLAIM_TYPE_REQUEST = 0x03,
|
||||
BATADV_CLAIM_TYPE_LOOPDETECT = 0x04,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -100,10 +100,6 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
|
||||
if (curr_router)
|
||||
batadv_neigh_node_put(curr_router);
|
||||
|
||||
/* increase refcount of new best neighbor */
|
||||
if (neigh_node && !kref_get_unless_zero(&neigh_node->refcount))
|
||||
neigh_node = NULL;
|
||||
|
||||
spin_lock_bh(&orig_node->neigh_list_lock);
|
||||
/* curr_router used earlier may not be the current orig_ifinfo->router
|
||||
* anymore because it was dereferenced outside of the neigh_list_lock
|
||||
@ -114,6 +110,10 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
curr_router = rcu_dereference_protected(orig_ifinfo->router, true);
|
||||
|
||||
/* increase refcount of new best neighbor */
|
||||
if (neigh_node)
|
||||
kref_get(&neigh_node->refcount);
|
||||
|
||||
rcu_assign_pointer(orig_ifinfo->router, neigh_node);
|
||||
spin_unlock_bh(&orig_node->neigh_list_lock);
|
||||
batadv_orig_ifinfo_put(orig_ifinfo);
|
||||
@ -163,18 +163,18 @@ out:
|
||||
* doesn't change otherwise.
|
||||
*
|
||||
* Return:
|
||||
* 0 if the packet is to be accepted.
|
||||
* 1 if the packet is to be ignored.
|
||||
* false if the packet is to be accepted.
|
||||
* true if the packet is to be ignored.
|
||||
*/
|
||||
int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
s32 seq_old_max_diff, unsigned long *last_reset,
|
||||
bool *protection_started)
|
||||
bool batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
s32 seq_old_max_diff, unsigned long *last_reset,
|
||||
bool *protection_started)
|
||||
{
|
||||
if (seq_num_diff <= -seq_old_max_diff ||
|
||||
seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
|
||||
if (!batadv_has_timed_out(*last_reset,
|
||||
BATADV_RESET_PROTECTION_MS))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
*last_reset = jiffies;
|
||||
if (protection_started)
|
||||
@ -183,7 +183,7 @@ int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
"old packet received, start protection\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool batadv_check_management_packet(struct sk_buff *skb,
|
||||
@ -718,8 +718,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_len) {
|
||||
static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_len)
|
||||
{
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_orig_node *orig_node;
|
||||
@ -730,11 +731,11 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
|
||||
/* check if there is enough data before accessing it */
|
||||
if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* create a copy of the skb (in case of for re-routing) to modify it. */
|
||||
if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
unicast_packet = (struct batadv_unicast_packet *)skb->data;
|
||||
vid = batadv_get_vid(skb, hdr_len);
|
||||
@ -758,7 +759,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
* table. If not, let the packet go untouched anyway because
|
||||
* there is nothing the node can do
|
||||
*/
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* retrieve the TTVN known by this node for the packet destination. This
|
||||
@ -774,7 +775,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
* not be possible to deliver it
|
||||
*/
|
||||
if (!orig_node)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
curr_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
|
||||
batadv_orig_node_put(orig_node);
|
||||
@ -785,7 +786,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
|
||||
if (!is_old_ttvn)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
old_ttvn = unicast_packet->ttvn;
|
||||
/* the packet was forged based on outdated network information. Its
|
||||
@ -798,7 +799,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
"Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
|
||||
unicast_packet->dest, ethhdr->h_dest,
|
||||
old_ttvn, curr_ttvn);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* the packet has not been re-routed: either the destination is
|
||||
@ -806,14 +807,14 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
* it is possible to drop the packet
|
||||
*/
|
||||
if (!batadv_is_my_client(bat_priv, ethhdr->h_dest, vid))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* update the header in order to let the packet be delivered to this
|
||||
* node's soft interface
|
||||
*/
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr);
|
||||
|
||||
@ -821,7 +822,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
|
||||
unicast_packet->ttvn = curr_ttvn;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -912,7 +913,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
|
||||
hdr_size))
|
||||
goto rx_success;
|
||||
|
||||
batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
|
||||
batadv_interface_rx(recv_if->soft_iface, skb, hdr_size,
|
||||
orig_node);
|
||||
|
||||
rx_success:
|
||||
@ -1122,8 +1123,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
|
||||
goto rx_success;
|
||||
|
||||
/* broadcast for me */
|
||||
batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
|
||||
orig_node);
|
||||
batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node);
|
||||
|
||||
rx_success:
|
||||
ret = NET_RX_SUCCESS;
|
||||
|
@ -51,8 +51,8 @@ struct batadv_neigh_node *
|
||||
batadv_find_router(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *recv_if);
|
||||
int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
s32 seq_old_max_diff, unsigned long *last_reset,
|
||||
bool *protection_started);
|
||||
bool batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
s32 seq_old_max_diff, unsigned long *last_reset,
|
||||
bool *protection_started);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/if.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/printk.h>
|
||||
@ -577,10 +578,15 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
||||
if (forw_packet->num_packets >= hard_iface->num_bcasts)
|
||||
continue;
|
||||
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
/* send a copy of the saved skb */
|
||||
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
|
||||
if (skb1)
|
||||
batadv_send_broadcast_skb(skb1, hard_iface);
|
||||
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
@ -186,7 +186,6 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
__be16 ethertype = htons(ETH_P_BATMAN);
|
||||
static const u8 stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
|
||||
0x00, 0x00};
|
||||
static const u8 ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
|
||||
@ -216,7 +215,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
case ETH_P_8021Q:
|
||||
vhdr = vlan_eth_hdr(skb);
|
||||
|
||||
if (vhdr->h_vlan_encapsulated_proto != ethertype) {
|
||||
/* drop batman-in-batman packets to prevent loops */
|
||||
if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) {
|
||||
network_offset += VLAN_HLEN;
|
||||
break;
|
||||
}
|
||||
@ -385,7 +385,6 @@ end:
|
||||
* batadv_interface_rx - receive ethernet frame on local batman-adv interface
|
||||
* @soft_iface: local interface which will receive the ethernet frame
|
||||
* @skb: ethernet frame for @soft_iface
|
||||
* @recv_if: interface on which the batman-adv packet was received
|
||||
* @hdr_size: size of already parsed batman-adv header
|
||||
* @orig_node: originator from which the batman-adv packet was sent
|
||||
*
|
||||
@ -400,12 +399,11 @@ end:
|
||||
* isolated clients.
|
||||
*/
|
||||
void batadv_interface_rx(struct net_device *soft_iface,
|
||||
struct sk_buff *skb, struct batadv_hard_iface *recv_if,
|
||||
int hdr_size, struct batadv_orig_node *orig_node)
|
||||
struct sk_buff *skb, int hdr_size,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_bcast_packet *batadv_bcast_packet;
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
__be16 ethertype = htons(ETH_P_BATMAN);
|
||||
struct vlan_ethhdr *vhdr;
|
||||
struct ethhdr *ethhdr;
|
||||
unsigned short vid;
|
||||
@ -414,10 +412,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
|
||||
batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
|
||||
is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
|
||||
|
||||
/* check if enough space is available for pulling, and pull */
|
||||
if (!pskb_may_pull(skb, hdr_size))
|
||||
goto dropped;
|
||||
|
||||
skb_pull_rcsum(skb, hdr_size);
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
@ -439,7 +433,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
|
||||
|
||||
vhdr = (struct vlan_ethhdr *)skb->data;
|
||||
|
||||
if (vhdr->h_vlan_encapsulated_proto != ethertype)
|
||||
/* drop batman-in-batman packets to prevent loops */
|
||||
if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN))
|
||||
break;
|
||||
|
||||
/* fall through */
|
||||
@ -890,13 +885,14 @@ static int batadv_softif_slave_add(struct net_device *dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct net *net = dev_net(dev);
|
||||
int ret = -EINVAL;
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
|
||||
if (!hard_iface || hard_iface->soft_iface)
|
||||
goto out;
|
||||
|
||||
ret = batadv_hardif_enable_interface(hard_iface, dev->name);
|
||||
ret = batadv_hardif_enable_interface(hard_iface, net, dev->name);
|
||||
|
||||
out:
|
||||
if (hard_iface)
|
||||
@ -977,7 +973,7 @@ static void batadv_softif_init_early(struct net_device *dev)
|
||||
|
||||
dev->netdev_ops = &batadv_netdev_ops;
|
||||
dev->destructor = batadv_softif_free;
|
||||
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
|
||||
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL;
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
|
||||
/* can't call min_mtu, because the needed variables
|
||||
@ -993,7 +989,7 @@ static void batadv_softif_init_early(struct net_device *dev)
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
}
|
||||
|
||||
struct net_device *batadv_softif_create(const char *name)
|
||||
struct net_device *batadv_softif_create(struct net *net, const char *name)
|
||||
{
|
||||
struct net_device *soft_iface;
|
||||
int ret;
|
||||
@ -1003,6 +999,8 @@ struct net_device *batadv_softif_create(const char *name)
|
||||
if (!soft_iface)
|
||||
return NULL;
|
||||
|
||||
dev_net_set(soft_iface, net);
|
||||
|
||||
soft_iface->rtnl_link_ops = &batadv_link_ops;
|
||||
|
||||
ret = register_netdevice(soft_iface);
|
||||
@ -1047,12 +1045,12 @@ static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
|
||||
unregister_netdevice_queue(soft_iface, head);
|
||||
}
|
||||
|
||||
int batadv_softif_is_valid(const struct net_device *net_dev)
|
||||
bool batadv_softif_is_valid(const struct net_device *net_dev)
|
||||
{
|
||||
if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct rtnl_link_ops batadv_link_ops __read_mostly = {
|
||||
|
@ -20,18 +20,20 @@
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <net/rtnetlink.h>
|
||||
|
||||
struct net_device;
|
||||
struct net;
|
||||
struct sk_buff;
|
||||
|
||||
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
|
||||
void batadv_interface_rx(struct net_device *soft_iface,
|
||||
struct sk_buff *skb, struct batadv_hard_iface *recv_if,
|
||||
int hdr_size, struct batadv_orig_node *orig_node);
|
||||
struct net_device *batadv_softif_create(const char *name);
|
||||
struct sk_buff *skb, int hdr_size,
|
||||
struct batadv_orig_node *orig_node);
|
||||
struct net_device *batadv_softif_create(struct net *net, const char *name);
|
||||
void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
|
||||
int batadv_softif_is_valid(const struct net_device *net_dev);
|
||||
bool batadv_softif_is_valid(const struct net_device *net_dev);
|
||||
extern struct rtnl_link_ops batadv_link_ops;
|
||||
int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
|
||||
void batadv_softif_vlan_put(struct batadv_softif_vlan *softif_vlan);
|
||||
|
@ -116,11 +116,13 @@ batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
|
||||
static char *batadv_uev_action_str[] = {
|
||||
"add",
|
||||
"del",
|
||||
"change"
|
||||
"change",
|
||||
"loopdetect",
|
||||
};
|
||||
|
||||
static char *batadv_uev_type_str[] = {
|
||||
"gw"
|
||||
"gw",
|
||||
"bla",
|
||||
};
|
||||
|
||||
/* Use this, if you have customized show and store functions for vlan attrs */
|
||||
@ -830,6 +832,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
|
||||
size_t count)
|
||||
{
|
||||
struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
|
||||
struct net *net = dev_net(net_dev);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int status_tmp = -1;
|
||||
int ret = count;
|
||||
@ -873,7 +876,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
BATADV_IF_CLEANUP_AUTO);
|
||||
|
||||
ret = batadv_hardif_enable_interface(hard_iface, buff);
|
||||
ret = batadv_hardif_enable_interface(hard_iface, net, buff);
|
||||
|
||||
unlock:
|
||||
rtnl_unlock();
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
#include "bridge_loop_avoidance.h"
|
||||
#include "hard-interface.h"
|
||||
@ -76,9 +75,9 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
|
||||
*
|
||||
* Compare the MAC address and the VLAN ID of the two TT entries and check if
|
||||
* they are the same TT client.
|
||||
* Return: 1 if the two TT clients are the same, 0 otherwise
|
||||
* Return: true if the two TT clients are the same, false otherwise
|
||||
*/
|
||||
static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
|
||||
static bool batadv_compare_tt(const struct hlist_node *node, const void *data2)
|
||||
{
|
||||
const void *data1 = container_of(node, struct batadv_tt_common_entry,
|
||||
hash_entry);
|
||||
@ -585,6 +584,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_tt_global_entry *tt_global = NULL;
|
||||
struct net *net = dev_net(soft_iface);
|
||||
struct batadv_softif_vlan *vlan;
|
||||
struct net_device *in_dev = NULL;
|
||||
struct hlist_head *head;
|
||||
@ -596,7 +596,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
|
||||
u32 match_mark;
|
||||
|
||||
if (ifindex != BATADV_NULL_IFINDEX)
|
||||
in_dev = dev_get_by_index(&init_net, ifindex);
|
||||
in_dev = dev_get_by_index(net, ifindex);
|
||||
|
||||
tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
|
||||
|
||||
@ -2361,19 +2361,19 @@ unlock:
|
||||
* @entry_ptr: to be checked local tt entry
|
||||
* @data_ptr: not used but definition required to satisfy the callback prototype
|
||||
*
|
||||
* Return: 1 if the entry is a valid, 0 otherwise.
|
||||
* Return: true if the entry is a valid, false otherwise.
|
||||
*/
|
||||
static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
|
||||
static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
|
||||
{
|
||||
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
|
||||
|
||||
if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
|
||||
return 0;
|
||||
return 1;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int batadv_tt_global_valid(const void *entry_ptr,
|
||||
const void *data_ptr)
|
||||
static bool batadv_tt_global_valid(const void *entry_ptr,
|
||||
const void *data_ptr)
|
||||
{
|
||||
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
|
||||
const struct batadv_tt_global_entry *tt_global_entry;
|
||||
@ -2381,7 +2381,7 @@ static int batadv_tt_global_valid(const void *entry_ptr,
|
||||
|
||||
if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
|
||||
tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
tt_global_entry = container_of(tt_common_entry,
|
||||
struct batadv_tt_global_entry,
|
||||
@ -2403,7 +2403,8 @@ static int batadv_tt_global_valid(const void *entry_ptr,
|
||||
static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
|
||||
struct batadv_hashtable *hash,
|
||||
void *tvlv_buff, u16 tt_len,
|
||||
int (*valid_cb)(const void *, const void *),
|
||||
bool (*valid_cb)(const void *,
|
||||
const void *),
|
||||
void *cb_data)
|
||||
{
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
@ -2552,11 +2553,11 @@ static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
|
||||
*
|
||||
* Return: true if the TT Request was sent, false otherwise
|
||||
*/
|
||||
static int batadv_send_tt_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *dst_orig_node,
|
||||
u8 ttvn,
|
||||
struct batadv_tvlv_tt_vlan_data *tt_vlan,
|
||||
u16 num_vlan, bool full_table)
|
||||
static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *dst_orig_node,
|
||||
u8 ttvn,
|
||||
struct batadv_tvlv_tt_vlan_data *tt_vlan,
|
||||
u16 num_vlan, bool full_table)
|
||||
{
|
||||
struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
|
||||
struct batadv_tt_req_node *tt_req_node = NULL;
|
||||
|
@ -657,6 +657,9 @@ struct batadv_priv_tt {
|
||||
* @num_requests: number of bla requests in flight
|
||||
* @claim_hash: hash table containing mesh nodes this host has claimed
|
||||
* @backbone_hash: hash table containing all detected backbone gateways
|
||||
* @loopdetect_addr: MAC address used for own loopdetection frames
|
||||
* @loopdetect_lasttime: time when the loopdetection frames were sent
|
||||
* @loopdetect_next: how many periods to wait for the next loopdetect process
|
||||
* @bcast_duplist: recently received broadcast packets array (for broadcast
|
||||
* duplicate suppression)
|
||||
* @bcast_duplist_curr: index of last broadcast packet added to bcast_duplist
|
||||
@ -668,6 +671,9 @@ struct batadv_priv_bla {
|
||||
atomic_t num_requests;
|
||||
struct batadv_hashtable *claim_hash;
|
||||
struct batadv_hashtable *backbone_hash;
|
||||
u8 loopdetect_addr[ETH_ALEN];
|
||||
unsigned long loopdetect_lasttime;
|
||||
atomic_t loopdetect_next;
|
||||
struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
|
||||
int bcast_duplist_curr;
|
||||
/* protects bcast_duplist & bcast_duplist_curr */
|
||||
@ -1012,6 +1018,7 @@ struct batadv_socket_packet {
|
||||
* resolved
|
||||
* @crc: crc16 checksum over all claims
|
||||
* @crc_lock: lock protecting crc
|
||||
* @report_work: work struct for reporting detected loops
|
||||
* @refcount: number of contexts the object is used
|
||||
* @rcu: struct used for freeing in an RCU-safe manner
|
||||
*/
|
||||
@ -1025,6 +1032,7 @@ struct batadv_bla_backbone_gw {
|
||||
atomic_t request_sent;
|
||||
u16 crc;
|
||||
spinlock_t crc_lock; /* protects crc */
|
||||
struct work_struct report_work;
|
||||
struct kref refcount;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user