The following commit has been merged in the merge/master branch:
commit 9449da10f3b84e3c61b67aa5e7a7092e56be6cc9
Merge: 894e104b3e39cf335655f6f3a5a6ac9a7b9f8bec 2e8bad33846faecd76e5abfa010f964dbccdd77e
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Sun May 1 22:41:07 2011 +0200
Merge remote-tracking branch 'origin/standalone/next' into merge/master
diff --combined net/batman-adv/aggregation.c
index af45d6b,c11788c..c11788c
--- a/net/batman-adv/aggregation.c
+++ b/net/batman-adv/aggregation.c
@@@ -95,7 -95,6 +95,6 @@@ static bool can_aggregate_with(struct b
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,
diff --combined net/batman-adv/gateway_client.c
index 2acd7a6,65f3953..65f3953
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@@ -127,7 -127,7 +127,7 @@@ void gw_election(struct bat_priv *bat_p
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 +310,13 @@@ void gw_node_update(struct bat_priv *ba
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 +354,7 @@@ deselect
gw_deselect(bat_priv);
unlock:
rcu_read_unlock();
- out:
+
if (curr_gw)
gw_node_free_ref(curr_gw);
}
@@@ -435,30 -439,32 +439,32 @@@ int gw_client_seq_print_text(struct seq
{
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;
-
- if (!bat_priv->primary_if) {
+ int gw_count = 0, ret = 0;
- return seq_printf(seq, "BATMAN mesh %s disabled - please "
- "specify interfaces to enable it\n",
- net_dev->name);
+ 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 - "
- "primary interface not active\n",
- net_dev->name);
+ 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 +482,10 @@@
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)
diff --combined net/batman-adv/hard-interface.c
index b3058e4,3e888f1..3e888f1
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@@ -110,47 -110,60 +110,60 @@@ out
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 +249,10 @@@ void update_min_mtu(struct net_device *
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 +263,18 @@@
* 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 +404,13 @@@ err
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 +419,12 @@@
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 +445,10 @@@
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 +538,7 @@@ static int hard_if_event(struct notifie
{
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 +574,12 @@@
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 +588,8 @@@
hardif_put:
hardif_free_ref(hard_iface);
out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
return NOTIFY_DONE;
}
diff --combined net/batman-adv/hard-interface.h
index a9ddf36,6426599..6426599
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@@ -45,4 -45,22 +45,22 @@@ static inline void hardif_free_ref(stru
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_ */
diff --combined net/batman-adv/icmp_socket.c
index 49079c2,fa22ba2..fa22ba2
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@@ -153,6 -153,7 +153,7 @@@ static ssize_t bat_socket_write(struct
{
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 +168,21 @@@
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 +240,7 @@@
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 +255,8 @@@ dst_unreach
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)
diff --combined net/batman-adv/main.h
index dc24869,0000000..ace7285
mode 100644,000000..100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@@ -1,178 -1,0 +1,180 @@@
+/*
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#ifndef _NET_BATMAN_ADV_MAIN_H_
+#define _NET_BATMAN_ADV_MAIN_H_
+
+#define DRIVER_AUTHOR "Marek Lindner <lindner_marek(a)yahoo.de>, " \
+ "Simon Wunderlich <siwu(a)hrz.tu-chemnitz.de>"
+#define DRIVER_DESC "B.A.T.M.A.N. advanced"
+#define DRIVER_DEVICE "batman-adv"
+
+#define SOURCE_VERSION "next"
+
+
+/* B.A.T.M.A.N. parameters */
+
+#define TQ_MAX_VALUE 255
+#define JITTER 20
+#define TTL 50 /* Time To Live of broadcast messages */
+
+#define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no
+ * valid packet comes in -> TODO: check
+ * influence on TQ_LOCAL_WINDOW_SIZE */
+#define LOCAL_HNA_TIMEOUT 3600 /* in seconds */
+
+#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
+ * messages in squence numbers (should be a
+ * multiple of our word size) */
+#define TQ_GLOBAL_WINDOW_SIZE 5
+#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
+#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
+#define TQ_TOTAL_BIDRECT_LIMIT 1
+
+#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
+
+#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
+
+#define VIS_INTERVAL 5000 /* 5 seconds */
+
+/* how much worse secondary interfaces may be to
+ * to be considered as bonding candidates */
+
+#define BONDING_TQ_THRESHOLD 50
+
+#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
+ * change the size of
+ * forw_packet->direct_link_flags */
+#define MAX_AGGREGATION_MS 100
+
+#define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */
+
+#define RESET_PROTECTION_MS 30000
+#define EXPECTED_SEQNO_RANGE 65536
+/* don't reset again within 30 seconds */
+
+#define MESH_INACTIVE 0
+#define MESH_ACTIVE 1
+#define MESH_DEACTIVATING 2
+
+#define BCAST_QUEUE_LEN 256
+#define BATMAN_QUEUE_LEN 256
+
+/*
+ * Debug Messages
+ */
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before
+ * kernel messages */
+
+#define DBG_BATMAN 1 /* all messages related to routing / flooding /
+ * broadcasting / etc */
+#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
+#define DBG_ALL 3
+
+
+/*
+ * Vis
+ */
+
+/*
+ * Kernel headers
+ */
+
+#include <linux/mutex.h> /* mutex */
+#include <linux/module.h> /* needed by all modules */
+#include <linux/netdevice.h> /* netdevice */
+#include <linux/etherdevice.h> /* ethernet address classifaction */
+#include <linux/if_ether.h> /* ethernet header */
+#include <linux/poll.h> /* poll_table */
+#include <linux/kthread.h> /* kernel threads */
+#include <linux/pkt_sched.h> /* schedule types */
+#include <linux/workqueue.h> /* workqueue */
+#include <linux/slab.h>
+#include <net/sock.h> /* struct sock */
+#include <linux/jiffies.h>
+#include <linux/seq_file.h>
+#include "types.h"
+
+#ifndef REVISION_VERSION
+#define REVISION_VERSION_STR ""
+#else
+#define REVISION_VERSION_STR " "REVISION_VERSION
+#endif
+
+extern struct list_head hardif_list;
+
+extern unsigned char broadcast_addr[];
+extern struct workqueue_struct *bat_event_workqueue;
+
+int mesh_init(struct net_device *soft_iface);
+void mesh_free(struct net_device *soft_iface);
+void inc_module_count(void);
+void dec_module_count(void);
+int is_my_mac(uint8_t *addr);
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
+
+#define bat_dbg(type, bat_priv, fmt, arg...) \
+ do { \
+ if (atomic_read(&bat_priv->log_level) & type) \
+ debug_log(bat_priv, fmt, ## arg); \
+ } \
+ while (0)
+#else /* !CONFIG_BATMAN_ADV_DEBUG */
+static inline void bat_dbg(char type __always_unused,
+ struct bat_priv *bat_priv __always_unused,
+ char *fmt __always_unused, ...)
+{
+}
+#endif
+
+#define bat_info(net_dev, fmt, arg...) \
+ do { \
+ struct net_device *_netdev = (net_dev); \
+ struct bat_priv *_batpriv = netdev_priv(_netdev); \
+ bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
+ pr_info("%s: " fmt, _netdev->name, ## arg); \
+ } while (0)
+#define bat_err(net_dev, fmt, arg...) \
+ do { \
+ struct net_device *_netdev = (net_dev); \
+ struct bat_priv *_batpriv = netdev_priv(_netdev); \
+ bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
+ pr_err("%s: " fmt, _netdev->name, ## arg); \
+ } while (0)
+
+/**
+ * returns 1 if they are the same ethernet addr
+ *
+ * note: can't use compare_ether_addr() as it requires aligned memory
+ */
+static inline int compare_eth(void *data1, void *data2)
+{
+ return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
++#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
++
+#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --combined net/batman-adv/originator.c
index 5b8fe32,ef4a9be..ef4a9be
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@@ -405,29 -405,34 +405,34 @@@ int orig_seq_print_text(struct seq_fil
struct hashtable_t *hash = bat_priv->orig_hash;
struct hlist_node *node, *node_tmp;
struct hlist_head *head;
+ struct hard_iface *primary_if;
struct orig_node *orig_node;
struct neigh_node *neigh_node, *neigh_node_tmp;
int batman_count = 0;
int last_seen_secs;
int last_seen_msecs;
- int i;
+ int i, ret = 0;
+
+ primary_if = primary_if_get_selected(bat_priv);
- if ((!bat_priv->primary_if) ||
- (bat_priv->primary_if->if_status != IF_ACTIVE)) {
- if (!bat_priv->primary_if)
- return seq_printf(seq, "BATMAN mesh %s disabled - "
- "please specify interfaces to enable it\n",
- net_dev->name);
+ if (!primary_if) {
+ ret = seq_printf(seq, "BATMAN mesh %s disabled - "
+ "please specify interfaces to enable it\n",
+ net_dev->name);
+ goto out;
+ }
- return seq_printf(seq, "BATMAN mesh %s "
- "disabled - primary interface not active\n",
- net_dev->name);
+ 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, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
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);
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
"outgoingIF", "Potential nexthops");
@@@ -474,7 -479,10 +479,10 @@@ next
if (batman_count == 0)
seq_printf(seq, "No batman nodes in range ...\n");
- return 0;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
diff --combined net/batman-adv/routing.c
index f6c6422,49f5715..49f5715
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@@ -904,6 -904,7 +904,7 @@@ int recv_bat_packet(struct sk_buff *skb
static int recv_my_icmp_packet(struct bat_priv *bat_priv,
struct sk_buff *skb, size_t icmp_len)
{
+ struct hard_iface *primary_if = NULL;
struct orig_node *orig_node = NULL;
struct neigh_node *router = NULL;
struct icmp_packet_rr *icmp_packet;
@@@ -917,7 -918,8 +918,8 @@@
goto out;
}
- if (!bat_priv->primary_if)
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
goto out;
/* answer echo request (ping) */
@@@ -937,8 -939,7 +939,7 @@@
icmp_packet = (struct icmp_packet_rr *)skb->data;
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig,
- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
icmp_packet->msg_type = ECHO_REPLY;
icmp_packet->ttl = TTL;
@@@ -946,6 -947,8 +947,8 @@@
ret = NET_RX_SUCCESS;
out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
if (router)
neigh_node_free_ref(router);
if (orig_node)
@@@ -956,6 -959,7 +959,7 @@@
static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
struct sk_buff *skb)
{
+ struct hard_iface *primary_if = NULL;
struct orig_node *orig_node = NULL;
struct neigh_node *router = NULL;
struct icmp_packet *icmp_packet;
@@@ -971,7 -975,8 +975,8 @@@
goto out;
}
- if (!bat_priv->primary_if)
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
goto out;
/* get routing information */
@@@ -990,8 -995,7 +995,7 @@@
icmp_packet = (struct icmp_packet *)skb->data;
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig,
- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
icmp_packet->msg_type = TTL_EXCEEDED;
icmp_packet->ttl = TTL;
@@@ -999,6 -1003,8 +1003,8 @@@
ret = NET_RX_SUCCESS;
out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
if (router)
neigh_node_free_ref(router);
if (orig_node)
@@@ -1310,13 -1316,10 +1316,10 @@@ int route_unicast_packet(struct sk_buf
}
/* get routing information */
orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
if (!orig_node)
- goto unlock;
-
- rcu_read_unlock();
+ goto out;
/* find_router() increases neigh_nodes refcount if found. */
neigh_node = find_router(bat_priv, orig_node, recv_if);
@@@ -1362,10 -1365,7 +1365,7 @@@
/* route it */
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
ret = NET_RX_SUCCESS;
- goto out;
- unlock:
- rcu_read_unlock();
out:
if (neigh_node)
neigh_node_free_ref(neigh_node);
@@@ -1464,13 -1464,10 +1464,10 @@@ int recv_bcast_packet(struct sk_buff *s
if (bcast_packet->ttl < 2)
goto out;
orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
if (!orig_node)
- goto rcu_unlock;
-
- rcu_read_unlock();
+ goto out;
spin_lock_bh(&orig_node->bcast_seqno_lock);
@@@ -1501,9 -1498,6 +1498,6 @@@
ret = NET_RX_SUCCESS;
goto out;
- rcu_unlock:
- rcu_read_unlock();
- goto out;
spin_unlock:
spin_unlock_bh(&orig_node->bcast_seqno_lock);
out:
diff --combined net/batman-adv/send.c
index e78670c,02b541a..02b541a
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@@ -244,6 -244,7 +244,7 @@@ static void rebuild_batman_packet(struc
void schedule_own_packet(struct hard_iface *hard_iface)
{
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ struct hard_iface *primary_if;
unsigned long send_time;
struct batman_packet *batman_packet;
int vis_server;
@@@ -253,6 -254,7 +254,7 @@@
return;
vis_server = atomic_read(&bat_priv->vis_mode);
+ primary_if = primary_if_get_selected(bat_priv);
/**
* the interface gets activated here to avoid race conditions between
@@@ -266,7 -268,7 +268,7 @@@
/* if local hna has changed and interface is a primary interface */
if ((atomic_read(&bat_priv->hna_local_changed)) &&
- (hard_iface == bat_priv->primary_if))
+ (hard_iface == primary_if))
rebuild_batman_packet(bat_priv, hard_iface);
/**
@@@ -284,7 -286,7 +286,7 @@@
else
batman_packet->flags &= ~VIS_SERVER;
- if ((hard_iface == bat_priv->primary_if) &&
+ if ((hard_iface == primary_if) &&
(atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
batman_packet->gw_flags =
(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
@@@ -299,6 -301,9 +301,9 @@@
hard_iface->packet_buff,
hard_iface->packet_len,
hard_iface, 1, send_time);
+
+ if (primary_if)
+ hardif_free_ref(primary_if);
}
void schedule_forward_packet(struct orig_node *orig_node,
@@@ -393,7 -398,6 +398,6 @@@ static void _add_bcast_packet_to_list(s
send_time);
}
- #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
/* add a broadcast packet to the queue and setup timers. broadcast packets
* are sent multiple times to increase probability for beeing received.
*
@@@ -404,6 -408,7 +408,7 @@@
* skb is freed. */
int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
{
+ struct hard_iface *primary_if = NULL;
struct forw_packet *forw_packet;
struct bcast_packet *bcast_packet;
@@@ -412,7 -417,8 +417,8 @@@
goto out;
}
- if (!bat_priv->primary_if)
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
goto out;
forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
@@@ -431,7 -437,7 +437,7 @@@
skb_reset_mac_header(skb);
forw_packet->skb = skb;
- forw_packet->if_incoming = bat_priv->primary_if;
+ forw_packet->if_incoming = primary_if;
/* how often did we send the bcast packet ? */
forw_packet->num_packets = 0;
@@@ -444,6 -450,8 +450,8 @@@ packet_free
out_and_inc:
atomic_inc(&bat_priv->bcast_queue_left);
out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
return NETDEV_TX_BUSY;
}
diff --combined net/batman-adv/soft-interface.c
index 1f6f756,1772e2b..1772e2b
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@@ -43,8 -43,6 +43,6 @@@ static void bat_get_drvinfo(struct net_
static u32 bat_get_msglevel(struct net_device *dev);
static void bat_set_msglevel(struct net_device *dev, u32 value);
static u32 bat_get_link(struct net_device *dev);
- static u32 bat_get_rx_csum(struct net_device *dev);
- static int bat_set_rx_csum(struct net_device *dev, u32 data);
static const struct ethtool_ops bat_ethtool_ops = {
.get_settings = bat_get_settings,
@@@ -52,8 -50,6 +50,6 @@@
.get_msglevel = bat_get_msglevel,
.set_msglevel = bat_set_msglevel,
.get_link = bat_get_link,
- .get_rx_csum = bat_get_rx_csum,
- .set_rx_csum = bat_set_rx_csum
};
int my_skb_head_push(struct sk_buff *skb, unsigned int len)
@@@ -215,13 -211,24 +211,24 @@@ int softif_neigh_seq_print_text(struct
struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct softif_neigh *softif_neigh;
+ struct hard_iface *primary_if;
struct hlist_node *node;
struct softif_neigh *curr_softif_neigh;
+ int ret = 0;
- if (!bat_priv->primary_if) {
- return seq_printf(seq, "BATMAN mesh %s disabled - "
- "please specify interfaces to enable it\n",
- net_dev->name);
+ 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 (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, "Softif neighbor list (%s)\n", net_dev->name);
@@@ -238,7 -245,10 +245,10 @@@
if (curr_softif_neigh)
softif_neigh_free_ref(curr_softif_neigh);
- return 0;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
@@@ -247,7 -257,8 +257,8 @@@
struct bat_priv *bat_priv = netdev_priv(dev);
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct batman_packet *batman_packet;
- struct softif_neigh *softif_neigh;
+ struct softif_neigh *softif_neigh = NULL;
+ struct hard_iface *primary_if = NULL;
struct softif_neigh *curr_softif_neigh = NULL;
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
@@@ -257,28 -268,34 +268,34 @@@
batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
if (batman_packet->version != COMPAT_VERSION)
- goto err;
+ goto out;
if (batman_packet->packet_type != BAT_PACKET)
- goto err;
+ goto out;
if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
- goto err;
+ goto out;
if (is_my_mac(batman_packet->orig))
- goto err;
+ goto out;
softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
-
if (!softif_neigh)
- goto err;
+ goto out;
curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+ if (!curr_softif_neigh)
+ goto out;
+
if (curr_softif_neigh == softif_neigh)
goto out;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
/* we got a neighbor but its mac is 'bigger' than ours */
- if (memcmp(bat_priv->primary_if->net_dev->dev_addr,
+ if (memcmp(primary_if->net_dev->dev_addr,
softif_neigh->addr, ETH_ALEN) < 0)
goto out;
@@@ -300,7 -317,7 +317,7 @@@
/* close own batX device and use softif_neigh as exit node */
if ((!curr_softif_neigh) &&
(memcmp(softif_neigh->addr,
- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
+ primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
bat_dbg(DBG_ROUTES, bat_priv,
"Setting mesh exit point to %pM (vid: %d).\n",
softif_neigh->addr, softif_neigh->vid);
@@@ -310,12 -327,13 +327,13 @@@
}
out:
- softif_neigh_free_ref(softif_neigh);
- err:
kfree_skb(skb);
+ if (softif_neigh)
+ softif_neigh_free_ref(softif_neigh);
if (curr_softif_neigh)
softif_neigh_free_ref(curr_softif_neigh);
-
+ if (primary_if)
+ hardif_free_ref(primary_if);
return;
}
@@@ -371,6 -389,7 +389,7 @@@ int interface_tx(struct sk_buff *skb, s
{
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct bat_priv *bat_priv = netdev_priv(soft_iface);
+ struct hard_iface *primary_if = NULL;
struct bcast_packet *bcast_packet;
struct vlan_ethhdr *vhdr;
struct softif_neigh *curr_softif_neigh = NULL;
@@@ -420,7 -439,8 +439,8 @@@
/* ethernet packet should be broadcasted */
if (do_bcast) {
- if (!bat_priv->primary_if)
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
goto dropped;
if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
@@@ -436,7 -456,7 +456,7 @@@
/* hw address of first interface is the orig mac because only
* this mac is known throughout the mesh */
memcpy(bcast_packet->orig,
- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ primary_if->net_dev->dev_addr, ETH_ALEN);
/* set broadcast sequence number */
bcast_packet->seqno =
@@@ -466,6 -486,8 +486,8 @@@ dropped_freed
end:
if (curr_softif_neigh)
softif_neigh_free_ref(curr_softif_neigh);
+ if (primary_if)
+ hardif_free_ref(primary_if);
return NETDEV_TX_OK;
}
@@@ -736,12 -758,3 +758,3 @@@ static u32 bat_get_link(struct net_devi
return 1;
}
- static u32 bat_get_rx_csum(struct net_device *dev)
- {
- return 0;
- }
-
- static int bat_set_rx_csum(struct net_device *dev, u32 data)
- {
- return -EOPNOTSUPP;
- }
diff --combined net/batman-adv/translation-table.c
index 8d15b48,f931830..f931830
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@@ -22,6 -22,7 +22,7 @@@
#include "main.h"
#include "translation-table.h"
#include "soft-interface.h"
+ #include "hard-interface.h"
#include "hash.h"
#include "originator.h"
@@@ -237,16 -238,26 +238,26 @@@ int hna_local_seq_print_text(struct seq
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hashtable_t *hash = bat_priv->hna_local_hash;
struct hna_local_entry *hna_local_entry;
+ struct hard_iface *primary_if;
struct hlist_node *node;
struct hlist_head *head;
size_t buf_size, pos;
char *buff;
- int i;
+ int i, ret = 0;
+
+ 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) {
- return seq_printf(seq, "BATMAN mesh %s disabled - "
- "please specify interfaces to enable it\n",
- net_dev->name);
+ 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, "Locally retrieved addresses (from %s) "
@@@ -269,7 -280,8 +280,8 @@@
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_bh(&bat_priv->hna_lhash_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
buff[0] = '\0';
@@@ -291,7 -303,10 +303,10 @@@
seq_printf(seq, "%s", buff);
kfree(buff);
- return 0;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
static void _hna_local_del(struct hlist_node *node, void *arg)
@@@ -468,16 -483,26 +483,26 @@@ int hna_global_seq_print_text(struct se
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hashtable_t *hash = bat_priv->hna_global_hash;
struct hna_global_entry *hna_global_entry;
+ struct hard_iface *primary_if;
struct hlist_node *node;
struct hlist_head *head;
size_t buf_size, pos;
char *buff;
- int i;
+ int i, ret = 0;
+
+ 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) {
- return seq_printf(seq, "BATMAN mesh %s disabled - "
- "please specify interfaces to enable it\n",
- net_dev->name);
+ 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, "Globally announced HNAs received via the mesh %s\n",
@@@ -499,7 -524,8 +524,8 @@@
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_bh(&bat_priv->hna_ghash_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
buff[0] = '\0';
pos = 0;
@@@ -522,7 -548,10 +548,10 @@@
seq_printf(seq, "%s", buff);
kfree(buff);
- return 0;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
static void _hna_global_del_orig(struct bat_priv *bat_priv,
diff --combined net/batman-adv/types.h
index 75123b1,947bafc..947bafc
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@@ -149,7 -149,6 +149,6 @@@ struct bat_priv
struct hlist_head softif_neigh_list;
struct softif_neigh __rcu *softif_neigh;
struct debug_log *debug_log;
- struct hard_iface *primary_if;
struct kobject *mesh_obj;
struct dentry *debug_dir;
struct hlist_head forw_bat_list;
@@@ -174,6 -173,7 +173,7 @@@
struct delayed_work orig_work;
struct delayed_work vis_work;
struct gw_node __rcu *curr_gw; /* rcu protected pointer */
+ struct hard_iface __rcu *primary_if; /* rcu protected pointer */
struct vis_info *my_vis_info;
};
diff --combined net/batman-adv/unicast.c
index d46acc8,b46cbf1..b46cbf1
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@@ -221,15 -221,17 +221,17 @@@ int frag_send_skb(struct sk_buff *skb,
struct hard_iface *hard_iface, uint8_t dstaddr[])
{
struct unicast_packet tmp_uc, *unicast_packet;
+ struct hard_iface *primary_if;
struct sk_buff *frag_skb;
struct unicast_frag_packet *frag1, *frag2;
int uc_hdr_len = sizeof(struct unicast_packet);
int ucf_hdr_len = sizeof(struct unicast_frag_packet);
int data_len = skb->len - uc_hdr_len;
- int large_tail = 0;
+ int large_tail = 0, ret = NET_RX_DROP;
uint16_t seqno;
- if (!bat_priv->primary_if)
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
goto dropped;
frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
@@@ -254,7 -256,7 +256,7 @@@
frag1->version = COMPAT_VERSION;
frag1->packet_type = BAT_UNICAST_FRAG;
- memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
if (data_len & 1)
@@@ -269,13 -271,17 +271,17 @@@
send_skb_packet(skb, hard_iface, dstaddr);
send_skb_packet(frag_skb, hard_iface, dstaddr);
- return NET_RX_SUCCESS;
+ ret = NET_RX_SUCCESS;
+ goto out;
drop_frag:
kfree_skb(frag_skb);
dropped:
kfree_skb(skb);
- return NET_RX_DROP;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
diff --combined net/batman-adv/vis.c
index d4cc4f5,c8f571d..c8f571d
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@@ -204,6 -204,7 +204,7 @@@ static ssize_t vis_data_read_entry(cha
int vis_seq_print_text(struct seq_file *seq, void *offset)
{
+ struct hard_iface *primary_if;
struct hlist_node *node;
struct hlist_head *head;
struct vis_info *info;
@@@ -215,15 -216,18 +216,18 @@@
HLIST_HEAD(vis_if_list);
struct if_list_entry *entry;
struct hlist_node *pos, *n;
- int i, j;
+ int i, j, ret = 0;
int vis_server = atomic_read(&bat_priv->vis_mode);
size_t buff_pos, buf_size;
char *buff;
int compare;
- if ((!bat_priv->primary_if) ||
- (vis_server == VIS_TYPE_CLIENT_UPDATE))
- return 0;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ if (vis_server == VIS_TYPE_CLIENT_UPDATE)
+ goto out;
buf_size = 1;
/* Estimate length */
@@@ -270,7 -274,8 +274,8 @@@
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_bh(&bat_priv->vis_hash_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
buff[0] = '\0';
buff_pos = 0;
@@@ -328,7 -333,10 +333,10 @@@
seq_printf(seq, "%s", buff);
kfree(buff);
- return 0;
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
/* add the info packet to the send list, if it was not
@@@ -815,16 -823,20 +823,20 @@@ out
/* only send one vis packet. called from send_vis_packets() */
static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
{
+ struct hard_iface *primary_if;
struct vis_packet *packet;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
packet = (struct vis_packet *)info->skb_packet->data;
if (packet->ttl < 2) {
pr_debug("Error - can't send vis packet: ttl exceeded\n");
- return;
+ goto out;
}
- memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr,
- ETH_ALEN);
+ memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
packet->ttl--;
if (is_broadcast_ether_addr(packet->target_orig))
@@@ -832,6 -844,10 +844,10 @@@
else
unicast_vis_packet(bat_priv, info);
packet->ttl++; /* restore TTL */
+
+ out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
}
/* called from timer; send (and maybe generate) vis packet. */
@@@ -858,8 -874,7 +874,7 @@@ static void send_vis_packets(struct wor
kref_get(&info->refcount);
spin_unlock_bh(&bat_priv->vis_hash_lock);
- if (bat_priv->primary_if)
- send_vis_packet(bat_priv, info);
+ send_vis_packet(bat_priv, info);
spin_lock_bh(&bat_priv->vis_hash_lock);
send_list_del(info);
--
linux integration