aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/soft-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r--net/batman-adv/soft-interface.c288
1 files changed, 199 insertions, 89 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 2711e870f557..6f20d339e33a 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -37,6 +37,7 @@
37#include <linux/if_ether.h> 37#include <linux/if_ether.h>
38#include "unicast.h" 38#include "unicast.h"
39#include "bridge_loop_avoidance.h" 39#include "bridge_loop_avoidance.h"
40#include "network-coding.h"
40 41
41 42
42static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); 43static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
@@ -401,55 +402,6 @@ static void batadv_set_lockdep_class(struct net_device *dev)
401} 402}
402 403
403/** 404/**
404 * batadv_softif_init - Late stage initialization of soft interface
405 * @dev: registered network device to modify
406 *
407 * Returns error code on failures
408 */
409static int batadv_softif_init(struct net_device *dev)
410{
411 batadv_set_lockdep_class(dev);
412
413 return 0;
414}
415
416static const struct net_device_ops batadv_netdev_ops = {
417 .ndo_init = batadv_softif_init,
418 .ndo_open = batadv_interface_open,
419 .ndo_stop = batadv_interface_release,
420 .ndo_get_stats = batadv_interface_stats,
421 .ndo_set_mac_address = batadv_interface_set_mac_addr,
422 .ndo_change_mtu = batadv_interface_change_mtu,
423 .ndo_start_xmit = batadv_interface_tx,
424 .ndo_validate_addr = eth_validate_addr
425};
426
427static void batadv_interface_setup(struct net_device *dev)
428{
429 struct batadv_priv *priv = netdev_priv(dev);
430
431 ether_setup(dev);
432
433 dev->netdev_ops = &batadv_netdev_ops;
434 dev->destructor = free_netdev;
435 dev->tx_queue_len = 0;
436
437 /* can't call min_mtu, because the needed variables
438 * have not been initialized yet
439 */
440 dev->mtu = ETH_DATA_LEN;
441 /* reserve more space in the skbuff for our header */
442 dev->hard_header_len = BATADV_HEADER_LEN;
443
444 /* generate random address */
445 eth_hw_addr_random(dev);
446
447 SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
448
449 memset(priv, 0, sizeof(*priv));
450}
451
452/**
453 * batadv_softif_destroy_finish - cleans up the remains of a softif 405 * batadv_softif_destroy_finish - cleans up the remains of a softif
454 * @work: work queue item 406 * @work: work queue item
455 * 407 *
@@ -465,7 +417,6 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
465 cleanup_work); 417 cleanup_work);
466 soft_iface = bat_priv->soft_iface; 418 soft_iface = bat_priv->soft_iface;
467 419
468 batadv_debugfs_del_meshif(soft_iface);
469 batadv_sysfs_del_meshif(soft_iface); 420 batadv_sysfs_del_meshif(soft_iface);
470 421
471 rtnl_lock(); 422 rtnl_lock();
@@ -473,21 +424,22 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
473 rtnl_unlock(); 424 rtnl_unlock();
474} 425}
475 426
476struct 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)
477{ 434{
478 struct net_device *soft_iface;
479 struct batadv_priv *bat_priv; 435 struct batadv_priv *bat_priv;
480 int ret; 436 int ret;
481 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; 437 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
482 438
483 soft_iface = alloc_netdev(sizeof(*bat_priv), name, 439 batadv_set_lockdep_class(dev);
484 batadv_interface_setup);
485
486 if (!soft_iface)
487 goto out;
488 440
489 bat_priv = netdev_priv(soft_iface); 441 bat_priv = netdev_priv(dev);
490 bat_priv->soft_iface = soft_iface; 442 bat_priv->soft_iface = dev;
491 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); 443 INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
492 444
493 /* batadv_interface_stats() needs to be available as soon as 445 /* batadv_interface_stats() needs to be available as soon as
@@ -495,14 +447,7 @@ struct net_device *batadv_softif_create(const char *name)
495 */ 447 */
496 bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); 448 bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
497 if (!bat_priv->bat_counters) 449 if (!bat_priv->bat_counters)
498 goto free_soft_iface; 450 return -ENOMEM;
499
500 ret = register_netdevice(soft_iface);
501 if (ret < 0) {
502 pr_err("Unable to register the batman interface '%s': %i\n",
503 name, ret);
504 goto free_bat_counters;
505 }
506 451
507 atomic_set(&bat_priv->aggregated_ogms, 1); 452 atomic_set(&bat_priv->aggregated_ogms, 1);
508 atomic_set(&bat_priv->bonding, 0); 453 atomic_set(&bat_priv->bonding, 0);
@@ -540,49 +485,196 @@ struct net_device *batadv_softif_create(const char *name)
540 bat_priv->primary_if = NULL; 485 bat_priv->primary_if = NULL;
541 bat_priv->num_ifaces = 0; 486 bat_priv->num_ifaces = 0;
542 487
543 ret = batadv_algo_select(bat_priv, batadv_routing_algo); 488 batadv_nc_init_bat_priv(bat_priv);
544 if (ret < 0)
545 goto unreg_soft_iface;
546 489
547 ret = batadv_sysfs_add_meshif(soft_iface); 490 ret = batadv_algo_select(bat_priv, batadv_routing_algo);
548 if (ret < 0) 491 if (ret < 0)
549 goto unreg_soft_iface; 492 goto free_bat_counters;
550 493
551 ret = batadv_debugfs_add_meshif(soft_iface); 494 ret = batadv_debugfs_add_meshif(dev);
552 if (ret < 0) 495 if (ret < 0)
553 goto unreg_sysfs; 496 goto free_bat_counters;
554 497
555 ret = batadv_mesh_init(soft_iface); 498 ret = batadv_mesh_init(dev);
556 if (ret < 0) 499 if (ret < 0)
557 goto unreg_debugfs; 500 goto unreg_debugfs;
558 501
559 return soft_iface; 502 return 0;
560 503
561unreg_debugfs: 504unreg_debugfs:
562 batadv_debugfs_del_meshif(soft_iface); 505 batadv_debugfs_del_meshif(dev);
563unreg_sysfs:
564 batadv_sysfs_del_meshif(soft_iface);
565unreg_soft_iface:
566 free_percpu(bat_priv->bat_counters);
567 unregister_netdevice(soft_iface);
568 return NULL;
569
570free_bat_counters: 506free_bat_counters:
571 free_percpu(bat_priv->bat_counters); 507 free_percpu(bat_priv->bat_counters);
572free_soft_iface: 508
573 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
574out: 531out:
575 return NULL; 532 if (hard_iface)
533 batadv_hardif_free_ref(hard_iface);
534 return ret;
576} 535}
577 536
578void batadv_softif_destroy(struct net_device *soft_iface) 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
586 /* some scheduled RCU callbacks need the bat_priv struct to accomplish
587 * their tasks. Wait for them all to be finished before freeing the
588 * netdev and its private data (bat_priv)
589 */
590 rcu_barrier();
591
592 free_netdev(dev);
593}
594
595/**
596 * batadv_softif_init_early - early stage initialization of soft interface
597 * @dev: registered network device to modify
598 */
599static void batadv_softif_init_early(struct net_device *dev)
600{
601 struct batadv_priv *priv = netdev_priv(dev);
602
603 ether_setup(dev);
604
605 dev->netdev_ops = &batadv_netdev_ops;
606 dev->destructor = batadv_softif_free;
607 dev->tx_queue_len = 0;
608
609 /* can't call min_mtu, because the needed variables
610 * have not been initialized yet
611 */
612 dev->mtu = ETH_DATA_LEN;
613 /* reserve more space in the skbuff for our header */
614 dev->hard_header_len = BATADV_HEADER_LEN;
615
616 /* generate random address */
617 eth_hw_addr_random(dev);
618
619 SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
620
621 memset(priv, 0, sizeof(*priv));
622}
623
624struct net_device *batadv_softif_create(const char *name)
625{
626 struct net_device *soft_iface;
627 int ret;
628
629 soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
630 batadv_softif_init_early);
631 if (!soft_iface)
632 return NULL;
633
634 soft_iface->rtnl_link_ops = &batadv_link_ops;
635
636 ret = register_netdevice(soft_iface);
637 if (ret < 0) {
638 pr_err("Unable to register the batman interface '%s': %i\n",
639 name, ret);
640 free_netdev(soft_iface);
641 return NULL;
642 }
643
644 return soft_iface;
645}
646
647/**
648 * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs
649 * @soft_iface: the to-be-removed batman-adv interface
650 */
651void batadv_softif_destroy_sysfs(struct net_device *soft_iface)
579{ 652{
580 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 653 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
581 654
582 batadv_mesh_free(soft_iface);
583 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work); 655 queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
584} 656}
585 657
658/**
659 * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink
660 * @soft_iface: the to-be-removed batman-adv interface
661 * @head: list pointer
662 */
663static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
664 struct list_head *head)
665{
666 struct batadv_hard_iface *hard_iface;
667
668 list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
669 if (hard_iface->soft_iface == soft_iface)
670 batadv_hardif_disable_interface(hard_iface,
671 BATADV_IF_CLEANUP_KEEP);
672 }
673
674 batadv_sysfs_del_meshif(soft_iface);
675 unregister_netdevice_queue(soft_iface, head);
676}
677
586int batadv_softif_is_valid(const struct net_device *net_dev) 678int batadv_softif_is_valid(const struct net_device *net_dev)
587{ 679{
588 if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) 680 if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
@@ -591,6 +683,13 @@ int batadv_softif_is_valid(const struct net_device *net_dev)
591 return 0; 683 return 0;
592} 684}
593 685
686struct rtnl_link_ops batadv_link_ops __read_mostly = {
687 .kind = "batadv",
688 .priv_size = sizeof(struct batadv_priv),
689 .setup = batadv_softif_init_early,
690 .dellink = batadv_softif_destroy_netlink,
691};
692
594/* ethtool */ 693/* ethtool */
595static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 694static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
596{ 695{
@@ -662,6 +761,17 @@ static const struct {
662 { "dat_put_rx" }, 761 { "dat_put_rx" },
663 { "dat_cached_reply_tx" }, 762 { "dat_cached_reply_tx" },
664#endif 763#endif
764#ifdef CONFIG_BATMAN_ADV_NC
765 { "nc_code" },
766 { "nc_code_bytes" },
767 { "nc_recode" },
768 { "nc_recode_bytes" },
769 { "nc_buffer" },
770 { "nc_decode" },
771 { "nc_decode_bytes" },
772 { "nc_decode_failed" },
773 { "nc_sniffed" },
774#endif
665}; 775};
666 776
667static void batadv_get_strings(struct net_device *dev, uint32_t stringset, 777static void batadv_get_strings(struct net_device *dev, uint32_t stringset,