Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
This commit is contained in:
commit
dcfd9cdc12
@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
|
|||||||
return false;
|
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 */
|
/* create a new aggregated packet and add this packet to it */
|
||||||
static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
|
static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
|
||||||
unsigned long send_time, bool direct_link,
|
unsigned long send_time, bool direct_link,
|
||||||
|
@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
curr_gw = gw_get_selected_gw_node(bat_priv);
|
curr_gw = gw_get_selected_gw_node(bat_priv);
|
||||||
if (!curr_gw)
|
if (curr_gw)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv,
|
|||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct gw_node *gw_node, *curr_gw;
|
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);
|
curr_gw = gw_get_selected_gw_node(bat_priv);
|
||||||
if (!curr_gw)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
|
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
|
||||||
@ -350,7 +354,7 @@ deselect:
|
|||||||
gw_deselect(bat_priv);
|
gw_deselect(bat_priv);
|
||||||
unlock:
|
unlock:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
out:
|
|
||||||
if (curr_gw)
|
if (curr_gw)
|
||||||
gw_node_free_ref(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 net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct gw_node *gw_node;
|
struct gw_node *gw_node;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
int gw_count = 0;
|
int gw_count = 0, ret = 0;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if) {
|
||||||
return seq_printf(seq, "BATMAN mesh %s disabled - please "
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
|
||||||
"specify interfaces to enable it\n",
|
"specify interfaces to enable it\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bat_priv->primary_if->if_status != IF_ACTIVE) {
|
if (primary_if->if_status != IF_ACTIVE) {
|
||||||
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
"primary interface not active\n",
|
||||||
"primary interface not active\n",
|
net_dev->name);
|
||||||
net_dev->name);
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
|
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",
|
"[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
|
||||||
"Gateway", "#", TQ_MAX_VALUE, "Nexthop",
|
"Gateway", "#", TQ_MAX_VALUE, "Nexthop",
|
||||||
"outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
|
"outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
|
||||||
bat_priv->primary_if->net_dev->name,
|
primary_if->net_dev->name,
|
||||||
bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
|
primary_if->net_dev->dev_addr, net_dev->name);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
|
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)
|
if (gw_count == 0)
|
||||||
seq_printf(seq, "No gateways in range ...\n");
|
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)
|
int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
|
||||||
|
@ -110,47 +110,60 @@ out:
|
|||||||
return hard_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 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 *)
|
vis_packet = (struct vis_packet *)
|
||||||
bat_priv->my_vis_info->skb_packet->data;
|
bat_priv->my_vis_info->skb_packet->data;
|
||||||
memcpy(vis_packet->vis_orig,
|
memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
|
||||||
memcpy(vis_packet->sender_orig,
|
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,
|
static void primary_if_select(struct bat_priv *bat_priv,
|
||||||
struct hard_iface *hard_iface)
|
struct hard_iface *new_hard_iface)
|
||||||
{
|
{
|
||||||
|
struct hard_iface *curr_hard_iface;
|
||||||
struct batman_packet *batman_packet;
|
struct batman_packet *batman_packet;
|
||||||
struct hard_iface *old_if;
|
|
||||||
|
|
||||||
if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount))
|
spin_lock_bh(&hardif_list_lock);
|
||||||
hard_iface = NULL;
|
|
||||||
|
|
||||||
old_if = bat_priv->primary_if;
|
if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
|
||||||
bat_priv->primary_if = hard_iface;
|
new_hard_iface = NULL;
|
||||||
|
|
||||||
if (old_if)
|
curr_hard_iface = bat_priv->primary_if;
|
||||||
hardif_free_ref(old_if);
|
rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
if (curr_hard_iface)
|
||||||
return;
|
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->flags = PRIMARIES_FIRST_HOP;
|
||||||
batman_packet->ttl = TTL;
|
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
|
* hacky trick to make sure that we send the HNA information via
|
||||||
* our new primary interface
|
* our new primary interface
|
||||||
*/
|
*/
|
||||||
atomic_set(&bat_priv->hna_local_changed, 1);
|
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)
|
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)
|
static void hardif_activate_interface(struct hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct bat_priv *bat_priv;
|
struct bat_priv *bat_priv;
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
|
|
||||||
if (hard_iface->if_status != IF_INACTIVE)
|
if (hard_iface->if_status != IF_INACTIVE)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
bat_priv = netdev_priv(hard_iface->soft_iface);
|
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 first active interface becomes our primary interface or
|
||||||
* the next active interface after the old primay interface was removed
|
* the next active interface after the old primay interface was removed
|
||||||
*/
|
*/
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
set_primary_if(bat_priv, hard_iface);
|
if (!primary_if)
|
||||||
|
primary_if_select(bat_priv, hard_iface);
|
||||||
|
|
||||||
bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
|
bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
|
||||||
hard_iface->net_dev->name);
|
hard_iface->net_dev->name);
|
||||||
|
|
||||||
update_min_mtu(hard_iface->soft_iface);
|
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)
|
static void hardif_deactivate_interface(struct hard_iface *hard_iface)
|
||||||
@ -386,12 +404,13 @@ err:
|
|||||||
void hardif_disable_interface(struct hard_iface *hard_iface)
|
void hardif_disable_interface(struct hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_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)
|
if (hard_iface->if_status == IF_ACTIVE)
|
||||||
hardif_deactivate_interface(hard_iface);
|
hardif_deactivate_interface(hard_iface);
|
||||||
|
|
||||||
if (hard_iface->if_status != IF_INACTIVE)
|
if (hard_iface->if_status != IF_INACTIVE)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
|
bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
|
||||||
hard_iface->net_dev->name);
|
hard_iface->net_dev->name);
|
||||||
@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
|
|||||||
bat_priv->num_ifaces--;
|
bat_priv->num_ifaces--;
|
||||||
orig_hash_del_if(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;
|
struct hard_iface *new_if;
|
||||||
|
|
||||||
new_if = hardif_get_active(hard_iface->soft_iface);
|
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)
|
if (new_if)
|
||||||
hardif_free_ref(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;
|
hard_iface->soft_iface = NULL;
|
||||||
hardif_free_ref(hard_iface);
|
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)
|
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 net_device *net_dev = (struct net_device *)ptr;
|
||||||
struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
|
struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
struct bat_priv *bat_priv;
|
struct bat_priv *bat_priv;
|
||||||
|
|
||||||
if (!hard_iface && event == NETDEV_REGISTER)
|
if (!hard_iface && event == NETDEV_REGISTER)
|
||||||
@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this,
|
|||||||
update_mac_addresses(hard_iface);
|
update_mac_addresses(hard_iface);
|
||||||
|
|
||||||
bat_priv = netdev_priv(hard_iface->soft_iface);
|
bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||||
if (hard_iface == bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
update_primary_addr(bat_priv);
|
if (!primary_if)
|
||||||
|
goto hardif_put;
|
||||||
|
|
||||||
|
if (hard_iface == primary_if)
|
||||||
|
primary_if_update_addr(bat_priv);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this,
|
|||||||
hardif_put:
|
hardif_put:
|
||||||
hardif_free_ref(hard_iface);
|
hardif_free_ref(hard_iface);
|
||||||
out:
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface)
|
|||||||
call_rcu(&hard_iface->rcu, hardif_free_rcu);
|
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_ */
|
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
|
||||||
|
@ -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 socket_client *socket_client = file->private_data;
|
||||||
struct bat_priv *bat_priv = socket_client->bat_priv;
|
struct bat_priv *bat_priv = socket_client->bat_priv;
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct icmp_packet_rr *icmp_packet;
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
return -EFAULT;
|
|
||||||
|
if (!primary_if) {
|
||||||
|
len = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (len >= sizeof(struct icmp_packet_rr))
|
if (len >= sizeof(struct icmp_packet_rr))
|
||||||
packet_len = sizeof(struct icmp_packet_rr);
|
packet_len = sizeof(struct icmp_packet_rr);
|
||||||
|
|
||||||
skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
|
skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
|
||||||
if (!skb)
|
if (!skb) {
|
||||||
return -ENOMEM;
|
len = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
skb_reserve(skb, sizeof(struct ethhdr));
|
skb_reserve(skb, sizeof(struct ethhdr));
|
||||||
icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
|
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;
|
goto dst_unreach;
|
||||||
|
|
||||||
memcpy(icmp_packet->orig,
|
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))
|
if (packet_len == sizeof(struct icmp_packet_rr))
|
||||||
memcpy(icmp_packet->rr,
|
memcpy(icmp_packet->rr,
|
||||||
@ -248,6 +255,8 @@ dst_unreach:
|
|||||||
free_skb:
|
free_skb:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
out:
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
if (neigh_node)
|
if (neigh_node)
|
||||||
neigh_node_free_ref(neigh_node);
|
neigh_node_free_ref(neigh_node);
|
||||||
if (orig_node)
|
if (orig_node)
|
||||||
|
@ -175,4 +175,6 @@ static inline int compare_eth(void *data1, void *data2)
|
|||||||
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
|
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_ */
|
#endif /* _NET_BATMAN_ADV_MAIN_H_ */
|
||||||
|
@ -405,29 +405,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
struct hashtable_t *hash = bat_priv->orig_hash;
|
struct hashtable_t *hash = bat_priv->orig_hash;
|
||||||
struct hlist_node *node, *node_tmp;
|
struct hlist_node *node, *node_tmp;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct neigh_node *neigh_node, *neigh_node_tmp;
|
struct neigh_node *neigh_node, *neigh_node_tmp;
|
||||||
int batman_count = 0;
|
int batman_count = 0;
|
||||||
int last_seen_secs;
|
int last_seen_secs;
|
||||||
int last_seen_msecs;
|
int last_seen_msecs;
|
||||||
int i;
|
int i, ret = 0;
|
||||||
|
|
||||||
if ((!bat_priv->primary_if) ||
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
(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);
|
|
||||||
|
|
||||||
return seq_printf(seq, "BATMAN mesh %s "
|
if (!primary_if) {
|
||||||
"disabled - primary interface not active\n",
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
net_dev->name);
|
"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, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
|
seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
|
||||||
SOURCE_VERSION, REVISION_VERSION_STR,
|
SOURCE_VERSION, REVISION_VERSION_STR,
|
||||||
bat_priv->primary_if->net_dev->name,
|
primary_if->net_dev->name,
|
||||||
bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
|
primary_if->net_dev->dev_addr, net_dev->name);
|
||||||
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
|
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
|
||||||
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
|
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
|
||||||
"outgoingIF", "Potential nexthops");
|
"outgoingIF", "Potential nexthops");
|
||||||
@ -474,7 +479,10 @@ next:
|
|||||||
if (batman_count == 0)
|
if (batman_count == 0)
|
||||||
seq_printf(seq, "No batman nodes in range ...\n");
|
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)
|
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
||||||
|
@ -904,6 +904,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
|
|||||||
static int recv_my_icmp_packet(struct bat_priv *bat_priv,
|
static int recv_my_icmp_packet(struct bat_priv *bat_priv,
|
||||||
struct sk_buff *skb, size_t icmp_len)
|
struct sk_buff *skb, size_t icmp_len)
|
||||||
{
|
{
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
struct orig_node *orig_node = NULL;
|
struct orig_node *orig_node = NULL;
|
||||||
struct neigh_node *router = NULL;
|
struct neigh_node *router = NULL;
|
||||||
struct icmp_packet_rr *icmp_packet;
|
struct icmp_packet_rr *icmp_packet;
|
||||||
@ -917,7 +918,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* answer echo request (ping) */
|
/* answer echo request (ping) */
|
||||||
@ -937,8 +939,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
|
|||||||
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
||||||
|
|
||||||
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
||||||
memcpy(icmp_packet->orig,
|
memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
|
||||||
icmp_packet->msg_type = ECHO_REPLY;
|
icmp_packet->msg_type = ECHO_REPLY;
|
||||||
icmp_packet->ttl = TTL;
|
icmp_packet->ttl = TTL;
|
||||||
|
|
||||||
@ -946,6 +947,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
|
|||||||
ret = NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
if (router)
|
if (router)
|
||||||
neigh_node_free_ref(router);
|
neigh_node_free_ref(router);
|
||||||
if (orig_node)
|
if (orig_node)
|
||||||
@ -956,6 +959,7 @@ out:
|
|||||||
static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
|
static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
struct orig_node *orig_node = NULL;
|
struct orig_node *orig_node = NULL;
|
||||||
struct neigh_node *router = NULL;
|
struct neigh_node *router = NULL;
|
||||||
struct icmp_packet *icmp_packet;
|
struct icmp_packet *icmp_packet;
|
||||||
@ -971,7 +975,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* get routing information */
|
/* get routing information */
|
||||||
@ -990,8 +995,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
|
|||||||
icmp_packet = (struct icmp_packet *)skb->data;
|
icmp_packet = (struct icmp_packet *)skb->data;
|
||||||
|
|
||||||
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
||||||
memcpy(icmp_packet->orig,
|
memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
|
||||||
icmp_packet->msg_type = TTL_EXCEEDED;
|
icmp_packet->msg_type = TTL_EXCEEDED;
|
||||||
icmp_packet->ttl = TTL;
|
icmp_packet->ttl = TTL;
|
||||||
|
|
||||||
@ -999,6 +1003,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
|
|||||||
ret = NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
if (router)
|
if (router)
|
||||||
neigh_node_free_ref(router);
|
neigh_node_free_ref(router);
|
||||||
if (orig_node)
|
if (orig_node)
|
||||||
@ -1310,13 +1316,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get routing information */
|
/* get routing information */
|
||||||
rcu_read_lock();
|
|
||||||
orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
|
orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
|
||||||
|
|
||||||
if (!orig_node)
|
if (!orig_node)
|
||||||
goto unlock;
|
goto out;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
/* find_router() increases neigh_nodes refcount if found. */
|
/* find_router() increases neigh_nodes refcount if found. */
|
||||||
neigh_node = find_router(bat_priv, orig_node, recv_if);
|
neigh_node = find_router(bat_priv, orig_node, recv_if);
|
||||||
@ -1362,10 +1365,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
|
|||||||
/* route it */
|
/* route it */
|
||||||
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
|
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
|
||||||
ret = NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
goto out;
|
|
||||||
|
|
||||||
unlock:
|
|
||||||
rcu_read_unlock();
|
|
||||||
out:
|
out:
|
||||||
if (neigh_node)
|
if (neigh_node)
|
||||||
neigh_node_free_ref(neigh_node);
|
neigh_node_free_ref(neigh_node);
|
||||||
@ -1464,13 +1464,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
|
|||||||
if (bcast_packet->ttl < 2)
|
if (bcast_packet->ttl < 2)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
|
orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
|
||||||
|
|
||||||
if (!orig_node)
|
if (!orig_node)
|
||||||
goto rcu_unlock;
|
goto out;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
spin_lock_bh(&orig_node->bcast_seqno_lock);
|
spin_lock_bh(&orig_node->bcast_seqno_lock);
|
||||||
|
|
||||||
@ -1501,9 +1498,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
|
|||||||
ret = NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rcu_unlock:
|
|
||||||
rcu_read_unlock();
|
|
||||||
goto out;
|
|
||||||
spin_unlock:
|
spin_unlock:
|
||||||
spin_unlock_bh(&orig_node->bcast_seqno_lock);
|
spin_unlock_bh(&orig_node->bcast_seqno_lock);
|
||||||
out:
|
out:
|
||||||
|
@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
|
|||||||
void schedule_own_packet(struct hard_iface *hard_iface)
|
void schedule_own_packet(struct hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||||
|
struct hard_iface *primary_if;
|
||||||
unsigned long send_time;
|
unsigned long send_time;
|
||||||
struct batman_packet *batman_packet;
|
struct batman_packet *batman_packet;
|
||||||
int vis_server;
|
int vis_server;
|
||||||
@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
vis_server = atomic_read(&bat_priv->vis_mode);
|
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
|
* the interface gets activated here to avoid race conditions between
|
||||||
@ -266,7 +268,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
|
|||||||
|
|
||||||
/* if local hna has changed and interface is a primary interface */
|
/* if local hna has changed and interface is a primary interface */
|
||||||
if ((atomic_read(&bat_priv->hna_local_changed)) &&
|
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);
|
rebuild_batman_packet(bat_priv, hard_iface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
|
|||||||
else
|
else
|
||||||
batman_packet->flags &= ~VIS_SERVER;
|
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))
|
(atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
|
||||||
batman_packet->gw_flags =
|
batman_packet->gw_flags =
|
||||||
(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
|
(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
|
||||||
@ -299,6 +301,9 @@ void schedule_own_packet(struct hard_iface *hard_iface)
|
|||||||
hard_iface->packet_buff,
|
hard_iface->packet_buff,
|
||||||
hard_iface->packet_len,
|
hard_iface->packet_len,
|
||||||
hard_iface, 1, send_time);
|
hard_iface, 1, send_time);
|
||||||
|
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule_forward_packet(struct orig_node *orig_node,
|
void schedule_forward_packet(struct orig_node *orig_node,
|
||||||
@ -393,7 +398,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
|
|||||||
send_time);
|
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
|
/* add a broadcast packet to the queue and setup timers. broadcast packets
|
||||||
* are sent multiple times to increase probability for beeing received.
|
* are sent multiple times to increase probability for beeing received.
|
||||||
*
|
*
|
||||||
@ -404,6 +408,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
|
|||||||
* skb is freed. */
|
* skb is freed. */
|
||||||
int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
|
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 forw_packet *forw_packet;
|
||||||
struct bcast_packet *bcast_packet;
|
struct bcast_packet *bcast_packet;
|
||||||
|
|
||||||
@ -412,7 +417,8 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
|
forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
|
||||||
@ -431,7 +437,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
|
|||||||
skb_reset_mac_header(skb);
|
skb_reset_mac_header(skb);
|
||||||
|
|
||||||
forw_packet->skb = 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 ? */
|
/* how often did we send the bcast packet ? */
|
||||||
forw_packet->num_packets = 0;
|
forw_packet->num_packets = 0;
|
||||||
@ -444,6 +450,8 @@ packet_free:
|
|||||||
out_and_inc:
|
out_and_inc:
|
||||||
atomic_inc(&bat_priv->bcast_queue_left);
|
atomic_inc(&bat_priv->bcast_queue_left);
|
||||||
out:
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,13 +211,24 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct softif_neigh *softif_neigh;
|
struct softif_neigh *softif_neigh;
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct softif_neigh *curr_softif_neigh;
|
struct softif_neigh *curr_softif_neigh;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
if (!primary_if) {
|
||||||
"please specify interfaces to enable it\n",
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
net_dev->name);
|
"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);
|
seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
|
||||||
@ -234,7 +245,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
if (curr_softif_neigh)
|
if (curr_softif_neigh)
|
||||||
softif_neigh_free_ref(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,
|
static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
@ -243,7 +257,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
struct bat_priv *bat_priv = netdev_priv(dev);
|
struct bat_priv *bat_priv = netdev_priv(dev);
|
||||||
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
||||||
struct batman_packet *batman_packet;
|
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;
|
struct softif_neigh *curr_softif_neigh = NULL;
|
||||||
|
|
||||||
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
|
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
|
||||||
@ -253,28 +268,34 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
|
batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
|
||||||
|
|
||||||
if (batman_packet->version != COMPAT_VERSION)
|
if (batman_packet->version != COMPAT_VERSION)
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
if (batman_packet->packet_type != BAT_PACKET)
|
if (batman_packet->packet_type != BAT_PACKET)
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
|
if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
if (is_my_mac(batman_packet->orig))
|
if (is_my_mac(batman_packet->orig))
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
|
softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
|
||||||
|
|
||||||
if (!softif_neigh)
|
if (!softif_neigh)
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
curr_softif_neigh = softif_neigh_get_selected(bat_priv);
|
curr_softif_neigh = softif_neigh_get_selected(bat_priv);
|
||||||
|
if (!curr_softif_neigh)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (curr_softif_neigh == softif_neigh)
|
if (curr_softif_neigh == softif_neigh)
|
||||||
goto out;
|
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 */
|
/* 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)
|
softif_neigh->addr, ETH_ALEN) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -296,7 +317,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
/* close own batX device and use softif_neigh as exit node */
|
/* close own batX device and use softif_neigh as exit node */
|
||||||
if ((!curr_softif_neigh) &&
|
if ((!curr_softif_neigh) &&
|
||||||
(memcmp(softif_neigh->addr,
|
(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,
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
"Setting mesh exit point to %pM (vid: %d).\n",
|
"Setting mesh exit point to %pM (vid: %d).\n",
|
||||||
softif_neigh->addr, softif_neigh->vid);
|
softif_neigh->addr, softif_neigh->vid);
|
||||||
@ -306,12 +327,13 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
softif_neigh_free_ref(softif_neigh);
|
|
||||||
err:
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
if (softif_neigh)
|
||||||
|
softif_neigh_free_ref(softif_neigh);
|
||||||
if (curr_softif_neigh)
|
if (curr_softif_neigh)
|
||||||
softif_neigh_free_ref(curr_softif_neigh);
|
softif_neigh_free_ref(curr_softif_neigh);
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +389,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
|
|||||||
{
|
{
|
||||||
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
||||||
struct bat_priv *bat_priv = netdev_priv(soft_iface);
|
struct bat_priv *bat_priv = netdev_priv(soft_iface);
|
||||||
|
struct hard_iface *primary_if = NULL;
|
||||||
struct bcast_packet *bcast_packet;
|
struct bcast_packet *bcast_packet;
|
||||||
struct vlan_ethhdr *vhdr;
|
struct vlan_ethhdr *vhdr;
|
||||||
struct softif_neigh *curr_softif_neigh = NULL;
|
struct softif_neigh *curr_softif_neigh = NULL;
|
||||||
@ -416,7 +439,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
|
|||||||
|
|
||||||
/* ethernet packet should be broadcasted */
|
/* ethernet packet should be broadcasted */
|
||||||
if (do_bcast) {
|
if (do_bcast) {
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if)
|
||||||
goto dropped;
|
goto dropped;
|
||||||
|
|
||||||
if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
|
if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
|
||||||
@ -432,7 +456,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
|
|||||||
/* hw address of first interface is the orig mac because only
|
/* hw address of first interface is the orig mac because only
|
||||||
* this mac is known throughout the mesh */
|
* this mac is known throughout the mesh */
|
||||||
memcpy(bcast_packet->orig,
|
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 */
|
/* set broadcast sequence number */
|
||||||
bcast_packet->seqno =
|
bcast_packet->seqno =
|
||||||
@ -462,6 +486,8 @@ dropped_freed:
|
|||||||
end:
|
end:
|
||||||
if (curr_softif_neigh)
|
if (curr_softif_neigh)
|
||||||
softif_neigh_free_ref(curr_softif_neigh);
|
softif_neigh_free_ref(curr_softif_neigh);
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "translation-table.h"
|
#include "translation-table.h"
|
||||||
#include "soft-interface.h"
|
#include "soft-interface.h"
|
||||||
|
#include "hard-interface.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "originator.h"
|
#include "originator.h"
|
||||||
|
|
||||||
@ -237,16 +238,26 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct hashtable_t *hash = bat_priv->hna_local_hash;
|
struct hashtable_t *hash = bat_priv->hna_local_hash;
|
||||||
struct hna_local_entry *hna_local_entry;
|
struct hna_local_entry *hna_local_entry;
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
size_t buf_size, pos;
|
size_t buf_size, pos;
|
||||||
char *buff;
|
char *buff;
|
||||||
int i;
|
int i, ret = 0;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
if (!primary_if) {
|
||||||
"please specify interfaces to enable it\n",
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
net_dev->name);
|
"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, "Locally retrieved addresses (from %s) "
|
seq_printf(seq, "Locally retrieved addresses (from %s) "
|
||||||
@ -269,7 +280,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
buff = kmalloc(buf_size, GFP_ATOMIC);
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
if (!buff) {
|
if (!buff) {
|
||||||
spin_unlock_bh(&bat_priv->hna_lhash_lock);
|
spin_unlock_bh(&bat_priv->hna_lhash_lock);
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
buff[0] = '\0';
|
buff[0] = '\0';
|
||||||
@ -291,7 +303,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
|
|
||||||
seq_printf(seq, "%s", buff);
|
seq_printf(seq, "%s", buff);
|
||||||
kfree(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)
|
static void _hna_local_del(struct hlist_node *node, void *arg)
|
||||||
@ -468,16 +483,26 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct hashtable_t *hash = bat_priv->hna_global_hash;
|
struct hashtable_t *hash = bat_priv->hna_global_hash;
|
||||||
struct hna_global_entry *hna_global_entry;
|
struct hna_global_entry *hna_global_entry;
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
size_t buf_size, pos;
|
size_t buf_size, pos;
|
||||||
char *buff;
|
char *buff;
|
||||||
int i;
|
int i, ret = 0;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
if (!primary_if) {
|
||||||
"please specify interfaces to enable it\n",
|
ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
|
||||||
net_dev->name);
|
"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, "Globally announced HNAs received via the mesh %s\n",
|
seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
|
||||||
@ -499,7 +524,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
buff = kmalloc(buf_size, GFP_ATOMIC);
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
if (!buff) {
|
if (!buff) {
|
||||||
spin_unlock_bh(&bat_priv->hna_ghash_lock);
|
spin_unlock_bh(&bat_priv->hna_ghash_lock);
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
buff[0] = '\0';
|
buff[0] = '\0';
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -522,7 +548,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
|
|
||||||
seq_printf(seq, "%s", buff);
|
seq_printf(seq, "%s", buff);
|
||||||
kfree(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,
|
static void _hna_global_del_orig(struct bat_priv *bat_priv,
|
||||||
|
@ -149,7 +149,6 @@ struct bat_priv {
|
|||||||
struct hlist_head softif_neigh_list;
|
struct hlist_head softif_neigh_list;
|
||||||
struct softif_neigh __rcu *softif_neigh;
|
struct softif_neigh __rcu *softif_neigh;
|
||||||
struct debug_log *debug_log;
|
struct debug_log *debug_log;
|
||||||
struct hard_iface *primary_if;
|
|
||||||
struct kobject *mesh_obj;
|
struct kobject *mesh_obj;
|
||||||
struct dentry *debug_dir;
|
struct dentry *debug_dir;
|
||||||
struct hlist_head forw_bat_list;
|
struct hlist_head forw_bat_list;
|
||||||
@ -174,6 +173,7 @@ struct bat_priv {
|
|||||||
struct delayed_work orig_work;
|
struct delayed_work orig_work;
|
||||||
struct delayed_work vis_work;
|
struct delayed_work vis_work;
|
||||||
struct gw_node __rcu *curr_gw; /* rcu protected pointer */
|
struct gw_node __rcu *curr_gw; /* rcu protected pointer */
|
||||||
|
struct hard_iface __rcu *primary_if; /* rcu protected pointer */
|
||||||
struct vis_info *my_vis_info;
|
struct vis_info *my_vis_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
|
|||||||
struct hard_iface *hard_iface, uint8_t dstaddr[])
|
struct hard_iface *hard_iface, uint8_t dstaddr[])
|
||||||
{
|
{
|
||||||
struct unicast_packet tmp_uc, *unicast_packet;
|
struct unicast_packet tmp_uc, *unicast_packet;
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct sk_buff *frag_skb;
|
struct sk_buff *frag_skb;
|
||||||
struct unicast_frag_packet *frag1, *frag2;
|
struct unicast_frag_packet *frag1, *frag2;
|
||||||
int uc_hdr_len = sizeof(struct unicast_packet);
|
int uc_hdr_len = sizeof(struct unicast_packet);
|
||||||
int ucf_hdr_len = sizeof(struct unicast_frag_packet);
|
int ucf_hdr_len = sizeof(struct unicast_frag_packet);
|
||||||
int data_len = skb->len - uc_hdr_len;
|
int data_len = skb->len - uc_hdr_len;
|
||||||
int large_tail = 0;
|
int large_tail = 0, ret = NET_RX_DROP;
|
||||||
uint16_t seqno;
|
uint16_t seqno;
|
||||||
|
|
||||||
if (!bat_priv->primary_if)
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
|
if (!primary_if)
|
||||||
goto dropped;
|
goto dropped;
|
||||||
|
|
||||||
frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
|
frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
|
||||||
@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
|
|||||||
frag1->version = COMPAT_VERSION;
|
frag1->version = COMPAT_VERSION;
|
||||||
frag1->packet_type = BAT_UNICAST_FRAG;
|
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));
|
memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
|
||||||
|
|
||||||
if (data_len & 1)
|
if (data_len & 1)
|
||||||
@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
|
|||||||
|
|
||||||
send_skb_packet(skb, hard_iface, dstaddr);
|
send_skb_packet(skb, hard_iface, dstaddr);
|
||||||
send_skb_packet(frag_skb, hard_iface, dstaddr);
|
send_skb_packet(frag_skb, hard_iface, dstaddr);
|
||||||
return NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
|
goto out;
|
||||||
|
|
||||||
drop_frag:
|
drop_frag:
|
||||||
kfree_skb(frag_skb);
|
kfree_skb(frag_skb);
|
||||||
dropped:
|
dropped:
|
||||||
kfree_skb(skb);
|
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)
|
int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
|
||||||
|
@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
|
|||||||
|
|
||||||
int vis_seq_print_text(struct seq_file *seq, void *offset)
|
int vis_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
{
|
{
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
struct vis_info *info;
|
struct vis_info *info;
|
||||||
@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
HLIST_HEAD(vis_if_list);
|
HLIST_HEAD(vis_if_list);
|
||||||
struct if_list_entry *entry;
|
struct if_list_entry *entry;
|
||||||
struct hlist_node *pos, *n;
|
struct hlist_node *pos, *n;
|
||||||
int i, j;
|
int i, j, ret = 0;
|
||||||
int vis_server = atomic_read(&bat_priv->vis_mode);
|
int vis_server = atomic_read(&bat_priv->vis_mode);
|
||||||
size_t buff_pos, buf_size;
|
size_t buff_pos, buf_size;
|
||||||
char *buff;
|
char *buff;
|
||||||
int compare;
|
int compare;
|
||||||
|
|
||||||
if ((!bat_priv->primary_if) ||
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
(vis_server == VIS_TYPE_CLIENT_UPDATE))
|
if (!primary_if)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
|
if (vis_server == VIS_TYPE_CLIENT_UPDATE)
|
||||||
|
goto out;
|
||||||
|
|
||||||
buf_size = 1;
|
buf_size = 1;
|
||||||
/* Estimate length */
|
/* Estimate length */
|
||||||
@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
buff = kmalloc(buf_size, GFP_ATOMIC);
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
if (!buff) {
|
if (!buff) {
|
||||||
spin_unlock_bh(&bat_priv->vis_hash_lock);
|
spin_unlock_bh(&bat_priv->vis_hash_lock);
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
buff[0] = '\0';
|
buff[0] = '\0';
|
||||||
buff_pos = 0;
|
buff_pos = 0;
|
||||||
@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
|
|||||||
seq_printf(seq, "%s", buff);
|
seq_printf(seq, "%s", buff);
|
||||||
kfree(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
|
/* add the info packet to the send list, if it was not
|
||||||
@ -815,16 +823,20 @@ out:
|
|||||||
/* only send one vis packet. called from send_vis_packets() */
|
/* only send one vis packet. called from send_vis_packets() */
|
||||||
static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
|
static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
|
||||||
{
|
{
|
||||||
|
struct hard_iface *primary_if;
|
||||||
struct vis_packet *packet;
|
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;
|
packet = (struct vis_packet *)info->skb_packet->data;
|
||||||
if (packet->ttl < 2) {
|
if (packet->ttl < 2) {
|
||||||
pr_debug("Error - can't send vis packet: ttl exceeded\n");
|
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,
|
memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||||
ETH_ALEN);
|
|
||||||
packet->ttl--;
|
packet->ttl--;
|
||||||
|
|
||||||
if (is_broadcast_ether_addr(packet->target_orig))
|
if (is_broadcast_ether_addr(packet->target_orig))
|
||||||
@ -832,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
|
|||||||
else
|
else
|
||||||
unicast_vis_packet(bat_priv, info);
|
unicast_vis_packet(bat_priv, info);
|
||||||
packet->ttl++; /* restore TTL */
|
packet->ttl++; /* restore TTL */
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (primary_if)
|
||||||
|
hardif_free_ref(primary_if);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called from timer; send (and maybe generate) vis packet. */
|
/* called from timer; send (and maybe generate) vis packet. */
|
||||||
@ -858,8 +874,7 @@ static void send_vis_packets(struct work_struct *work)
|
|||||||
kref_get(&info->refcount);
|
kref_get(&info->refcount);
|
||||||
spin_unlock_bh(&bat_priv->vis_hash_lock);
|
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);
|
spin_lock_bh(&bat_priv->vis_hash_lock);
|
||||||
send_list_del(info);
|
send_list_del(info);
|
||||||
|
Loading…
Reference in New Issue
Block a user