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

Commit dcfd9cdc 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 56157872 32ae9b22
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
	return false;
}

#define atomic_dec_not_zero(v)          atomic_add_unless((v), -1, 0)
/* 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,
+27 −18
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv)
		return;

	curr_gw = gw_get_selected_gw_node(bat_priv);
	if (!curr_gw)
	if (curr_gw)
		goto out;

	rcu_read_lock();
@@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv,
	struct hlist_node *node;
	struct gw_node *gw_node, *curr_gw;

	/**
	 * Note: We don't need a NULL check here, since curr_gw never gets
	 * dereferenced. If curr_gw is NULL we also should not exit as we may
	 * have this gateway in our list (duplication check!) even though we
	 * have no currently selected gateway.
	 */
	curr_gw = gw_get_selected_gw_node(bat_priv);
	if (!curr_gw)
		goto out;

	rcu_read_lock();
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -350,7 +354,7 @@ void gw_node_update(struct bat_priv *bat_priv,
	gw_deselect(bat_priv);
unlock:
	rcu_read_unlock();
out:

	if (curr_gw)
		gw_node_free_ref(curr_gw);
}
@@ -435,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
{
	struct net_device *net_dev = (struct net_device *)seq->private;
	struct bat_priv *bat_priv = netdev_priv(net_dev);
	struct hard_iface *primary_if;
	struct gw_node *gw_node;
	struct hlist_node *node;
	int gw_count = 0;
	int gw_count = 0, ret = 0;

	if (!bat_priv->primary_if) {

		return seq_printf(seq, "BATMAN mesh %s disabled - please "
	primary_if = primary_if_get_selected(bat_priv);
	if (!primary_if) {
		ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
				 "specify interfaces to enable it\n",
				 net_dev->name);
		goto out;
	}

	if (bat_priv->primary_if->if_status != IF_ACTIVE) {

		return seq_printf(seq, "BATMAN mesh %s disabled - "
	if (primary_if->if_status != IF_ACTIVE) {
		ret = seq_printf(seq, "BATMAN mesh %s disabled - "
				 "primary interface not active\n",
				 net_dev->name);
		goto out;
	}

	seq_printf(seq, "      %-12s (%s/%i) %17s [%10s]: gw_class ... "
		   "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
		   "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
		   "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
		   bat_priv->primary_if->net_dev->name,
		   bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
		   primary_if->net_dev->name,
		   primary_if->net_dev->dev_addr, net_dev->name);

	rcu_read_lock();
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -476,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
	if (gw_count == 0)
		seq_printf(seq, "No gateways in range ...\n");

	return 0;
out:
	if (primary_if)
		hardif_free_ref(primary_if);
	return ret;
}

int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
+57 −26
Original line number Diff line number Diff line
@@ -110,47 +110,60 @@ static struct hard_iface *hardif_get_active(struct net_device *soft_iface)
	return hard_iface;
}

static void update_primary_addr(struct bat_priv *bat_priv)
static void primary_if_update_addr(struct bat_priv *bat_priv)
{
	struct vis_packet *vis_packet;
	struct hard_iface *primary_if;

	primary_if = primary_if_get_selected(bat_priv);
	if (!primary_if)
		goto out;

	vis_packet = (struct vis_packet *)
				bat_priv->my_vis_info->skb_packet->data;
	memcpy(vis_packet->vis_orig,
	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
	memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
	memcpy(vis_packet->sender_orig,
	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
	       primary_if->net_dev->dev_addr, ETH_ALEN);

out:
	if (primary_if)
		hardif_free_ref(primary_if);
}

static void set_primary_if(struct bat_priv *bat_priv,
			   struct hard_iface *hard_iface)
static void primary_if_select(struct bat_priv *bat_priv,
			      struct hard_iface *new_hard_iface)
{
	struct hard_iface *curr_hard_iface;
	struct batman_packet *batman_packet;
	struct hard_iface *old_if;

	if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount))
		hard_iface = NULL;
	spin_lock_bh(&hardif_list_lock);

	old_if = bat_priv->primary_if;
	bat_priv->primary_if = hard_iface;
	if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
		new_hard_iface = NULL;

	if (old_if)
		hardif_free_ref(old_if);
	curr_hard_iface = bat_priv->primary_if;
	rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);

	if (!bat_priv->primary_if)
		return;
	if (curr_hard_iface)
		hardif_free_ref(curr_hard_iface);

	batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
	if (!new_hard_iface)
		goto out;

	batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff);
	batman_packet->flags = PRIMARIES_FIRST_HOP;
	batman_packet->ttl = TTL;

	update_primary_addr(bat_priv);
	primary_if_update_addr(bat_priv);

	/***
	 * hacky trick to make sure that we send the HNA information via
	 * our new primary interface
	 */
	atomic_set(&bat_priv->hna_local_changed, 1);

out:
	spin_unlock_bh(&hardif_list_lock);
}

static bool hardif_is_iface_up(struct hard_iface *hard_iface)
@@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface)
static void hardif_activate_interface(struct hard_iface *hard_iface)
{
	struct bat_priv *bat_priv;
	struct hard_iface *primary_if = NULL;

	if (hard_iface->if_status != IF_INACTIVE)
		return;
		goto out;

	bat_priv = netdev_priv(hard_iface->soft_iface);

@@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
	 * the first active interface becomes our primary interface or
	 * the next active interface after the old primay interface was removed
	 */
	if (!bat_priv->primary_if)
		set_primary_if(bat_priv, hard_iface);
	primary_if = primary_if_get_selected(bat_priv);
	if (!primary_if)
		primary_if_select(bat_priv, hard_iface);

	bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
		 hard_iface->net_dev->name);

	update_min_mtu(hard_iface->soft_iface);
	return;

out:
	if (primary_if)
		hardif_free_ref(primary_if);
}

static void hardif_deactivate_interface(struct hard_iface *hard_iface)
@@ -386,12 +404,13 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
void hardif_disable_interface(struct hard_iface *hard_iface)
{
	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
	struct hard_iface *primary_if = NULL;

	if (hard_iface->if_status == IF_ACTIVE)
		hardif_deactivate_interface(hard_iface);

	if (hard_iface->if_status != IF_INACTIVE)
		return;
		goto out;

	bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
		 hard_iface->net_dev->name);
@@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
	bat_priv->num_ifaces--;
	orig_hash_del_if(hard_iface, bat_priv->num_ifaces);

	if (hard_iface == bat_priv->primary_if) {
	primary_if = primary_if_get_selected(bat_priv);
	if (hard_iface == primary_if) {
		struct hard_iface *new_if;

		new_if = hardif_get_active(hard_iface->soft_iface);
		set_primary_if(bat_priv, new_if);
		primary_if_select(bat_priv, new_if);

		if (new_if)
			hardif_free_ref(new_if);
@@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface)

	hard_iface->soft_iface = NULL;
	hardif_free_ref(hard_iface);

out:
	if (primary_if)
		hardif_free_ref(primary_if);
}

static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
@@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this,
{
	struct net_device *net_dev = (struct net_device *)ptr;
	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
	struct hard_iface *primary_if = NULL;
	struct bat_priv *bat_priv;

	if (!hard_iface && event == NETDEV_REGISTER)
@@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this,
		update_mac_addresses(hard_iface);

		bat_priv = netdev_priv(hard_iface->soft_iface);
		if (hard_iface == bat_priv->primary_if)
			update_primary_addr(bat_priv);
		primary_if = primary_if_get_selected(bat_priv);
		if (!primary_if)
			goto hardif_put;

		if (hard_iface == primary_if)
			primary_if_update_addr(bat_priv);
		break;
	default:
		break;
@@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this,
hardif_put:
	hardif_free_ref(hard_iface);
out:
	if (primary_if)
		hardif_free_ref(primary_if);
	return NOTIFY_DONE;
}

+18 −0
Original line number Diff line number Diff line
@@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface)
		call_rcu(&hard_iface->rcu, hardif_free_rcu);
}

static inline struct hard_iface *primary_if_get_selected(
						struct bat_priv *bat_priv)
{
	struct hard_iface *hard_iface;

	rcu_read_lock();
	hard_iface = rcu_dereference(bat_priv->primary_if);
	if (!hard_iface)
		goto out;

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

out:
	rcu_read_unlock();
	return hard_iface;
}

#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
+14 −5
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
{
	struct socket_client *socket_client = file->private_data;
	struct bat_priv *bat_priv = socket_client->bat_priv;
	struct hard_iface *primary_if = NULL;
	struct sk_buff *skb;
	struct icmp_packet_rr *icmp_packet;

@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
		return -EINVAL;
	}

	if (!bat_priv->primary_if)
		return -EFAULT;
	primary_if = primary_if_get_selected(bat_priv);

	if (!primary_if) {
		len = -EFAULT;
		goto out;
	}

	if (len >= sizeof(struct icmp_packet_rr))
		packet_len = sizeof(struct icmp_packet_rr);

	skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
	if (!skb)
		return -ENOMEM;
	if (!skb) {
		len = -ENOMEM;
		goto out;
	}

	skb_reserve(skb, sizeof(struct ethhdr));
	icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
@@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
		goto dst_unreach;

	memcpy(icmp_packet->orig,
	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
	       primary_if->net_dev->dev_addr, ETH_ALEN);

	if (packet_len == sizeof(struct icmp_packet_rr))
		memcpy(icmp_packet->rr,
@@ -248,6 +255,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
free_skb:
	kfree_skb(skb);
out:
	if (primary_if)
		hardif_free_ref(primary_if);
	if (neigh_node)
		neigh_node_free_ref(neigh_node);
	if (orig_node)
Loading