Commit cf88585b authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 953abb38 676970e5
......@@ -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 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
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,9 +1168,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
* @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,
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,
......@@ -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,
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,9 +101,9 @@ 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,
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,
......@@ -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,9 +125,9 @@ 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,
static bool batadv_compare_claim(const struct hlist_node *node,
const void *data2)
{
const void *data1 = container_of(node, struct batadv_bla_claim,
......@@ -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 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
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,
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,
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,9 +867,9 @@ 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,
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)
......@@ -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,9 +905,9 @@ 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,
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)
......@@ -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,10 +1015,10 @@ 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,
static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if,
struct sk_buff *skb)
{
......@@ -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,
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,
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,
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 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
*
* 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,
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,18 +27,19 @@ struct seq_file;
struct sk_buff;
#ifdef CONFIG_BATMAN_ADV_BLA
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
bool 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,
bool 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_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,
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,
......@@ -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,
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,
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,
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,9 +32,9 @@ 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 *,
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,9 +510,9 @@ 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,
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,10 +163,10 @@ void batadv_update_route(struct batadv_priv *bat_priv,
* 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,
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)
{
......@@ -174,7 +174,7 @@ int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_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 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
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,7 +51,7 @@ 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,
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);
......
......@@ -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 @@ static int batadv_interface_tx(struct sk_buff *skb,
* 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 @@ static int batadv_interface_tx(struct sk_buff *skb,
* 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,18 +2361,18 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv,
* @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,
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;
......@@ -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,7 +2553,7 @@ 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,
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,
......
......@@ -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;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment