aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/Kconfig9
-rw-r--r--net/batman-adv/Makefile1
-rw-r--r--net/batman-adv/main.c6
-rw-r--r--net/batman-adv/main.h1
-rw-r--r--net/batman-adv/multicast.c218
-rw-r--r--net/batman-adv/multicast.h41
-rw-r--r--net/batman-adv/translation-table.c22
-rw-r--r--net/batman-adv/types.h24
8 files changed, 318 insertions, 4 deletions
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index fa780b76630e..11660a3aab5a 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -50,6 +50,15 @@ config BATMAN_ADV_NC
50 If you think that your network does not need this feature you 50 If you think that your network does not need this feature you
51 can safely disable it and save some space. 51 can safely disable it and save some space.
52 52
53config BATMAN_ADV_MCAST
54 bool "Multicast optimisation"
55 depends on BATMAN_ADV
56 default n
57 help
58 This option enables the multicast optimisation which aims to
59 reduce the air overhead while improving the reliability of
60 multicast messages.
61
53config BATMAN_ADV_DEBUG 62config BATMAN_ADV_DEBUG
54 bool "B.A.T.M.A.N. debugging" 63 bool "B.A.T.M.A.N. debugging"
55 depends on BATMAN_ADV 64 depends on BATMAN_ADV
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 42df18f877e9..eb7d8c0388e4 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -36,3 +36,4 @@ batman-adv-y += send.o
36batman-adv-y += soft-interface.o 36batman-adv-y += soft-interface.o
37batman-adv-y += sysfs.o 37batman-adv-y += sysfs.o
38batman-adv-y += translation-table.o 38batman-adv-y += translation-table.o
39batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index fbeaebde080d..58e98c89a68f 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -34,6 +34,7 @@
34#include "gateway_client.h" 34#include "gateway_client.h"
35#include "bridge_loop_avoidance.h" 35#include "bridge_loop_avoidance.h"
36#include "distributed-arp-table.h" 36#include "distributed-arp-table.h"
37#include "multicast.h"
37#include "gateway_common.h" 38#include "gateway_common.h"
38#include "hash.h" 39#include "hash.h"
39#include "bat_algo.h" 40#include "bat_algo.h"
@@ -120,6 +121,9 @@ int batadv_mesh_init(struct net_device *soft_iface)
120 INIT_LIST_HEAD(&bat_priv->tt.changes_list); 121 INIT_LIST_HEAD(&bat_priv->tt.changes_list);
121 INIT_LIST_HEAD(&bat_priv->tt.req_list); 122 INIT_LIST_HEAD(&bat_priv->tt.req_list);
122 INIT_LIST_HEAD(&bat_priv->tt.roam_list); 123 INIT_LIST_HEAD(&bat_priv->tt.roam_list);
124#ifdef CONFIG_BATMAN_ADV_MCAST
125 INIT_HLIST_HEAD(&bat_priv->mcast.mla_list);
126#endif
123 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); 127 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
124 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); 128 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
125 INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); 129 INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
@@ -169,6 +173,8 @@ void batadv_mesh_free(struct net_device *soft_iface)
169 batadv_dat_free(bat_priv); 173 batadv_dat_free(bat_priv);
170 batadv_bla_free(bat_priv); 174 batadv_bla_free(bat_priv);
171 175
176 batadv_mcast_free(bat_priv);
177
172 /* Free the TT and the originator tables only after having terminated 178 /* Free the TT and the originator tables only after having terminated
173 * all the other depending components which may use these structures for 179 * all the other depending components which may use these structures for
174 * their purposes. 180 * their purposes.
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 9374f1a51348..aa4f73a044c5 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -176,6 +176,7 @@ enum batadv_uev_type {
176#include <linux/percpu.h> 176#include <linux/percpu.h>
177#include <linux/slab.h> 177#include <linux/slab.h>
178#include <net/sock.h> /* struct sock */ 178#include <net/sock.h> /* struct sock */
179#include <net/addrconf.h> /* ipv6 address stuff */
179#include <net/rtnetlink.h> 180#include <net/rtnetlink.h>
180#include <linux/jiffies.h> 181#include <linux/jiffies.h>
181#include <linux/seq_file.h> 182#include <linux/seq_file.h>
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
new file mode 100644
index 000000000000..e099fd67403c
--- /dev/null
+++ b/net/batman-adv/multicast.c
@@ -0,0 +1,218 @@
1/* Copyright (C) 2014 B.A.T.M.A.N. contributors:
2 *
3 * Linus Lüssing
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "main.h"
19#include "multicast.h"
20#include "originator.h"
21#include "hard-interface.h"
22#include "translation-table.h"
23
24/**
25 * batadv_mcast_mla_softif_get - get softif multicast listeners
26 * @dev: the device to collect multicast addresses from
27 * @mcast_list: a list to put found addresses into
28 *
29 * Collect multicast addresses of the local multicast listeners
30 * on the given soft interface, dev, in the given mcast_list.
31 *
32 * Returns -ENOMEM on memory allocation error or the number of
33 * items added to the mcast_list otherwise.
34 */
35static int batadv_mcast_mla_softif_get(struct net_device *dev,
36 struct hlist_head *mcast_list)
37{
38 struct netdev_hw_addr *mc_list_entry;
39 struct batadv_hw_addr *new;
40 int ret = 0;
41
42 netif_addr_lock_bh(dev);
43 netdev_for_each_mc_addr(mc_list_entry, dev) {
44 new = kmalloc(sizeof(*new), GFP_ATOMIC);
45 if (!new) {
46 ret = -ENOMEM;
47 break;
48 }
49
50 ether_addr_copy(new->addr, mc_list_entry->addr);
51 hlist_add_head(&new->list, mcast_list);
52 ret++;
53 }
54 netif_addr_unlock_bh(dev);
55
56 return ret;
57}
58
59/**
60 * batadv_mcast_mla_is_duplicate - check whether an address is in a list
61 * @mcast_addr: the multicast address to check
62 * @mcast_list: the list with multicast addresses to search in
63 *
64 * Returns true if the given address is already in the given list.
65 * Otherwise returns false.
66 */
67static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr,
68 struct hlist_head *mcast_list)
69{
70 struct batadv_hw_addr *mcast_entry;
71
72 hlist_for_each_entry(mcast_entry, mcast_list, list)
73 if (batadv_compare_eth(mcast_entry->addr, mcast_addr))
74 return true;
75
76 return false;
77}
78
79/**
80 * batadv_mcast_mla_list_free - free a list of multicast addresses
81 * @mcast_list: the list to free
82 *
83 * Removes and frees all items in the given mcast_list.
84 */
85static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
86{
87 struct batadv_hw_addr *mcast_entry;
88 struct hlist_node *tmp;
89
90 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
91 hlist_del(&mcast_entry->list);
92 kfree(mcast_entry);
93 }
94}
95
96/**
97 * batadv_mcast_mla_tt_retract - clean up multicast listener announcements
98 * @bat_priv: the bat priv with all the soft interface information
99 * @mcast_list: a list of addresses which should _not_ be removed
100 *
101 * Retracts the announcement of any multicast listener from the
102 * translation table except the ones listed in the given mcast_list.
103 *
104 * If mcast_list is NULL then all are retracted.
105 */
106static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
107 struct hlist_head *mcast_list)
108{
109 struct batadv_hw_addr *mcast_entry;
110 struct hlist_node *tmp;
111
112 hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
113 list) {
114 if (mcast_list &&
115 batadv_mcast_mla_is_duplicate(mcast_entry->addr,
116 mcast_list))
117 continue;
118
119 batadv_tt_local_remove(bat_priv, mcast_entry->addr,
120 BATADV_NO_FLAGS,
121 "mcast TT outdated", false);
122
123 hlist_del(&mcast_entry->list);
124 kfree(mcast_entry);
125 }
126}
127
128/**
129 * batadv_mcast_mla_tt_add - add multicast listener announcements
130 * @bat_priv: the bat priv with all the soft interface information
131 * @mcast_list: a list of addresses which are going to get added
132 *
133 * Adds multicast listener announcements from the given mcast_list to the
134 * translation table if they have not been added yet.
135 */
136static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
137 struct hlist_head *mcast_list)
138{
139 struct batadv_hw_addr *mcast_entry;
140 struct hlist_node *tmp;
141
142 if (!mcast_list)
143 return;
144
145 hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
146 if (batadv_mcast_mla_is_duplicate(mcast_entry->addr,
147 &bat_priv->mcast.mla_list))
148 continue;
149
150 if (!batadv_tt_local_add(bat_priv->soft_iface,
151 mcast_entry->addr, BATADV_NO_FLAGS,
152 BATADV_NULL_IFINDEX, BATADV_NO_MARK))
153 continue;
154
155 hlist_del(&mcast_entry->list);
156 hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list);
157 }
158}
159
160/**
161 * batadv_mcast_has_bridge - check whether the soft-iface is bridged
162 * @bat_priv: the bat priv with all the soft interface information
163 *
164 * Checks whether there is a bridge on top of our soft interface. Returns
165 * true if so, false otherwise.
166 */
167static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
168{
169 struct net_device *upper = bat_priv->soft_iface;
170
171 rcu_read_lock();
172 do {
173 upper = netdev_master_upper_dev_get_rcu(upper);
174 } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
175 rcu_read_unlock();
176
177 return upper;
178}
179
180/**
181 * batadv_mcast_mla_update - update the own MLAs
182 * @bat_priv: the bat priv with all the soft interface information
183 *
184 * Update the own multicast listener announcements in the translation
185 * table.
186 */
187void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
188{
189 struct net_device *soft_iface = bat_priv->soft_iface;
190 struct hlist_head mcast_list = HLIST_HEAD_INIT;
191 int ret;
192
193 /* Avoid attaching MLAs, if there is a bridge on top of our soft
194 * interface, we don't support that yet (TODO)
195 */
196 if (batadv_mcast_has_bridge(bat_priv))
197 goto update;
198
199 ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
200 if (ret < 0)
201 goto out;
202
203update:
204 batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
205 batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
206
207out:
208 batadv_mcast_mla_list_free(&mcast_list);
209}
210
211/**
212 * batadv_mcast_free - free the multicast optimizations structures
213 * @bat_priv: the bat priv with all the soft interface information
214 */
215void batadv_mcast_free(struct batadv_priv *bat_priv)
216{
217 batadv_mcast_mla_tt_retract(bat_priv, NULL);
218}
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h
new file mode 100644
index 000000000000..7513e024b807
--- /dev/null
+++ b/net/batman-adv/multicast.h
@@ -0,0 +1,41 @@
1/* Copyright (C) 2014 B.A.T.M.A.N. contributors:
2 *
3 * Linus Lüssing
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _NET_BATMAN_ADV_MULTICAST_H_
19#define _NET_BATMAN_ADV_MULTICAST_H_
20
21#ifdef CONFIG_BATMAN_ADV_MCAST
22
23void batadv_mcast_mla_update(struct batadv_priv *bat_priv);
24
25void batadv_mcast_free(struct batadv_priv *bat_priv);
26
27#else
28
29static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
30{
31 return;
32}
33
34static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
35{
36 return;
37}
38
39#endif /* CONFIG_BATMAN_ADV_MCAST */
40
41#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 6d0da58d755e..4082d05a93a9 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -24,6 +24,7 @@
24#include "originator.h" 24#include "originator.h"
25#include "routing.h" 25#include "routing.h"
26#include "bridge_loop_avoidance.h" 26#include "bridge_loop_avoidance.h"
27#include "multicast.h"
27 28
28#include <linux/crc32c.h> 29#include <linux/crc32c.h>
29 30
@@ -484,7 +485,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
484{ 485{
485 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 486 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
486 struct batadv_tt_local_entry *tt_local; 487 struct batadv_tt_local_entry *tt_local;
487 struct batadv_tt_global_entry *tt_global; 488 struct batadv_tt_global_entry *tt_global = NULL;
488 struct net_device *in_dev = NULL; 489 struct net_device *in_dev = NULL;
489 struct hlist_head *head; 490 struct hlist_head *head;
490 struct batadv_tt_orig_list_entry *orig_entry; 491 struct batadv_tt_orig_list_entry *orig_entry;
@@ -497,7 +498,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
497 in_dev = dev_get_by_index(&init_net, ifindex); 498 in_dev = dev_get_by_index(&init_net, ifindex);
498 499
499 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid); 500 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
500 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); 501
502 if (!is_multicast_ether_addr(addr))
503 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
501 504
502 if (tt_local) { 505 if (tt_local) {
503 tt_local->last_seen = jiffies; 506 tt_local->last_seen = jiffies;
@@ -562,8 +565,11 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
562 tt_local->last_seen = jiffies; 565 tt_local->last_seen = jiffies;
563 tt_local->common.added_at = tt_local->last_seen; 566 tt_local->common.added_at = tt_local->last_seen;
564 567
565 /* the batman interface mac address should never be purged */ 568 /* the batman interface mac and multicast addresses should never be
566 if (batadv_compare_eth(addr, soft_iface->dev_addr)) 569 * purged
570 */
571 if (batadv_compare_eth(addr, soft_iface->dev_addr) ||
572 is_multicast_ether_addr(addr))
567 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; 573 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
568 574
569 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, 575 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
@@ -1361,6 +1367,11 @@ add_orig_entry:
1361 ret = true; 1367 ret = true;
1362 1368
1363out_remove: 1369out_remove:
1370 /* Do not remove multicast addresses from the local hash on
1371 * global additions
1372 */
1373 if (is_multicast_ether_addr(tt_addr))
1374 goto out;
1364 1375
1365 /* remove address from local hash if present */ 1376 /* remove address from local hash if present */
1366 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid, 1377 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
@@ -3120,6 +3131,9 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
3120 */ 3131 */
3121static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv) 3132static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
3122{ 3133{
3134 /* Update multicast addresses in local translation table */
3135 batadv_mcast_mla_update(bat_priv);
3136
3123 if (atomic_read(&bat_priv->tt.local_changes) < 1) { 3137 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
3124 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) 3138 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
3125 batadv_tt_tvlv_container_update(bat_priv); 3139 batadv_tt_tvlv_container_update(bat_priv);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 9f52517d0e74..d553264135d3 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -607,6 +607,16 @@ struct batadv_priv_dat {
607}; 607};
608#endif 608#endif
609 609
610#ifdef CONFIG_BATMAN_ADV_MCAST
611/**
612 * struct batadv_priv_mcast - per mesh interface mcast data
613 * @mla_list: list of multicast addresses we are currently announcing via TT
614 */
615struct batadv_priv_mcast {
616 struct hlist_head mla_list;
617};
618#endif
619
610/** 620/**
611 * struct batadv_priv_nc - per mesh interface network coding private data 621 * struct batadv_priv_nc - per mesh interface network coding private data
612 * @work: work queue callback item for cleanup 622 * @work: work queue callback item for cleanup
@@ -702,6 +712,7 @@ struct batadv_softif_vlan {
702 * @tt: translation table data 712 * @tt: translation table data
703 * @tvlv: type-version-length-value data 713 * @tvlv: type-version-length-value data
704 * @dat: distributed arp table data 714 * @dat: distributed arp table data
715 * @mcast: multicast data
705 * @network_coding: bool indicating whether network coding is enabled 716 * @network_coding: bool indicating whether network coding is enabled
706 * @batadv_priv_nc: network coding data 717 * @batadv_priv_nc: network coding data
707 */ 718 */
@@ -759,6 +770,9 @@ struct batadv_priv {
759#ifdef CONFIG_BATMAN_ADV_DAT 770#ifdef CONFIG_BATMAN_ADV_DAT
760 struct batadv_priv_dat dat; 771 struct batadv_priv_dat dat;
761#endif 772#endif
773#ifdef CONFIG_BATMAN_ADV_MCAST
774 struct batadv_priv_mcast mcast;
775#endif
762#ifdef CONFIG_BATMAN_ADV_NC 776#ifdef CONFIG_BATMAN_ADV_NC
763 atomic_t network_coding; 777 atomic_t network_coding;
764 struct batadv_priv_nc nc; 778 struct batadv_priv_nc nc;
@@ -1116,6 +1130,16 @@ struct batadv_dat_entry {
1116}; 1130};
1117 1131
1118/** 1132/**
1133 * struct batadv_hw_addr - a list entry for a MAC address
1134 * @list: list node for the linking of entries
1135 * @addr: the MAC address of this list entry
1136 */
1137struct batadv_hw_addr {
1138 struct hlist_node list;
1139 unsigned char addr[ETH_ALEN];
1140};
1141
1142/**
1119 * struct batadv_dat_candidate - candidate destination for DAT operations 1143 * struct batadv_dat_candidate - candidate destination for DAT operations
1120 * @type: the type of the selected candidate. It can one of the following: 1144 * @type: the type of the selected candidate. It can one of the following:
1121 * - BATADV_DAT_CANDIDATE_NOT_FOUND 1145 * - BATADV_DAT_CANDIDATE_NOT_FOUND