Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -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();

+13 −1
Original line number Diff line number Diff line
@@ -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:
+8 −8
Original line number Diff line number Diff line
@@ -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;
}
+8 −7
Original line number Diff line number Diff line
@@ -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_ */
+227 −87

File changed.

Preview size limit exceeded, changes collapsed.

Loading