summarylogtreecommitdiffstats
path: root/1001-batman-adv-introduce-no_rebroadcast-option.patch
blob: 80a99479d9d3cab37fbcc24392b9eba4514c2e03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
From bb66988dc6972d5400b4ff4f0b49ed090007d635 Mon Sep 17 00:00:00 2001
Message-Id: <bb66988dc6972d5400b4ff4f0b49ed090007d635.1466049319.git.mschiffer@universe-factory.net>
From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
Date: Tue, 24 Sep 2013 04:36:27 +0200
Subject: [PATCH 1/2] batman-adv: introduce 'no_rebroadcast' option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch introduces a new sysfs option named "no_rebroadcast" on
a per hard interface basis. It allows manually enabling a split-horizon
like behaviour for the layer 2 multicast payload frames, in that
incoming multicast payload frames on such a hard interface are only
being rebroadcasted on all interfaces except the incoming one instead
of being rebroadcasted on all interfaces.

Such an option should only be enabled if you are certain that these
rebroadcasts are unnecessary. This is usually the case for instance
for point-to-point wifi longshots or wired links.

This option can especially safe a significant amount of upload overhead
if the neighbourhood on a link is rather large, for instance in some
transitive, symmetric VPN configurations.

Using this option wrongly will break your mesh network, use this option
wisely and at your own risk!

---
 net/batman-adv/hard-interface.c                    |  2 +
 net/batman-adv/send.c                              |  4 ++
 net/batman-adv/sysfs.c                             | 59 ++++++++++++++++++++++
 net/batman-adv/types.h                             |  1 +
 4 files changed

diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 8c2f399..48e53d0 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -690,6 +690,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
 	kref_init(&hard_iface->refcount);
 	kref_get(&hard_iface->refcount);
 
+	atomic_set(&hard_iface->no_rebroadcast, 0);
+
 	batadv_check_known_mac_addr(hard_iface->net_dev);
 	list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
 
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index f2f1256..3736d75 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -578,6 +578,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
 		if (forw_packet->num_packets >= hard_iface->num_bcasts)
 			continue;
 
+		if (atomic_read(&hard_iface->no_rebroadcast) &&
+		    forw_packet->skb->dev == hard_iface->net_dev)
+			continue;
+
 		if (!kref_get_unless_zero(&hard_iface->refcount))
 			continue;
 
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 414b207..9aa043f 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -134,6 +134,17 @@ struct batadv_attribute batadv_attr_vlan_##_name = {	\
 	.store  = _store,				\
 }
 
+/* Use this, if you have customized show and store functions
+ * for hard interface attrs
+ */
+#define BATADV_ATTR_HIF(_name, _mode, _show, _store)	\
+struct batadv_attribute batadv_attr_hif_##_name = {	\
+	.attr = {.name = __stringify(_name),		\
+		 .mode = _mode },			\
+	.show   = _show,				\
+	.store  = _store,				\
+};
+
 /* Use this, if you have customized show and store functions */
 #define BATADV_ATTR(_name, _mode, _show, _store)	\
 struct batadv_attribute batadv_attr_##_name = {		\
@@ -293,6 +304,52 @@ ssize_t batadv_show_##_name(struct kobject *kobj,			\
 	static BATADV_ATTR(_name, _mode, batadv_show_##_name,		\
 			   batadv_store_##_name)
 
+#define BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func)			\
+ssize_t batadv_store_hif_##_name(struct kobject *kobj,			\
+				 struct attribute *attr, char *buff,	\
+				 size_t count)				\
+{									\
+	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
+	struct batadv_hard_iface *hard_iface;				\
+	size_t res;							\
+									\
+	hard_iface = batadv_hardif_get_by_netdev(net_dev);		\
+	if (!hard_iface)						\
+		return 0;						\
+									\
+	res = __batadv_store_bool_attr(buff, count, _post_func,		\
+					      attr, &hard_iface->_name,	\
+					      hard_iface->soft_iface);	\
+	batadv_hardif_put(hard_iface);					\
+	return res;							\
+}
+
+#define BATADV_ATTR_HIF_SHOW_BOOL(_name)				\
+ssize_t batadv_show_hif_##_name(struct kobject *kobj,			\
+				struct attribute *attr, char *buff)	\
+{									\
+	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
+	struct batadv_hard_iface *hard_iface;				\
+	size_t res;							\
+									\
+	hard_iface = batadv_hardif_get_by_netdev(net_dev);		\
+	if (!hard_iface)						\
+		return 0;						\
+									\
+	res = sprintf(buff, "%s\n",					\
+		      atomic_read(&hard_iface->_name) == 0 ?		\
+				"disabled" : "enabled");		\
+	batadv_hardif_put(hard_iface);					\
+	return res;							\
+}
+
+/* Use this, if you are going to turn a [name] in the vlan struct on or off */
+#define BATADV_ATTR_HIF_BOOL(_name, _mode, _post_func)			\
+	static BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func)		\
+	static BATADV_ATTR_HIF_SHOW_BOOL(_name)				\
+	static BATADV_ATTR_HIF(_name, _mode, batadv_show_hif_##_name,	\
+			       batadv_store_hif_##_name)
+
 static int batadv_store_bool_attr(char *buff, size_t count,
 				  struct net_device *net_dev,
 				  const char *attr_name, atomic_t *attr,
@@ -993,6 +1050,7 @@ static ssize_t batadv_show_throughput_override(struct kobject *kobj,
 static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
 		   batadv_store_mesh_iface);
 static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+BATADV_ATTR_HIF_BOOL(no_rebroadcast, S_IRUGO | S_IWUSR, NULL);
 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
 BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
 		     2 * BATADV_JITTER, INT_MAX, NULL);
@@ -1004,6 +1062,7 @@ static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
 static struct batadv_attribute *batadv_batman_attrs[] = {
 	&batadv_attr_mesh_iface,
 	&batadv_attr_iface_status,
+	&batadv_attr_hif_no_rebroadcast,
 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
 	&batadv_attr_elp_interval,
 	&batadv_attr_throughput_override,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index ba846b0..1a596c5 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -156,6 +156,7 @@ struct batadv_hard_iface {
 	struct hlist_head neigh_list;
 	/* neigh_list_lock protects: neigh_list */
 	spinlock_t neigh_list_lock;
+	atomic_t no_rebroadcast;
 };
 
 /**
-- 
2.8.3