diff options
author | David S. Miller <davem@davemloft.net> | 2016-07-01 17:05:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-01 17:05:00 -0400 |
commit | 3ea00443f1b17405ce9e1421bb7706777339926e (patch) | |
tree | bc2708a8e693cc19ca8a6501c4307a3f62055d99 /net/batman-adv | |
parent | ca9354a1d47d8e30dee114fc946fd71f1d403ca7 (diff) | |
parent | 4e3e823b5a503235630921287f130e1d8d22d200 (diff) |
Merge tag 'batadv-next-for-davem-20160701' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says:
====================
This feature patchset includes the following changes:
- two patches with minimal clean up work by Antonio Quartulli and
Simon Wunderlich
- eight patches of B.A.T.M.A.N. V, API and documentation clean
up work, by Antonio Quartulli and Marek Lindner
- Andrew Lunn fixed the skb priority adoption when forwarding
fragmented packets (two patches)
- Multicast optimization support is now enabled for bridges which
comes with some protocol updates, by Linus Luessing
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/Kconfig | 2 | ||||
-rw-r--r-- | net/batman-adv/bat_algo.h | 7 | ||||
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 72 | ||||
-rw-r--r-- | net/batman-adv/bat_v.c | 29 | ||||
-rw-r--r-- | net/batman-adv/bat_v_elp.c | 4 | ||||
-rw-r--r-- | net/batman-adv/bat_v_ogm.c | 4 | ||||
-rw-r--r-- | net/batman-adv/debugfs.c | 23 | ||||
-rw-r--r-- | net/batman-adv/fragmentation.c | 12 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 15 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.c | 6 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 6 | ||||
-rw-r--r-- | net/batman-adv/main.c | 2 | ||||
-rw-r--r-- | net/batman-adv/main.h | 6 | ||||
-rw-r--r-- | net/batman-adv/multicast.c | 499 | ||||
-rw-r--r-- | net/batman-adv/multicast.h | 3 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 40 | ||||
-rw-r--r-- | net/batman-adv/originator.h | 6 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 7 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 2 | ||||
-rw-r--r-- | net/batman-adv/send.c | 61 | ||||
-rw-r--r-- | net/batman-adv/send.h | 4 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 10 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 22 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 2 | ||||
-rw-r--r-- | net/batman-adv/types.h | 32 |
25 files changed, 694 insertions, 182 deletions
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index f66930ee3c0b..833bb145ba3c 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig | |||
@@ -66,7 +66,7 @@ config BATMAN_ADV_NC | |||
66 | 66 | ||
67 | config BATMAN_ADV_MCAST | 67 | config BATMAN_ADV_MCAST |
68 | bool "Multicast optimisation" | 68 | bool "Multicast optimisation" |
69 | depends on BATMAN_ADV | 69 | depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y) |
70 | default n | 70 | default n |
71 | help | 71 | help |
72 | This option enables the multicast optimisation which aims to | 72 | This option enables the multicast optimisation which aims to |
diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h index 03dafd33d23b..36542962de7d 100644 --- a/net/batman-adv/bat_algo.h +++ b/net/batman-adv/bat_algo.h | |||
@@ -18,13 +18,14 @@ | |||
18 | #ifndef _NET_BATMAN_ADV_BAT_ALGO_H_ | 18 | #ifndef _NET_BATMAN_ADV_BAT_ALGO_H_ |
19 | #define _NET_BATMAN_ADV_BAT_ALGO_H_ | 19 | #define _NET_BATMAN_ADV_BAT_ALGO_H_ |
20 | 20 | ||
21 | struct batadv_priv; | 21 | #include "main.h" |
22 | 22 | ||
23 | int batadv_iv_init(void); | 23 | int batadv_iv_init(void); |
24 | 24 | ||
25 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 25 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
26 | 26 | ||
27 | int batadv_v_init(void); | 27 | int batadv_v_init(void); |
28 | void batadv_v_hardif_init(struct batadv_hard_iface *hardif); | ||
28 | int batadv_v_mesh_init(struct batadv_priv *bat_priv); | 29 | int batadv_v_mesh_init(struct batadv_priv *bat_priv); |
29 | void batadv_v_mesh_free(struct batadv_priv *bat_priv); | 30 | void batadv_v_mesh_free(struct batadv_priv *bat_priv); |
30 | 31 | ||
@@ -35,6 +36,10 @@ static inline int batadv_v_init(void) | |||
35 | return 0; | 36 | return 0; |
36 | } | 37 | } |
37 | 38 | ||
39 | static inline void batadv_v_hardif_init(struct batadv_hard_iface *hardif) | ||
40 | { | ||
41 | } | ||
42 | |||
38 | static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv) | 43 | static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv) |
39 | { | 44 | { |
40 | return 0; | 45 | return 0; |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index ce2f203048d3..4815db978c27 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/if_ether.h> | 30 | #include <linux/if_ether.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <linux/kernel.h> | ||
33 | #include <linux/list.h> | 34 | #include <linux/list.h> |
34 | #include <linux/kref.h> | 35 | #include <linux/kref.h> |
35 | #include <linux/lockdep.h> | 36 | #include <linux/lockdep.h> |
@@ -58,6 +59,8 @@ | |||
58 | #include "send.h" | 59 | #include "send.h" |
59 | #include "translation-table.h" | 60 | #include "translation-table.h" |
60 | 61 | ||
62 | static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work); | ||
63 | |||
61 | /** | 64 | /** |
62 | * enum batadv_dup_status - duplicate status | 65 | * enum batadv_dup_status - duplicate status |
63 | * @BATADV_NO_DUP: the packet is no duplicate | 66 | * @BATADV_NO_DUP: the packet is no duplicate |
@@ -336,7 +339,8 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | |||
336 | { | 339 | { |
337 | struct batadv_neigh_node *neigh_node; | 340 | struct batadv_neigh_node *neigh_node; |
338 | 341 | ||
339 | neigh_node = batadv_neigh_node_new(orig_node, hard_iface, neigh_addr); | 342 | neigh_node = batadv_neigh_node_get_or_create(orig_node, |
343 | hard_iface, neigh_addr); | ||
340 | if (!neigh_node) | 344 | if (!neigh_node) |
341 | goto out; | 345 | goto out; |
342 | 346 | ||
@@ -730,7 +734,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
730 | 734 | ||
731 | /* start timer for this packet */ | 735 | /* start timer for this packet */ |
732 | INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, | 736 | INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, |
733 | batadv_send_outstanding_bat_ogm_packet); | 737 | batadv_iv_send_outstanding_bat_ogm_packet); |
734 | queue_delayed_work(batadv_event_workqueue, | 738 | queue_delayed_work(batadv_event_workqueue, |
735 | &forw_packet_aggr->delayed_work, | 739 | &forw_packet_aggr->delayed_work, |
736 | send_time - jiffies); | 740 | send_time - jiffies); |
@@ -937,6 +941,19 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
937 | u16 tvlv_len = 0; | 941 | u16 tvlv_len = 0; |
938 | unsigned long send_time; | 942 | unsigned long send_time; |
939 | 943 | ||
944 | if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || | ||
945 | (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) | ||
946 | return; | ||
947 | |||
948 | /* the interface gets activated here to avoid race conditions between | ||
949 | * the moment of activating the interface in | ||
950 | * hardif_activate_interface() where the originator mac is set and | ||
951 | * outdated packets (especially uninitialized mac addresses) in the | ||
952 | * packet queue | ||
953 | */ | ||
954 | if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) | ||
955 | hard_iface->if_status = BATADV_IF_ACTIVE; | ||
956 | |||
940 | primary_if = batadv_primary_if_get_selected(bat_priv); | 957 | primary_if = batadv_primary_if_get_selected(bat_priv); |
941 | 958 | ||
942 | if (hard_iface == primary_if) { | 959 | if (hard_iface == primary_if) { |
@@ -1778,6 +1795,45 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, | |||
1778 | batadv_orig_node_put(orig_node); | 1795 | batadv_orig_node_put(orig_node); |
1779 | } | 1796 | } |
1780 | 1797 | ||
1798 | static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) | ||
1799 | { | ||
1800 | struct delayed_work *delayed_work; | ||
1801 | struct batadv_forw_packet *forw_packet; | ||
1802 | struct batadv_priv *bat_priv; | ||
1803 | |||
1804 | delayed_work = to_delayed_work(work); | ||
1805 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | ||
1806 | delayed_work); | ||
1807 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); | ||
1808 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | ||
1809 | hlist_del(&forw_packet->list); | ||
1810 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | ||
1811 | |||
1812 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) | ||
1813 | goto out; | ||
1814 | |||
1815 | batadv_iv_ogm_emit(forw_packet); | ||
1816 | |||
1817 | /* we have to have at least one packet in the queue to determine the | ||
1818 | * queues wake up time unless we are shutting down. | ||
1819 | * | ||
1820 | * only re-schedule if this is the "original" copy, e.g. the OGM of the | ||
1821 | * primary interface should only be rescheduled once per period, but | ||
1822 | * this function will be called for the forw_packet instances of the | ||
1823 | * other secondary interfaces as well. | ||
1824 | */ | ||
1825 | if (forw_packet->own && | ||
1826 | forw_packet->if_incoming == forw_packet->if_outgoing) | ||
1827 | batadv_iv_ogm_schedule(forw_packet->if_incoming); | ||
1828 | |||
1829 | out: | ||
1830 | /* don't count own packet */ | ||
1831 | if (!forw_packet->own) | ||
1832 | atomic_inc(&bat_priv->batman_queue_left); | ||
1833 | |||
1834 | batadv_forw_packet_free(forw_packet); | ||
1835 | } | ||
1836 | |||
1781 | static int batadv_iv_ogm_receive(struct sk_buff *skb, | 1837 | static int batadv_iv_ogm_receive(struct sk_buff *skb, |
1782 | struct batadv_hard_iface *if_incoming) | 1838 | struct batadv_hard_iface *if_incoming) |
1783 | { | 1839 | { |
@@ -1794,7 +1850,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
1794 | /* did we receive a B.A.T.M.A.N. IV OGM packet on an interface | 1850 | /* did we receive a B.A.T.M.A.N. IV OGM packet on an interface |
1795 | * that does not have B.A.T.M.A.N. IV enabled ? | 1851 | * that does not have B.A.T.M.A.N. IV enabled ? |
1796 | */ | 1852 | */ |
1797 | if (bat_priv->bat_algo_ops->bat_ogm_emit != batadv_iv_ogm_emit) | 1853 | if (bat_priv->bat_algo_ops->bat_iface_enable != |
1854 | batadv_iv_ogm_iface_enable) | ||
1798 | return NET_RX_DROP; | 1855 | return NET_RX_DROP; |
1799 | 1856 | ||
1800 | batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX); | 1857 | batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX); |
@@ -2052,14 +2109,19 @@ out: | |||
2052 | return ret; | 2109 | return ret; |
2053 | } | 2110 | } |
2054 | 2111 | ||
2112 | static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface) | ||
2113 | { | ||
2114 | /* begin scheduling originator messages on that interface */ | ||
2115 | batadv_iv_ogm_schedule(hard_iface); | ||
2116 | } | ||
2117 | |||
2055 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { | 2118 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { |
2056 | .name = "BATMAN_IV", | 2119 | .name = "BATMAN_IV", |
2120 | .bat_iface_activate = batadv_iv_iface_activate, | ||
2057 | .bat_iface_enable = batadv_iv_ogm_iface_enable, | 2121 | .bat_iface_enable = batadv_iv_ogm_iface_enable, |
2058 | .bat_iface_disable = batadv_iv_ogm_iface_disable, | 2122 | .bat_iface_disable = batadv_iv_ogm_iface_disable, |
2059 | .bat_iface_update_mac = batadv_iv_ogm_iface_update_mac, | 2123 | .bat_iface_update_mac = batadv_iv_ogm_iface_update_mac, |
2060 | .bat_primary_iface_set = batadv_iv_ogm_primary_iface_set, | 2124 | .bat_primary_iface_set = batadv_iv_ogm_primary_iface_set, |
2061 | .bat_ogm_schedule = batadv_iv_ogm_schedule, | ||
2062 | .bat_ogm_emit = batadv_iv_ogm_emit, | ||
2063 | .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, | 2125 | .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, |
2064 | .bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob, | 2126 | .bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob, |
2065 | .bat_neigh_print = batadv_iv_neigh_print, | 2127 | .bat_neigh_print = batadv_iv_neigh_print, |
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 0a12e5cdd65d..c2fea812fb48 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c | |||
@@ -70,11 +70,6 @@ static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) | |||
70 | if (ret < 0) | 70 | if (ret < 0) |
71 | batadv_v_elp_iface_disable(hard_iface); | 71 | batadv_v_elp_iface_disable(hard_iface); |
72 | 72 | ||
73 | /* enable link throughput auto-detection by setting the throughput | ||
74 | * override to zero | ||
75 | */ | ||
76 | atomic_set(&hard_iface->bat_v.throughput_override, 0); | ||
77 | |||
78 | return ret; | 73 | return ret; |
79 | } | 74 | } |
80 | 75 | ||
@@ -119,14 +114,6 @@ batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh) | |||
119 | batadv_v_elp_throughput_metric_update); | 114 | batadv_v_elp_throughput_metric_update); |
120 | } | 115 | } |
121 | 116 | ||
122 | static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface) | ||
123 | { | ||
124 | } | ||
125 | |||
126 | static void batadv_v_ogm_emit(struct batadv_forw_packet *forw_packet) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /** | 117 | /** |
131 | * batadv_v_orig_print_neigh - print neighbors for the originator table | 118 | * batadv_v_orig_print_neigh - print neighbors for the originator table |
132 | * @orig_node: the orig_node for which the neighbors are printed | 119 | * @orig_node: the orig_node for which the neighbors are printed |
@@ -340,8 +327,6 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { | |||
340 | .bat_iface_update_mac = batadv_v_iface_update_mac, | 327 | .bat_iface_update_mac = batadv_v_iface_update_mac, |
341 | .bat_primary_iface_set = batadv_v_primary_iface_set, | 328 | .bat_primary_iface_set = batadv_v_primary_iface_set, |
342 | .bat_hardif_neigh_init = batadv_v_hardif_neigh_init, | 329 | .bat_hardif_neigh_init = batadv_v_hardif_neigh_init, |
343 | .bat_ogm_emit = batadv_v_ogm_emit, | ||
344 | .bat_ogm_schedule = batadv_v_ogm_schedule, | ||
345 | .bat_orig_print = batadv_v_orig_print, | 330 | .bat_orig_print = batadv_v_orig_print, |
346 | .bat_neigh_cmp = batadv_v_neigh_cmp, | 331 | .bat_neigh_cmp = batadv_v_neigh_cmp, |
347 | .bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob, | 332 | .bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob, |
@@ -349,6 +334,20 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { | |||
349 | }; | 334 | }; |
350 | 335 | ||
351 | /** | 336 | /** |
337 | * batadv_v_hardif_init - initialize the algorithm specific fields in the | ||
338 | * hard-interface object | ||
339 | * @hard_iface: the hard-interface to initialize | ||
340 | */ | ||
341 | void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface) | ||
342 | { | ||
343 | /* enable link throughput auto-detection by setting the throughput | ||
344 | * override to zero | ||
345 | */ | ||
346 | atomic_set(&hard_iface->bat_v.throughput_override, 0); | ||
347 | atomic_set(&hard_iface->bat_v.elp_interval, 500); | ||
348 | } | ||
349 | |||
350 | /** | ||
352 | * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a | 351 | * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a |
353 | * mesh | 352 | * mesh |
354 | * @bat_priv: the object representing the mesh interface to initialise | 353 | * @bat_priv: the object representing the mesh interface to initialise |
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index df42eb1365a0..cf0262becd08 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c | |||
@@ -344,7 +344,6 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface) | |||
344 | /* randomize initial seqno to avoid collision */ | 344 | /* randomize initial seqno to avoid collision */ |
345 | get_random_bytes(&random_seqno, sizeof(random_seqno)); | 345 | get_random_bytes(&random_seqno, sizeof(random_seqno)); |
346 | atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno); | 346 | atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno); |
347 | atomic_set(&hard_iface->bat_v.elp_interval, 500); | ||
348 | 347 | ||
349 | /* assume full-duplex by default */ | 348 | /* assume full-duplex by default */ |
350 | hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX; | 349 | hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX; |
@@ -443,7 +442,8 @@ static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv, | |||
443 | if (!orig_neigh) | 442 | if (!orig_neigh) |
444 | return; | 443 | return; |
445 | 444 | ||
446 | neigh = batadv_neigh_node_new(orig_neigh, if_incoming, neigh_addr); | 445 | neigh = batadv_neigh_node_get_or_create(orig_neigh, |
446 | if_incoming, neigh_addr); | ||
447 | if (!neigh) | 447 | if (!neigh) |
448 | goto orig_free; | 448 | goto orig_free; |
449 | 449 | ||
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index 473ebb9a0e73..23ea9bfb9f67 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c | |||
@@ -683,8 +683,8 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset, | |||
683 | if (!orig_node) | 683 | if (!orig_node) |
684 | return; | 684 | return; |
685 | 685 | ||
686 | neigh_node = batadv_neigh_node_new(orig_node, if_incoming, | 686 | neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming, |
687 | ethhdr->h_source); | 687 | ethhdr->h_source); |
688 | if (!neigh_node) | 688 | if (!neigh_node) |
689 | goto out; | 689 | goto out; |
690 | 690 | ||
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 952900466d88..f187a8ff2184 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "distributed-arp-table.h" | 48 | #include "distributed-arp-table.h" |
49 | #include "gateway_client.h" | 49 | #include "gateway_client.h" |
50 | #include "icmp_socket.h" | 50 | #include "icmp_socket.h" |
51 | #include "multicast.h" | ||
51 | #include "network-coding.h" | 52 | #include "network-coding.h" |
52 | #include "originator.h" | 53 | #include "originator.h" |
53 | #include "translation-table.h" | 54 | #include "translation-table.h" |
@@ -363,6 +364,22 @@ static int batadv_nc_nodes_open(struct inode *inode, struct file *file) | |||
363 | } | 364 | } |
364 | #endif | 365 | #endif |
365 | 366 | ||
367 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
368 | /** | ||
369 | * batadv_mcast_flags_open - prepare file handler for reads from mcast_flags | ||
370 | * @inode: inode which was opened | ||
371 | * @file: file handle to be initialized | ||
372 | * | ||
373 | * Return: 0 on success or negative error number in case of failure | ||
374 | */ | ||
375 | static int batadv_mcast_flags_open(struct inode *inode, struct file *file) | ||
376 | { | ||
377 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
378 | |||
379 | return single_open(file, batadv_mcast_flags_seq_print_text, net_dev); | ||
380 | } | ||
381 | #endif | ||
382 | |||
366 | #define BATADV_DEBUGINFO(_name, _mode, _open) \ | 383 | #define BATADV_DEBUGINFO(_name, _mode, _open) \ |
367 | struct batadv_debuginfo batadv_debuginfo_##_name = { \ | 384 | struct batadv_debuginfo batadv_debuginfo_##_name = { \ |
368 | .attr = { \ | 385 | .attr = { \ |
@@ -407,6 +424,9 @@ static BATADV_DEBUGINFO(transtable_local, S_IRUGO, | |||
407 | #ifdef CONFIG_BATMAN_ADV_NC | 424 | #ifdef CONFIG_BATMAN_ADV_NC |
408 | static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); | 425 | static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); |
409 | #endif | 426 | #endif |
427 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
428 | static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open); | ||
429 | #endif | ||
410 | 430 | ||
411 | static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | 431 | static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { |
412 | &batadv_debuginfo_neighbors, | 432 | &batadv_debuginfo_neighbors, |
@@ -424,6 +444,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | |||
424 | #ifdef CONFIG_BATMAN_ADV_NC | 444 | #ifdef CONFIG_BATMAN_ADV_NC |
425 | &batadv_debuginfo_nc_nodes, | 445 | &batadv_debuginfo_nc_nodes, |
426 | #endif | 446 | #endif |
447 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
448 | &batadv_debuginfo_mcast_flags, | ||
449 | #endif | ||
427 | NULL, | 450 | NULL, |
428 | }; | 451 | }; |
429 | 452 | ||
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 65536db1bff7..9f41a0a0d6ab 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/lockdep.h> | 28 | #include <linux/lockdep.h> |
29 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
30 | #include <linux/pkt_sched.h> | ||
31 | #include <linux/skbuff.h> | 30 | #include <linux/skbuff.h> |
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
33 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
@@ -414,7 +413,7 @@ static struct sk_buff *batadv_frag_create(struct sk_buff *skb, | |||
414 | if (!skb_fragment) | 413 | if (!skb_fragment) |
415 | goto err; | 414 | goto err; |
416 | 415 | ||
417 | skb->priority = TC_PRIO_CONTROL; | 416 | skb_fragment->priority = skb->priority; |
418 | 417 | ||
419 | /* Eat the last mtu-bytes of the skb */ | 418 | /* Eat the last mtu-bytes of the skb */ |
420 | skb_reserve(skb_fragment, header_size + ETH_HLEN); | 419 | skb_reserve(skb_fragment, header_size + ETH_HLEN); |
@@ -473,6 +472,15 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
473 | frag_header.reserved = 0; | 472 | frag_header.reserved = 0; |
474 | frag_header.no = 0; | 473 | frag_header.no = 0; |
475 | frag_header.total_size = htons(skb->len); | 474 | frag_header.total_size = htons(skb->len); |
475 | |||
476 | /* skb->priority values from 256->263 are magic values to | ||
477 | * directly indicate a specific 802.1d priority. This is used | ||
478 | * to allow 802.1d priority to be passed directly in from VLAN | ||
479 | * tags, etc. | ||
480 | */ | ||
481 | if (skb->priority >= 256 && skb->priority <= 263) | ||
482 | frag_header.priority = skb->priority - 256; | ||
483 | |||
476 | ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); | 484 | ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); |
477 | ether_addr_copy(frag_header.dest, orig_node->orig); | 485 | ether_addr_copy(frag_header.dest, orig_node->orig); |
478 | 486 | ||
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 5839c569f769..18c3715e5e27 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -192,7 +192,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
192 | 192 | ||
193 | tq_avg = router_ifinfo->bat_iv.tq_avg; | 193 | tq_avg = router_ifinfo->bat_iv.tq_avg; |
194 | 194 | ||
195 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 195 | switch (atomic_read(&bat_priv->gw.sel_class)) { |
196 | case 1: /* fast connection */ | 196 | case 1: /* fast connection */ |
197 | tmp_gw_factor = tq_avg * tq_avg; | 197 | tmp_gw_factor = tq_avg * tq_avg; |
198 | tmp_gw_factor *= gw_node->bandwidth_down; | 198 | tmp_gw_factor *= gw_node->bandwidth_down; |
@@ -255,7 +255,7 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv) | |||
255 | { | 255 | { |
256 | struct batadv_gw_node *curr_gw; | 256 | struct batadv_gw_node *curr_gw; |
257 | 257 | ||
258 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 258 | if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) |
259 | return; | 259 | return; |
260 | 260 | ||
261 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 261 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
@@ -283,7 +283,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
283 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | 283 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; |
284 | char gw_addr[18] = { '\0' }; | 284 | char gw_addr[18] = { '\0' }; |
285 | 285 | ||
286 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 286 | if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) |
287 | goto out; | 287 | goto out; |
288 | 288 | ||
289 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 289 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
@@ -402,8 +402,8 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, | |||
402 | /* if the routing class is greater than 3 the value tells us how much | 402 | /* if the routing class is greater than 3 the value tells us how much |
403 | * greater the TQ value of the new gateway must be | 403 | * greater the TQ value of the new gateway must be |
404 | */ | 404 | */ |
405 | if ((atomic_read(&bat_priv->gw_sel_class) > 3) && | 405 | if ((atomic_read(&bat_priv->gw.sel_class) > 3) && |
406 | (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class))) | 406 | (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw.sel_class))) |
407 | goto out; | 407 | goto out; |
408 | 408 | ||
409 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 409 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
@@ -638,8 +638,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
638 | goto out; | 638 | goto out; |
639 | 639 | ||
640 | seq_printf(seq, | 640 | seq_printf(seq, |
641 | " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", | 641 | " Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", |
642 | "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", | ||
643 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, | 642 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, |
644 | primary_if->net_dev->dev_addr, net_dev->name); | 643 | primary_if->net_dev->dev_addr, net_dev->name); |
645 | 644 | ||
@@ -821,7 +820,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
821 | if (!gw_node) | 820 | if (!gw_node) |
822 | goto out; | 821 | goto out; |
823 | 822 | ||
824 | switch (atomic_read(&bat_priv->gw_mode)) { | 823 | switch (atomic_read(&bat_priv->gw.mode)) { |
825 | case BATADV_GW_MODE_SERVER: | 824 | case BATADV_GW_MODE_SERVER: |
826 | /* If we are a GW then we are our best GW. We can artificially | 825 | /* If we are a GW then we are our best GW. We can artificially |
827 | * set the tq towards ourself as the maximum value | 826 | * set the tq towards ourself as the maximum value |
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 4423047889e1..3c269457776e 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
@@ -144,7 +144,7 @@ void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) | |||
144 | u32 down, up; | 144 | u32 down, up; |
145 | char gw_mode; | 145 | char gw_mode; |
146 | 146 | ||
147 | gw_mode = atomic_read(&bat_priv->gw_mode); | 147 | gw_mode = atomic_read(&bat_priv->gw.mode); |
148 | 148 | ||
149 | switch (gw_mode) { | 149 | switch (gw_mode) { |
150 | case BATADV_GW_MODE_OFF: | 150 | case BATADV_GW_MODE_OFF: |
@@ -241,8 +241,8 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | |||
241 | 241 | ||
242 | /* restart gateway selection if fast or late switching was enabled */ | 242 | /* restart gateway selection if fast or late switching was enabled */ |
243 | if ((gateway.bandwidth_down != 0) && | 243 | if ((gateway.bandwidth_down != 0) && |
244 | (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && | 244 | (atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) && |
245 | (atomic_read(&bat_priv->gw_sel_class) > 2)) | 245 | (atomic_read(&bat_priv->gw.sel_class) > 2)) |
246 | batadv_gw_check_election(bat_priv, orig); | 246 | batadv_gw_check_election(bat_priv, orig); |
247 | } | 247 | } |
248 | 248 | ||
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 8c2f39962fa5..3696929e5692 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | 39 | ||
40 | #include "bat_algo.h" | ||
40 | #include "bridge_loop_avoidance.h" | 41 | #include "bridge_loop_avoidance.h" |
41 | #include "debugfs.h" | 42 | #include "debugfs.h" |
42 | #include "distributed-arp-table.h" | 43 | #include "distributed-arp-table.h" |
@@ -553,9 +554,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
553 | 554 | ||
554 | batadv_hardif_recalc_extra_skbroom(soft_iface); | 555 | batadv_hardif_recalc_extra_skbroom(soft_iface); |
555 | 556 | ||
556 | /* begin scheduling originator messages on that interface */ | ||
557 | batadv_schedule_bat_ogm(hard_iface); | ||
558 | |||
559 | out: | 557 | out: |
560 | return 0; | 558 | return 0; |
561 | 559 | ||
@@ -686,6 +684,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
686 | if (batadv_is_wifi_netdev(net_dev)) | 684 | if (batadv_is_wifi_netdev(net_dev)) |
687 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; | 685 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; |
688 | 686 | ||
687 | batadv_v_hardif_init(hard_iface); | ||
688 | |||
689 | /* extra reference for return */ | 689 | /* extra reference for return */ |
690 | kref_init(&hard_iface->refcount); | 690 | kref_init(&hard_iface->refcount); |
691 | kref_get(&hard_iface->refcount); | 691 | kref_get(&hard_iface->refcount); |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 5f2974bd1227..627d14ececaf 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -569,8 +569,6 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) | |||
569 | !bat_algo_ops->bat_iface_disable || | 569 | !bat_algo_ops->bat_iface_disable || |
570 | !bat_algo_ops->bat_iface_update_mac || | 570 | !bat_algo_ops->bat_iface_update_mac || |
571 | !bat_algo_ops->bat_primary_iface_set || | 571 | !bat_algo_ops->bat_primary_iface_set || |
572 | !bat_algo_ops->bat_ogm_schedule || | ||
573 | !bat_algo_ops->bat_ogm_emit || | ||
574 | !bat_algo_ops->bat_neigh_cmp || | 572 | !bat_algo_ops->bat_neigh_cmp || |
575 | !bat_algo_ops->bat_neigh_is_similar_or_better) { | 573 | !bat_algo_ops->bat_neigh_is_similar_or_better) { |
576 | pr_info("Routing algo '%s' does not implement required ops\n", | 574 | pr_info("Routing algo '%s' does not implement required ops\n", |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 76925266deed..cd83e2824f70 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define BATADV_DRIVER_DEVICE "batman-adv" | 24 | #define BATADV_DRIVER_DEVICE "batman-adv" |
25 | 25 | ||
26 | #ifndef BATADV_SOURCE_VERSION | 26 | #ifndef BATADV_SOURCE_VERSION |
27 | #define BATADV_SOURCE_VERSION "2016.2" | 27 | #define BATADV_SOURCE_VERSION "2016.3" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | /* B.A.T.M.A.N. parameters */ | 30 | /* B.A.T.M.A.N. parameters */ |
@@ -231,6 +231,7 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr); | |||
231 | * @BATADV_DBG_BLA: bridge loop avoidance messages | 231 | * @BATADV_DBG_BLA: bridge loop avoidance messages |
232 | * @BATADV_DBG_DAT: ARP snooping and DAT related messages | 232 | * @BATADV_DBG_DAT: ARP snooping and DAT related messages |
233 | * @BATADV_DBG_NC: network coding related messages | 233 | * @BATADV_DBG_NC: network coding related messages |
234 | * @BATADV_DBG_MCAST: multicast related messages | ||
234 | * @BATADV_DBG_ALL: the union of all the above log levels | 235 | * @BATADV_DBG_ALL: the union of all the above log levels |
235 | */ | 236 | */ |
236 | enum batadv_dbg_level { | 237 | enum batadv_dbg_level { |
@@ -240,7 +241,8 @@ enum batadv_dbg_level { | |||
240 | BATADV_DBG_BLA = BIT(3), | 241 | BATADV_DBG_BLA = BIT(3), |
241 | BATADV_DBG_DAT = BIT(4), | 242 | BATADV_DBG_DAT = BIT(4), |
242 | BATADV_DBG_NC = BIT(5), | 243 | BATADV_DBG_NC = BIT(5), |
243 | BATADV_DBG_ALL = 63, | 244 | BATADV_DBG_MCAST = BIT(6), |
245 | BATADV_DBG_ALL = 127, | ||
244 | }; | 246 | }; |
245 | 247 | ||
246 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 248 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index c32f24fafe67..d3222db60fd0 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
@@ -25,17 +25,23 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/icmpv6.h> | ||
29 | #include <linux/if_bridge.h> | ||
28 | #include <linux/if_ether.h> | 30 | #include <linux/if_ether.h> |
29 | #include <linux/in6.h> | 31 | #include <linux/igmp.h> |
30 | #include <linux/in.h> | 32 | #include <linux/in.h> |
33 | #include <linux/in6.h> | ||
31 | #include <linux/ip.h> | 34 | #include <linux/ip.h> |
32 | #include <linux/ipv6.h> | 35 | #include <linux/ipv6.h> |
36 | #include <linux/kernel.h> | ||
33 | #include <linux/kref.h> | 37 | #include <linux/kref.h> |
34 | #include <linux/list.h> | 38 | #include <linux/list.h> |
35 | #include <linux/lockdep.h> | 39 | #include <linux/lockdep.h> |
36 | #include <linux/netdevice.h> | 40 | #include <linux/netdevice.h> |
41 | #include <linux/printk.h> | ||
37 | #include <linux/rculist.h> | 42 | #include <linux/rculist.h> |
38 | #include <linux/rcupdate.h> | 43 | #include <linux/rcupdate.h> |
44 | #include <linux/seq_file.h> | ||
39 | #include <linux/skbuff.h> | 45 | #include <linux/skbuff.h> |
40 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
41 | #include <linux/spinlock.h> | 47 | #include <linux/spinlock.h> |
@@ -43,18 +49,55 @@ | |||
43 | #include <linux/string.h> | 49 | #include <linux/string.h> |
44 | #include <linux/types.h> | 50 | #include <linux/types.h> |
45 | #include <net/addrconf.h> | 51 | #include <net/addrconf.h> |
52 | #include <net/if_inet6.h> | ||
53 | #include <net/ip.h> | ||
46 | #include <net/ipv6.h> | 54 | #include <net/ipv6.h> |
47 | 55 | ||
56 | #include "hard-interface.h" | ||
57 | #include "hash.h" | ||
48 | #include "packet.h" | 58 | #include "packet.h" |
49 | #include "translation-table.h" | 59 | #include "translation-table.h" |
50 | 60 | ||
51 | /** | 61 | /** |
62 | * batadv_mcast_get_bridge - get the bridge on top of the softif if it exists | ||
63 | * @soft_iface: netdev struct of the mesh interface | ||
64 | * | ||
65 | * If the given soft interface has a bridge on top then the refcount | ||
66 | * of the according net device is increased. | ||
67 | * | ||
68 | * Return: NULL if no such bridge exists. Otherwise the net device of the | ||
69 | * bridge. | ||
70 | */ | ||
71 | static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface) | ||
72 | { | ||
73 | struct net_device *upper = soft_iface; | ||
74 | |||
75 | rcu_read_lock(); | ||
76 | do { | ||
77 | upper = netdev_master_upper_dev_get_rcu(upper); | ||
78 | } while (upper && !(upper->priv_flags & IFF_EBRIDGE)); | ||
79 | |||
80 | if (upper) | ||
81 | dev_hold(upper); | ||
82 | rcu_read_unlock(); | ||
83 | |||
84 | return upper; | ||
85 | } | ||
86 | |||
87 | /** | ||
52 | * batadv_mcast_mla_softif_get - get softif multicast listeners | 88 | * batadv_mcast_mla_softif_get - get softif multicast listeners |
53 | * @dev: the device to collect multicast addresses from | 89 | * @dev: the device to collect multicast addresses from |
54 | * @mcast_list: a list to put found addresses into | 90 | * @mcast_list: a list to put found addresses into |
55 | * | 91 | * |
56 | * Collect multicast addresses of the local multicast listeners | 92 | * Collects multicast addresses of multicast listeners residing |
57 | * on the given soft interface, dev, in the given mcast_list. | 93 | * on this kernel on the given soft interface, dev, in |
94 | * the given mcast_list. In general, multicast listeners provided by | ||
95 | * your multicast receiving applications run directly on this node. | ||
96 | * | ||
97 | * If there is a bridge interface on top of dev, collects from that one | ||
98 | * instead. Just like with IP addresses and routes, multicast listeners | ||
99 | * will(/should) register to the bridge interface instead of an | ||
100 | * enslaved bat0. | ||
58 | * | 101 | * |
59 | * Return: -ENOMEM on memory allocation error or the number of | 102 | * Return: -ENOMEM on memory allocation error or the number of |
60 | * items added to the mcast_list otherwise. | 103 | * items added to the mcast_list otherwise. |
@@ -62,12 +105,13 @@ | |||
62 | static int batadv_mcast_mla_softif_get(struct net_device *dev, | 105 | static int batadv_mcast_mla_softif_get(struct net_device *dev, |
63 | struct hlist_head *mcast_list) | 106 | struct hlist_head *mcast_list) |
64 | { | 107 | { |
108 | struct net_device *bridge = batadv_mcast_get_bridge(dev); | ||
65 | struct netdev_hw_addr *mc_list_entry; | 109 | struct netdev_hw_addr *mc_list_entry; |
66 | struct batadv_hw_addr *new; | 110 | struct batadv_hw_addr *new; |
67 | int ret = 0; | 111 | int ret = 0; |
68 | 112 | ||
69 | netif_addr_lock_bh(dev); | 113 | netif_addr_lock_bh(bridge ? bridge : dev); |
70 | netdev_for_each_mc_addr(mc_list_entry, dev) { | 114 | netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) { |
71 | new = kmalloc(sizeof(*new), GFP_ATOMIC); | 115 | new = kmalloc(sizeof(*new), GFP_ATOMIC); |
72 | if (!new) { | 116 | if (!new) { |
73 | ret = -ENOMEM; | 117 | ret = -ENOMEM; |
@@ -78,7 +122,10 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, | |||
78 | hlist_add_head(&new->list, mcast_list); | 122 | hlist_add_head(&new->list, mcast_list); |
79 | ret++; | 123 | ret++; |
80 | } | 124 | } |
81 | netif_addr_unlock_bh(dev); | 125 | netif_addr_unlock_bh(bridge ? bridge : dev); |
126 | |||
127 | if (bridge) | ||
128 | dev_put(bridge); | ||
82 | 129 | ||
83 | return ret; | 130 | return ret; |
84 | } | 131 | } |
@@ -104,6 +151,83 @@ static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr, | |||
104 | } | 151 | } |
105 | 152 | ||
106 | /** | 153 | /** |
154 | * batadv_mcast_mla_br_addr_cpy - copy a bridge multicast address | ||
155 | * @dst: destination to write to - a multicast MAC address | ||
156 | * @src: source to read from - a multicast IP address | ||
157 | * | ||
158 | * Converts a given multicast IPv4/IPv6 address from a bridge | ||
159 | * to its matching multicast MAC address and copies it into the given | ||
160 | * destination buffer. | ||
161 | * | ||
162 | * Caller needs to make sure the destination buffer can hold | ||
163 | * at least ETH_ALEN bytes. | ||
164 | */ | ||
165 | static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src) | ||
166 | { | ||
167 | if (src->proto == htons(ETH_P_IP)) | ||
168 | ip_eth_mc_map(src->u.ip4, dst); | ||
169 | #if IS_ENABLED(CONFIG_IPV6) | ||
170 | else if (src->proto == htons(ETH_P_IPV6)) | ||
171 | ipv6_eth_mc_map(&src->u.ip6, dst); | ||
172 | #endif | ||
173 | else | ||
174 | eth_zero_addr(dst); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * batadv_mcast_mla_bridge_get - get bridged-in multicast listeners | ||
179 | * @dev: a bridge slave whose bridge to collect multicast addresses from | ||
180 | * @mcast_list: a list to put found addresses into | ||
181 | * | ||
182 | * Collects multicast addresses of multicast listeners residing | ||
183 | * on foreign, non-mesh devices which we gave access to our mesh via | ||
184 | * a bridge on top of the given soft interface, dev, in the given | ||
185 | * mcast_list. | ||
186 | * | ||
187 | * Return: -ENOMEM on memory allocation error or the number of | ||
188 | * items added to the mcast_list otherwise. | ||
189 | */ | ||
190 | static int batadv_mcast_mla_bridge_get(struct net_device *dev, | ||
191 | struct hlist_head *mcast_list) | ||
192 | { | ||
193 | struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list); | ||
194 | struct br_ip_list *br_ip_entry, *tmp; | ||
195 | struct batadv_hw_addr *new; | ||
196 | u8 mcast_addr[ETH_ALEN]; | ||
197 | int ret; | ||
198 | |||
199 | /* we don't need to detect these devices/listeners, the IGMP/MLD | ||
200 | * snooping code of the Linux bridge already does that for us | ||
201 | */ | ||
202 | ret = br_multicast_list_adjacent(dev, &bridge_mcast_list); | ||
203 | if (ret < 0) | ||
204 | goto out; | ||
205 | |||
206 | list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) { | ||
207 | batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr); | ||
208 | if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list)) | ||
209 | continue; | ||
210 | |||
211 | new = kmalloc(sizeof(*new), GFP_ATOMIC); | ||
212 | if (!new) { | ||
213 | ret = -ENOMEM; | ||
214 | break; | ||
215 | } | ||
216 | |||
217 | ether_addr_copy(new->addr, mcast_addr); | ||
218 | hlist_add_head(&new->list, mcast_list); | ||
219 | } | ||
220 | |||
221 | out: | ||
222 | list_for_each_entry_safe(br_ip_entry, tmp, &bridge_mcast_list, list) { | ||
223 | list_del(&br_ip_entry->list); | ||
224 | kfree(br_ip_entry); | ||
225 | } | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | /** | ||
107 | * batadv_mcast_mla_list_free - free a list of multicast addresses | 231 | * batadv_mcast_mla_list_free - free a list of multicast addresses |
108 | * @bat_priv: the bat priv with all the soft interface information | 232 | * @bat_priv: the bat priv with all the soft interface information |
109 | * @mcast_list: the list to free | 233 | * @mcast_list: the list to free |
@@ -214,44 +338,195 @@ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) | |||
214 | } | 338 | } |
215 | 339 | ||
216 | /** | 340 | /** |
341 | * batadv_mcast_querier_log - debug output regarding the querier status on link | ||
342 | * @bat_priv: the bat priv with all the soft interface information | ||
343 | * @str_proto: a string for the querier protocol (e.g. "IGMP" or "MLD") | ||
344 | * @old_state: the previous querier state on our link | ||
345 | * @new_state: the new querier state on our link | ||
346 | * | ||
347 | * Outputs debug messages to the logging facility with log level 'mcast' | ||
348 | * regarding changes to the querier status on the link which are relevant | ||
349 | * to our multicast optimizations. | ||
350 | * | ||
351 | * Usually this is about whether a querier appeared or vanished in | ||
352 | * our mesh or whether the querier is in the suboptimal position of being | ||
353 | * behind our local bridge segment: Snooping switches will directly | ||
354 | * forward listener reports to the querier, therefore batman-adv and | ||
355 | * the bridge will potentially not see these listeners - the querier is | ||
356 | * potentially shadowing listeners from us then. | ||
357 | * | ||
358 | * This is only interesting for nodes with a bridge on top of their | ||
359 | * soft interface. | ||
360 | */ | ||
361 | static void | ||
362 | batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto, | ||
363 | struct batadv_mcast_querier_state *old_state, | ||
364 | struct batadv_mcast_querier_state *new_state) | ||
365 | { | ||
366 | if (!old_state->exists && new_state->exists) | ||
367 | batadv_info(bat_priv->soft_iface, "%s Querier appeared\n", | ||
368 | str_proto); | ||
369 | else if (old_state->exists && !new_state->exists) | ||
370 | batadv_info(bat_priv->soft_iface, | ||
371 | "%s Querier disappeared - multicast optimizations disabled\n", | ||
372 | str_proto); | ||
373 | else if (!bat_priv->mcast.bridged && !new_state->exists) | ||
374 | batadv_info(bat_priv->soft_iface, | ||
375 | "No %s Querier present - multicast optimizations disabled\n", | ||
376 | str_proto); | ||
377 | |||
378 | if (new_state->exists) { | ||
379 | if ((!old_state->shadowing && new_state->shadowing) || | ||
380 | (!old_state->exists && new_state->shadowing)) | ||
381 | batadv_dbg(BATADV_DBG_MCAST, bat_priv, | ||
382 | "%s Querier is behind our bridged segment: Might shadow listeners\n", | ||
383 | str_proto); | ||
384 | else if (old_state->shadowing && !new_state->shadowing) | ||
385 | batadv_dbg(BATADV_DBG_MCAST, bat_priv, | ||
386 | "%s Querier is not behind our bridged segment\n", | ||
387 | str_proto); | ||
388 | } | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * batadv_mcast_bridge_log - debug output for topology changes in bridged setups | ||
393 | * @bat_priv: the bat priv with all the soft interface information | ||
394 | * @bridged: a flag about whether the soft interface is currently bridged or not | ||
395 | * @querier_ipv4: (maybe) new status of a potential, selected IGMP querier | ||
396 | * @querier_ipv6: (maybe) new status of a potential, selected MLD querier | ||
397 | * | ||
398 | * If no bridges are ever used on this node, then this function does nothing. | ||
399 | * | ||
400 | * Otherwise this function outputs debug information to the 'mcast' log level | ||
401 | * which might be relevant to our multicast optimizations. | ||
402 | * | ||
403 | * More precisely, it outputs information when a bridge interface is added or | ||
404 | * removed from a soft interface. And when a bridge is present, it further | ||
405 | * outputs information about the querier state which is relevant for the | ||
406 | * multicast flags this node is going to set. | ||
407 | */ | ||
408 | static void | ||
409 | batadv_mcast_bridge_log(struct batadv_priv *bat_priv, bool bridged, | ||
410 | struct batadv_mcast_querier_state *querier_ipv4, | ||
411 | struct batadv_mcast_querier_state *querier_ipv6) | ||
412 | { | ||
413 | if (!bat_priv->mcast.bridged && bridged) | ||
414 | batadv_dbg(BATADV_DBG_MCAST, bat_priv, | ||
415 | "Bridge added: Setting Unsnoopables(U)-flag\n"); | ||
416 | else if (bat_priv->mcast.bridged && !bridged) | ||
417 | batadv_dbg(BATADV_DBG_MCAST, bat_priv, | ||
418 | "Bridge removed: Unsetting Unsnoopables(U)-flag\n"); | ||
419 | |||
420 | if (bridged) { | ||
421 | batadv_mcast_querier_log(bat_priv, "IGMP", | ||
422 | &bat_priv->mcast.querier_ipv4, | ||
423 | querier_ipv4); | ||
424 | batadv_mcast_querier_log(bat_priv, "MLD", | ||
425 | &bat_priv->mcast.querier_ipv6, | ||
426 | querier_ipv6); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * batadv_mcast_flags_logs - output debug information about mcast flag changes | ||
432 | * @bat_priv: the bat priv with all the soft interface information | ||
433 | * @flags: flags indicating the new multicast state | ||
434 | * | ||
435 | * Whenever the multicast flags this nodes announces changes (@mcast_flags vs. | ||
436 | * bat_priv->mcast.flags), this notifies userspace via the 'mcast' log level. | ||
437 | */ | ||
438 | static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags) | ||
439 | { | ||
440 | u8 old_flags = bat_priv->mcast.flags; | ||
441 | char str_old_flags[] = "[...]"; | ||
442 | |||
443 | sprintf(str_old_flags, "[%c%c%c]", | ||
444 | (old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', | ||
445 | (old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', | ||
446 | (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.'); | ||
447 | |||
448 | batadv_dbg(BATADV_DBG_MCAST, bat_priv, | ||
449 | "Changing multicast flags from '%s' to '[%c%c%c]'\n", | ||
450 | bat_priv->mcast.enabled ? str_old_flags : "<undefined>", | ||
451 | (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', | ||
452 | (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', | ||
453 | (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.'); | ||
454 | } | ||
455 | |||
456 | /** | ||
217 | * batadv_mcast_mla_tvlv_update - update multicast tvlv | 457 | * batadv_mcast_mla_tvlv_update - update multicast tvlv |
218 | * @bat_priv: the bat priv with all the soft interface information | 458 | * @bat_priv: the bat priv with all the soft interface information |
219 | * | 459 | * |
220 | * Updates the own multicast tvlv with our current multicast related settings, | 460 | * Updates the own multicast tvlv with our current multicast related settings, |
221 | * capabilities and inabilities. | 461 | * capabilities and inabilities. |
222 | * | 462 | * |
223 | * Return: true if the tvlv container is registered afterwards. Otherwise | 463 | * Return: false if we want all IPv4 && IPv6 multicast traffic and true |
224 | * returns false. | 464 | * otherwise. |
225 | */ | 465 | */ |
226 | static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) | 466 | static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) |
227 | { | 467 | { |
228 | struct batadv_tvlv_mcast_data mcast_data; | 468 | struct batadv_tvlv_mcast_data mcast_data; |
469 | struct batadv_mcast_querier_state querier4 = {false, false}; | ||
470 | struct batadv_mcast_querier_state querier6 = {false, false}; | ||
471 | struct net_device *dev = bat_priv->soft_iface; | ||
472 | bool bridged; | ||
229 | 473 | ||
230 | mcast_data.flags = BATADV_NO_FLAGS; | 474 | mcast_data.flags = BATADV_NO_FLAGS; |
231 | memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved)); | 475 | memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved)); |
232 | 476 | ||
233 | /* Avoid attaching MLAs, if there is a bridge on top of our soft | 477 | bridged = batadv_mcast_has_bridge(bat_priv); |
234 | * interface, we don't support that yet (TODO) | 478 | if (!bridged) |
479 | goto update; | ||
480 | |||
481 | #if !IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) | ||
482 | pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n"); | ||
483 | #endif | ||
484 | |||
485 | querier4.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP); | ||
486 | querier4.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP); | ||
487 | |||
488 | querier6.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6); | ||
489 | querier6.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6); | ||
490 | |||
491 | mcast_data.flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES; | ||
492 | |||
493 | /* 1) If no querier exists at all, then multicast listeners on | ||
494 | * our local TT clients behind the bridge will keep silent. | ||
495 | * 2) If the selected querier is on one of our local TT clients, | ||
496 | * behind the bridge, then this querier might shadow multicast | ||
497 | * listeners on our local TT clients, behind this bridge. | ||
498 | * | ||
499 | * In both cases, we will signalize other batman nodes that | ||
500 | * we need all multicast traffic of the according protocol. | ||
235 | */ | 501 | */ |
236 | if (batadv_mcast_has_bridge(bat_priv)) { | 502 | if (!querier4.exists || querier4.shadowing) |
237 | if (bat_priv->mcast.enabled) { | 503 | mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV4; |
238 | batadv_tvlv_container_unregister(bat_priv, | ||
239 | BATADV_TVLV_MCAST, 1); | ||
240 | bat_priv->mcast.enabled = false; | ||
241 | } | ||
242 | 504 | ||
243 | return false; | 505 | if (!querier6.exists || querier6.shadowing) |
244 | } | 506 | mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV6; |
507 | |||
508 | update: | ||
509 | batadv_mcast_bridge_log(bat_priv, bridged, &querier4, &querier6); | ||
510 | |||
511 | bat_priv->mcast.querier_ipv4.exists = querier4.exists; | ||
512 | bat_priv->mcast.querier_ipv4.shadowing = querier4.shadowing; | ||
513 | |||
514 | bat_priv->mcast.querier_ipv6.exists = querier6.exists; | ||
515 | bat_priv->mcast.querier_ipv6.shadowing = querier6.shadowing; | ||
516 | |||
517 | bat_priv->mcast.bridged = bridged; | ||
245 | 518 | ||
246 | if (!bat_priv->mcast.enabled || | 519 | if (!bat_priv->mcast.enabled || |
247 | mcast_data.flags != bat_priv->mcast.flags) { | 520 | mcast_data.flags != bat_priv->mcast.flags) { |
248 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1, | 521 | batadv_mcast_flags_log(bat_priv, mcast_data.flags); |
522 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2, | ||
249 | &mcast_data, sizeof(mcast_data)); | 523 | &mcast_data, sizeof(mcast_data)); |
250 | bat_priv->mcast.flags = mcast_data.flags; | 524 | bat_priv->mcast.flags = mcast_data.flags; |
251 | bat_priv->mcast.enabled = true; | 525 | bat_priv->mcast.enabled = true; |
252 | } | 526 | } |
253 | 527 | ||
254 | return true; | 528 | return !(mcast_data.flags & |
529 | (BATADV_MCAST_WANT_ALL_IPV4 + BATADV_MCAST_WANT_ALL_IPV6)); | ||
255 | } | 530 | } |
256 | 531 | ||
257 | /** | 532 | /** |
@@ -274,6 +549,10 @@ void batadv_mcast_mla_update(struct batadv_priv *bat_priv) | |||
274 | if (ret < 0) | 549 | if (ret < 0) |
275 | goto out; | 550 | goto out; |
276 | 551 | ||
552 | ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list); | ||
553 | if (ret < 0) | ||
554 | goto out; | ||
555 | |||
277 | update: | 556 | update: |
278 | batadv_mcast_mla_tt_retract(bat_priv, &mcast_list); | 557 | batadv_mcast_mla_tt_retract(bat_priv, &mcast_list); |
279 | batadv_mcast_mla_tt_add(bat_priv, &mcast_list); | 558 | batadv_mcast_mla_tt_add(bat_priv, &mcast_list); |
@@ -283,6 +562,31 @@ out: | |||
283 | } | 562 | } |
284 | 563 | ||
285 | /** | 564 | /** |
565 | * batadv_mcast_is_report_ipv4 - check for IGMP reports | ||
566 | * @skb: the ethernet frame destined for the mesh | ||
567 | * | ||
568 | * This call might reallocate skb data. | ||
569 | * | ||
570 | * Checks whether the given frame is a valid IGMP report. | ||
571 | * | ||
572 | * Return: If so then true, otherwise false. | ||
573 | */ | ||
574 | static bool batadv_mcast_is_report_ipv4(struct sk_buff *skb) | ||
575 | { | ||
576 | if (ip_mc_check_igmp(skb, NULL) < 0) | ||
577 | return false; | ||
578 | |||
579 | switch (igmp_hdr(skb)->type) { | ||
580 | case IGMP_HOST_MEMBERSHIP_REPORT: | ||
581 | case IGMPV2_HOST_MEMBERSHIP_REPORT: | ||
582 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | ||
583 | return true; | ||
584 | } | ||
585 | |||
586 | return false; | ||
587 | } | ||
588 | |||
589 | /** | ||
286 | * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential | 590 | * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential |
287 | * @bat_priv: the bat priv with all the soft interface information | 591 | * @bat_priv: the bat priv with all the soft interface information |
288 | * @skb: the IPv4 packet to check | 592 | * @skb: the IPv4 packet to check |
@@ -304,6 +608,9 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, | |||
304 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) | 608 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) |
305 | return -ENOMEM; | 609 | return -ENOMEM; |
306 | 610 | ||
611 | if (batadv_mcast_is_report_ipv4(skb)) | ||
612 | return -EINVAL; | ||
613 | |||
307 | iphdr = ip_hdr(skb); | 614 | iphdr = ip_hdr(skb); |
308 | 615 | ||
309 | /* TODO: Implement Multicast Router Discovery (RFC4286), | 616 | /* TODO: Implement Multicast Router Discovery (RFC4286), |
@@ -320,6 +627,31 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, | |||
320 | return 0; | 627 | return 0; |
321 | } | 628 | } |
322 | 629 | ||
630 | #if IS_ENABLED(CONFIG_IPV6) | ||
631 | /** | ||
632 | * batadv_mcast_is_report_ipv6 - check for MLD reports | ||
633 | * @skb: the ethernet frame destined for the mesh | ||
634 | * | ||
635 | * This call might reallocate skb data. | ||
636 | * | ||
637 | * Checks whether the given frame is a valid MLD report. | ||
638 | * | ||
639 | * Return: If so then true, otherwise false. | ||
640 | */ | ||
641 | static bool batadv_mcast_is_report_ipv6(struct sk_buff *skb) | ||
642 | { | ||
643 | if (ipv6_mc_check_mld(skb, NULL) < 0) | ||
644 | return false; | ||
645 | |||
646 | switch (icmp6_hdr(skb)->icmp6_type) { | ||
647 | case ICMPV6_MGM_REPORT: | ||
648 | case ICMPV6_MLD2_REPORT: | ||
649 | return true; | ||
650 | } | ||
651 | |||
652 | return false; | ||
653 | } | ||
654 | |||
323 | /** | 655 | /** |
324 | * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential | 656 | * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential |
325 | * @bat_priv: the bat priv with all the soft interface information | 657 | * @bat_priv: the bat priv with all the soft interface information |
@@ -341,6 +673,9 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | |||
341 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr))) | 673 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr))) |
342 | return -ENOMEM; | 674 | return -ENOMEM; |
343 | 675 | ||
676 | if (batadv_mcast_is_report_ipv6(skb)) | ||
677 | return -EINVAL; | ||
678 | |||
344 | ip6hdr = ipv6_hdr(skb); | 679 | ip6hdr = ipv6_hdr(skb); |
345 | 680 | ||
346 | /* TODO: Implement Multicast Router Discovery (RFC4286), | 681 | /* TODO: Implement Multicast Router Discovery (RFC4286), |
@@ -357,6 +692,7 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | |||
357 | 692 | ||
358 | return 0; | 693 | return 0; |
359 | } | 694 | } |
695 | #endif | ||
360 | 696 | ||
361 | /** | 697 | /** |
362 | * batadv_mcast_forw_mode_check - check for optimized forwarding potential | 698 | * batadv_mcast_forw_mode_check - check for optimized forwarding potential |
@@ -385,9 +721,11 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, | |||
385 | case ETH_P_IP: | 721 | case ETH_P_IP: |
386 | return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, | 722 | return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, |
387 | is_unsnoopable); | 723 | is_unsnoopable); |
724 | #if IS_ENABLED(CONFIG_IPV6) | ||
388 | case ETH_P_IPV6: | 725 | case ETH_P_IPV6: |
389 | return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb, | 726 | return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb, |
390 | is_unsnoopable); | 727 | is_unsnoopable); |
728 | #endif | ||
391 | default: | 729 | default: |
392 | return -EINVAL; | 730 | return -EINVAL; |
393 | } | 731 | } |
@@ -728,18 +1066,18 @@ static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv, | |||
728 | } | 1066 | } |
729 | 1067 | ||
730 | /** | 1068 | /** |
731 | * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container | 1069 | * batadv_mcast_tvlv_ogm_handler - process incoming multicast tvlv container |
732 | * @bat_priv: the bat priv with all the soft interface information | 1070 | * @bat_priv: the bat priv with all the soft interface information |
733 | * @orig: the orig_node of the ogm | 1071 | * @orig: the orig_node of the ogm |
734 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) | 1072 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) |
735 | * @tvlv_value: tvlv buffer containing the multicast data | 1073 | * @tvlv_value: tvlv buffer containing the multicast data |
736 | * @tvlv_value_len: tvlv buffer length | 1074 | * @tvlv_value_len: tvlv buffer length |
737 | */ | 1075 | */ |
738 | static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | 1076 | static void batadv_mcast_tvlv_ogm_handler(struct batadv_priv *bat_priv, |
739 | struct batadv_orig_node *orig, | 1077 | struct batadv_orig_node *orig, |
740 | u8 flags, | 1078 | u8 flags, |
741 | void *tvlv_value, | 1079 | void *tvlv_value, |
742 | u16 tvlv_value_len) | 1080 | u16 tvlv_value_len) |
743 | { | 1081 | { |
744 | bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | 1082 | bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
745 | u8 mcast_flags = BATADV_NO_FLAGS; | 1083 | u8 mcast_flags = BATADV_NO_FLAGS; |
@@ -789,19 +1127,120 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | |||
789 | */ | 1127 | */ |
790 | void batadv_mcast_init(struct batadv_priv *bat_priv) | 1128 | void batadv_mcast_init(struct batadv_priv *bat_priv) |
791 | { | 1129 | { |
792 | batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1, | 1130 | batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler, |
793 | NULL, BATADV_TVLV_MCAST, 1, | 1131 | NULL, BATADV_TVLV_MCAST, 2, |
794 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | 1132 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
795 | } | 1133 | } |
796 | 1134 | ||
797 | /** | 1135 | /** |
1136 | * batadv_mcast_flags_print_header - print own mcast flags to debugfs table | ||
1137 | * @bat_priv: the bat priv with all the soft interface information | ||
1138 | * @seq: debugfs table seq_file struct | ||
1139 | * | ||
1140 | * Prints our own multicast flags including a more specific reason why | ||
1141 | * they are set, that is prints the bridge and querier state too, to | ||
1142 | * the debugfs table specified via @seq. | ||
1143 | */ | ||
1144 | static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv, | ||
1145 | struct seq_file *seq) | ||
1146 | { | ||
1147 | u8 flags = bat_priv->mcast.flags; | ||
1148 | char querier4, querier6, shadowing4, shadowing6; | ||
1149 | bool bridged = bat_priv->mcast.bridged; | ||
1150 | |||
1151 | if (bridged) { | ||
1152 | querier4 = bat_priv->mcast.querier_ipv4.exists ? '.' : '4'; | ||
1153 | querier6 = bat_priv->mcast.querier_ipv6.exists ? '.' : '6'; | ||
1154 | shadowing4 = bat_priv->mcast.querier_ipv4.shadowing ? '4' : '.'; | ||
1155 | shadowing6 = bat_priv->mcast.querier_ipv6.shadowing ? '6' : '.'; | ||
1156 | } else { | ||
1157 | querier4 = '?'; | ||
1158 | querier6 = '?'; | ||
1159 | shadowing4 = '?'; | ||
1160 | shadowing6 = '?'; | ||
1161 | } | ||
1162 | |||
1163 | seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n", | ||
1164 | (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', | ||
1165 | (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', | ||
1166 | (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.'); | ||
1167 | seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? 'U' : '.'); | ||
1168 | seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n", | ||
1169 | querier4, querier6); | ||
1170 | seq_printf(seq, "* Shadowing IGMP/MLD Querier [4/6]:\t%c/%c\n", | ||
1171 | shadowing4, shadowing6); | ||
1172 | seq_puts(seq, "-------------------------------------------\n"); | ||
1173 | seq_printf(seq, " %-10s %s\n", "Originator", "Flags"); | ||
1174 | } | ||
1175 | |||
1176 | /** | ||
1177 | * batadv_mcast_flags_seq_print_text - print the mcast flags of other nodes | ||
1178 | * @seq: seq file to print on | ||
1179 | * @offset: not used | ||
1180 | * | ||
1181 | * This prints a table of (primary) originators and their according | ||
1182 | * multicast flags, including (in the header) our own. | ||
1183 | * | ||
1184 | * Return: always 0 | ||
1185 | */ | ||
1186 | int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset) | ||
1187 | { | ||
1188 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
1189 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
1190 | struct batadv_hard_iface *primary_if; | ||
1191 | struct batadv_hashtable *hash = bat_priv->orig_hash; | ||
1192 | struct batadv_orig_node *orig_node; | ||
1193 | struct hlist_head *head; | ||
1194 | u8 flags; | ||
1195 | u32 i; | ||
1196 | |||
1197 | primary_if = batadv_seq_print_text_primary_if_get(seq); | ||
1198 | if (!primary_if) | ||
1199 | return 0; | ||
1200 | |||
1201 | batadv_mcast_flags_print_header(bat_priv, seq); | ||
1202 | |||
1203 | for (i = 0; i < hash->size; i++) { | ||
1204 | head = &hash->table[i]; | ||
1205 | |||
1206 | rcu_read_lock(); | ||
1207 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { | ||
1208 | if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, | ||
1209 | &orig_node->capa_initialized)) | ||
1210 | continue; | ||
1211 | |||
1212 | if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, | ||
1213 | &orig_node->capabilities)) { | ||
1214 | seq_printf(seq, "%pM -\n", orig_node->orig); | ||
1215 | continue; | ||
1216 | } | ||
1217 | |||
1218 | flags = orig_node->mcast_flags; | ||
1219 | |||
1220 | seq_printf(seq, "%pM [%c%c%c]\n", orig_node->orig, | ||
1221 | (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) | ||
1222 | ? 'U' : '.', | ||
1223 | (flags & BATADV_MCAST_WANT_ALL_IPV4) | ||
1224 | ? '4' : '.', | ||
1225 | (flags & BATADV_MCAST_WANT_ALL_IPV6) | ||
1226 | ? '6' : '.'); | ||
1227 | } | ||
1228 | rcu_read_unlock(); | ||
1229 | } | ||
1230 | |||
1231 | batadv_hardif_put(primary_if); | ||
1232 | |||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | /** | ||
798 | * batadv_mcast_free - free the multicast optimizations structures | 1237 | * batadv_mcast_free - free the multicast optimizations structures |
799 | * @bat_priv: the bat priv with all the soft interface information | 1238 | * @bat_priv: the bat priv with all the soft interface information |
800 | */ | 1239 | */ |
801 | void batadv_mcast_free(struct batadv_priv *bat_priv) | 1240 | void batadv_mcast_free(struct batadv_priv *bat_priv) |
802 | { | 1241 | { |
803 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1); | 1242 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 2); |
804 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1); | 1243 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 2); |
805 | 1244 | ||
806 | spin_lock_bh(&bat_priv->tt.commit_lock); | 1245 | spin_lock_bh(&bat_priv->tt.commit_lock); |
807 | batadv_mcast_mla_tt_retract(bat_priv, NULL); | 1246 | batadv_mcast_mla_tt_retract(bat_priv, NULL); |
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h index 80bceec55592..1fb00ba84907 100644 --- a/net/batman-adv/multicast.h +++ b/net/batman-adv/multicast.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include "main.h" | 21 | #include "main.h" |
22 | 22 | ||
23 | struct seq_file; | ||
23 | struct sk_buff; | 24 | struct sk_buff; |
24 | 25 | ||
25 | /** | 26 | /** |
@@ -46,6 +47,8 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
46 | 47 | ||
47 | void batadv_mcast_init(struct batadv_priv *bat_priv); | 48 | void batadv_mcast_init(struct batadv_priv *bat_priv); |
48 | 49 | ||
50 | int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset); | ||
51 | |||
49 | void batadv_mcast_free(struct batadv_priv *bat_priv); | 52 | void batadv_mcast_free(struct batadv_priv *bat_priv); |
50 | 53 | ||
51 | void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); | 54 | void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 7f51bc2c06eb..076d258c92e1 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -251,10 +251,8 @@ static void batadv_neigh_node_release(struct kref *ref) | |||
251 | struct hlist_node *node_tmp; | 251 | struct hlist_node *node_tmp; |
252 | struct batadv_neigh_node *neigh_node; | 252 | struct batadv_neigh_node *neigh_node; |
253 | struct batadv_neigh_ifinfo *neigh_ifinfo; | 253 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
254 | struct batadv_algo_ops *bao; | ||
255 | 254 | ||
256 | neigh_node = container_of(ref, struct batadv_neigh_node, refcount); | 255 | neigh_node = container_of(ref, struct batadv_neigh_node, refcount); |
257 | bao = neigh_node->orig_node->bat_priv->bat_algo_ops; | ||
258 | 256 | ||
259 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, | 257 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, |
260 | &neigh_node->ifinfo_list, list) { | 258 | &neigh_node->ifinfo_list, list) { |
@@ -263,9 +261,6 @@ static void batadv_neigh_node_release(struct kref *ref) | |||
263 | 261 | ||
264 | batadv_hardif_neigh_put(neigh_node->hardif_neigh); | 262 | batadv_hardif_neigh_put(neigh_node->hardif_neigh); |
265 | 263 | ||
266 | if (bao->bat_neigh_free) | ||
267 | bao->bat_neigh_free(neigh_node); | ||
268 | |||
269 | batadv_hardif_put(neigh_node->if_incoming); | 264 | batadv_hardif_put(neigh_node->if_incoming); |
270 | 265 | ||
271 | kfree_rcu(neigh_node, rcu); | 266 | kfree_rcu(neigh_node, rcu); |
@@ -602,19 +597,19 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, | |||
602 | } | 597 | } |
603 | 598 | ||
604 | /** | 599 | /** |
605 | * batadv_neigh_node_new - create and init a new neigh_node object | 600 | * batadv_neigh_node_create - create a neigh node object |
606 | * @orig_node: originator object representing the neighbour | 601 | * @orig_node: originator object representing the neighbour |
607 | * @hard_iface: the interface where the neighbour is connected to | 602 | * @hard_iface: the interface where the neighbour is connected to |
608 | * @neigh_addr: the mac address of the neighbour interface | 603 | * @neigh_addr: the mac address of the neighbour interface |
609 | * | 604 | * |
610 | * Allocates a new neigh_node object and initialises all the generic fields. | 605 | * Allocates a new neigh_node object and initialises all the generic fields. |
611 | * | 606 | * |
612 | * Return: neighbor when found. Othwerwise NULL | 607 | * Return: the neighbour node if found or created or NULL otherwise. |
613 | */ | 608 | */ |
614 | struct batadv_neigh_node * | 609 | static struct batadv_neigh_node * |
615 | batadv_neigh_node_new(struct batadv_orig_node *orig_node, | 610 | batadv_neigh_node_create(struct batadv_orig_node *orig_node, |
616 | struct batadv_hard_iface *hard_iface, | 611 | struct batadv_hard_iface *hard_iface, |
617 | const u8 *neigh_addr) | 612 | const u8 *neigh_addr) |
618 | { | 613 | { |
619 | struct batadv_neigh_node *neigh_node; | 614 | struct batadv_neigh_node *neigh_node; |
620 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; | 615 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; |
@@ -667,6 +662,29 @@ out: | |||
667 | } | 662 | } |
668 | 663 | ||
669 | /** | 664 | /** |
665 | * batadv_neigh_node_get_or_create - retrieve or create a neigh node object | ||
666 | * @orig_node: originator object representing the neighbour | ||
667 | * @hard_iface: the interface where the neighbour is connected to | ||
668 | * @neigh_addr: the mac address of the neighbour interface | ||
669 | * | ||
670 | * Return: the neighbour node if found or created or NULL otherwise. | ||
671 | */ | ||
672 | struct batadv_neigh_node * | ||
673 | batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node, | ||
674 | struct batadv_hard_iface *hard_iface, | ||
675 | const u8 *neigh_addr) | ||
676 | { | ||
677 | struct batadv_neigh_node *neigh_node = NULL; | ||
678 | |||
679 | /* first check without locking to avoid the overhead */ | ||
680 | neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); | ||
681 | if (neigh_node) | ||
682 | return neigh_node; | ||
683 | |||
684 | return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr); | ||
685 | } | ||
686 | |||
687 | /** | ||
670 | * batadv_hardif_neigh_seq_print_text - print the single hop neighbour list | 688 | * batadv_hardif_neigh_seq_print_text - print the single hop neighbour list |
671 | * @seq: neighbour table seq_file struct | 689 | * @seq: neighbour table seq_file struct |
672 | * @offset: not used | 690 | * @offset: not used |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 64a8951e5844..566306bf05dc 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -46,9 +46,9 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, | |||
46 | void | 46 | void |
47 | batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh); | 47 | batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh); |
48 | struct batadv_neigh_node * | 48 | struct batadv_neigh_node * |
49 | batadv_neigh_node_new(struct batadv_orig_node *orig_node, | 49 | batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node, |
50 | struct batadv_hard_iface *hard_iface, | 50 | struct batadv_hard_iface *hard_iface, |
51 | const u8 *neigh_addr); | 51 | const u8 *neigh_addr); |
52 | void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node); | 52 | void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node); |
53 | struct batadv_neigh_node * | 53 | struct batadv_neigh_node * |
54 | batadv_orig_router_get(struct batadv_orig_node *orig_node, | 54 | batadv_orig_router_get(struct batadv_orig_node *orig_node, |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 372128ddb474..71567794df17 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -420,6 +420,7 @@ struct batadv_unicast_4addr_packet { | |||
420 | * @dest: final destination used when routing fragments | 420 | * @dest: final destination used when routing fragments |
421 | * @orig: originator of the fragment used when merging the packet | 421 | * @orig: originator of the fragment used when merging the packet |
422 | * @no: fragment number within this sequence | 422 | * @no: fragment number within this sequence |
423 | * @priority: priority of frame, from ToS IP precedence or 802.1p | ||
423 | * @reserved: reserved byte for alignment | 424 | * @reserved: reserved byte for alignment |
424 | * @seqno: sequence identification | 425 | * @seqno: sequence identification |
425 | * @total_size: size of the merged packet | 426 | * @total_size: size of the merged packet |
@@ -430,9 +431,11 @@ struct batadv_frag_packet { | |||
430 | u8 ttl; | 431 | u8 ttl; |
431 | #if defined(__BIG_ENDIAN_BITFIELD) | 432 | #if defined(__BIG_ENDIAN_BITFIELD) |
432 | u8 no:4; | 433 | u8 no:4; |
433 | u8 reserved:4; | 434 | u8 priority:3; |
435 | u8 reserved:1; | ||
434 | #elif defined(__LITTLE_ENDIAN_BITFIELD) | 436 | #elif defined(__LITTLE_ENDIAN_BITFIELD) |
435 | u8 reserved:4; | 437 | u8 reserved:1; |
438 | u8 priority:3; | ||
436 | u8 no:4; | 439 | u8 no:4; |
437 | #else | 440 | #else |
438 | #error "unknown bitfield endianness" | 441 | #error "unknown bitfield endianness" |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 396c0134c5ab..319a58820197 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -1007,6 +1007,8 @@ int batadv_recv_frag_packet(struct sk_buff *skb, | |||
1007 | if (!orig_node_src) | 1007 | if (!orig_node_src) |
1008 | goto out; | 1008 | goto out; |
1009 | 1009 | ||
1010 | skb->priority = frag_packet->priority + 256; | ||
1011 | |||
1010 | /* Route the fragment if it is not for us and too big to be merged. */ | 1012 | /* Route the fragment if it is not for us and too big to be merged. */ |
1011 | if (!batadv_is_my_mac(bat_priv, frag_packet->dest) && | 1013 | if (!batadv_is_my_mac(bat_priv, frag_packet->dest) && |
1012 | batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) { | 1014 | batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) { |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index b1a4e8a811c8..59e695b5cfbd 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -428,27 +428,7 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
428 | orig_node, vid); | 428 | orig_node, vid); |
429 | } | 429 | } |
430 | 430 | ||
431 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) | 431 | void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) |
432 | { | ||
433 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | ||
434 | |||
435 | if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || | ||
436 | (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) | ||
437 | return; | ||
438 | |||
439 | /* the interface gets activated here to avoid race conditions between | ||
440 | * the moment of activating the interface in | ||
441 | * hardif_activate_interface() where the originator mac is set and | ||
442 | * outdated packets (especially uninitialized mac addresses) in the | ||
443 | * packet queue | ||
444 | */ | ||
445 | if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) | ||
446 | hard_iface->if_status = BATADV_IF_ACTIVE; | ||
447 | |||
448 | bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface); | ||
449 | } | ||
450 | |||
451 | static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) | ||
452 | { | 432 | { |
453 | kfree_skb(forw_packet->skb); | 433 | kfree_skb(forw_packet->skb); |
454 | if (forw_packet->if_incoming) | 434 | if (forw_packet->if_incoming) |
@@ -604,45 +584,6 @@ out: | |||
604 | atomic_inc(&bat_priv->bcast_queue_left); | 584 | atomic_inc(&bat_priv->bcast_queue_left); |
605 | } | 585 | } |
606 | 586 | ||
607 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) | ||
608 | { | ||
609 | struct delayed_work *delayed_work; | ||
610 | struct batadv_forw_packet *forw_packet; | ||
611 | struct batadv_priv *bat_priv; | ||
612 | |||
613 | delayed_work = to_delayed_work(work); | ||
614 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | ||
615 | delayed_work); | ||
616 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); | ||
617 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | ||
618 | hlist_del(&forw_packet->list); | ||
619 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | ||
620 | |||
621 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) | ||
622 | goto out; | ||
623 | |||
624 | bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet); | ||
625 | |||
626 | /* we have to have at least one packet in the queue to determine the | ||
627 | * queues wake up time unless we are shutting down. | ||
628 | * | ||
629 | * only re-schedule if this is the "original" copy, e.g. the OGM of the | ||
630 | * primary interface should only be rescheduled once per period, but | ||
631 | * this function will be called for the forw_packet instances of the | ||
632 | * other secondary interfaces as well. | ||
633 | */ | ||
634 | if (forw_packet->own && | ||
635 | forw_packet->if_incoming == forw_packet->if_outgoing) | ||
636 | batadv_schedule_bat_ogm(forw_packet->if_incoming); | ||
637 | |||
638 | out: | ||
639 | /* don't count own packet */ | ||
640 | if (!forw_packet->own) | ||
641 | atomic_inc(&bat_priv->batman_queue_left); | ||
642 | |||
643 | batadv_forw_packet_free(forw_packet); | ||
644 | } | ||
645 | |||
646 | void | 587 | void |
647 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | 588 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, |
648 | const struct batadv_hard_iface *hard_iface) | 589 | const struct batadv_hard_iface *hard_iface) |
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 6fd7270d8ce6..7cecb7563b45 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "packet.h" | 26 | #include "packet.h" |
27 | 27 | ||
28 | struct sk_buff; | 28 | struct sk_buff; |
29 | struct work_struct; | ||
30 | 29 | ||
30 | void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet); | ||
31 | int batadv_send_skb_to_orig(struct sk_buff *skb, | 31 | int batadv_send_skb_to_orig(struct sk_buff *skb, |
32 | struct batadv_orig_node *orig_node, | 32 | struct batadv_orig_node *orig_node, |
33 | struct batadv_hard_iface *recv_if); | 33 | struct batadv_hard_iface *recv_if); |
@@ -38,11 +38,9 @@ int batadv_send_broadcast_skb(struct sk_buff *skb, | |||
38 | struct batadv_hard_iface *hard_iface); | 38 | struct batadv_hard_iface *hard_iface); |
39 | int batadv_send_unicast_skb(struct sk_buff *skb, | 39 | int batadv_send_unicast_skb(struct sk_buff *skb, |
40 | struct batadv_neigh_node *neigh_node); | 40 | struct batadv_neigh_node *neigh_node); |
41 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface); | ||
42 | int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, | 41 | int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, |
43 | const struct sk_buff *skb, | 42 | const struct sk_buff *skb, |
44 | unsigned long delay); | 43 | unsigned long delay); |
45 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work); | ||
46 | void | 44 | void |
47 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | 45 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, |
48 | const struct batadv_hard_iface *hard_iface); | 46 | const struct batadv_hard_iface *hard_iface); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 287a3879ed7e..4ba894ca8b2a 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -255,7 +255,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
255 | if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) | 255 | if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) |
256 | goto dropped; | 256 | goto dropped; |
257 | 257 | ||
258 | gw_mode = atomic_read(&bat_priv->gw_mode); | 258 | gw_mode = atomic_read(&bat_priv->gw.mode); |
259 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 259 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
260 | /* if gw mode is off, broadcast every packet */ | 260 | /* if gw mode is off, broadcast every packet */ |
261 | if (gw_mode == BATADV_GW_MODE_OFF) { | 261 | if (gw_mode == BATADV_GW_MODE_OFF) { |
@@ -808,6 +808,10 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
808 | atomic_set(&bat_priv->distributed_arp_table, 1); | 808 | atomic_set(&bat_priv->distributed_arp_table, 1); |
809 | #endif | 809 | #endif |
810 | #ifdef CONFIG_BATMAN_ADV_MCAST | 810 | #ifdef CONFIG_BATMAN_ADV_MCAST |
811 | bat_priv->mcast.querier_ipv4.exists = false; | ||
812 | bat_priv->mcast.querier_ipv4.shadowing = false; | ||
813 | bat_priv->mcast.querier_ipv6.exists = false; | ||
814 | bat_priv->mcast.querier_ipv6.shadowing = false; | ||
811 | bat_priv->mcast.flags = BATADV_NO_FLAGS; | 815 | bat_priv->mcast.flags = BATADV_NO_FLAGS; |
812 | atomic_set(&bat_priv->multicast_mode, 1); | 816 | atomic_set(&bat_priv->multicast_mode, 1); |
813 | atomic_set(&bat_priv->mcast.num_disabled, 0); | 817 | atomic_set(&bat_priv->mcast.num_disabled, 0); |
@@ -815,8 +819,8 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
815 | atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); | 819 | atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); |
816 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); | 820 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); |
817 | #endif | 821 | #endif |
818 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 822 | atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); |
819 | atomic_set(&bat_priv->gw_sel_class, 20); | 823 | atomic_set(&bat_priv->gw.sel_class, 20); |
820 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 824 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
821 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | 825 | atomic_set(&bat_priv->gw.bandwidth_up, 20); |
822 | atomic_set(&bat_priv->orig_interval, 1000); | 826 | atomic_set(&bat_priv->orig_interval, 1000); |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 414b2074165f..233abcf33c03 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -389,12 +389,12 @@ static int batadv_store_uint_attr(const char *buff, size_t count, | |||
389 | return count; | 389 | return count; |
390 | } | 390 | } |
391 | 391 | ||
392 | static inline ssize_t | 392 | static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, |
393 | __batadv_store_uint_attr(const char *buff, size_t count, | 393 | int min, int max, |
394 | int min, int max, | 394 | void (*post_func)(struct net_device *), |
395 | void (*post_func)(struct net_device *), | 395 | const struct attribute *attr, |
396 | const struct attribute *attr, | 396 | atomic_t *attr_store, |
397 | atomic_t *attr_store, struct net_device *net_dev) | 397 | struct net_device *net_dev) |
398 | { | 398 | { |
399 | int ret; | 399 | int ret; |
400 | 400 | ||
@@ -427,7 +427,7 @@ static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr, | |||
427 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 427 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
428 | int bytes_written; | 428 | int bytes_written; |
429 | 429 | ||
430 | switch (atomic_read(&bat_priv->gw_mode)) { | 430 | switch (atomic_read(&bat_priv->gw.mode)) { |
431 | case BATADV_GW_MODE_CLIENT: | 431 | case BATADV_GW_MODE_CLIENT: |
432 | bytes_written = sprintf(buff, "%s\n", | 432 | bytes_written = sprintf(buff, "%s\n", |
433 | BATADV_GW_MODE_CLIENT_NAME); | 433 | BATADV_GW_MODE_CLIENT_NAME); |
@@ -476,10 +476,10 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, | |||
476 | return -EINVAL; | 476 | return -EINVAL; |
477 | } | 477 | } |
478 | 478 | ||
479 | if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp) | 479 | if (atomic_read(&bat_priv->gw.mode) == gw_mode_tmp) |
480 | return count; | 480 | return count; |
481 | 481 | ||
482 | switch (atomic_read(&bat_priv->gw_mode)) { | 482 | switch (atomic_read(&bat_priv->gw.mode)) { |
483 | case BATADV_GW_MODE_CLIENT: | 483 | case BATADV_GW_MODE_CLIENT: |
484 | curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME; | 484 | curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME; |
485 | break; | 485 | break; |
@@ -508,7 +508,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, | |||
508 | * state | 508 | * state |
509 | */ | 509 | */ |
510 | batadv_gw_check_client_stop(bat_priv); | 510 | batadv_gw_check_client_stop(bat_priv); |
511 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); | 511 | atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp); |
512 | batadv_gw_tvlv_container_update(bat_priv); | 512 | batadv_gw_tvlv_container_update(bat_priv); |
513 | return count; | 513 | return count; |
514 | } | 514 | } |
@@ -624,7 +624,7 @@ BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR, | |||
624 | 2 * BATADV_JITTER, INT_MAX, NULL); | 624 | 2 * BATADV_JITTER, INT_MAX, NULL); |
625 | BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0, | 625 | BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0, |
626 | BATADV_TQ_MAX_VALUE, NULL); | 626 | BATADV_TQ_MAX_VALUE, NULL); |
627 | BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1, | 627 | BATADV_ATTR_SIF_UINT(gw_sel_class, gw.sel_class, S_IRUGO | S_IWUSR, 1, |
628 | BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect); | 628 | BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect); |
629 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, | 629 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, |
630 | batadv_store_gw_bwidth); | 630 | batadv_store_gw_bwidth); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 57ec87f37050..0d441aac1ad5 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -996,7 +996,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
996 | struct batadv_tt_local_entry *tt_local; | 996 | struct batadv_tt_local_entry *tt_local; |
997 | struct batadv_hard_iface *primary_if; | 997 | struct batadv_hard_iface *primary_if; |
998 | struct hlist_head *head; | 998 | struct hlist_head *head; |
999 | unsigned short vid; | ||
1000 | u32 i; | 999 | u32 i; |
1001 | int last_seen_secs; | 1000 | int last_seen_secs; |
1002 | int last_seen_msecs; | 1001 | int last_seen_msecs; |
@@ -1023,7 +1022,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
1023 | tt_local = container_of(tt_common_entry, | 1022 | tt_local = container_of(tt_common_entry, |
1024 | struct batadv_tt_local_entry, | 1023 | struct batadv_tt_local_entry, |
1025 | common); | 1024 | common); |
1026 | vid = tt_common_entry->vid; | ||
1027 | last_seen_jiffies = jiffies - tt_local->last_seen; | 1025 | last_seen_jiffies = jiffies - tt_local->last_seen; |
1028 | last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); | 1026 | last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); |
1029 | last_seen_secs = last_seen_msecs / 1000; | 1027 | last_seen_secs = last_seen_msecs / 1000; |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ba846b078af8..02e22763a880 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -707,6 +707,8 @@ struct batadv_priv_debug_log { | |||
707 | * @list: list of available gateway nodes | 707 | * @list: list of available gateway nodes |
708 | * @list_lock: lock protecting gw_list & curr_gw | 708 | * @list_lock: lock protecting gw_list & curr_gw |
709 | * @curr_gw: pointer to currently selected gateway node | 709 | * @curr_gw: pointer to currently selected gateway node |
710 | * @mode: gateway operation: off, client or server (see batadv_gw_modes) | ||
711 | * @sel_class: gateway selection class (applies if gw_mode client) | ||
710 | * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) | 712 | * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) |
711 | * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) | 713 | * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) |
712 | * @reselect: bool indicating a gateway re-selection is in progress | 714 | * @reselect: bool indicating a gateway re-selection is in progress |
@@ -715,6 +717,8 @@ struct batadv_priv_gw { | |||
715 | struct hlist_head list; | 717 | struct hlist_head list; |
716 | spinlock_t list_lock; /* protects gw_list & curr_gw */ | 718 | spinlock_t list_lock; /* protects gw_list & curr_gw */ |
717 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ | 719 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ |
720 | atomic_t mode; | ||
721 | atomic_t sel_class; | ||
718 | atomic_t bandwidth_down; | 722 | atomic_t bandwidth_down; |
719 | atomic_t bandwidth_up; | 723 | atomic_t bandwidth_up; |
720 | atomic_t reselect; | 724 | atomic_t reselect; |
@@ -751,14 +755,28 @@ struct batadv_priv_dat { | |||
751 | 755 | ||
752 | #ifdef CONFIG_BATMAN_ADV_MCAST | 756 | #ifdef CONFIG_BATMAN_ADV_MCAST |
753 | /** | 757 | /** |
758 | * struct batadv_mcast_querier_state - IGMP/MLD querier state when bridged | ||
759 | * @exists: whether a querier exists in the mesh | ||
760 | * @shadowing: if a querier exists, whether it is potentially shadowing | ||
761 | * multicast listeners (i.e. querier is behind our own bridge segment) | ||
762 | */ | ||
763 | struct batadv_mcast_querier_state { | ||
764 | bool exists; | ||
765 | bool shadowing; | ||
766 | }; | ||
767 | |||
768 | /** | ||
754 | * struct batadv_priv_mcast - per mesh interface mcast data | 769 | * struct batadv_priv_mcast - per mesh interface mcast data |
755 | * @mla_list: list of multicast addresses we are currently announcing via TT | 770 | * @mla_list: list of multicast addresses we are currently announcing via TT |
756 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable | 771 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable |
757 | * multicast traffic | 772 | * multicast traffic |
758 | * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic | 773 | * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic |
759 | * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic | 774 | * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic |
775 | * @querier_ipv4: the current state of an IGMP querier in the mesh | ||
776 | * @querier_ipv6: the current state of an MLD querier in the mesh | ||
760 | * @flags: the flags we have last sent in our mcast tvlv | 777 | * @flags: the flags we have last sent in our mcast tvlv |
761 | * @enabled: whether the multicast tvlv is currently enabled | 778 | * @enabled: whether the multicast tvlv is currently enabled |
779 | * @bridged: whether the soft interface has a bridge on top | ||
762 | * @num_disabled: number of nodes that have no mcast tvlv | 780 | * @num_disabled: number of nodes that have no mcast tvlv |
763 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic | 781 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic |
764 | * @num_want_all_ipv4: counter for items in want_all_ipv4_list | 782 | * @num_want_all_ipv4: counter for items in want_all_ipv4_list |
@@ -771,8 +789,11 @@ struct batadv_priv_mcast { | |||
771 | struct hlist_head want_all_unsnoopables_list; | 789 | struct hlist_head want_all_unsnoopables_list; |
772 | struct hlist_head want_all_ipv4_list; | 790 | struct hlist_head want_all_ipv4_list; |
773 | struct hlist_head want_all_ipv6_list; | 791 | struct hlist_head want_all_ipv6_list; |
792 | struct batadv_mcast_querier_state querier_ipv4; | ||
793 | struct batadv_mcast_querier_state querier_ipv6; | ||
774 | u8 flags; | 794 | u8 flags; |
775 | bool enabled; | 795 | bool enabled; |
796 | bool bridged; | ||
776 | atomic_t num_disabled; | 797 | atomic_t num_disabled; |
777 | atomic_t num_want_all_unsnoopables; | 798 | atomic_t num_want_all_unsnoopables; |
778 | atomic_t num_want_all_ipv4; | 799 | atomic_t num_want_all_ipv4; |
@@ -865,8 +886,6 @@ struct batadv_priv_bat_v { | |||
865 | * enabled | 886 | * enabled |
866 | * @multicast_mode: Enable or disable multicast optimizations on this node's | 887 | * @multicast_mode: Enable or disable multicast optimizations on this node's |
867 | * sender/originating side | 888 | * sender/originating side |
868 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) | ||
869 | * @gw_sel_class: gateway selection class (applies if gw_mode client) | ||
870 | * @orig_interval: OGM broadcast interval in milliseconds | 889 | * @orig_interval: OGM broadcast interval in milliseconds |
871 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop | 890 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop |
872 | * @log_level: configured log level (see batadv_dbg_level) | 891 | * @log_level: configured log level (see batadv_dbg_level) |
@@ -922,8 +941,6 @@ struct batadv_priv { | |||
922 | #ifdef CONFIG_BATMAN_ADV_MCAST | 941 | #ifdef CONFIG_BATMAN_ADV_MCAST |
923 | atomic_t multicast_mode; | 942 | atomic_t multicast_mode; |
924 | #endif | 943 | #endif |
925 | atomic_t gw_mode; | ||
926 | atomic_t gw_sel_class; | ||
927 | atomic_t orig_interval; | 944 | atomic_t orig_interval; |
928 | atomic_t hop_penalty; | 945 | atomic_t hop_penalty; |
929 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 946 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
@@ -1271,8 +1288,6 @@ struct batadv_forw_packet { | |||
1271 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information | 1288 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information |
1272 | * belonging to this hard-interface | 1289 | * belonging to this hard-interface |
1273 | * @bat_primary_iface_set: called when primary interface is selected / changed | 1290 | * @bat_primary_iface_set: called when primary interface is selected / changed |
1274 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue | ||
1275 | * @bat_ogm_emit: send scheduled OGM | ||
1276 | * @bat_hardif_neigh_init: called on creation of single hop entry | 1291 | * @bat_hardif_neigh_init: called on creation of single hop entry |
1277 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective | 1292 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective |
1278 | * outgoing interfaces | 1293 | * outgoing interfaces |
@@ -1280,8 +1295,6 @@ struct batadv_forw_packet { | |||
1280 | * better than neigh2 for their respective outgoing interface from the metric | 1295 | * better than neigh2 for their respective outgoing interface from the metric |
1281 | * prospective | 1296 | * prospective |
1282 | * @bat_neigh_print: print the single hop neighbor list (optional) | 1297 | * @bat_neigh_print: print the single hop neighbor list (optional) |
1283 | * @bat_neigh_free: free the resources allocated by the routing algorithm for a | ||
1284 | * neigh_node object | ||
1285 | * @bat_orig_print: print the originator table (optional) | 1298 | * @bat_orig_print: print the originator table (optional) |
1286 | * @bat_orig_free: free the resources allocated by the routing algorithm for an | 1299 | * @bat_orig_free: free the resources allocated by the routing algorithm for an |
1287 | * orig_node object | 1300 | * orig_node object |
@@ -1298,8 +1311,6 @@ struct batadv_algo_ops { | |||
1298 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); | 1311 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); |
1299 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); | 1312 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); |
1300 | void (*bat_primary_iface_set)(struct batadv_hard_iface *hard_iface); | 1313 | void (*bat_primary_iface_set)(struct batadv_hard_iface *hard_iface); |
1301 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); | ||
1302 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); | ||
1303 | /* neigh_node handling API */ | 1314 | /* neigh_node handling API */ |
1304 | void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh); | 1315 | void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh); |
1305 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, | 1316 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, |
@@ -1312,7 +1323,6 @@ struct batadv_algo_ops { | |||
1312 | struct batadv_neigh_node *neigh2, | 1323 | struct batadv_neigh_node *neigh2, |
1313 | struct batadv_hard_iface *if_outgoing2); | 1324 | struct batadv_hard_iface *if_outgoing2); |
1314 | void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); | 1325 | void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); |
1315 | void (*bat_neigh_free)(struct batadv_neigh_node *neigh); | ||
1316 | /* orig_node handling API */ | 1326 | /* orig_node handling API */ |
1317 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, | 1327 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, |
1318 | struct batadv_hard_iface *hard_iface); | 1328 | struct batadv_hard_iface *hard_iface); |