aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-03-28 14:34:23 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-28 14:34:23 -0400
commitea407f0b97ad6a1fed8e72121bd19d66f02524f6 (patch)
tree51a0ff3f3dbb7228150380aca2795e3eeb06b5bf /net
parent9631d79e815197dbe90080aedfbab6de41218d85 (diff)
parent0c81465357ffe29da9ff20103afe4a59908e0d30 (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/Makefile2
-rw-r--r--net/batman-adv/gateway_client.c2
-rw-r--r--net/batman-adv/hard-interface.c66
-rw-r--r--net/batman-adv/hard-interface.h13
-rw-r--r--net/batman-adv/main.c4
-rw-r--r--net/batman-adv/main.h3
-rw-r--r--net/batman-adv/network-coding.c10
-rw-r--r--net/batman-adv/originator.c4
-rw-r--r--net/batman-adv/packet.h2
-rw-r--r--net/batman-adv/soft-interface.c269
-rw-r--r--net/batman-adv/soft-interface.h3
-rw-r--r--net/batman-adv/sysfs.c6
-rw-r--r--net/batman-adv/vis.c4
13 files changed, 268 insertions, 120 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 4b8f192a9e43..acbac2a9c62f 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -1,5 +1,5 @@
1# 1#
2# Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: 2# Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
3# 3#
4# Marek Lindner, Simon Wunderlich 4# Marek Lindner, Simon Wunderlich
5# 5#
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 34f99a46ec1d..f105219f4a4b 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -500,7 +500,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
500 rcu_read_unlock(); 500 rcu_read_unlock();
501 501
502 if (gw_count == 0) 502 if (gw_count == 0)
503 seq_printf(seq, "No gateways in range ...\n"); 503 seq_puts(seq, "No gateways in range ...\n");
504 504
505out: 505out:
506 if (primary_if) 506 if (primary_if)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 368219e026a9..522243aff2f3 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -307,11 +307,35 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
307 batadv_update_min_mtu(hard_iface->soft_iface); 307 batadv_update_min_mtu(hard_iface->soft_iface);
308} 308}
309 309
310/**
311 * batadv_master_del_slave - remove hard_iface from the current master interface
312 * @slave: the interface enslaved in another master
313 * @master: the master from which slave has to be removed
314 *
315 * Invoke ndo_del_slave on master passing slave as argument. In this way slave
316 * is free'd and master can correctly change its internal state.
317 * Return 0 on success, a negative value representing the error otherwise
318 */
319static int batadv_master_del_slave(struct batadv_hard_iface *slave,
320 struct net_device *master)
321{
322 int ret;
323
324 if (!master)
325 return 0;
326
327 ret = -EBUSY;
328 if (master->netdev_ops->ndo_del_slave)
329 ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);
330
331 return ret;
332}
333
310int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, 334int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
311 const char *iface_name) 335 const char *iface_name)
312{ 336{
313 struct batadv_priv *bat_priv; 337 struct batadv_priv *bat_priv;
314 struct net_device *soft_iface; 338 struct net_device *soft_iface, *master;
315 __be16 ethertype = __constant_htons(ETH_P_BATMAN); 339 __be16 ethertype = __constant_htons(ETH_P_BATMAN);
316 int ret; 340 int ret;
317 341
@@ -321,11 +345,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
321 if (!atomic_inc_not_zero(&hard_iface->refcount)) 345 if (!atomic_inc_not_zero(&hard_iface->refcount))
322 goto out; 346 goto out;
323 347
324 /* hard-interface is part of a bridge */
325 if (hard_iface->net_dev->priv_flags & IFF_BRIDGE_PORT)
326 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",
327 hard_iface->net_dev->name);
328
329 soft_iface = dev_get_by_name(&init_net, iface_name); 348 soft_iface = dev_get_by_name(&init_net, iface_name);
330 349
331 if (!soft_iface) { 350 if (!soft_iface) {
@@ -347,12 +366,24 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
347 goto err_dev; 366 goto err_dev;
348 } 367 }
349 368
369 /* check if the interface is enslaved in another virtual one and
370 * in that case unlink it first
371 */
372 master = netdev_master_upper_dev_get(hard_iface->net_dev);
373 ret = batadv_master_del_slave(hard_iface, master);
374 if (ret)
375 goto err_dev;
376
350 hard_iface->soft_iface = soft_iface; 377 hard_iface->soft_iface = soft_iface;
351 bat_priv = netdev_priv(hard_iface->soft_iface); 378 bat_priv = netdev_priv(hard_iface->soft_iface);
352 379
380 ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface);
381 if (ret)
382 goto err_dev;
383
353 ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); 384 ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
354 if (ret < 0) 385 if (ret < 0)
355 goto err_dev; 386 goto err_upper;
356 387
357 hard_iface->if_num = bat_priv->num_ifaces; 388 hard_iface->if_num = bat_priv->num_ifaces;
358 bat_priv->num_ifaces++; 389 bat_priv->num_ifaces++;
@@ -362,7 +393,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
362 bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); 393 bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
363 bat_priv->num_ifaces--; 394 bat_priv->num_ifaces--;
364 hard_iface->if_status = BATADV_IF_NOT_IN_USE; 395 hard_iface->if_status = BATADV_IF_NOT_IN_USE;
365 goto err_dev; 396 goto err_upper;
366 } 397 }
367 398
368 hard_iface->batman_adv_ptype.type = ethertype; 399 hard_iface->batman_adv_ptype.type = ethertype;
@@ -401,14 +432,18 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
401out: 432out:
402 return 0; 433 return 0;
403 434
435err_upper:
436 netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface);
404err_dev: 437err_dev:
438 hard_iface->soft_iface = NULL;
405 dev_put(soft_iface); 439 dev_put(soft_iface);
406err: 440err:
407 batadv_hardif_free_ref(hard_iface); 441 batadv_hardif_free_ref(hard_iface);
408 return ret; 442 return ret;
409} 443}
410 444
411void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface) 445void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
446 enum batadv_hard_if_cleanup autodel)
412{ 447{
413 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 448 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
414 struct batadv_hard_iface *primary_if = NULL; 449 struct batadv_hard_iface *primary_if = NULL;
@@ -446,9 +481,10 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
446 dev_put(hard_iface->soft_iface); 481 dev_put(hard_iface->soft_iface);
447 482
448 /* nobody uses this interface anymore */ 483 /* nobody uses this interface anymore */
449 if (!bat_priv->num_ifaces) 484 if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO)
450 batadv_softif_destroy(hard_iface->soft_iface); 485 batadv_softif_destroy_sysfs(hard_iface->soft_iface);
451 486
487 netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
452 hard_iface->soft_iface = NULL; 488 hard_iface->soft_iface = NULL;
453 batadv_hardif_free_ref(hard_iface); 489 batadv_hardif_free_ref(hard_iface);
454 490
@@ -533,7 +569,8 @@ static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
533 569
534 /* first deactivate interface */ 570 /* first deactivate interface */
535 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 571 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
536 batadv_hardif_disable_interface(hard_iface); 572 batadv_hardif_disable_interface(hard_iface,
573 BATADV_IF_CLEANUP_AUTO);
537 574
538 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 575 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
539 return; 576 return;
@@ -563,6 +600,11 @@ static int batadv_hard_if_event(struct notifier_block *this,
563 struct batadv_hard_iface *primary_if = NULL; 600 struct batadv_hard_iface *primary_if = NULL;
564 struct batadv_priv *bat_priv; 601 struct batadv_priv *bat_priv;
565 602
603 if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
604 batadv_sysfs_add_meshif(net_dev);
605 return NOTIFY_DONE;
606 }
607
566 hard_iface = batadv_hardif_get_by_netdev(net_dev); 608 hard_iface = batadv_hardif_get_by_netdev(net_dev);
567 if (!hard_iface && event == NETDEV_REGISTER) 609 if (!hard_iface && event == NETDEV_REGISTER)
568 hard_iface = batadv_hardif_add_interface(net_dev); 610 hard_iface = batadv_hardif_add_interface(net_dev);
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 308437d52e22..49892881a7c5 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -29,13 +29,24 @@ enum batadv_hard_if_state {
29 BATADV_IF_I_WANT_YOU, 29 BATADV_IF_I_WANT_YOU,
30}; 30};
31 31
32/**
33 * enum batadv_hard_if_cleanup - Cleanup modi for soft_iface after slave removal
34 * @BATADV_IF_CLEANUP_KEEP: Don't automatically delete soft-interface
35 * @BATADV_IF_CLEANUP_AUTO: Delete soft-interface after last slave was removed
36 */
37enum batadv_hard_if_cleanup {
38 BATADV_IF_CLEANUP_KEEP,
39 BATADV_IF_CLEANUP_AUTO,
40};
41
32extern struct notifier_block batadv_hard_if_notifier; 42extern struct notifier_block batadv_hard_if_notifier;
33 43
34struct batadv_hard_iface* 44struct batadv_hard_iface*
35batadv_hardif_get_by_netdev(const struct net_device *net_dev); 45batadv_hardif_get_by_netdev(const struct net_device *net_dev);
36int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, 46int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
37 const char *iface_name); 47 const char *iface_name);
38void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface); 48void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
49 enum batadv_hard_if_cleanup autodel);
39void batadv_hardif_remove_interfaces(void); 50void batadv_hardif_remove_interfaces(void);
40int batadv_hardif_min_mtu(struct net_device *soft_iface); 51int batadv_hardif_min_mtu(struct net_device *soft_iface);
41void batadv_update_min_mtu(struct net_device *soft_iface); 52void batadv_update_min_mtu(struct net_device *soft_iface);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 0495a7dc7505..6277735cd89e 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -71,6 +71,7 @@ static int __init batadv_init(void)
71 batadv_debugfs_init(); 71 batadv_debugfs_init();
72 72
73 register_netdevice_notifier(&batadv_hard_if_notifier); 73 register_netdevice_notifier(&batadv_hard_if_notifier);
74 rtnl_link_register(&batadv_link_ops);
74 75
75 pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", 76 pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
76 BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION); 77 BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
@@ -81,6 +82,7 @@ static int __init batadv_init(void)
81static void __exit batadv_exit(void) 82static void __exit batadv_exit(void)
82{ 83{
83 batadv_debugfs_destroy(); 84 batadv_debugfs_destroy();
85 rtnl_link_unregister(&batadv_link_ops);
84 unregister_netdevice_notifier(&batadv_hard_if_notifier); 86 unregister_netdevice_notifier(&batadv_hard_if_notifier);
85 batadv_hardif_remove_interfaces(); 87 batadv_hardif_remove_interfaces();
86 88
@@ -417,7 +419,7 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
417{ 419{
418 struct batadv_algo_ops *bat_algo_ops; 420 struct batadv_algo_ops *bat_algo_ops;
419 421
420 seq_printf(seq, "Available routing algorithms:\n"); 422 seq_puts(seq, "Available routing algorithms:\n");
421 423
422 hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) { 424 hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) {
423 seq_printf(seq, "%s\n", bat_algo_ops->name); 425 seq_printf(seq, "%s\n", bat_algo_ops->name);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 0afd4ee7708b..f90f5bc8e426 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -26,7 +26,7 @@
26#define BATADV_DRIVER_DEVICE "batman-adv" 26#define BATADV_DRIVER_DEVICE "batman-adv"
27 27
28#ifndef BATADV_SOURCE_VERSION 28#ifndef BATADV_SOURCE_VERSION
29#define BATADV_SOURCE_VERSION "2013.1.0" 29#define BATADV_SOURCE_VERSION "2013.2.0"
30#endif 30#endif
31 31
32/* B.A.T.M.A.N. parameters */ 32/* B.A.T.M.A.N. parameters */
@@ -152,6 +152,7 @@ enum batadv_uev_type {
152#include <linux/percpu.h> 152#include <linux/percpu.h>
153#include <linux/slab.h> 153#include <linux/slab.h>
154#include <net/sock.h> /* struct sock */ 154#include <net/sock.h> /* struct sock */
155#include <net/rtnetlink.h>
155#include <linux/jiffies.h> 156#include <linux/jiffies.h>
156#include <linux/seq_file.h> 157#include <linux/seq_file.h>
157#include "types.h" 158#include "types.h"
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index 57280797bf4e..6b9a54485314 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -654,7 +654,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
654 struct batadv_orig_node *orig_node, 654 struct batadv_orig_node *orig_node,
655 struct batadv_ogm_packet *ogm_packet) 655 struct batadv_ogm_packet *ogm_packet)
656{ 656{
657 if (orig_node->last_real_seqno != ogm_packet->seqno) 657 if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
658 return false; 658 return false;
659 if (orig_node->last_ttl != ogm_packet->header.ttl + 1) 659 if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
660 return false; 660 return false;
@@ -1760,23 +1760,23 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
1760 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 1760 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1761 seq_printf(seq, "Node: %pM\n", orig_node->orig); 1761 seq_printf(seq, "Node: %pM\n", orig_node->orig);
1762 1762
1763 seq_printf(seq, " Ingoing: "); 1763 seq_puts(seq, " Ingoing: ");
1764 /* For each in_nc_node to this orig_node */ 1764 /* For each in_nc_node to this orig_node */
1765 list_for_each_entry_rcu(nc_node, 1765 list_for_each_entry_rcu(nc_node,
1766 &orig_node->in_coding_list, 1766 &orig_node->in_coding_list,
1767 list) 1767 list)
1768 seq_printf(seq, "%pM ", 1768 seq_printf(seq, "%pM ",
1769 nc_node->addr); 1769 nc_node->addr);
1770 seq_printf(seq, "\n"); 1770 seq_puts(seq, "\n");
1771 1771
1772 seq_printf(seq, " Outgoing: "); 1772 seq_puts(seq, " Outgoing: ");
1773 /* For out_nc_node to this orig_node */ 1773 /* For out_nc_node to this orig_node */
1774 list_for_each_entry_rcu(nc_node, 1774 list_for_each_entry_rcu(nc_node,
1775 &orig_node->out_coding_list, 1775 &orig_node->out_coding_list,
1776 list) 1776 list)
1777 seq_printf(seq, "%pM ", 1777 seq_printf(seq, "%pM ",
1778 nc_node->addr); 1778 nc_node->addr);
1779 seq_printf(seq, "\n\n"); 1779 seq_puts(seq, "\n\n");
1780 } 1780 }
1781 rcu_read_unlock(); 1781 rcu_read_unlock();
1782 } 1782 }
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 585e684a380b..2f3452546636 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -465,7 +465,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
465 neigh_node_tmp->tq_avg); 465 neigh_node_tmp->tq_avg);
466 } 466 }
467 467
468 seq_printf(seq, "\n"); 468 seq_puts(seq, "\n");
469 batman_count++; 469 batman_count++;
470 470
471next: 471next:
@@ -475,7 +475,7 @@ next:
475 } 475 }
476 476
477 if (batman_count == 0) 477 if (batman_count == 0)
478 seq_printf(seq, "No batman nodes in range ...\n"); 478 seq_puts(seq, "No batman nodes in range ...\n");
479 479
480out: 480out:
481 if (primary_if) 481 if (primary_if)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index a07995834b84..a51ccfc39da4 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -308,7 +308,7 @@ struct batadv_coded_packet {
308 uint8_t second_source[ETH_ALEN]; 308 uint8_t second_source[ETH_ALEN];
309 uint8_t second_orig_dest[ETH_ALEN]; 309 uint8_t second_orig_dest[ETH_ALEN];
310 __be32 second_crc; 310 __be32 second_crc;
311 uint16_t coded_len; 311 __be16 coded_len;
312}; 312};
313 313
314#endif /* _NET_BATMAN_ADV_PACKET_H_ */ 314#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index f93ae42abb58..403b8c46085e 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -402,55 +402,6 @@ static void batadv_set_lockdep_class(struct net_device *dev)
402} 402}
403 403
404/** 404/**
405 * batadv_softif_init - Late stage initialization of soft interface
406 * @dev: registered network device to modify
407 *
408 * Returns error code on failures
409 */
410static int batadv_softif_init(struct net_device *dev)
411{
412 batadv_set_lockdep_class(dev);
413
414 return 0;
415}
416
417static const struct net_device_ops batadv_netdev_ops = {
418 .ndo_init = batadv_softif_init,
419 .ndo_open = batadv_interface_open,
420 .ndo_stop = batadv_interface_release,
421 .ndo_get_stats = batadv_interface_stats,
422 .ndo_set_mac_address = batadv_interface_set_mac_addr,
423 .ndo_change_mtu = batadv_interface_change_mtu,
424 .ndo_start_xmit = batadv_interface_tx,
425 .ndo_validate_addr = eth_validate_addr
426};
427
428static void batadv_interface_setup(struct net_device *dev)
429{
430 struct batadv_priv *priv = netdev_priv(dev);
431
432 ether_setup(dev);
433
434 dev->netdev_ops = &batadv_netdev_ops;
435 dev->destructor = free_netdev;
436 dev->tx_queue_len = 0;
437
438 /* can't call min_mtu, because the needed variables
439 * have not been initialized yet
440 */
441 dev->mtu = ETH_DATA_LEN;
442 /* reserve more space in the skbuff for our header */
443 dev->hard_header_len = BATADV_HEADER_LEN;
444
445 /* generate random address */
446 eth_hw_addr_random(dev);
447
448 SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
449
450 memset(priv, 0, sizeof(*priv));
451}
452
453/**
454 * batadv_softif_destroy_finish - cleans up the remains of a softif 405 * batadv_softif_destroy_finish - cleans up the remains of a softif
455 * @work: work queue item 406 * @work: work queue item
456 * 407 *
@@ -466,7 +417,6 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
466 cleanup_work); 417 cleanup_work);
467 soft_iface = bat_priv->soft_iface; 418 soft_iface = bat_priv->soft_iface;
468 419
469 batadv_debugfs_del_meshif(soft_iface);
470 batadv_sysfs_del_meshif(soft_iface); 420 batadv_sysfs_del_meshif(soft_iface);
471 421
472 rtnl_lock(); 422 rtnl_lock();
@@ -474,21 +424,22 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
474 rtnl_unlock(); 424 rtnl_unlock();
475} 425}
476 426
477struct net_device *batadv_softif_create(const char *name) 427/**
428 * batadv_softif_init_late - late stage initialization of soft interface
429 * @dev: registered network device to modify
430 *
431 * Returns error code on failures
432 */
433static int batadv_softif_init_late(struct net_device *dev)
478{ 434{
479 struct net_device *soft_iface;
480 struct batadv_priv *bat_priv; 435 struct batadv_priv *bat_priv;
481 int ret; 436 int ret;
482 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; 437 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
483 438
484 soft_iface = alloc_netdev(sizeof(*bat_priv), name, 439 batadv_set_lockdep_class(dev);
485 batadv_interface_setup);
486
487 if (!soft_iface)
488 goto out;
489 440
490 bat_priv = netdev_priv(soft_iface); 441 bat_priv = netdev_priv(dev);
491 bat_priv->soft_iface = soft_iface; 442 bat_priv->soft_iface = dev;
492 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); 443 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
493 444
494 /* batadv_interface_stats() needs to be available as soon as 445 /* batadv_interface_stats() needs to be available as soon as
@@ -496,14 +447,7 @@ struct net_device *batadv_softif_create(const char *name)
496 */ 447 */
497 bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); 448 bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
498 if (!bat_priv->bat_counters) 449 if (!bat_priv->bat_counters)
499 goto free_soft_iface; 450 return -ENOMEM;
500
501 ret = register_netdevice(soft_iface);
502 if (ret < 0) {
503 pr_err("Unable to register the batman interface '%s': %i\n",
504 name, ret);
505 goto free_bat_counters;
506 }
507 451
508 atomic_set(&bat_priv->aggregated_ogms, 1); 452 atomic_set(&bat_priv->aggregated_ogms, 1);
509 atomic_set(&bat_priv->bonding, 0); 453 atomic_set(&bat_priv->bonding, 0);
@@ -541,51 +485,189 @@ struct net_device *batadv_softif_create(const char *name)
541 bat_priv->primary_if = NULL; 485 bat_priv->primary_if = NULL;
542 bat_priv->num_ifaces = 0; 486 bat_priv->num_ifaces = 0;
543 487
544 ret = batadv_algo_select(bat_priv, batadv_routing_algo);
545 if (ret < 0)
546 goto unreg_soft_iface;
547
548 batadv_nc_init_bat_priv(bat_priv); 488 batadv_nc_init_bat_priv(bat_priv);
549 489
550 ret = batadv_sysfs_add_meshif(soft_iface); 490 ret = batadv_algo_select(bat_priv, batadv_routing_algo);
551 if (ret < 0) 491 if (ret < 0)
552 goto unreg_soft_iface; 492 goto free_bat_counters;
553 493
554 ret = batadv_debugfs_add_meshif(soft_iface); 494 ret = batadv_debugfs_add_meshif(dev);
555 if (ret < 0) 495 if (ret < 0)
556 goto unreg_sysfs; 496 goto free_bat_counters;
557 497
558 ret = batadv_mesh_init(soft_iface); 498 ret = batadv_mesh_init(dev);
559 if (ret < 0) 499 if (ret < 0)
560 goto unreg_debugfs; 500 goto unreg_debugfs;
561 501
562 return soft_iface; 502 return 0;
563 503
564unreg_debugfs: 504unreg_debugfs:
565 batadv_debugfs_del_meshif(soft_iface); 505 batadv_debugfs_del_meshif(dev);
566unreg_sysfs:
567 batadv_sysfs_del_meshif(soft_iface);
568unreg_soft_iface:
569 free_percpu(bat_priv->bat_counters);
570 unregister_netdevice(soft_iface);
571 return NULL;
572
573free_bat_counters: 506free_bat_counters:
574 free_percpu(bat_priv->bat_counters); 507 free_percpu(bat_priv->bat_counters);
575free_soft_iface: 508
576 free_netdev(soft_iface); 509 return ret;
510}
511
512/**
513 * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
514 * @dev: batadv_soft_interface used as master interface
515 * @slave_dev: net_device which should become the slave interface
516 *
517 * Return 0 if successful or error otherwise.
518 */
519static int batadv_softif_slave_add(struct net_device *dev,
520 struct net_device *slave_dev)
521{
522 struct batadv_hard_iface *hard_iface;
523 int ret = -EINVAL;
524
525 hard_iface = batadv_hardif_get_by_netdev(slave_dev);
526 if (!hard_iface || hard_iface->soft_iface != NULL)
527 goto out;
528
529 ret = batadv_hardif_enable_interface(hard_iface, dev->name);
530
577out: 531out:
578 return NULL; 532 if (hard_iface)
533 batadv_hardif_free_ref(hard_iface);
534 return ret;
535}
536
537/**
538 * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface
539 * @dev: batadv_soft_interface used as master interface
540 * @slave_dev: net_device which should be removed from the master interface
541 *
542 * Return 0 if successful or error otherwise.
543 */
544static int batadv_softif_slave_del(struct net_device *dev,
545 struct net_device *slave_dev)
546{
547 struct batadv_hard_iface *hard_iface;
548 int ret = -EINVAL;
549
550 hard_iface = batadv_hardif_get_by_netdev(slave_dev);
551
552 if (!hard_iface || hard_iface->soft_iface != dev)
553 goto out;
554
555 batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP);
556 ret = 0;
557
558out:
559 if (hard_iface)
560 batadv_hardif_free_ref(hard_iface);
561 return ret;
562}
563
564static const struct net_device_ops batadv_netdev_ops = {
565 .ndo_init = batadv_softif_init_late,
566 .ndo_open = batadv_interface_open,
567 .ndo_stop = batadv_interface_release,
568 .ndo_get_stats = batadv_interface_stats,
569 .ndo_set_mac_address = batadv_interface_set_mac_addr,
570 .ndo_change_mtu = batadv_interface_change_mtu,
571 .ndo_start_xmit = batadv_interface_tx,
572 .ndo_validate_addr = eth_validate_addr,
573 .ndo_add_slave = batadv_softif_slave_add,
574 .ndo_del_slave = batadv_softif_slave_del,
575};
576
577/**
578 * batadv_softif_free - Deconstructor of batadv_soft_interface
579 * @dev: Device to cleanup and remove
580 */
581static void batadv_softif_free(struct net_device *dev)
582{
583 batadv_debugfs_del_meshif(dev);
584 batadv_mesh_free(dev);
585 free_netdev(dev);
579} 586}
580 587
581void batadv_softif_destroy(struct net_device *soft_iface) 588/**
589 * batadv_softif_init_early - early stage initialization of soft interface
590 * @dev: registered network device to modify
591 */
592static void batadv_softif_init_early(struct net_device *dev)
593{
594 struct batadv_priv *priv = netdev_priv(dev);
595
596 ether_setup(dev);
597
598 dev->netdev_ops = &batadv_netdev_ops;
599 dev->destructor = batadv_softif_free;
600 dev->tx_queue_len = 0;
601
602 /* can't call min_mtu, because the needed variables
603 * have not been initialized yet
604 */
605 dev->mtu = ETH_DATA_LEN;
606 /* reserve more space in the skbuff for our header */
607 dev->hard_header_len = BATADV_HEADER_LEN;
608
609 /* generate random address */
610 eth_hw_addr_random(dev);
611
612 SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
613
614 memset(priv, 0, sizeof(*priv));
615}
616
617struct net_device *batadv_softif_create(const char *name)
618{
619 struct net_device *soft_iface;
620 int ret;
621
622 soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
623 batadv_softif_init_early);
624 if (!soft_iface)
625 return NULL;
626
627 soft_iface->rtnl_link_ops = &batadv_link_ops;
628
629 ret = register_netdevice(soft_iface);
630 if (ret < 0) {
631 pr_err("Unable to register the batman interface '%s': %i\n",
632 name, ret);
633 free_netdev(soft_iface);
634 return NULL;
635 }
636
637 return soft_iface;
638}
639
640/**
641 * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs
642 * @soft_iface: the to-be-removed batman-adv interface
643 */
644void batadv_softif_destroy_sysfs(struct net_device *soft_iface)
582{ 645{
583 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 646 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
584 647
585 batadv_mesh_free(soft_iface);
586 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work); 648 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
587} 649}
588 650
651/**
652 * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink
653 * @soft_iface: the to-be-removed batman-adv interface
654 * @head: list pointer
655 */
656static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
657 struct list_head *head)
658{
659 struct batadv_hard_iface *hard_iface;
660
661 list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
662 if (hard_iface->soft_iface == soft_iface)
663 batadv_hardif_disable_interface(hard_iface,
664 BATADV_IF_CLEANUP_KEEP);
665 }
666
667 batadv_sysfs_del_meshif(soft_iface);
668 unregister_netdevice_queue(soft_iface, head);
669}
670
589int batadv_softif_is_valid(const struct net_device *net_dev) 671int batadv_softif_is_valid(const struct net_device *net_dev)
590{ 672{
591 if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) 673 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)
594 return 0; 676 return 0;
595} 677}
596 678
679struct rtnl_link_ops batadv_link_ops __read_mostly = {
680 .kind = "batadv",
681 .priv_size = sizeof(struct batadv_priv),
682 .setup = batadv_softif_init_early,
683 .dellink = batadv_softif_destroy_netlink,
684};
685
597/* ethtool */ 686/* ethtool */
598static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 687static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
599{ 688{
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 43182e5e603a..2f2472c2ea0d 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -25,7 +25,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
25 struct sk_buff *skb, struct batadv_hard_iface *recv_if, 25 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
26 int hdr_size, struct batadv_orig_node *orig_node); 26 int hdr_size, struct batadv_orig_node *orig_node);
27struct net_device *batadv_softif_create(const char *name); 27struct net_device *batadv_softif_create(const char *name);
28void batadv_softif_destroy(struct net_device *soft_iface); 28void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
29int batadv_softif_is_valid(const struct net_device *net_dev); 29int batadv_softif_is_valid(const struct net_device *net_dev);
30extern struct rtnl_link_ops batadv_link_ops;
30 31
31#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */ 32#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index ce39f62f751e..15a22efa9a67 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -588,13 +588,15 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
588 } 588 }
589 589
590 if (status_tmp == BATADV_IF_NOT_IN_USE) { 590 if (status_tmp == BATADV_IF_NOT_IN_USE) {
591 batadv_hardif_disable_interface(hard_iface); 591 batadv_hardif_disable_interface(hard_iface,
592 BATADV_IF_CLEANUP_AUTO);
592 goto unlock; 593 goto unlock;
593 } 594 }
594 595
595 /* if the interface already is in use */ 596 /* if the interface already is in use */
596 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 597 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
597 batadv_hardif_disable_interface(hard_iface); 598 batadv_hardif_disable_interface(hard_iface,
599 BATADV_IF_CLEANUP_AUTO);
598 600
599 ret = batadv_hardif_enable_interface(hard_iface, buff); 601 ret = batadv_hardif_enable_interface(hard_iface, buff);
600 602
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index c053244b97bd..962ccf3b8382 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -149,7 +149,7 @@ static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
149 149
150 hlist_for_each_entry(entry, if_list, list) { 150 hlist_for_each_entry(entry, if_list, list) {
151 if (entry->primary) 151 if (entry->primary)
152 seq_printf(seq, "PRIMARY, "); 152 seq_puts(seq, "PRIMARY, ");
153 else 153 else
154 seq_printf(seq, "SEC %pM, ", entry->addr); 154 seq_printf(seq, "SEC %pM, ", entry->addr);
155 } 155 }
@@ -207,7 +207,7 @@ static void batadv_vis_data_read_entries(struct seq_file *seq,
207 if (batadv_compare_eth(entry->addr, packet->vis_orig)) 207 if (batadv_compare_eth(entry->addr, packet->vis_orig))
208 batadv_vis_data_read_prim_sec(seq, list); 208 batadv_vis_data_read_prim_sec(seq, list);
209 209
210 seq_printf(seq, "\n"); 210 seq_puts(seq, "\n");
211 } 211 }
212} 212}
213 213