diff options
Diffstat (limited to 'net/batman-adv/hard-interface.c')
| -rw-r--r-- | net/batman-adv/hard-interface.c | 139 | 
1 files changed, 67 insertions, 72 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index c478e6bcf89..fbda6b54baf 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:   *   * Marek Lindner, Simon Wunderlich   * @@ -12,9 +12,7 @@   * 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 + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include "main.h" @@ -25,9 +23,11 @@  #include "translation-table.h"  #include "routing.h"  #include "sysfs.h" +#include "debugfs.h"  #include "originator.h"  #include "hash.h"  #include "bridge_loop_avoidance.h" +#include "gateway_client.h"  #include <linux/if_arp.h>  #include <linux/if_ether.h> @@ -83,19 +83,17 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)  		return true;  	/* no more parents..stop recursion */ -	if (net_dev->iflink == net_dev->ifindex) +	if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex)  		return false;  	/* recurse over the parent device */ -	parent_dev = dev_get_by_index(&init_net, net_dev->iflink); +	parent_dev = __dev_get_by_index(&init_net, net_dev->iflink);  	/* if we got a NULL parent_dev there is something broken.. */  	if (WARN(!parent_dev, "Cannot find parent device"))  		return false;  	ret = batadv_is_on_batman_iface(parent_dev); -	if (parent_dev) -		dev_put(parent_dev);  	return ret;  } @@ -124,8 +122,11 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)   *   * Returns true if the net device is a 802.11 wireless device, false otherwise.   */ -static bool batadv_is_wifi_netdev(struct net_device *net_device) +bool batadv_is_wifi_netdev(struct net_device *net_device)  { +	if (!net_device) +		return false; +  #ifdef CONFIG_WIRELESS_EXT  	/* pre-cfg80211 drivers have to implement WEXT, so it is possible to  	 * check for wireless_handlers != NULL @@ -141,34 +142,6 @@ static bool batadv_is_wifi_netdev(struct net_device *net_device)  	return false;  } -/** - * batadv_is_wifi_iface - check if the given interface represented by ifindex - *  is a wifi interface - * @ifindex: interface index to check - * - * Returns true if the interface represented by ifindex is a 802.11 wireless - * device, false otherwise. - */ -bool batadv_is_wifi_iface(int ifindex) -{ -	struct net_device *net_device = NULL; -	bool ret = false; - -	if (ifindex == BATADV_NULL_IFINDEX) -		goto out; - -	net_device = dev_get_by_index(&init_net, ifindex); -	if (!net_device) -		goto out; - -	ret = batadv_is_wifi_netdev(net_device); - -out: -	if (net_device) -		dev_put(net_device); -	return ret; -} -  static struct batadv_hard_iface *  batadv_hardif_get_active(const struct net_device *soft_iface)  { @@ -194,22 +167,13 @@ out:  static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,  					  struct batadv_hard_iface *oldif)  { -	struct batadv_vis_packet *vis_packet;  	struct batadv_hard_iface *primary_if; -	struct sk_buff *skb;  	primary_if = batadv_primary_if_get_selected(bat_priv);  	if (!primary_if)  		goto out;  	batadv_dat_init_own_addr(bat_priv, primary_if); - -	skb = bat_priv->vis.my_info->skb_packet; -	vis_packet = (struct batadv_vis_packet *)skb->data; -	memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); -	memcpy(vis_packet->sender_orig, -	       primary_if->net_dev->dev_addr, ETH_ALEN); -  	batadv_bla_update_orig_address(bat_priv, primary_if, oldif);  out:  	if (primary_if) @@ -275,15 +239,9 @@ static void batadv_check_known_mac_addr(const struct net_device *net_dev)  int batadv_hardif_min_mtu(struct net_device *soft_iface)  { -	const struct batadv_priv *bat_priv = netdev_priv(soft_iface); +	struct batadv_priv *bat_priv = netdev_priv(soft_iface);  	const struct batadv_hard_iface *hard_iface; -	/* allow big frames if all devices are capable to do so -	 * (have MTU > 1500 + BAT_HEADER_LEN) -	 */ -	int min_mtu = ETH_DATA_LEN; - -	if (atomic_read(&bat_priv->fragmentation)) -		goto out; +	int min_mtu = INT_MAX;  	rcu_read_lock();  	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { @@ -294,23 +252,46 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)  		if (hard_iface->soft_iface != soft_iface)  			continue; -		min_mtu = min_t(int, -				hard_iface->net_dev->mtu - BATADV_HEADER_LEN, -				min_mtu); +		min_mtu = min_t(int, hard_iface->net_dev->mtu, min_mtu);  	}  	rcu_read_unlock(); + +	if (atomic_read(&bat_priv->fragmentation) == 0) +		goto out; + +	/* with fragmentation enabled the maximum size of internally generated +	 * packets such as translation table exchanges or tvlv containers, etc +	 * has to be calculated +	 */ +	min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); +	min_mtu -= sizeof(struct batadv_frag_packet); +	min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; +  out: -	return min_mtu; +	/* report to the other components the maximum amount of bytes that +	 * batman-adv can send over the wire (without considering the payload +	 * overhead). For example, this value is used by TT to compute the +	 * maximum local table table size +	 */ +	atomic_set(&bat_priv->packet_size_max, min_mtu); + +	/* the real soft-interface MTU is computed by removing the payload +	 * overhead from the maximum amount of bytes that was just computed. +	 * +	 * However batman-adv does not support MTUs bigger than ETH_DATA_LEN +	 */ +	return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN);  }  /* adjusts the MTU if a new interface with a smaller MTU appeared. */  void batadv_update_min_mtu(struct net_device *soft_iface)  { -	int min_mtu; +	soft_iface->mtu = batadv_hardif_min_mtu(soft_iface); -	min_mtu = batadv_hardif_min_mtu(soft_iface); -	if (soft_iface->mtu != min_mtu) -		soft_iface->mtu = min_mtu; +	/* Check if the local translate table should be cleaned up to match a +	 * new (and smaller) MTU. +	 */ +	batadv_tt_local_resize_to_mtu(soft_iface);  }  static void @@ -388,7 +369,8 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,  {  	struct batadv_priv *bat_priv;  	struct net_device *soft_iface, *master; -	__be16 ethertype = __constant_htons(ETH_P_BATMAN); +	__be16 ethertype = htons(ETH_P_BATMAN); +	int max_header_len = batadv_max_header_len();  	int ret;  	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) @@ -453,23 +435,22 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,  	hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;  	dev_add_pack(&hard_iface->batman_adv_ptype); -	atomic_set(&hard_iface->frag_seqno, 1);  	batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",  		    hard_iface->net_dev->name);  	if (atomic_read(&bat_priv->fragmentation) && -	    hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) +	    hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)  		batadv_info(hard_iface->soft_iface, -			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n", +			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %i would solve the problem.\n",  			    hard_iface->net_dev->name, hard_iface->net_dev->mtu, -			    ETH_DATA_LEN + BATADV_HEADER_LEN); +			    ETH_DATA_LEN + max_header_len);  	if (!atomic_read(&bat_priv->fragmentation) && -	    hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) +	    hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)  		batadv_info(hard_iface->soft_iface, -			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n", +			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %i.\n",  			    hard_iface->net_dev->name, hard_iface->net_dev->mtu, -			    ETH_DATA_LEN + BATADV_HEADER_LEN); +			    ETH_DATA_LEN + max_header_len);  	if (batadv_hardif_is_iface_up(hard_iface))  		batadv_hardif_activate_interface(hard_iface); @@ -533,8 +514,12 @@ 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 && autodel == BATADV_IF_CLEANUP_AUTO) -		batadv_softif_destroy_sysfs(hard_iface->soft_iface); +	if (!bat_priv->num_ifaces) { +		batadv_gw_check_client_stop(bat_priv); + +		if (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; @@ -559,6 +544,7 @@ static void batadv_hardif_remove_interface_finish(struct work_struct *work)  	hard_iface = container_of(work, struct batadv_hard_iface,  				  cleanup_work); +	batadv_debugfs_del_hardif(hard_iface);  	batadv_sysfs_del_hardif(&hard_iface->hardif_obj);  	batadv_hardif_free_ref(hard_iface);  } @@ -589,6 +575,11 @@ batadv_hardif_add_interface(struct net_device *net_dev)  	hard_iface->net_dev = net_dev;  	hard_iface->soft_iface = NULL;  	hard_iface->if_status = BATADV_IF_NOT_IN_USE; + +	ret = batadv_debugfs_add_hardif(hard_iface); +	if (ret) +		goto free_sysfs; +  	INIT_LIST_HEAD(&hard_iface->list);  	INIT_WORK(&hard_iface->cleanup_work,  		  batadv_hardif_remove_interface_finish); @@ -605,6 +596,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)  	return hard_iface; +free_sysfs: +	batadv_sysfs_del_hardif(&hard_iface->hardif_obj);  free_if:  	kfree(hard_iface);  release_dev: @@ -652,6 +645,8 @@ static int batadv_hard_if_event(struct notifier_block *this,  	if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {  		batadv_sysfs_add_meshif(net_dev); +		bat_priv = netdev_priv(net_dev); +		batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);  		return NOTIFY_DONE;  	}  | 
