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

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

Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge

parents 5e2b61f7 e44d8fe2
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
			       int packet_len,
			       unsigned long send_time,
			       bool directlink,
			       struct batman_if *if_incoming,
			       struct hard_iface *if_incoming,
			       struct forw_packet *forw_packet)
{
	struct batman_packet *batman_packet =
@@ -99,7 +99,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
/* create a new aggregated packet and add this packet to it */
static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
				  unsigned long send_time, bool direct_link,
				  struct batman_if *if_incoming,
				  struct hard_iface *if_incoming,
				  int own_packet)
{
	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -188,7 +188,7 @@ static void aggregate(struct forw_packet *forw_packet_aggr,

void add_bat_packet_to_list(struct bat_priv *bat_priv,
			    unsigned char *packet_buff, int packet_len,
			    struct batman_if *if_incoming, char own_packet,
			    struct hard_iface *if_incoming, char own_packet,
			    unsigned long send_time)
{
	/**
@@ -247,7 +247,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,

/* unpack the aggregated packets and process them one by one */
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
			     int packet_len, struct batman_if *if_incoming)
			     int packet_len, struct hard_iface *if_incoming)
{
	struct batman_packet *batman_packet;
	int buff_pos = 0;
+2 −2
Original line number Diff line number Diff line
@@ -35,9 +35,9 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)

void add_bat_packet_to_list(struct bat_priv *bat_priv,
			    unsigned char *packet_buff, int packet_len,
			    struct batman_if *if_incoming, char own_packet,
			    struct hard_iface *if_incoming, char own_packet,
			    unsigned long send_time);
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
			     int packet_len, struct batman_if *if_incoming);
			     int packet_len, struct hard_iface *if_incoming);

#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
+26 −25
Original line number Diff line number Diff line
@@ -441,16 +441,16 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
			       char *buff)
{
	struct net_device *net_dev = kobj_to_netdev(kobj);
	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
	ssize_t length;

	if (!batman_if)
	if (!hard_iface)
		return 0;

	length = sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ?
			 "none" : batman_if->soft_iface->name);
	length = sprintf(buff, "%s\n", hard_iface->if_status == IF_NOT_IN_USE ?
			 "none" : hard_iface->soft_iface->name);

	kref_put(&batman_if->refcount, hardif_free_ref);
	hardif_free_ref(hard_iface);

	return length;
}
@@ -459,11 +459,11 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
				char *buff, size_t count)
{
	struct net_device *net_dev = kobj_to_netdev(kobj);
	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
	int status_tmp = -1;
	int ret;
	int ret = count;

	if (!batman_if)
	if (!hard_iface)
		return count;

	if (buff[count - 1] == '\n')
@@ -472,7 +472,7 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
	if (strlen(buff) >= IFNAMSIZ) {
		pr_err("Invalid parameter for 'mesh_iface' setting received: "
		       "interface name too long '%s'\n", buff);
		kref_put(&batman_if->refcount, hardif_free_ref);
		hardif_free_ref(hard_iface);
		return -EINVAL;
	}

@@ -481,30 +481,31 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
	else
		status_tmp = IF_I_WANT_YOU;

	if ((batman_if->if_status == status_tmp) || ((batman_if->soft_iface) &&
	    (strncmp(batman_if->soft_iface->name, buff, IFNAMSIZ) == 0))) {
		kref_put(&batman_if->refcount, hardif_free_ref);
		return count;
	}
	if (hard_iface->if_status == status_tmp)
		goto out;

	if ((hard_iface->soft_iface) &&
	    (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
		goto out;

	if (status_tmp == IF_NOT_IN_USE) {
		rtnl_lock();
		hardif_disable_interface(batman_if);
		hardif_disable_interface(hard_iface);
		rtnl_unlock();
		kref_put(&batman_if->refcount, hardif_free_ref);
		return count;
		goto out;
	}

	/* if the interface already is in use */
	if (batman_if->if_status != IF_NOT_IN_USE) {
	if (hard_iface->if_status != IF_NOT_IN_USE) {
		rtnl_lock();
		hardif_disable_interface(batman_if);
		hardif_disable_interface(hard_iface);
		rtnl_unlock();
	}

	ret = hardif_enable_interface(batman_if, buff);
	kref_put(&batman_if->refcount, hardif_free_ref);
	ret = hardif_enable_interface(hard_iface, buff);

out:
	hardif_free_ref(hard_iface);
	return ret;
}

@@ -512,13 +513,13 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
				 char *buff)
{
	struct net_device *net_dev = kobj_to_netdev(kobj);
	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
	ssize_t length;

	if (!batman_if)
	if (!hard_iface)
		return 0;

	switch (batman_if->if_status) {
	switch (hard_iface->if_status) {
	case IF_TO_BE_REMOVED:
		length = sprintf(buff, "disabling\n");
		break;
@@ -537,7 +538,7 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
		break;
	}

	kref_put(&batman_if->refcount, hardif_free_ref);
	hardif_free_ref(hard_iface);

	return length;
}
+90 −50
Original line number Diff line number Diff line
@@ -28,58 +28,75 @@
#include <linux/udp.h>
#include <linux/if_vlan.h>

static void gw_node_free_ref(struct kref *refcount)
static void gw_node_free_rcu(struct rcu_head *rcu)
{
	struct gw_node *gw_node;

	gw_node = container_of(refcount, struct gw_node, refcount);
	gw_node = container_of(rcu, struct gw_node, rcu);
	kfree(gw_node);
}

static void gw_node_free_rcu(struct rcu_head *rcu)
static void gw_node_free_ref(struct gw_node *gw_node)
{
	struct gw_node *gw_node;

	gw_node = container_of(rcu, struct gw_node, rcu);
	kref_put(&gw_node->refcount, gw_node_free_ref);
	if (atomic_dec_and_test(&gw_node->refcount))
		call_rcu(&gw_node->rcu, gw_node_free_rcu);
}

void *gw_get_selected(struct bat_priv *bat_priv)
{
	struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
	struct gw_node *curr_gateway_tmp;
	struct orig_node *orig_node = NULL;

	rcu_read_lock();
	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
	if (!curr_gateway_tmp)
		return NULL;
		goto out;

	orig_node = curr_gateway_tmp->orig_node;
	if (!orig_node)
		goto out;

	if (!atomic_inc_not_zero(&orig_node->refcount))
		orig_node = NULL;

	return curr_gateway_tmp->orig_node;
out:
	rcu_read_unlock();
	return orig_node;
}

void gw_deselect(struct bat_priv *bat_priv)
{
	struct gw_node *gw_node = bat_priv->curr_gw;
	struct gw_node *gw_node;

	bat_priv->curr_gw = NULL;
	spin_lock_bh(&bat_priv->gw_list_lock);
	gw_node = rcu_dereference(bat_priv->curr_gw);
	rcu_assign_pointer(bat_priv->curr_gw, NULL);
	spin_unlock_bh(&bat_priv->gw_list_lock);

	if (gw_node)
		kref_put(&gw_node->refcount, gw_node_free_ref);
		gw_node_free_ref(gw_node);
}

static struct gw_node *gw_select(struct bat_priv *bat_priv,
			  struct gw_node *new_gw_node)
static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
{
	struct gw_node *curr_gw_node = bat_priv->curr_gw;
	struct gw_node *curr_gw_node;

	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
		new_gw_node = NULL;

	if (new_gw_node)
		kref_get(&new_gw_node->refcount);
	spin_lock_bh(&bat_priv->gw_list_lock);
	curr_gw_node = rcu_dereference(bat_priv->curr_gw);
	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
	spin_unlock_bh(&bat_priv->gw_list_lock);

	bat_priv->curr_gw = new_gw_node;
	return curr_gw_node;
	if (curr_gw_node)
		gw_node_free_ref(curr_gw_node);
}

void gw_election(struct bat_priv *bat_priv)
{
	struct hlist_node *node;
	struct gw_node *gw_node, *curr_gw_tmp = NULL, *old_gw_node = NULL;
	struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL;
	uint8_t max_tq = 0;
	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
	int down, up;
@@ -93,19 +110,23 @@ void gw_election(struct bat_priv *bat_priv)
	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
		return;

	if (bat_priv->curr_gw)
	rcu_read_lock();
	curr_gw = rcu_dereference(bat_priv->curr_gw);
	if (curr_gw) {
		rcu_read_unlock();
		return;
	}

	rcu_read_lock();
	if (hlist_empty(&bat_priv->gw_list)) {
		rcu_read_unlock();

		if (bat_priv->curr_gw) {
		if (curr_gw) {
			rcu_read_unlock();
			bat_dbg(DBG_BATMAN, bat_priv,
				"Removing selected gateway - "
				"no gateway in range\n");
			gw_deselect(bat_priv);
		}
		} else
			rcu_read_unlock();

		return;
	}
@@ -154,12 +175,12 @@ void gw_election(struct bat_priv *bat_priv)
			max_gw_factor = tmp_gw_factor;
	}

	if (bat_priv->curr_gw != curr_gw_tmp) {
		if ((bat_priv->curr_gw) && (!curr_gw_tmp))
	if (curr_gw != curr_gw_tmp) {
		if ((curr_gw) && (!curr_gw_tmp))
			bat_dbg(DBG_BATMAN, bat_priv,
				"Removing selected gateway - "
				"no gateway in range\n");
		else if ((!bat_priv->curr_gw) && (curr_gw_tmp))
		else if ((!curr_gw) && (curr_gw_tmp))
			bat_dbg(DBG_BATMAN, bat_priv,
				"Adding route to gateway %pM "
				"(gw_flags: %i, tq: %i)\n",
@@ -174,43 +195,43 @@ void gw_election(struct bat_priv *bat_priv)
				curr_gw_tmp->orig_node->gw_flags,
				curr_gw_tmp->orig_node->router->tq_avg);

		old_gw_node = gw_select(bat_priv, curr_gw_tmp);
		gw_select(bat_priv, curr_gw_tmp);
	}

	rcu_read_unlock();

	/* the kfree() has to be outside of the rcu lock */
	if (old_gw_node)
		kref_put(&old_gw_node->refcount, gw_node_free_ref);
}

void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
{
	struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
	struct gw_node *curr_gateway_tmp;
	uint8_t gw_tq_avg, orig_tq_avg;

	rcu_read_lock();
	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
	if (!curr_gateway_tmp)
		return;
		goto out_rcu;

	if (!curr_gateway_tmp->orig_node)
		goto deselect;
		goto deselect_rcu;

	if (!curr_gateway_tmp->orig_node->router)
		goto deselect;
		goto deselect_rcu;

	/* this node already is the gateway */
	if (curr_gateway_tmp->orig_node == orig_node)
		return;
		goto out_rcu;

	if (!orig_node->router)
		return;
		goto out_rcu;

	gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg;
	rcu_read_unlock();

	orig_tq_avg = orig_node->router->tq_avg;

	/* the TQ value has to be better */
	if (orig_tq_avg < gw_tq_avg)
		return;
		goto out;

	/**
	 * if the routing class is greater than 3 the value tells us how much
@@ -218,15 +239,23 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
	 **/
	if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
	    (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
		return;
		goto out;

	bat_dbg(DBG_BATMAN, bat_priv,
		"Restarting gateway selection: better gateway found (tq curr: "
		"%i, tq new: %i)\n",
		gw_tq_avg, orig_tq_avg);
	goto deselect;

out_rcu:
	rcu_read_unlock();
	goto out;
deselect_rcu:
	rcu_read_unlock();
deselect:
	gw_deselect(bat_priv);
out:
	return;
}

static void gw_node_add(struct bat_priv *bat_priv,
@@ -242,7 +271,7 @@ static void gw_node_add(struct bat_priv *bat_priv,
	memset(gw_node, 0, sizeof(struct gw_node));
	INIT_HLIST_NODE(&gw_node->list);
	gw_node->orig_node = orig_node;
	kref_init(&gw_node->refcount);
	atomic_set(&gw_node->refcount, 1);

	spin_lock_bh(&bat_priv->gw_list_lock);
	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
@@ -283,7 +312,7 @@ void gw_node_update(struct bat_priv *bat_priv,
				"Gateway %pM removed from gateway list\n",
				orig_node->orig);

			if (gw_node == bat_priv->curr_gw) {
			if (gw_node == rcu_dereference(bat_priv->curr_gw)) {
				rcu_read_unlock();
				gw_deselect(bat_priv);
				return;
@@ -321,11 +350,11 @@ void gw_node_purge(struct bat_priv *bat_priv)
		    atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
			continue;

		if (bat_priv->curr_gw == gw_node)
		if (rcu_dereference(bat_priv->curr_gw) == gw_node)
			gw_deselect(bat_priv);

		hlist_del_rcu(&gw_node->list);
		call_rcu(&gw_node->rcu, gw_node_free_rcu);
		gw_node_free_ref(gw_node);
	}


@@ -335,12 +364,16 @@ void gw_node_purge(struct bat_priv *bat_priv)
static int _write_buffer_text(struct bat_priv *bat_priv,
			      struct seq_file *seq, struct gw_node *gw_node)
{
	int down, up;
	struct gw_node *curr_gw;
	int down, up, ret;

	gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);

	return seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
		       (bat_priv->curr_gw == gw_node ? "=>" : "  "),
	rcu_read_lock();
	curr_gw = rcu_dereference(bat_priv->curr_gw);

	ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
		       (curr_gw == gw_node ? "=>" : "  "),
		       gw_node->orig_node->orig,
		       gw_node->orig_node->router->tq_avg,
		       gw_node->orig_node->router->addr,
@@ -350,6 +383,9 @@ static int _write_buffer_text(struct bat_priv *bat_priv,
		       (down > 2048 ? "MBit" : "KBit"),
		       (up > 2048 ? up / 1024 : up),
		       (up > 2048 ? "MBit" : "KBit"));

	rcu_read_unlock();
	return ret;
}

int gw_client_seq_print_text(struct seq_file *seq, void *offset)
@@ -470,8 +506,12 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
	if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)
		return -1;

	if (!bat_priv->curr_gw)
	rcu_read_lock();
	if (!rcu_dereference(bat_priv->curr_gw)) {
		rcu_read_unlock();
		return 0;
	}
	rcu_read_unlock();

	return 1;
}
+208 −199

File changed.

Preview size limit exceeded, changes collapsed.

Loading