Included changes:
- A fix for the network coding component which has been added within the last pull request (so it is in linux-3.10). The problem has been spotted thanks to Fengguang Wu's automated daily checks on our tree. - Implementation of the RTNL API for virtual interface creation/deletion and slave manipulation - substitution of seq_printf with seq_puts when possible - minor cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABCAAGBQJRUsb7AAoJEADl0hg6qKeOf/sQAJ4VRwpB5WLIjtLPQ1Dvd/qu thPAn4vpv02Is8H7NRULRN9aqUIzWrWtXkhBTAOh0EHq3mki6a+QT4TUQ4qswTPv BaVS70hoTtN1OdcntWTATCUuX2Y2HD/D3Cw2IZIG7X9oqTEpoTpnuQygMsG/c1+s MtNO57/WUKlwLv0pAu9IHh4qCj00eF5YHsPmsWzoWAvi/4aCgESQfXGy4Dm6HqLB E8XuVLOLtw7NSw0V7n//KtEE2llTWkfslm06dSsAmqEtzOfOCCuA4Z0asnMPJt7s 4HknqNE0D0aR0sfS+W6G24gFQbIV8R4SYWnUfMFCvvT7Ds96RONdgkfWw39nM7XB y70kXUbfDBIeHiiV2uqbTZnbuAa61p8Y8jCJvWz0nujI1/QPnUA1bqEgC2AMTc1J I6rS8mhWC6Rg+ohkK7HSQfgiZ5xcWtjFuVuOhKr0cPwhaCI0yP5PCB/B3yxuJxwD egkL58fgPhgii3DOxInAqLS/aPT5vl49J91qC3+z2/xYS3zRxHsyIRkMwgfoI2Ab TofVmzKqDwENA+CnjCPQx2gn6w/QpK8g5xmW1GgbzuKddiCcQFKnezgpeSdnQrsM CP/8Tu6r3QSLlHebysMuhsCwyT1hv8Yt0PTDpBqtIXRpV5enTYa9xW3F+UTU65ZY p9fKQXJYDLLEhfcy/TJM =FoTZ -----END PGP SIGNATURE----- Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge Included changes: - A fix for the network coding component which has been added within the last pull request (so it is in linux-3.10). The problem has been spotted thanks to Fengguang Wu's automated daily checks on our tree. - Implementation of the RTNL API for virtual interface creation/deletion and slave manipulation - substitution of seq_printf with seq_puts when possible - minor cleanups Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ea407f0b97
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
|
||||
# Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
|
||||
#
|
||||
# Marek Lindner, Simon Wunderlich
|
||||
#
|
||||
|
|
|
@ -500,7 +500,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
|
|||
rcu_read_unlock();
|
||||
|
||||
if (gw_count == 0)
|
||||
seq_printf(seq, "No gateways in range ...\n");
|
||||
seq_puts(seq, "No gateways in range ...\n");
|
||||
|
||||
out:
|
||||
if (primary_if)
|
||||
|
|
|
@ -307,11 +307,35 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
|
|||
batadv_update_min_mtu(hard_iface->soft_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_master_del_slave - remove hard_iface from the current master interface
|
||||
* @slave: the interface enslaved in another master
|
||||
* @master: the master from which slave has to be removed
|
||||
*
|
||||
* Invoke ndo_del_slave on master passing slave as argument. In this way slave
|
||||
* is free'd and master can correctly change its internal state.
|
||||
* Return 0 on success, a negative value representing the error otherwise
|
||||
*/
|
||||
static int batadv_master_del_slave(struct batadv_hard_iface *slave,
|
||||
struct net_device *master)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!master)
|
||||
return 0;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (master->netdev_ops->ndo_del_slave)
|
||||
ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
const char *iface_name)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
struct net_device *soft_iface;
|
||||
struct net_device *soft_iface, *master;
|
||||
__be16 ethertype = __constant_htons(ETH_P_BATMAN);
|
||||
int ret;
|
||||
|
||||
|
@ -321,11 +345,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
if (!atomic_inc_not_zero(&hard_iface->refcount))
|
||||
goto out;
|
||||
|
||||
/* hard-interface is part of a bridge */
|
||||
if (hard_iface->net_dev->priv_flags & IFF_BRIDGE_PORT)
|
||||
pr_err("You are about to enable batman-adv on '%s' which already is part of a bridge. Unless you know exactly what you are doing this is probably wrong and won't work the way you think it would.\n",
|
||||
hard_iface->net_dev->name);
|
||||
|
||||
soft_iface = dev_get_by_name(&init_net, iface_name);
|
||||
|
||||
if (!soft_iface) {
|
||||
|
@ -347,12 +366,24 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
goto err_dev;
|
||||
}
|
||||
|
||||
/* check if the interface is enslaved in another virtual one and
|
||||
* in that case unlink it first
|
||||
*/
|
||||
master = netdev_master_upper_dev_get(hard_iface->net_dev);
|
||||
ret = batadv_master_del_slave(hard_iface, master);
|
||||
if (ret)
|
||||
goto err_dev;
|
||||
|
||||
hard_iface->soft_iface = soft_iface;
|
||||
bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||
|
||||
ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface);
|
||||
if (ret)
|
||||
goto err_dev;
|
||||
|
||||
ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
|
||||
if (ret < 0)
|
||||
goto err_dev;
|
||||
goto err_upper;
|
||||
|
||||
hard_iface->if_num = bat_priv->num_ifaces;
|
||||
bat_priv->num_ifaces++;
|
||||
|
@ -362,7 +393,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
|
||||
bat_priv->num_ifaces--;
|
||||
hard_iface->if_status = BATADV_IF_NOT_IN_USE;
|
||||
goto err_dev;
|
||||
goto err_upper;
|
||||
}
|
||||
|
||||
hard_iface->batman_adv_ptype.type = ethertype;
|
||||
|
@ -401,14 +432,18 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
out:
|
||||
return 0;
|
||||
|
||||
err_upper:
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface);
|
||||
err_dev:
|
||||
hard_iface->soft_iface = NULL;
|
||||
dev_put(soft_iface);
|
||||
err:
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
||||
enum batadv_hard_if_cleanup autodel)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
|
@ -446,9 +481,10 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
|||
dev_put(hard_iface->soft_iface);
|
||||
|
||||
/* nobody uses this interface anymore */
|
||||
if (!bat_priv->num_ifaces)
|
||||
batadv_softif_destroy(hard_iface->soft_iface);
|
||||
if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO)
|
||||
batadv_softif_destroy_sysfs(hard_iface->soft_iface);
|
||||
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
|
||||
hard_iface->soft_iface = NULL;
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
|
||||
|
@ -533,7 +569,8 @@ static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
|
|||
|
||||
/* first deactivate interface */
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
BATADV_IF_CLEANUP_AUTO);
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
return;
|
||||
|
@ -563,6 +600,11 @@ static int batadv_hard_if_event(struct notifier_block *this,
|
|||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
|
||||
batadv_sysfs_add_meshif(net_dev);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(net_dev);
|
||||
if (!hard_iface && event == NETDEV_REGISTER)
|
||||
hard_iface = batadv_hardif_add_interface(net_dev);
|
||||
|
|
|
@ -29,13 +29,24 @@ enum batadv_hard_if_state {
|
|||
BATADV_IF_I_WANT_YOU,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum batadv_hard_if_cleanup - Cleanup modi for soft_iface after slave removal
|
||||
* @BATADV_IF_CLEANUP_KEEP: Don't automatically delete soft-interface
|
||||
* @BATADV_IF_CLEANUP_AUTO: Delete soft-interface after last slave was removed
|
||||
*/
|
||||
enum batadv_hard_if_cleanup {
|
||||
BATADV_IF_CLEANUP_KEEP,
|
||||
BATADV_IF_CLEANUP_AUTO,
|
||||
};
|
||||
|
||||
extern struct notifier_block batadv_hard_if_notifier;
|
||||
|
||||
struct batadv_hard_iface*
|
||||
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
const char *iface_name);
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface);
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
||||
enum batadv_hard_if_cleanup autodel);
|
||||
void batadv_hardif_remove_interfaces(void);
|
||||
int batadv_hardif_min_mtu(struct net_device *soft_iface);
|
||||
void batadv_update_min_mtu(struct net_device *soft_iface);
|
||||
|
|
|
@ -71,6 +71,7 @@ static int __init batadv_init(void)
|
|||
batadv_debugfs_init();
|
||||
|
||||
register_netdevice_notifier(&batadv_hard_if_notifier);
|
||||
rtnl_link_register(&batadv_link_ops);
|
||||
|
||||
pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
|
||||
BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
|
||||
|
@ -81,6 +82,7 @@ static int __init batadv_init(void)
|
|||
static void __exit batadv_exit(void)
|
||||
{
|
||||
batadv_debugfs_destroy();
|
||||
rtnl_link_unregister(&batadv_link_ops);
|
||||
unregister_netdevice_notifier(&batadv_hard_if_notifier);
|
||||
batadv_hardif_remove_interfaces();
|
||||
|
||||
|
@ -417,7 +419,7 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
|
|||
{
|
||||
struct batadv_algo_ops *bat_algo_ops;
|
||||
|
||||
seq_printf(seq, "Available routing algorithms:\n");
|
||||
seq_puts(seq, "Available routing algorithms:\n");
|
||||
|
||||
hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) {
|
||||
seq_printf(seq, "%s\n", bat_algo_ops->name);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define BATADV_DRIVER_DEVICE "batman-adv"
|
||||
|
||||
#ifndef BATADV_SOURCE_VERSION
|
||||
#define BATADV_SOURCE_VERSION "2013.1.0"
|
||||
#define BATADV_SOURCE_VERSION "2013.2.0"
|
||||
#endif
|
||||
|
||||
/* B.A.T.M.A.N. parameters */
|
||||
|
@ -152,6 +152,7 @@ enum batadv_uev_type {
|
|||
#include <linux/percpu.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/sock.h> /* struct sock */
|
||||
#include <net/rtnetlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "types.h"
|
||||
|
|
|
@ -654,7 +654,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
|
|||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_ogm_packet *ogm_packet)
|
||||
{
|
||||
if (orig_node->last_real_seqno != ogm_packet->seqno)
|
||||
if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
|
||||
return false;
|
||||
if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
|
||||
return false;
|
||||
|
@ -1760,23 +1760,23 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
|
|||
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
|
||||
seq_printf(seq, "Node: %pM\n", orig_node->orig);
|
||||
|
||||
seq_printf(seq, " Ingoing: ");
|
||||
seq_puts(seq, " Ingoing: ");
|
||||
/* For each in_nc_node to this orig_node */
|
||||
list_for_each_entry_rcu(nc_node,
|
||||
&orig_node->in_coding_list,
|
||||
list)
|
||||
seq_printf(seq, "%pM ",
|
||||
nc_node->addr);
|
||||
seq_printf(seq, "\n");
|
||||
seq_puts(seq, "\n");
|
||||
|
||||
seq_printf(seq, " Outgoing: ");
|
||||
seq_puts(seq, " Outgoing: ");
|
||||
/* For out_nc_node to this orig_node */
|
||||
list_for_each_entry_rcu(nc_node,
|
||||
&orig_node->out_coding_list,
|
||||
list)
|
||||
seq_printf(seq, "%pM ",
|
||||
nc_node->addr);
|
||||
seq_printf(seq, "\n\n");
|
||||
seq_puts(seq, "\n\n");
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
@ -465,7 +465,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
|
|||
neigh_node_tmp->tq_avg);
|
||||
}
|
||||
|
||||
seq_printf(seq, "\n");
|
||||
seq_puts(seq, "\n");
|
||||
batman_count++;
|
||||
|
||||
next:
|
||||
|
@ -475,7 +475,7 @@ next:
|
|||
}
|
||||
|
||||
if (batman_count == 0)
|
||||
seq_printf(seq, "No batman nodes in range ...\n");
|
||||
seq_puts(seq, "No batman nodes in range ...\n");
|
||||
|
||||
out:
|
||||
if (primary_if)
|
||||
|
|
|
@ -308,7 +308,7 @@ struct batadv_coded_packet {
|
|||
uint8_t second_source[ETH_ALEN];
|
||||
uint8_t second_orig_dest[ETH_ALEN];
|
||||
__be32 second_crc;
|
||||
uint16_t coded_len;
|
||||
__be16 coded_len;
|
||||
};
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_PACKET_H_ */
|
||||
|
|
|
@ -401,55 +401,6 @@ static void batadv_set_lockdep_class(struct net_device *dev)
|
|||
netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_init - Late stage initialization of soft interface
|
||||
* @dev: registered network device to modify
|
||||
*
|
||||
* Returns error code on failures
|
||||
*/
|
||||
static int batadv_softif_init(struct net_device *dev)
|
||||
{
|
||||
batadv_set_lockdep_class(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops batadv_netdev_ops = {
|
||||
.ndo_init = batadv_softif_init,
|
||||
.ndo_open = batadv_interface_open,
|
||||
.ndo_stop = batadv_interface_release,
|
||||
.ndo_get_stats = batadv_interface_stats,
|
||||
.ndo_set_mac_address = batadv_interface_set_mac_addr,
|
||||
.ndo_change_mtu = batadv_interface_change_mtu,
|
||||
.ndo_start_xmit = batadv_interface_tx,
|
||||
.ndo_validate_addr = eth_validate_addr
|
||||
};
|
||||
|
||||
static void batadv_interface_setup(struct net_device *dev)
|
||||
{
|
||||
struct batadv_priv *priv = netdev_priv(dev);
|
||||
|
||||
ether_setup(dev);
|
||||
|
||||
dev->netdev_ops = &batadv_netdev_ops;
|
||||
dev->destructor = free_netdev;
|
||||
dev->tx_queue_len = 0;
|
||||
|
||||
/* can't call min_mtu, because the needed variables
|
||||
* have not been initialized yet
|
||||
*/
|
||||
dev->mtu = ETH_DATA_LEN;
|
||||
/* reserve more space in the skbuff for our header */
|
||||
dev->hard_header_len = BATADV_HEADER_LEN;
|
||||
|
||||
/* generate random address */
|
||||
eth_hw_addr_random(dev);
|
||||
|
||||
SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_destroy_finish - cleans up the remains of a softif
|
||||
* @work: work queue item
|
||||
|
@ -466,7 +417,6 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
|
|||
cleanup_work);
|
||||
soft_iface = bat_priv->soft_iface;
|
||||
|
||||
batadv_debugfs_del_meshif(soft_iface);
|
||||
batadv_sysfs_del_meshif(soft_iface);
|
||||
|
||||
rtnl_lock();
|
||||
|
@ -474,21 +424,22 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
|
|||
rtnl_unlock();
|
||||
}
|
||||
|
||||
struct net_device *batadv_softif_create(const char *name)
|
||||
/**
|
||||
* batadv_softif_init_late - late stage initialization of soft interface
|
||||
* @dev: registered network device to modify
|
||||
*
|
||||
* Returns error code on failures
|
||||
*/
|
||||
static int batadv_softif_init_late(struct net_device *dev)
|
||||
{
|
||||
struct net_device *soft_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
int ret;
|
||||
size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
|
||||
|
||||
soft_iface = alloc_netdev(sizeof(*bat_priv), name,
|
||||
batadv_interface_setup);
|
||||
batadv_set_lockdep_class(dev);
|
||||
|
||||
if (!soft_iface)
|
||||
goto out;
|
||||
|
||||
bat_priv = netdev_priv(soft_iface);
|
||||
bat_priv->soft_iface = soft_iface;
|
||||
bat_priv = netdev_priv(dev);
|
||||
bat_priv->soft_iface = dev;
|
||||
INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
|
||||
|
||||
/* batadv_interface_stats() needs to be available as soon as
|
||||
|
@ -496,14 +447,7 @@ struct net_device *batadv_softif_create(const char *name)
|
|||
*/
|
||||
bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
|
||||
if (!bat_priv->bat_counters)
|
||||
goto free_soft_iface;
|
||||
|
||||
ret = register_netdevice(soft_iface);
|
||||
if (ret < 0) {
|
||||
pr_err("Unable to register the batman interface '%s': %i\n",
|
||||
name, ret);
|
||||
goto free_bat_counters;
|
||||
}
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_set(&bat_priv->aggregated_ogms, 1);
|
||||
atomic_set(&bat_priv->bonding, 0);
|
||||
|
@ -541,51 +485,189 @@ struct net_device *batadv_softif_create(const char *name)
|
|||
bat_priv->primary_if = NULL;
|
||||
bat_priv->num_ifaces = 0;
|
||||
|
||||
ret = batadv_algo_select(bat_priv, batadv_routing_algo);
|
||||
if (ret < 0)
|
||||
goto unreg_soft_iface;
|
||||
|
||||
batadv_nc_init_bat_priv(bat_priv);
|
||||
|
||||
ret = batadv_sysfs_add_meshif(soft_iface);
|
||||
ret = batadv_algo_select(bat_priv, batadv_routing_algo);
|
||||
if (ret < 0)
|
||||
goto unreg_soft_iface;
|
||||
goto free_bat_counters;
|
||||
|
||||
ret = batadv_debugfs_add_meshif(soft_iface);
|
||||
ret = batadv_debugfs_add_meshif(dev);
|
||||
if (ret < 0)
|
||||
goto unreg_sysfs;
|
||||
goto free_bat_counters;
|
||||
|
||||
ret = batadv_mesh_init(soft_iface);
|
||||
ret = batadv_mesh_init(dev);
|
||||
if (ret < 0)
|
||||
goto unreg_debugfs;
|
||||
|
||||
return soft_iface;
|
||||
return 0;
|
||||
|
||||
unreg_debugfs:
|
||||
batadv_debugfs_del_meshif(soft_iface);
|
||||
unreg_sysfs:
|
||||
batadv_sysfs_del_meshif(soft_iface);
|
||||
unreg_soft_iface:
|
||||
free_percpu(bat_priv->bat_counters);
|
||||
unregister_netdevice(soft_iface);
|
||||
return NULL;
|
||||
|
||||
batadv_debugfs_del_meshif(dev);
|
||||
free_bat_counters:
|
||||
free_percpu(bat_priv->bat_counters);
|
||||
free_soft_iface:
|
||||
free_netdev(soft_iface);
|
||||
out:
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void batadv_softif_destroy(struct net_device *soft_iface)
|
||||
/**
|
||||
* batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
|
||||
* @dev: batadv_soft_interface used as master interface
|
||||
* @slave_dev: net_device which should become the slave interface
|
||||
*
|
||||
* Return 0 if successful or error otherwise.
|
||||
*/
|
||||
static int batadv_softif_slave_add(struct net_device *dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int ret = -EINVAL;
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
|
||||
if (!hard_iface || hard_iface->soft_iface != NULL)
|
||||
goto out;
|
||||
|
||||
ret = batadv_hardif_enable_interface(hard_iface, dev->name);
|
||||
|
||||
out:
|
||||
if (hard_iface)
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface
|
||||
* @dev: batadv_soft_interface used as master interface
|
||||
* @slave_dev: net_device which should be removed from the master interface
|
||||
*
|
||||
* Return 0 if successful or error otherwise.
|
||||
*/
|
||||
static int batadv_softif_slave_del(struct net_device *dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int ret = -EINVAL;
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
|
||||
|
||||
if (!hard_iface || hard_iface->soft_iface != dev)
|
||||
goto out;
|
||||
|
||||
batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (hard_iface)
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct net_device_ops batadv_netdev_ops = {
|
||||
.ndo_init = batadv_softif_init_late,
|
||||
.ndo_open = batadv_interface_open,
|
||||
.ndo_stop = batadv_interface_release,
|
||||
.ndo_get_stats = batadv_interface_stats,
|
||||
.ndo_set_mac_address = batadv_interface_set_mac_addr,
|
||||
.ndo_change_mtu = batadv_interface_change_mtu,
|
||||
.ndo_start_xmit = batadv_interface_tx,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_add_slave = batadv_softif_slave_add,
|
||||
.ndo_del_slave = batadv_softif_slave_del,
|
||||
};
|
||||
|
||||
/**
|
||||
* batadv_softif_free - Deconstructor of batadv_soft_interface
|
||||
* @dev: Device to cleanup and remove
|
||||
*/
|
||||
static void batadv_softif_free(struct net_device *dev)
|
||||
{
|
||||
batadv_debugfs_del_meshif(dev);
|
||||
batadv_mesh_free(dev);
|
||||
free_netdev(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_init_early - early stage initialization of soft interface
|
||||
* @dev: registered network device to modify
|
||||
*/
|
||||
static void batadv_softif_init_early(struct net_device *dev)
|
||||
{
|
||||
struct batadv_priv *priv = netdev_priv(dev);
|
||||
|
||||
ether_setup(dev);
|
||||
|
||||
dev->netdev_ops = &batadv_netdev_ops;
|
||||
dev->destructor = batadv_softif_free;
|
||||
dev->tx_queue_len = 0;
|
||||
|
||||
/* can't call min_mtu, because the needed variables
|
||||
* have not been initialized yet
|
||||
*/
|
||||
dev->mtu = ETH_DATA_LEN;
|
||||
/* reserve more space in the skbuff for our header */
|
||||
dev->hard_header_len = BATADV_HEADER_LEN;
|
||||
|
||||
/* generate random address */
|
||||
eth_hw_addr_random(dev);
|
||||
|
||||
SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
}
|
||||
|
||||
struct net_device *batadv_softif_create(const char *name)
|
||||
{
|
||||
struct net_device *soft_iface;
|
||||
int ret;
|
||||
|
||||
soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
|
||||
batadv_softif_init_early);
|
||||
if (!soft_iface)
|
||||
return NULL;
|
||||
|
||||
soft_iface->rtnl_link_ops = &batadv_link_ops;
|
||||
|
||||
ret = register_netdevice(soft_iface);
|
||||
if (ret < 0) {
|
||||
pr_err("Unable to register the batman interface '%s': %i\n",
|
||||
name, ret);
|
||||
free_netdev(soft_iface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return soft_iface;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs
|
||||
* @soft_iface: the to-be-removed batman-adv interface
|
||||
*/
|
||||
void batadv_softif_destroy_sysfs(struct net_device *soft_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
|
||||
batadv_mesh_free(soft_iface);
|
||||
queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink
|
||||
* @soft_iface: the to-be-removed batman-adv interface
|
||||
* @head: list pointer
|
||||
*/
|
||||
static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
|
||||
list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
|
||||
if (hard_iface->soft_iface == soft_iface)
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
BATADV_IF_CLEANUP_KEEP);
|
||||
}
|
||||
|
||||
batadv_sysfs_del_meshif(soft_iface);
|
||||
unregister_netdevice_queue(soft_iface, head);
|
||||
}
|
||||
|
||||
int batadv_softif_is_valid(const struct net_device *net_dev)
|
||||
{
|
||||
if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
|
||||
|
@ -594,6 +676,13 @@ int batadv_softif_is_valid(const struct net_device *net_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct rtnl_link_ops batadv_link_ops __read_mostly = {
|
||||
.kind = "batadv",
|
||||
.priv_size = sizeof(struct batadv_priv),
|
||||
.setup = batadv_softif_init_early,
|
||||
.dellink = batadv_softif_destroy_netlink,
|
||||
};
|
||||
|
||||
/* ethtool */
|
||||
static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
|
|||
struct sk_buff *skb, struct batadv_hard_iface *recv_if,
|
||||
int hdr_size, struct batadv_orig_node *orig_node);
|
||||
struct net_device *batadv_softif_create(const char *name);
|
||||
void batadv_softif_destroy(struct net_device *soft_iface);
|
||||
void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
|
||||
int batadv_softif_is_valid(const struct net_device *net_dev);
|
||||
extern struct rtnl_link_ops batadv_link_ops;
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
|
||||
|
|
|
@ -588,13 +588,15 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
|
|||
}
|
||||
|
||||
if (status_tmp == BATADV_IF_NOT_IN_USE) {
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
BATADV_IF_CLEANUP_AUTO);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* if the interface already is in use */
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
BATADV_IF_CLEANUP_AUTO);
|
||||
|
||||
ret = batadv_hardif_enable_interface(hard_iface, buff);
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
|
|||
|
||||
hlist_for_each_entry(entry, if_list, list) {
|
||||
if (entry->primary)
|
||||
seq_printf(seq, "PRIMARY, ");
|
||||
seq_puts(seq, "PRIMARY, ");
|
||||
else
|
||||
seq_printf(seq, "SEC %pM, ", entry->addr);
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ static void batadv_vis_data_read_entries(struct seq_file *seq,
|
|||
if (batadv_compare_eth(entry->addr, packet->vis_orig))
|
||||
batadv_vis_data_read_prim_sec(seq, list);
|
||||
|
||||
seq_printf(seq, "\n");
|
||||
seq_puts(seq, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue