Commit c799443ee13ef37221732839f1cca6f11c798b7a
Committed by
Antonio Quartulli
1 parent
d737ccbed3
batman-adv: Delete unnecessary checks before the function call "kfree_skb"
The kfree_skb() function tests whether its argument is NULL and then returns immediately. Thus the test around the calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <a@unstable.cc>
Showing 3 changed files with 3 additions and 6 deletions Inline Diff
net/batman-adv/main.c
1 | /* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of version 2 of the GNU General Public |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "main.h" | 18 | #include "main.h" |
19 | 19 | ||
20 | #include <linux/atomic.h> | 20 | #include <linux/atomic.h> |
21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
22 | #include <linux/byteorder/generic.h> | 22 | #include <linux/byteorder/generic.h> |
23 | #include <linux/crc32c.h> | 23 | #include <linux/crc32c.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/if_ether.h> | 26 | #include <linux/if_ether.h> |
27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/ip.h> | 29 | #include <linux/ip.h> |
30 | #include <linux/ipv6.h> | 30 | #include <linux/ipv6.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/lockdep.h> | 33 | #include <linux/lockdep.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/netdevice.h> | 36 | #include <linux/netdevice.h> |
37 | #include <linux/pkt_sched.h> | 37 | #include <linux/pkt_sched.h> |
38 | #include <linux/rculist.h> | 38 | #include <linux/rculist.h> |
39 | #include <linux/rcupdate.h> | 39 | #include <linux/rcupdate.h> |
40 | #include <linux/seq_file.h> | 40 | #include <linux/seq_file.h> |
41 | #include <linux/skbuff.h> | 41 | #include <linux/skbuff.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
44 | #include <linux/stddef.h> | 44 | #include <linux/stddef.h> |
45 | #include <linux/string.h> | 45 | #include <linux/string.h> |
46 | #include <linux/workqueue.h> | 46 | #include <linux/workqueue.h> |
47 | #include <net/dsfield.h> | 47 | #include <net/dsfield.h> |
48 | #include <net/rtnetlink.h> | 48 | #include <net/rtnetlink.h> |
49 | 49 | ||
50 | #include "bat_algo.h" | 50 | #include "bat_algo.h" |
51 | #include "bridge_loop_avoidance.h" | 51 | #include "bridge_loop_avoidance.h" |
52 | #include "debugfs.h" | 52 | #include "debugfs.h" |
53 | #include "distributed-arp-table.h" | 53 | #include "distributed-arp-table.h" |
54 | #include "gateway_client.h" | 54 | #include "gateway_client.h" |
55 | #include "gateway_common.h" | 55 | #include "gateway_common.h" |
56 | #include "hard-interface.h" | 56 | #include "hard-interface.h" |
57 | #include "icmp_socket.h" | 57 | #include "icmp_socket.h" |
58 | #include "multicast.h" | 58 | #include "multicast.h" |
59 | #include "network-coding.h" | 59 | #include "network-coding.h" |
60 | #include "originator.h" | 60 | #include "originator.h" |
61 | #include "packet.h" | 61 | #include "packet.h" |
62 | #include "routing.h" | 62 | #include "routing.h" |
63 | #include "send.h" | 63 | #include "send.h" |
64 | #include "soft-interface.h" | 64 | #include "soft-interface.h" |
65 | #include "translation-table.h" | 65 | #include "translation-table.h" |
66 | 66 | ||
67 | /* List manipulations on hardif_list have to be rtnl_lock()'ed, | 67 | /* List manipulations on hardif_list have to be rtnl_lock()'ed, |
68 | * list traversals just rcu-locked | 68 | * list traversals just rcu-locked |
69 | */ | 69 | */ |
70 | struct list_head batadv_hardif_list; | 70 | struct list_head batadv_hardif_list; |
71 | static int (*batadv_rx_handler[256])(struct sk_buff *, | 71 | static int (*batadv_rx_handler[256])(struct sk_buff *, |
72 | struct batadv_hard_iface *); | 72 | struct batadv_hard_iface *); |
73 | char batadv_routing_algo[20] = "BATMAN_IV"; | 73 | char batadv_routing_algo[20] = "BATMAN_IV"; |
74 | static struct hlist_head batadv_algo_list; | 74 | static struct hlist_head batadv_algo_list; |
75 | 75 | ||
76 | unsigned char batadv_broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 76 | unsigned char batadv_broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
77 | 77 | ||
78 | struct workqueue_struct *batadv_event_workqueue; | 78 | struct workqueue_struct *batadv_event_workqueue; |
79 | 79 | ||
80 | static void batadv_recv_handler_init(void); | 80 | static void batadv_recv_handler_init(void); |
81 | 81 | ||
82 | static int __init batadv_init(void) | 82 | static int __init batadv_init(void) |
83 | { | 83 | { |
84 | INIT_LIST_HEAD(&batadv_hardif_list); | 84 | INIT_LIST_HEAD(&batadv_hardif_list); |
85 | INIT_HLIST_HEAD(&batadv_algo_list); | 85 | INIT_HLIST_HEAD(&batadv_algo_list); |
86 | 86 | ||
87 | batadv_recv_handler_init(); | 87 | batadv_recv_handler_init(); |
88 | 88 | ||
89 | batadv_iv_init(); | 89 | batadv_iv_init(); |
90 | batadv_nc_init(); | 90 | batadv_nc_init(); |
91 | 91 | ||
92 | batadv_event_workqueue = create_singlethread_workqueue("bat_events"); | 92 | batadv_event_workqueue = create_singlethread_workqueue("bat_events"); |
93 | 93 | ||
94 | if (!batadv_event_workqueue) | 94 | if (!batadv_event_workqueue) |
95 | return -ENOMEM; | 95 | return -ENOMEM; |
96 | 96 | ||
97 | batadv_socket_init(); | 97 | batadv_socket_init(); |
98 | batadv_debugfs_init(); | 98 | batadv_debugfs_init(); |
99 | 99 | ||
100 | register_netdevice_notifier(&batadv_hard_if_notifier); | 100 | register_netdevice_notifier(&batadv_hard_if_notifier); |
101 | rtnl_link_register(&batadv_link_ops); | 101 | rtnl_link_register(&batadv_link_ops); |
102 | 102 | ||
103 | pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", | 103 | pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", |
104 | BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION); | 104 | BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION); |
105 | 105 | ||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | static void __exit batadv_exit(void) | 109 | static void __exit batadv_exit(void) |
110 | { | 110 | { |
111 | batadv_debugfs_destroy(); | 111 | batadv_debugfs_destroy(); |
112 | rtnl_link_unregister(&batadv_link_ops); | 112 | rtnl_link_unregister(&batadv_link_ops); |
113 | unregister_netdevice_notifier(&batadv_hard_if_notifier); | 113 | unregister_netdevice_notifier(&batadv_hard_if_notifier); |
114 | batadv_hardif_remove_interfaces(); | 114 | batadv_hardif_remove_interfaces(); |
115 | 115 | ||
116 | flush_workqueue(batadv_event_workqueue); | 116 | flush_workqueue(batadv_event_workqueue); |
117 | destroy_workqueue(batadv_event_workqueue); | 117 | destroy_workqueue(batadv_event_workqueue); |
118 | batadv_event_workqueue = NULL; | 118 | batadv_event_workqueue = NULL; |
119 | 119 | ||
120 | rcu_barrier(); | 120 | rcu_barrier(); |
121 | } | 121 | } |
122 | 122 | ||
123 | int batadv_mesh_init(struct net_device *soft_iface) | 123 | int batadv_mesh_init(struct net_device *soft_iface) |
124 | { | 124 | { |
125 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 125 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
126 | int ret; | 126 | int ret; |
127 | 127 | ||
128 | spin_lock_init(&bat_priv->forw_bat_list_lock); | 128 | spin_lock_init(&bat_priv->forw_bat_list_lock); |
129 | spin_lock_init(&bat_priv->forw_bcast_list_lock); | 129 | spin_lock_init(&bat_priv->forw_bcast_list_lock); |
130 | spin_lock_init(&bat_priv->tt.changes_list_lock); | 130 | spin_lock_init(&bat_priv->tt.changes_list_lock); |
131 | spin_lock_init(&bat_priv->tt.req_list_lock); | 131 | spin_lock_init(&bat_priv->tt.req_list_lock); |
132 | spin_lock_init(&bat_priv->tt.roam_list_lock); | 132 | spin_lock_init(&bat_priv->tt.roam_list_lock); |
133 | spin_lock_init(&bat_priv->tt.last_changeset_lock); | 133 | spin_lock_init(&bat_priv->tt.last_changeset_lock); |
134 | spin_lock_init(&bat_priv->tt.commit_lock); | 134 | spin_lock_init(&bat_priv->tt.commit_lock); |
135 | spin_lock_init(&bat_priv->gw.list_lock); | 135 | spin_lock_init(&bat_priv->gw.list_lock); |
136 | #ifdef CONFIG_BATMAN_ADV_MCAST | 136 | #ifdef CONFIG_BATMAN_ADV_MCAST |
137 | spin_lock_init(&bat_priv->mcast.want_lists_lock); | 137 | spin_lock_init(&bat_priv->mcast.want_lists_lock); |
138 | #endif | 138 | #endif |
139 | spin_lock_init(&bat_priv->tvlv.container_list_lock); | 139 | spin_lock_init(&bat_priv->tvlv.container_list_lock); |
140 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); | 140 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); |
141 | spin_lock_init(&bat_priv->softif_vlan_list_lock); | 141 | spin_lock_init(&bat_priv->softif_vlan_list_lock); |
142 | 142 | ||
143 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 143 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
144 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 144 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
145 | INIT_HLIST_HEAD(&bat_priv->gw.list); | 145 | INIT_HLIST_HEAD(&bat_priv->gw.list); |
146 | #ifdef CONFIG_BATMAN_ADV_MCAST | 146 | #ifdef CONFIG_BATMAN_ADV_MCAST |
147 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); | 147 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); |
148 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list); | 148 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list); |
149 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv6_list); | 149 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv6_list); |
150 | #endif | 150 | #endif |
151 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); | 151 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); |
152 | INIT_HLIST_HEAD(&bat_priv->tt.req_list); | 152 | INIT_HLIST_HEAD(&bat_priv->tt.req_list); |
153 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); | 153 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); |
154 | #ifdef CONFIG_BATMAN_ADV_MCAST | 154 | #ifdef CONFIG_BATMAN_ADV_MCAST |
155 | INIT_HLIST_HEAD(&bat_priv->mcast.mla_list); | 155 | INIT_HLIST_HEAD(&bat_priv->mcast.mla_list); |
156 | #endif | 156 | #endif |
157 | INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); | 157 | INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); |
158 | INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); | 158 | INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); |
159 | INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); | 159 | INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); |
160 | 160 | ||
161 | ret = batadv_originator_init(bat_priv); | 161 | ret = batadv_originator_init(bat_priv); |
162 | if (ret < 0) | 162 | if (ret < 0) |
163 | goto err; | 163 | goto err; |
164 | 164 | ||
165 | ret = batadv_tt_init(bat_priv); | 165 | ret = batadv_tt_init(bat_priv); |
166 | if (ret < 0) | 166 | if (ret < 0) |
167 | goto err; | 167 | goto err; |
168 | 168 | ||
169 | ret = batadv_bla_init(bat_priv); | 169 | ret = batadv_bla_init(bat_priv); |
170 | if (ret < 0) | 170 | if (ret < 0) |
171 | goto err; | 171 | goto err; |
172 | 172 | ||
173 | ret = batadv_dat_init(bat_priv); | 173 | ret = batadv_dat_init(bat_priv); |
174 | if (ret < 0) | 174 | if (ret < 0) |
175 | goto err; | 175 | goto err; |
176 | 176 | ||
177 | ret = batadv_nc_mesh_init(bat_priv); | 177 | ret = batadv_nc_mesh_init(bat_priv); |
178 | if (ret < 0) | 178 | if (ret < 0) |
179 | goto err; | 179 | goto err; |
180 | 180 | ||
181 | batadv_gw_init(bat_priv); | 181 | batadv_gw_init(bat_priv); |
182 | batadv_mcast_init(bat_priv); | 182 | batadv_mcast_init(bat_priv); |
183 | 183 | ||
184 | atomic_set(&bat_priv->gw.reselect, 0); | 184 | atomic_set(&bat_priv->gw.reselect, 0); |
185 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); | 185 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); |
186 | 186 | ||
187 | return 0; | 187 | return 0; |
188 | 188 | ||
189 | err: | 189 | err: |
190 | batadv_mesh_free(soft_iface); | 190 | batadv_mesh_free(soft_iface); |
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | 193 | ||
194 | void batadv_mesh_free(struct net_device *soft_iface) | 194 | void batadv_mesh_free(struct net_device *soft_iface) |
195 | { | 195 | { |
196 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 196 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
197 | 197 | ||
198 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); | 198 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); |
199 | 199 | ||
200 | batadv_purge_outstanding_packets(bat_priv, NULL); | 200 | batadv_purge_outstanding_packets(bat_priv, NULL); |
201 | 201 | ||
202 | batadv_gw_node_free(bat_priv); | 202 | batadv_gw_node_free(bat_priv); |
203 | batadv_nc_mesh_free(bat_priv); | 203 | batadv_nc_mesh_free(bat_priv); |
204 | batadv_dat_free(bat_priv); | 204 | batadv_dat_free(bat_priv); |
205 | batadv_bla_free(bat_priv); | 205 | batadv_bla_free(bat_priv); |
206 | 206 | ||
207 | batadv_mcast_free(bat_priv); | 207 | batadv_mcast_free(bat_priv); |
208 | 208 | ||
209 | /* Free the TT and the originator tables only after having terminated | 209 | /* Free the TT and the originator tables only after having terminated |
210 | * all the other depending components which may use these structures for | 210 | * all the other depending components which may use these structures for |
211 | * their purposes. | 211 | * their purposes. |
212 | */ | 212 | */ |
213 | batadv_tt_free(bat_priv); | 213 | batadv_tt_free(bat_priv); |
214 | 214 | ||
215 | /* Since the originator table clean up routine is accessing the TT | 215 | /* Since the originator table clean up routine is accessing the TT |
216 | * tables as well, it has to be invoked after the TT tables have been | 216 | * tables as well, it has to be invoked after the TT tables have been |
217 | * freed and marked as empty. This ensures that no cleanup RCU callbacks | 217 | * freed and marked as empty. This ensures that no cleanup RCU callbacks |
218 | * accessing the TT data are scheduled for later execution. | 218 | * accessing the TT data are scheduled for later execution. |
219 | */ | 219 | */ |
220 | batadv_originator_free(bat_priv); | 220 | batadv_originator_free(bat_priv); |
221 | 221 | ||
222 | batadv_gw_free(bat_priv); | 222 | batadv_gw_free(bat_priv); |
223 | 223 | ||
224 | free_percpu(bat_priv->bat_counters); | 224 | free_percpu(bat_priv->bat_counters); |
225 | bat_priv->bat_counters = NULL; | 225 | bat_priv->bat_counters = NULL; |
226 | 226 | ||
227 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | 227 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); |
228 | } | 228 | } |
229 | 229 | ||
230 | /** | 230 | /** |
231 | * batadv_is_my_mac - check if the given mac address belongs to any of the real | 231 | * batadv_is_my_mac - check if the given mac address belongs to any of the real |
232 | * interfaces in the current mesh | 232 | * interfaces in the current mesh |
233 | * @bat_priv: the bat priv with all the soft interface information | 233 | * @bat_priv: the bat priv with all the soft interface information |
234 | * @addr: the address to check | 234 | * @addr: the address to check |
235 | * | 235 | * |
236 | * Returns 'true' if the mac address was found, false otherwise. | 236 | * Returns 'true' if the mac address was found, false otherwise. |
237 | */ | 237 | */ |
238 | bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr) | 238 | bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr) |
239 | { | 239 | { |
240 | const struct batadv_hard_iface *hard_iface; | 240 | const struct batadv_hard_iface *hard_iface; |
241 | bool is_my_mac = false; | 241 | bool is_my_mac = false; |
242 | 242 | ||
243 | rcu_read_lock(); | 243 | rcu_read_lock(); |
244 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 244 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { |
245 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | 245 | if (hard_iface->if_status != BATADV_IF_ACTIVE) |
246 | continue; | 246 | continue; |
247 | 247 | ||
248 | if (hard_iface->soft_iface != bat_priv->soft_iface) | 248 | if (hard_iface->soft_iface != bat_priv->soft_iface) |
249 | continue; | 249 | continue; |
250 | 250 | ||
251 | if (batadv_compare_eth(hard_iface->net_dev->dev_addr, addr)) { | 251 | if (batadv_compare_eth(hard_iface->net_dev->dev_addr, addr)) { |
252 | is_my_mac = true; | 252 | is_my_mac = true; |
253 | break; | 253 | break; |
254 | } | 254 | } |
255 | } | 255 | } |
256 | rcu_read_unlock(); | 256 | rcu_read_unlock(); |
257 | return is_my_mac; | 257 | return is_my_mac; |
258 | } | 258 | } |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * batadv_seq_print_text_primary_if_get - called from debugfs table printing | 261 | * batadv_seq_print_text_primary_if_get - called from debugfs table printing |
262 | * function that requires the primary interface | 262 | * function that requires the primary interface |
263 | * @seq: debugfs table seq_file struct | 263 | * @seq: debugfs table seq_file struct |
264 | * | 264 | * |
265 | * Returns primary interface if found or NULL otherwise. | 265 | * Returns primary interface if found or NULL otherwise. |
266 | */ | 266 | */ |
267 | struct batadv_hard_iface * | 267 | struct batadv_hard_iface * |
268 | batadv_seq_print_text_primary_if_get(struct seq_file *seq) | 268 | batadv_seq_print_text_primary_if_get(struct seq_file *seq) |
269 | { | 269 | { |
270 | struct net_device *net_dev = (struct net_device *)seq->private; | 270 | struct net_device *net_dev = (struct net_device *)seq->private; |
271 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 271 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
272 | struct batadv_hard_iface *primary_if; | 272 | struct batadv_hard_iface *primary_if; |
273 | 273 | ||
274 | primary_if = batadv_primary_if_get_selected(bat_priv); | 274 | primary_if = batadv_primary_if_get_selected(bat_priv); |
275 | 275 | ||
276 | if (!primary_if) { | 276 | if (!primary_if) { |
277 | seq_printf(seq, | 277 | seq_printf(seq, |
278 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | 278 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", |
279 | net_dev->name); | 279 | net_dev->name); |
280 | goto out; | 280 | goto out; |
281 | } | 281 | } |
282 | 282 | ||
283 | if (primary_if->if_status == BATADV_IF_ACTIVE) | 283 | if (primary_if->if_status == BATADV_IF_ACTIVE) |
284 | goto out; | 284 | goto out; |
285 | 285 | ||
286 | seq_printf(seq, | 286 | seq_printf(seq, |
287 | "BATMAN mesh %s disabled - primary interface not active\n", | 287 | "BATMAN mesh %s disabled - primary interface not active\n", |
288 | net_dev->name); | 288 | net_dev->name); |
289 | batadv_hardif_free_ref(primary_if); | 289 | batadv_hardif_free_ref(primary_if); |
290 | primary_if = NULL; | 290 | primary_if = NULL; |
291 | 291 | ||
292 | out: | 292 | out: |
293 | return primary_if; | 293 | return primary_if; |
294 | } | 294 | } |
295 | 295 | ||
296 | /** | 296 | /** |
297 | * batadv_max_header_len - calculate maximum encapsulation overhead for a | 297 | * batadv_max_header_len - calculate maximum encapsulation overhead for a |
298 | * payload packet | 298 | * payload packet |
299 | * | 299 | * |
300 | * Return the maximum encapsulation overhead in bytes. | 300 | * Return the maximum encapsulation overhead in bytes. |
301 | */ | 301 | */ |
302 | int batadv_max_header_len(void) | 302 | int batadv_max_header_len(void) |
303 | { | 303 | { |
304 | int header_len = 0; | 304 | int header_len = 0; |
305 | 305 | ||
306 | header_len = max_t(int, header_len, | 306 | header_len = max_t(int, header_len, |
307 | sizeof(struct batadv_unicast_packet)); | 307 | sizeof(struct batadv_unicast_packet)); |
308 | header_len = max_t(int, header_len, | 308 | header_len = max_t(int, header_len, |
309 | sizeof(struct batadv_unicast_4addr_packet)); | 309 | sizeof(struct batadv_unicast_4addr_packet)); |
310 | header_len = max_t(int, header_len, | 310 | header_len = max_t(int, header_len, |
311 | sizeof(struct batadv_bcast_packet)); | 311 | sizeof(struct batadv_bcast_packet)); |
312 | 312 | ||
313 | #ifdef CONFIG_BATMAN_ADV_NC | 313 | #ifdef CONFIG_BATMAN_ADV_NC |
314 | header_len = max_t(int, header_len, | 314 | header_len = max_t(int, header_len, |
315 | sizeof(struct batadv_coded_packet)); | 315 | sizeof(struct batadv_coded_packet)); |
316 | #endif | 316 | #endif |
317 | 317 | ||
318 | return header_len + ETH_HLEN; | 318 | return header_len + ETH_HLEN; |
319 | } | 319 | } |
320 | 320 | ||
321 | /** | 321 | /** |
322 | * batadv_skb_set_priority - sets skb priority according to packet content | 322 | * batadv_skb_set_priority - sets skb priority according to packet content |
323 | * @skb: the packet to be sent | 323 | * @skb: the packet to be sent |
324 | * @offset: offset to the packet content | 324 | * @offset: offset to the packet content |
325 | * | 325 | * |
326 | * This function sets a value between 256 and 263 (802.1d priority), which | 326 | * This function sets a value between 256 and 263 (802.1d priority), which |
327 | * can be interpreted by the cfg80211 or other drivers. | 327 | * can be interpreted by the cfg80211 or other drivers. |
328 | */ | 328 | */ |
329 | void batadv_skb_set_priority(struct sk_buff *skb, int offset) | 329 | void batadv_skb_set_priority(struct sk_buff *skb, int offset) |
330 | { | 330 | { |
331 | struct iphdr ip_hdr_tmp, *ip_hdr; | 331 | struct iphdr ip_hdr_tmp, *ip_hdr; |
332 | struct ipv6hdr ip6_hdr_tmp, *ip6_hdr; | 332 | struct ipv6hdr ip6_hdr_tmp, *ip6_hdr; |
333 | struct ethhdr ethhdr_tmp, *ethhdr; | 333 | struct ethhdr ethhdr_tmp, *ethhdr; |
334 | struct vlan_ethhdr *vhdr, vhdr_tmp; | 334 | struct vlan_ethhdr *vhdr, vhdr_tmp; |
335 | u32 prio; | 335 | u32 prio; |
336 | 336 | ||
337 | /* already set, do nothing */ | 337 | /* already set, do nothing */ |
338 | if (skb->priority >= 256 && skb->priority <= 263) | 338 | if (skb->priority >= 256 && skb->priority <= 263) |
339 | return; | 339 | return; |
340 | 340 | ||
341 | ethhdr = skb_header_pointer(skb, offset, sizeof(*ethhdr), ðhdr_tmp); | 341 | ethhdr = skb_header_pointer(skb, offset, sizeof(*ethhdr), ðhdr_tmp); |
342 | if (!ethhdr) | 342 | if (!ethhdr) |
343 | return; | 343 | return; |
344 | 344 | ||
345 | switch (ethhdr->h_proto) { | 345 | switch (ethhdr->h_proto) { |
346 | case htons(ETH_P_8021Q): | 346 | case htons(ETH_P_8021Q): |
347 | vhdr = skb_header_pointer(skb, offset + sizeof(*vhdr), | 347 | vhdr = skb_header_pointer(skb, offset + sizeof(*vhdr), |
348 | sizeof(*vhdr), &vhdr_tmp); | 348 | sizeof(*vhdr), &vhdr_tmp); |
349 | if (!vhdr) | 349 | if (!vhdr) |
350 | return; | 350 | return; |
351 | prio = ntohs(vhdr->h_vlan_TCI) & VLAN_PRIO_MASK; | 351 | prio = ntohs(vhdr->h_vlan_TCI) & VLAN_PRIO_MASK; |
352 | prio = prio >> VLAN_PRIO_SHIFT; | 352 | prio = prio >> VLAN_PRIO_SHIFT; |
353 | break; | 353 | break; |
354 | case htons(ETH_P_IP): | 354 | case htons(ETH_P_IP): |
355 | ip_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), | 355 | ip_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), |
356 | sizeof(*ip_hdr), &ip_hdr_tmp); | 356 | sizeof(*ip_hdr), &ip_hdr_tmp); |
357 | if (!ip_hdr) | 357 | if (!ip_hdr) |
358 | return; | 358 | return; |
359 | prio = (ipv4_get_dsfield(ip_hdr) & 0xfc) >> 5; | 359 | prio = (ipv4_get_dsfield(ip_hdr) & 0xfc) >> 5; |
360 | break; | 360 | break; |
361 | case htons(ETH_P_IPV6): | 361 | case htons(ETH_P_IPV6): |
362 | ip6_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), | 362 | ip6_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), |
363 | sizeof(*ip6_hdr), &ip6_hdr_tmp); | 363 | sizeof(*ip6_hdr), &ip6_hdr_tmp); |
364 | if (!ip6_hdr) | 364 | if (!ip6_hdr) |
365 | return; | 365 | return; |
366 | prio = (ipv6_get_dsfield(ip6_hdr) & 0xfc) >> 5; | 366 | prio = (ipv6_get_dsfield(ip6_hdr) & 0xfc) >> 5; |
367 | break; | 367 | break; |
368 | default: | 368 | default: |
369 | return; | 369 | return; |
370 | } | 370 | } |
371 | 371 | ||
372 | skb->priority = prio + 256; | 372 | skb->priority = prio + 256; |
373 | } | 373 | } |
374 | 374 | ||
375 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, | 375 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, |
376 | struct batadv_hard_iface *recv_if) | 376 | struct batadv_hard_iface *recv_if) |
377 | { | 377 | { |
378 | return NET_RX_DROP; | 378 | return NET_RX_DROP; |
379 | } | 379 | } |
380 | 380 | ||
381 | /* incoming packets with the batman ethertype received on any active hard | 381 | /* incoming packets with the batman ethertype received on any active hard |
382 | * interface | 382 | * interface |
383 | */ | 383 | */ |
384 | int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | 384 | int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, |
385 | struct packet_type *ptype, | 385 | struct packet_type *ptype, |
386 | struct net_device *orig_dev) | 386 | struct net_device *orig_dev) |
387 | { | 387 | { |
388 | struct batadv_priv *bat_priv; | 388 | struct batadv_priv *bat_priv; |
389 | struct batadv_ogm_packet *batadv_ogm_packet; | 389 | struct batadv_ogm_packet *batadv_ogm_packet; |
390 | struct batadv_hard_iface *hard_iface; | 390 | struct batadv_hard_iface *hard_iface; |
391 | u8 idx; | 391 | u8 idx; |
392 | int ret; | 392 | int ret; |
393 | 393 | ||
394 | hard_iface = container_of(ptype, struct batadv_hard_iface, | 394 | hard_iface = container_of(ptype, struct batadv_hard_iface, |
395 | batman_adv_ptype); | 395 | batman_adv_ptype); |
396 | skb = skb_share_check(skb, GFP_ATOMIC); | 396 | skb = skb_share_check(skb, GFP_ATOMIC); |
397 | 397 | ||
398 | /* skb was released by skb_share_check() */ | 398 | /* skb was released by skb_share_check() */ |
399 | if (!skb) | 399 | if (!skb) |
400 | goto err_out; | 400 | goto err_out; |
401 | 401 | ||
402 | /* packet should hold at least type and version */ | 402 | /* packet should hold at least type and version */ |
403 | if (unlikely(!pskb_may_pull(skb, 2))) | 403 | if (unlikely(!pskb_may_pull(skb, 2))) |
404 | goto err_free; | 404 | goto err_free; |
405 | 405 | ||
406 | /* expect a valid ethernet header here. */ | 406 | /* expect a valid ethernet header here. */ |
407 | if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb))) | 407 | if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb))) |
408 | goto err_free; | 408 | goto err_free; |
409 | 409 | ||
410 | if (!hard_iface->soft_iface) | 410 | if (!hard_iface->soft_iface) |
411 | goto err_free; | 411 | goto err_free; |
412 | 412 | ||
413 | bat_priv = netdev_priv(hard_iface->soft_iface); | 413 | bat_priv = netdev_priv(hard_iface->soft_iface); |
414 | 414 | ||
415 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 415 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
416 | goto err_free; | 416 | goto err_free; |
417 | 417 | ||
418 | /* discard frames on not active interfaces */ | 418 | /* discard frames on not active interfaces */ |
419 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | 419 | if (hard_iface->if_status != BATADV_IF_ACTIVE) |
420 | goto err_free; | 420 | goto err_free; |
421 | 421 | ||
422 | batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data; | 422 | batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data; |
423 | 423 | ||
424 | if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) { | 424 | if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) { |
425 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 425 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
426 | "Drop packet: incompatible batman version (%i)\n", | 426 | "Drop packet: incompatible batman version (%i)\n", |
427 | batadv_ogm_packet->version); | 427 | batadv_ogm_packet->version); |
428 | goto err_free; | 428 | goto err_free; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* reset control block to avoid left overs from previous users */ | 431 | /* reset control block to avoid left overs from previous users */ |
432 | memset(skb->cb, 0, sizeof(struct batadv_skb_cb)); | 432 | memset(skb->cb, 0, sizeof(struct batadv_skb_cb)); |
433 | 433 | ||
434 | /* all receive handlers return whether they received or reused | 434 | /* all receive handlers return whether they received or reused |
435 | * the supplied skb. if not, we have to free the skb. | 435 | * the supplied skb. if not, we have to free the skb. |
436 | */ | 436 | */ |
437 | idx = batadv_ogm_packet->packet_type; | 437 | idx = batadv_ogm_packet->packet_type; |
438 | ret = (*batadv_rx_handler[idx])(skb, hard_iface); | 438 | ret = (*batadv_rx_handler[idx])(skb, hard_iface); |
439 | 439 | ||
440 | if (ret == NET_RX_DROP) | 440 | if (ret == NET_RX_DROP) |
441 | kfree_skb(skb); | 441 | kfree_skb(skb); |
442 | 442 | ||
443 | /* return NET_RX_SUCCESS in any case as we | 443 | /* return NET_RX_SUCCESS in any case as we |
444 | * most probably dropped the packet for | 444 | * most probably dropped the packet for |
445 | * routing-logical reasons. | 445 | * routing-logical reasons. |
446 | */ | 446 | */ |
447 | return NET_RX_SUCCESS; | 447 | return NET_RX_SUCCESS; |
448 | 448 | ||
449 | err_free: | 449 | err_free: |
450 | kfree_skb(skb); | 450 | kfree_skb(skb); |
451 | err_out: | 451 | err_out: |
452 | return NET_RX_DROP; | 452 | return NET_RX_DROP; |
453 | } | 453 | } |
454 | 454 | ||
455 | static void batadv_recv_handler_init(void) | 455 | static void batadv_recv_handler_init(void) |
456 | { | 456 | { |
457 | int i; | 457 | int i; |
458 | 458 | ||
459 | for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++) | 459 | for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++) |
460 | batadv_rx_handler[i] = batadv_recv_unhandled_packet; | 460 | batadv_rx_handler[i] = batadv_recv_unhandled_packet; |
461 | 461 | ||
462 | for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++) | 462 | for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++) |
463 | batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet; | 463 | batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet; |
464 | 464 | ||
465 | /* compile time checks for sizes */ | 465 | /* compile time checks for sizes */ |
466 | BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6); | 466 | BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6); |
467 | BUILD_BUG_ON(sizeof(struct batadv_ogm_packet) != 24); | 467 | BUILD_BUG_ON(sizeof(struct batadv_ogm_packet) != 24); |
468 | BUILD_BUG_ON(sizeof(struct batadv_icmp_header) != 20); | 468 | BUILD_BUG_ON(sizeof(struct batadv_icmp_header) != 20); |
469 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet) != 20); | 469 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet) != 20); |
470 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet_rr) != 116); | 470 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet_rr) != 116); |
471 | BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10); | 471 | BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10); |
472 | BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18); | 472 | BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18); |
473 | BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20); | 473 | BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20); |
474 | BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14); | 474 | BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14); |
475 | BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46); | 475 | BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46); |
476 | BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20); | 476 | BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20); |
477 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_hdr) != 4); | 477 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_hdr) != 4); |
478 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_gateway_data) != 8); | 478 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_gateway_data) != 8); |
479 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_vlan_data) != 8); | 479 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_vlan_data) != 8); |
480 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12); | 480 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12); |
481 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8); | 481 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8); |
482 | 482 | ||
483 | /* broadcast packet */ | 483 | /* broadcast packet */ |
484 | batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; | 484 | batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; |
485 | 485 | ||
486 | /* unicast packets ... */ | 486 | /* unicast packets ... */ |
487 | /* unicast with 4 addresses packet */ | 487 | /* unicast with 4 addresses packet */ |
488 | batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; | 488 | batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; |
489 | /* unicast packet */ | 489 | /* unicast packet */ |
490 | batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; | 490 | batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; |
491 | /* unicast tvlv packet */ | 491 | /* unicast tvlv packet */ |
492 | batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv; | 492 | batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv; |
493 | /* batman icmp packet */ | 493 | /* batman icmp packet */ |
494 | batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; | 494 | batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; |
495 | /* Fragmented packets */ | 495 | /* Fragmented packets */ |
496 | batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_frag_packet; | 496 | batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_frag_packet; |
497 | } | 497 | } |
498 | 498 | ||
499 | int | 499 | int |
500 | batadv_recv_handler_register(u8 packet_type, | 500 | batadv_recv_handler_register(u8 packet_type, |
501 | int (*recv_handler)(struct sk_buff *, | 501 | int (*recv_handler)(struct sk_buff *, |
502 | struct batadv_hard_iface *)) | 502 | struct batadv_hard_iface *)) |
503 | { | 503 | { |
504 | int (*curr)(struct sk_buff *, | 504 | int (*curr)(struct sk_buff *, |
505 | struct batadv_hard_iface *); | 505 | struct batadv_hard_iface *); |
506 | curr = batadv_rx_handler[packet_type]; | 506 | curr = batadv_rx_handler[packet_type]; |
507 | 507 | ||
508 | if ((curr != batadv_recv_unhandled_packet) && | 508 | if ((curr != batadv_recv_unhandled_packet) && |
509 | (curr != batadv_recv_unhandled_unicast_packet)) | 509 | (curr != batadv_recv_unhandled_unicast_packet)) |
510 | return -EBUSY; | 510 | return -EBUSY; |
511 | 511 | ||
512 | batadv_rx_handler[packet_type] = recv_handler; | 512 | batadv_rx_handler[packet_type] = recv_handler; |
513 | return 0; | 513 | return 0; |
514 | } | 514 | } |
515 | 515 | ||
516 | void batadv_recv_handler_unregister(u8 packet_type) | 516 | void batadv_recv_handler_unregister(u8 packet_type) |
517 | { | 517 | { |
518 | batadv_rx_handler[packet_type] = batadv_recv_unhandled_packet; | 518 | batadv_rx_handler[packet_type] = batadv_recv_unhandled_packet; |
519 | } | 519 | } |
520 | 520 | ||
521 | static struct batadv_algo_ops *batadv_algo_get(char *name) | 521 | static struct batadv_algo_ops *batadv_algo_get(char *name) |
522 | { | 522 | { |
523 | struct batadv_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; | 523 | struct batadv_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; |
524 | 524 | ||
525 | hlist_for_each_entry(bat_algo_ops_tmp, &batadv_algo_list, list) { | 525 | hlist_for_each_entry(bat_algo_ops_tmp, &batadv_algo_list, list) { |
526 | if (strcmp(bat_algo_ops_tmp->name, name) != 0) | 526 | if (strcmp(bat_algo_ops_tmp->name, name) != 0) |
527 | continue; | 527 | continue; |
528 | 528 | ||
529 | bat_algo_ops = bat_algo_ops_tmp; | 529 | bat_algo_ops = bat_algo_ops_tmp; |
530 | break; | 530 | break; |
531 | } | 531 | } |
532 | 532 | ||
533 | return bat_algo_ops; | 533 | return bat_algo_ops; |
534 | } | 534 | } |
535 | 535 | ||
536 | int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) | 536 | int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) |
537 | { | 537 | { |
538 | struct batadv_algo_ops *bat_algo_ops_tmp; | 538 | struct batadv_algo_ops *bat_algo_ops_tmp; |
539 | 539 | ||
540 | bat_algo_ops_tmp = batadv_algo_get(bat_algo_ops->name); | 540 | bat_algo_ops_tmp = batadv_algo_get(bat_algo_ops->name); |
541 | if (bat_algo_ops_tmp) { | 541 | if (bat_algo_ops_tmp) { |
542 | pr_info("Trying to register already registered routing algorithm: %s\n", | 542 | pr_info("Trying to register already registered routing algorithm: %s\n", |
543 | bat_algo_ops->name); | 543 | bat_algo_ops->name); |
544 | return -EEXIST; | 544 | return -EEXIST; |
545 | } | 545 | } |
546 | 546 | ||
547 | /* all algorithms must implement all ops (for now) */ | 547 | /* all algorithms must implement all ops (for now) */ |
548 | if (!bat_algo_ops->bat_iface_enable || | 548 | if (!bat_algo_ops->bat_iface_enable || |
549 | !bat_algo_ops->bat_iface_disable || | 549 | !bat_algo_ops->bat_iface_disable || |
550 | !bat_algo_ops->bat_iface_update_mac || | 550 | !bat_algo_ops->bat_iface_update_mac || |
551 | !bat_algo_ops->bat_primary_iface_set || | 551 | !bat_algo_ops->bat_primary_iface_set || |
552 | !bat_algo_ops->bat_ogm_schedule || | 552 | !bat_algo_ops->bat_ogm_schedule || |
553 | !bat_algo_ops->bat_ogm_emit || | 553 | !bat_algo_ops->bat_ogm_emit || |
554 | !bat_algo_ops->bat_neigh_cmp || | 554 | !bat_algo_ops->bat_neigh_cmp || |
555 | !bat_algo_ops->bat_neigh_is_similar_or_better) { | 555 | !bat_algo_ops->bat_neigh_is_similar_or_better) { |
556 | pr_info("Routing algo '%s' does not implement required ops\n", | 556 | pr_info("Routing algo '%s' does not implement required ops\n", |
557 | bat_algo_ops->name); | 557 | bat_algo_ops->name); |
558 | return -EINVAL; | 558 | return -EINVAL; |
559 | } | 559 | } |
560 | 560 | ||
561 | INIT_HLIST_NODE(&bat_algo_ops->list); | 561 | INIT_HLIST_NODE(&bat_algo_ops->list); |
562 | hlist_add_head(&bat_algo_ops->list, &batadv_algo_list); | 562 | hlist_add_head(&bat_algo_ops->list, &batadv_algo_list); |
563 | 563 | ||
564 | return 0; | 564 | return 0; |
565 | } | 565 | } |
566 | 566 | ||
567 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name) | 567 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name) |
568 | { | 568 | { |
569 | struct batadv_algo_ops *bat_algo_ops; | 569 | struct batadv_algo_ops *bat_algo_ops; |
570 | 570 | ||
571 | bat_algo_ops = batadv_algo_get(name); | 571 | bat_algo_ops = batadv_algo_get(name); |
572 | if (!bat_algo_ops) | 572 | if (!bat_algo_ops) |
573 | return -EINVAL; | 573 | return -EINVAL; |
574 | 574 | ||
575 | bat_priv->bat_algo_ops = bat_algo_ops; | 575 | bat_priv->bat_algo_ops = bat_algo_ops; |
576 | 576 | ||
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | 579 | ||
580 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset) | 580 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset) |
581 | { | 581 | { |
582 | struct batadv_algo_ops *bat_algo_ops; | 582 | struct batadv_algo_ops *bat_algo_ops; |
583 | 583 | ||
584 | seq_puts(seq, "Available routing algorithms:\n"); | 584 | seq_puts(seq, "Available routing algorithms:\n"); |
585 | 585 | ||
586 | hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) { | 586 | hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) { |
587 | seq_printf(seq, " * %s\n", bat_algo_ops->name); | 587 | seq_printf(seq, " * %s\n", bat_algo_ops->name); |
588 | } | 588 | } |
589 | 589 | ||
590 | return 0; | 590 | return 0; |
591 | } | 591 | } |
592 | 592 | ||
593 | /** | 593 | /** |
594 | * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in | 594 | * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in |
595 | * the header | 595 | * the header |
596 | * @skb: skb pointing to fragmented socket buffers | 596 | * @skb: skb pointing to fragmented socket buffers |
597 | * @payload_ptr: Pointer to position inside the head buffer of the skb | 597 | * @payload_ptr: Pointer to position inside the head buffer of the skb |
598 | * marking the start of the data to be CRC'ed | 598 | * marking the start of the data to be CRC'ed |
599 | * | 599 | * |
600 | * payload_ptr must always point to an address in the skb head buffer and not to | 600 | * payload_ptr must always point to an address in the skb head buffer and not to |
601 | * a fragment. | 601 | * a fragment. |
602 | */ | 602 | */ |
603 | __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr) | 603 | __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr) |
604 | { | 604 | { |
605 | u32 crc = 0; | 605 | u32 crc = 0; |
606 | unsigned int from; | 606 | unsigned int from; |
607 | unsigned int to = skb->len; | 607 | unsigned int to = skb->len; |
608 | struct skb_seq_state st; | 608 | struct skb_seq_state st; |
609 | const u8 *data; | 609 | const u8 *data; |
610 | unsigned int len; | 610 | unsigned int len; |
611 | unsigned int consumed = 0; | 611 | unsigned int consumed = 0; |
612 | 612 | ||
613 | from = (unsigned int)(payload_ptr - skb->data); | 613 | from = (unsigned int)(payload_ptr - skb->data); |
614 | 614 | ||
615 | skb_prepare_seq_read(skb, from, to, &st); | 615 | skb_prepare_seq_read(skb, from, to, &st); |
616 | while ((len = skb_seq_read(consumed, &data, &st)) != 0) { | 616 | while ((len = skb_seq_read(consumed, &data, &st)) != 0) { |
617 | crc = crc32c(crc, data, len); | 617 | crc = crc32c(crc, data, len); |
618 | consumed += len; | 618 | consumed += len; |
619 | } | 619 | } |
620 | 620 | ||
621 | return htonl(crc); | 621 | return htonl(crc); |
622 | } | 622 | } |
623 | 623 | ||
624 | /** | 624 | /** |
625 | * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and | 625 | * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and |
626 | * possibly free it | 626 | * possibly free it |
627 | * @tvlv_handler: the tvlv handler to free | 627 | * @tvlv_handler: the tvlv handler to free |
628 | */ | 628 | */ |
629 | static void | 629 | static void |
630 | batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler) | 630 | batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler) |
631 | { | 631 | { |
632 | if (atomic_dec_and_test(&tvlv_handler->refcount)) | 632 | if (atomic_dec_and_test(&tvlv_handler->refcount)) |
633 | kfree_rcu(tvlv_handler, rcu); | 633 | kfree_rcu(tvlv_handler, rcu); |
634 | } | 634 | } |
635 | 635 | ||
636 | /** | 636 | /** |
637 | * batadv_tvlv_handler_get - retrieve tvlv handler from the tvlv handler list | 637 | * batadv_tvlv_handler_get - retrieve tvlv handler from the tvlv handler list |
638 | * based on the provided type and version (both need to match) | 638 | * based on the provided type and version (both need to match) |
639 | * @bat_priv: the bat priv with all the soft interface information | 639 | * @bat_priv: the bat priv with all the soft interface information |
640 | * @type: tvlv handler type to look for | 640 | * @type: tvlv handler type to look for |
641 | * @version: tvlv handler version to look for | 641 | * @version: tvlv handler version to look for |
642 | * | 642 | * |
643 | * Returns tvlv handler if found or NULL otherwise. | 643 | * Returns tvlv handler if found or NULL otherwise. |
644 | */ | 644 | */ |
645 | static struct batadv_tvlv_handler | 645 | static struct batadv_tvlv_handler |
646 | *batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version) | 646 | *batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version) |
647 | { | 647 | { |
648 | struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL; | 648 | struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL; |
649 | 649 | ||
650 | rcu_read_lock(); | 650 | rcu_read_lock(); |
651 | hlist_for_each_entry_rcu(tvlv_handler_tmp, | 651 | hlist_for_each_entry_rcu(tvlv_handler_tmp, |
652 | &bat_priv->tvlv.handler_list, list) { | 652 | &bat_priv->tvlv.handler_list, list) { |
653 | if (tvlv_handler_tmp->type != type) | 653 | if (tvlv_handler_tmp->type != type) |
654 | continue; | 654 | continue; |
655 | 655 | ||
656 | if (tvlv_handler_tmp->version != version) | 656 | if (tvlv_handler_tmp->version != version) |
657 | continue; | 657 | continue; |
658 | 658 | ||
659 | if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount)) | 659 | if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount)) |
660 | continue; | 660 | continue; |
661 | 661 | ||
662 | tvlv_handler = tvlv_handler_tmp; | 662 | tvlv_handler = tvlv_handler_tmp; |
663 | break; | 663 | break; |
664 | } | 664 | } |
665 | rcu_read_unlock(); | 665 | rcu_read_unlock(); |
666 | 666 | ||
667 | return tvlv_handler; | 667 | return tvlv_handler; |
668 | } | 668 | } |
669 | 669 | ||
670 | /** | 670 | /** |
671 | * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and | 671 | * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and |
672 | * possibly free it | 672 | * possibly free it |
673 | * @tvlv: the tvlv container to free | 673 | * @tvlv: the tvlv container to free |
674 | */ | 674 | */ |
675 | static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv) | 675 | static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv) |
676 | { | 676 | { |
677 | if (atomic_dec_and_test(&tvlv->refcount)) | 677 | if (atomic_dec_and_test(&tvlv->refcount)) |
678 | kfree(tvlv); | 678 | kfree(tvlv); |
679 | } | 679 | } |
680 | 680 | ||
681 | /** | 681 | /** |
682 | * batadv_tvlv_container_get - retrieve tvlv container from the tvlv container | 682 | * batadv_tvlv_container_get - retrieve tvlv container from the tvlv container |
683 | * list based on the provided type and version (both need to match) | 683 | * list based on the provided type and version (both need to match) |
684 | * @bat_priv: the bat priv with all the soft interface information | 684 | * @bat_priv: the bat priv with all the soft interface information |
685 | * @type: tvlv container type to look for | 685 | * @type: tvlv container type to look for |
686 | * @version: tvlv container version to look for | 686 | * @version: tvlv container version to look for |
687 | * | 687 | * |
688 | * Has to be called with the appropriate locks being acquired | 688 | * Has to be called with the appropriate locks being acquired |
689 | * (tvlv.container_list_lock). | 689 | * (tvlv.container_list_lock). |
690 | * | 690 | * |
691 | * Returns tvlv container if found or NULL otherwise. | 691 | * Returns tvlv container if found or NULL otherwise. |
692 | */ | 692 | */ |
693 | static struct batadv_tvlv_container | 693 | static struct batadv_tvlv_container |
694 | *batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version) | 694 | *batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version) |
695 | { | 695 | { |
696 | struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL; | 696 | struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL; |
697 | 697 | ||
698 | hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) { | 698 | hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) { |
699 | if (tvlv_tmp->tvlv_hdr.type != type) | 699 | if (tvlv_tmp->tvlv_hdr.type != type) |
700 | continue; | 700 | continue; |
701 | 701 | ||
702 | if (tvlv_tmp->tvlv_hdr.version != version) | 702 | if (tvlv_tmp->tvlv_hdr.version != version) |
703 | continue; | 703 | continue; |
704 | 704 | ||
705 | if (!atomic_inc_not_zero(&tvlv_tmp->refcount)) | 705 | if (!atomic_inc_not_zero(&tvlv_tmp->refcount)) |
706 | continue; | 706 | continue; |
707 | 707 | ||
708 | tvlv = tvlv_tmp; | 708 | tvlv = tvlv_tmp; |
709 | break; | 709 | break; |
710 | } | 710 | } |
711 | 711 | ||
712 | return tvlv; | 712 | return tvlv; |
713 | } | 713 | } |
714 | 714 | ||
715 | /** | 715 | /** |
716 | * batadv_tvlv_container_list_size - calculate the size of the tvlv container | 716 | * batadv_tvlv_container_list_size - calculate the size of the tvlv container |
717 | * list entries | 717 | * list entries |
718 | * @bat_priv: the bat priv with all the soft interface information | 718 | * @bat_priv: the bat priv with all the soft interface information |
719 | * | 719 | * |
720 | * Has to be called with the appropriate locks being acquired | 720 | * Has to be called with the appropriate locks being acquired |
721 | * (tvlv.container_list_lock). | 721 | * (tvlv.container_list_lock). |
722 | * | 722 | * |
723 | * Returns size of all currently registered tvlv containers in bytes. | 723 | * Returns size of all currently registered tvlv containers in bytes. |
724 | */ | 724 | */ |
725 | static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) | 725 | static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) |
726 | { | 726 | { |
727 | struct batadv_tvlv_container *tvlv; | 727 | struct batadv_tvlv_container *tvlv; |
728 | u16 tvlv_len = 0; | 728 | u16 tvlv_len = 0; |
729 | 729 | ||
730 | hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { | 730 | hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { |
731 | tvlv_len += sizeof(struct batadv_tvlv_hdr); | 731 | tvlv_len += sizeof(struct batadv_tvlv_hdr); |
732 | tvlv_len += ntohs(tvlv->tvlv_hdr.len); | 732 | tvlv_len += ntohs(tvlv->tvlv_hdr.len); |
733 | } | 733 | } |
734 | 734 | ||
735 | return tvlv_len; | 735 | return tvlv_len; |
736 | } | 736 | } |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * batadv_tvlv_container_remove - remove tvlv container from the tvlv container | 739 | * batadv_tvlv_container_remove - remove tvlv container from the tvlv container |
740 | * list | 740 | * list |
741 | * @bat_priv: the bat priv with all the soft interface information | 741 | * @bat_priv: the bat priv with all the soft interface information |
742 | * @tvlv: the to be removed tvlv container | 742 | * @tvlv: the to be removed tvlv container |
743 | * | 743 | * |
744 | * Has to be called with the appropriate locks being acquired | 744 | * Has to be called with the appropriate locks being acquired |
745 | * (tvlv.container_list_lock). | 745 | * (tvlv.container_list_lock). |
746 | */ | 746 | */ |
747 | static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv, | 747 | static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv, |
748 | struct batadv_tvlv_container *tvlv) | 748 | struct batadv_tvlv_container *tvlv) |
749 | { | 749 | { |
750 | lockdep_assert_held(&bat_priv->tvlv.container_list_lock); | 750 | lockdep_assert_held(&bat_priv->tvlv.container_list_lock); |
751 | 751 | ||
752 | if (!tvlv) | 752 | if (!tvlv) |
753 | return; | 753 | return; |
754 | 754 | ||
755 | hlist_del(&tvlv->list); | 755 | hlist_del(&tvlv->list); |
756 | 756 | ||
757 | /* first call to decrement the counter, second call to free */ | 757 | /* first call to decrement the counter, second call to free */ |
758 | batadv_tvlv_container_free_ref(tvlv); | 758 | batadv_tvlv_container_free_ref(tvlv); |
759 | batadv_tvlv_container_free_ref(tvlv); | 759 | batadv_tvlv_container_free_ref(tvlv); |
760 | } | 760 | } |
761 | 761 | ||
762 | /** | 762 | /** |
763 | * batadv_tvlv_container_unregister - unregister tvlv container based on the | 763 | * batadv_tvlv_container_unregister - unregister tvlv container based on the |
764 | * provided type and version (both need to match) | 764 | * provided type and version (both need to match) |
765 | * @bat_priv: the bat priv with all the soft interface information | 765 | * @bat_priv: the bat priv with all the soft interface information |
766 | * @type: tvlv container type to unregister | 766 | * @type: tvlv container type to unregister |
767 | * @version: tvlv container type to unregister | 767 | * @version: tvlv container type to unregister |
768 | */ | 768 | */ |
769 | void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, | 769 | void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, |
770 | u8 type, u8 version) | 770 | u8 type, u8 version) |
771 | { | 771 | { |
772 | struct batadv_tvlv_container *tvlv; | 772 | struct batadv_tvlv_container *tvlv; |
773 | 773 | ||
774 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); | 774 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); |
775 | tvlv = batadv_tvlv_container_get(bat_priv, type, version); | 775 | tvlv = batadv_tvlv_container_get(bat_priv, type, version); |
776 | batadv_tvlv_container_remove(bat_priv, tvlv); | 776 | batadv_tvlv_container_remove(bat_priv, tvlv); |
777 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); | 777 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); |
778 | } | 778 | } |
779 | 779 | ||
780 | /** | 780 | /** |
781 | * batadv_tvlv_container_register - register tvlv type, version and content | 781 | * batadv_tvlv_container_register - register tvlv type, version and content |
782 | * to be propagated with each (primary interface) OGM | 782 | * to be propagated with each (primary interface) OGM |
783 | * @bat_priv: the bat priv with all the soft interface information | 783 | * @bat_priv: the bat priv with all the soft interface information |
784 | * @type: tvlv container type | 784 | * @type: tvlv container type |
785 | * @version: tvlv container version | 785 | * @version: tvlv container version |
786 | * @tvlv_value: tvlv container content | 786 | * @tvlv_value: tvlv container content |
787 | * @tvlv_value_len: tvlv container content length | 787 | * @tvlv_value_len: tvlv container content length |
788 | * | 788 | * |
789 | * If a container of the same type and version was already registered the new | 789 | * If a container of the same type and version was already registered the new |
790 | * content is going to replace the old one. | 790 | * content is going to replace the old one. |
791 | */ | 791 | */ |
792 | void batadv_tvlv_container_register(struct batadv_priv *bat_priv, | 792 | void batadv_tvlv_container_register(struct batadv_priv *bat_priv, |
793 | u8 type, u8 version, | 793 | u8 type, u8 version, |
794 | void *tvlv_value, u16 tvlv_value_len) | 794 | void *tvlv_value, u16 tvlv_value_len) |
795 | { | 795 | { |
796 | struct batadv_tvlv_container *tvlv_old, *tvlv_new; | 796 | struct batadv_tvlv_container *tvlv_old, *tvlv_new; |
797 | 797 | ||
798 | if (!tvlv_value) | 798 | if (!tvlv_value) |
799 | tvlv_value_len = 0; | 799 | tvlv_value_len = 0; |
800 | 800 | ||
801 | tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC); | 801 | tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC); |
802 | if (!tvlv_new) | 802 | if (!tvlv_new) |
803 | return; | 803 | return; |
804 | 804 | ||
805 | tvlv_new->tvlv_hdr.version = version; | 805 | tvlv_new->tvlv_hdr.version = version; |
806 | tvlv_new->tvlv_hdr.type = type; | 806 | tvlv_new->tvlv_hdr.type = type; |
807 | tvlv_new->tvlv_hdr.len = htons(tvlv_value_len); | 807 | tvlv_new->tvlv_hdr.len = htons(tvlv_value_len); |
808 | 808 | ||
809 | memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len)); | 809 | memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len)); |
810 | INIT_HLIST_NODE(&tvlv_new->list); | 810 | INIT_HLIST_NODE(&tvlv_new->list); |
811 | atomic_set(&tvlv_new->refcount, 1); | 811 | atomic_set(&tvlv_new->refcount, 1); |
812 | 812 | ||
813 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); | 813 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); |
814 | tvlv_old = batadv_tvlv_container_get(bat_priv, type, version); | 814 | tvlv_old = batadv_tvlv_container_get(bat_priv, type, version); |
815 | batadv_tvlv_container_remove(bat_priv, tvlv_old); | 815 | batadv_tvlv_container_remove(bat_priv, tvlv_old); |
816 | hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list); | 816 | hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list); |
817 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); | 817 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); |
818 | } | 818 | } |
819 | 819 | ||
820 | /** | 820 | /** |
821 | * batadv_tvlv_realloc_packet_buff - reallocate packet buffer to accommodate | 821 | * batadv_tvlv_realloc_packet_buff - reallocate packet buffer to accommodate |
822 | * requested packet size | 822 | * requested packet size |
823 | * @packet_buff: packet buffer | 823 | * @packet_buff: packet buffer |
824 | * @packet_buff_len: packet buffer size | 824 | * @packet_buff_len: packet buffer size |
825 | * @min_packet_len: requested packet minimum size | 825 | * @min_packet_len: requested packet minimum size |
826 | * @additional_packet_len: requested additional packet size on top of minimum | 826 | * @additional_packet_len: requested additional packet size on top of minimum |
827 | * size | 827 | * size |
828 | * | 828 | * |
829 | * Returns true of the packet buffer could be changed to the requested size, | 829 | * Returns true of the packet buffer could be changed to the requested size, |
830 | * false otherwise. | 830 | * false otherwise. |
831 | */ | 831 | */ |
832 | static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff, | 832 | static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff, |
833 | int *packet_buff_len, | 833 | int *packet_buff_len, |
834 | int min_packet_len, | 834 | int min_packet_len, |
835 | int additional_packet_len) | 835 | int additional_packet_len) |
836 | { | 836 | { |
837 | unsigned char *new_buff; | 837 | unsigned char *new_buff; |
838 | 838 | ||
839 | new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC); | 839 | new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC); |
840 | 840 | ||
841 | /* keep old buffer if kmalloc should fail */ | 841 | /* keep old buffer if kmalloc should fail */ |
842 | if (!new_buff) | 842 | if (!new_buff) |
843 | return false; | 843 | return false; |
844 | 844 | ||
845 | memcpy(new_buff, *packet_buff, min_packet_len); | 845 | memcpy(new_buff, *packet_buff, min_packet_len); |
846 | kfree(*packet_buff); | 846 | kfree(*packet_buff); |
847 | *packet_buff = new_buff; | 847 | *packet_buff = new_buff; |
848 | *packet_buff_len = min_packet_len + additional_packet_len; | 848 | *packet_buff_len = min_packet_len + additional_packet_len; |
849 | 849 | ||
850 | return true; | 850 | return true; |
851 | } | 851 | } |
852 | 852 | ||
853 | /** | 853 | /** |
854 | * batadv_tvlv_container_ogm_append - append tvlv container content to given | 854 | * batadv_tvlv_container_ogm_append - append tvlv container content to given |
855 | * OGM packet buffer | 855 | * OGM packet buffer |
856 | * @bat_priv: the bat priv with all the soft interface information | 856 | * @bat_priv: the bat priv with all the soft interface information |
857 | * @packet_buff: ogm packet buffer | 857 | * @packet_buff: ogm packet buffer |
858 | * @packet_buff_len: ogm packet buffer size including ogm header and tvlv | 858 | * @packet_buff_len: ogm packet buffer size including ogm header and tvlv |
859 | * content | 859 | * content |
860 | * @packet_min_len: ogm header size to be preserved for the OGM itself | 860 | * @packet_min_len: ogm header size to be preserved for the OGM itself |
861 | * | 861 | * |
862 | * The ogm packet might be enlarged or shrunk depending on the current size | 862 | * The ogm packet might be enlarged or shrunk depending on the current size |
863 | * and the size of the to-be-appended tvlv containers. | 863 | * and the size of the to-be-appended tvlv containers. |
864 | * | 864 | * |
865 | * Returns size of all appended tvlv containers in bytes. | 865 | * Returns size of all appended tvlv containers in bytes. |
866 | */ | 866 | */ |
867 | u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, | 867 | u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, |
868 | unsigned char **packet_buff, | 868 | unsigned char **packet_buff, |
869 | int *packet_buff_len, int packet_min_len) | 869 | int *packet_buff_len, int packet_min_len) |
870 | { | 870 | { |
871 | struct batadv_tvlv_container *tvlv; | 871 | struct batadv_tvlv_container *tvlv; |
872 | struct batadv_tvlv_hdr *tvlv_hdr; | 872 | struct batadv_tvlv_hdr *tvlv_hdr; |
873 | u16 tvlv_value_len; | 873 | u16 tvlv_value_len; |
874 | void *tvlv_value; | 874 | void *tvlv_value; |
875 | bool ret; | 875 | bool ret; |
876 | 876 | ||
877 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); | 877 | spin_lock_bh(&bat_priv->tvlv.container_list_lock); |
878 | tvlv_value_len = batadv_tvlv_container_list_size(bat_priv); | 878 | tvlv_value_len = batadv_tvlv_container_list_size(bat_priv); |
879 | 879 | ||
880 | ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len, | 880 | ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len, |
881 | packet_min_len, tvlv_value_len); | 881 | packet_min_len, tvlv_value_len); |
882 | 882 | ||
883 | if (!ret) | 883 | if (!ret) |
884 | goto end; | 884 | goto end; |
885 | 885 | ||
886 | if (!tvlv_value_len) | 886 | if (!tvlv_value_len) |
887 | goto end; | 887 | goto end; |
888 | 888 | ||
889 | tvlv_value = (*packet_buff) + packet_min_len; | 889 | tvlv_value = (*packet_buff) + packet_min_len; |
890 | 890 | ||
891 | hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { | 891 | hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { |
892 | tvlv_hdr = tvlv_value; | 892 | tvlv_hdr = tvlv_value; |
893 | tvlv_hdr->type = tvlv->tvlv_hdr.type; | 893 | tvlv_hdr->type = tvlv->tvlv_hdr.type; |
894 | tvlv_hdr->version = tvlv->tvlv_hdr.version; | 894 | tvlv_hdr->version = tvlv->tvlv_hdr.version; |
895 | tvlv_hdr->len = tvlv->tvlv_hdr.len; | 895 | tvlv_hdr->len = tvlv->tvlv_hdr.len; |
896 | tvlv_value = tvlv_hdr + 1; | 896 | tvlv_value = tvlv_hdr + 1; |
897 | memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len)); | 897 | memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len)); |
898 | tvlv_value = (u8 *)tvlv_value + ntohs(tvlv->tvlv_hdr.len); | 898 | tvlv_value = (u8 *)tvlv_value + ntohs(tvlv->tvlv_hdr.len); |
899 | } | 899 | } |
900 | 900 | ||
901 | end: | 901 | end: |
902 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); | 902 | spin_unlock_bh(&bat_priv->tvlv.container_list_lock); |
903 | return tvlv_value_len; | 903 | return tvlv_value_len; |
904 | } | 904 | } |
905 | 905 | ||
906 | /** | 906 | /** |
907 | * batadv_tvlv_call_handler - parse the given tvlv buffer to call the | 907 | * batadv_tvlv_call_handler - parse the given tvlv buffer to call the |
908 | * appropriate handlers | 908 | * appropriate handlers |
909 | * @bat_priv: the bat priv with all the soft interface information | 909 | * @bat_priv: the bat priv with all the soft interface information |
910 | * @tvlv_handler: tvlv callback function handling the tvlv content | 910 | * @tvlv_handler: tvlv callback function handling the tvlv content |
911 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet | 911 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet |
912 | * @orig_node: orig node emitting the ogm packet | 912 | * @orig_node: orig node emitting the ogm packet |
913 | * @src: source mac address of the unicast packet | 913 | * @src: source mac address of the unicast packet |
914 | * @dst: destination mac address of the unicast packet | 914 | * @dst: destination mac address of the unicast packet |
915 | * @tvlv_value: tvlv content | 915 | * @tvlv_value: tvlv content |
916 | * @tvlv_value_len: tvlv content length | 916 | * @tvlv_value_len: tvlv content length |
917 | * | 917 | * |
918 | * Returns success if handler was not found or the return value of the handler | 918 | * Returns success if handler was not found or the return value of the handler |
919 | * callback. | 919 | * callback. |
920 | */ | 920 | */ |
921 | static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, | 921 | static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, |
922 | struct batadv_tvlv_handler *tvlv_handler, | 922 | struct batadv_tvlv_handler *tvlv_handler, |
923 | bool ogm_source, | 923 | bool ogm_source, |
924 | struct batadv_orig_node *orig_node, | 924 | struct batadv_orig_node *orig_node, |
925 | u8 *src, u8 *dst, | 925 | u8 *src, u8 *dst, |
926 | void *tvlv_value, u16 tvlv_value_len) | 926 | void *tvlv_value, u16 tvlv_value_len) |
927 | { | 927 | { |
928 | if (!tvlv_handler) | 928 | if (!tvlv_handler) |
929 | return NET_RX_SUCCESS; | 929 | return NET_RX_SUCCESS; |
930 | 930 | ||
931 | if (ogm_source) { | 931 | if (ogm_source) { |
932 | if (!tvlv_handler->ogm_handler) | 932 | if (!tvlv_handler->ogm_handler) |
933 | return NET_RX_SUCCESS; | 933 | return NET_RX_SUCCESS; |
934 | 934 | ||
935 | if (!orig_node) | 935 | if (!orig_node) |
936 | return NET_RX_SUCCESS; | 936 | return NET_RX_SUCCESS; |
937 | 937 | ||
938 | tvlv_handler->ogm_handler(bat_priv, orig_node, | 938 | tvlv_handler->ogm_handler(bat_priv, orig_node, |
939 | BATADV_NO_FLAGS, | 939 | BATADV_NO_FLAGS, |
940 | tvlv_value, tvlv_value_len); | 940 | tvlv_value, tvlv_value_len); |
941 | tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED; | 941 | tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED; |
942 | } else { | 942 | } else { |
943 | if (!src) | 943 | if (!src) |
944 | return NET_RX_SUCCESS; | 944 | return NET_RX_SUCCESS; |
945 | 945 | ||
946 | if (!dst) | 946 | if (!dst) |
947 | return NET_RX_SUCCESS; | 947 | return NET_RX_SUCCESS; |
948 | 948 | ||
949 | if (!tvlv_handler->unicast_handler) | 949 | if (!tvlv_handler->unicast_handler) |
950 | return NET_RX_SUCCESS; | 950 | return NET_RX_SUCCESS; |
951 | 951 | ||
952 | return tvlv_handler->unicast_handler(bat_priv, src, | 952 | return tvlv_handler->unicast_handler(bat_priv, src, |
953 | dst, tvlv_value, | 953 | dst, tvlv_value, |
954 | tvlv_value_len); | 954 | tvlv_value_len); |
955 | } | 955 | } |
956 | 956 | ||
957 | return NET_RX_SUCCESS; | 957 | return NET_RX_SUCCESS; |
958 | } | 958 | } |
959 | 959 | ||
960 | /** | 960 | /** |
961 | * batadv_tvlv_containers_process - parse the given tvlv buffer to call the | 961 | * batadv_tvlv_containers_process - parse the given tvlv buffer to call the |
962 | * appropriate handlers | 962 | * appropriate handlers |
963 | * @bat_priv: the bat priv with all the soft interface information | 963 | * @bat_priv: the bat priv with all the soft interface information |
964 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet | 964 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet |
965 | * @orig_node: orig node emitting the ogm packet | 965 | * @orig_node: orig node emitting the ogm packet |
966 | * @src: source mac address of the unicast packet | 966 | * @src: source mac address of the unicast packet |
967 | * @dst: destination mac address of the unicast packet | 967 | * @dst: destination mac address of the unicast packet |
968 | * @tvlv_value: tvlv content | 968 | * @tvlv_value: tvlv content |
969 | * @tvlv_value_len: tvlv content length | 969 | * @tvlv_value_len: tvlv content length |
970 | * | 970 | * |
971 | * Returns success when processing an OGM or the return value of all called | 971 | * Returns success when processing an OGM or the return value of all called |
972 | * handler callbacks. | 972 | * handler callbacks. |
973 | */ | 973 | */ |
974 | int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, | 974 | int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, |
975 | bool ogm_source, | 975 | bool ogm_source, |
976 | struct batadv_orig_node *orig_node, | 976 | struct batadv_orig_node *orig_node, |
977 | u8 *src, u8 *dst, | 977 | u8 *src, u8 *dst, |
978 | void *tvlv_value, u16 tvlv_value_len) | 978 | void *tvlv_value, u16 tvlv_value_len) |
979 | { | 979 | { |
980 | struct batadv_tvlv_handler *tvlv_handler; | 980 | struct batadv_tvlv_handler *tvlv_handler; |
981 | struct batadv_tvlv_hdr *tvlv_hdr; | 981 | struct batadv_tvlv_hdr *tvlv_hdr; |
982 | u16 tvlv_value_cont_len; | 982 | u16 tvlv_value_cont_len; |
983 | u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND; | 983 | u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND; |
984 | int ret = NET_RX_SUCCESS; | 984 | int ret = NET_RX_SUCCESS; |
985 | 985 | ||
986 | while (tvlv_value_len >= sizeof(*tvlv_hdr)) { | 986 | while (tvlv_value_len >= sizeof(*tvlv_hdr)) { |
987 | tvlv_hdr = tvlv_value; | 987 | tvlv_hdr = tvlv_value; |
988 | tvlv_value_cont_len = ntohs(tvlv_hdr->len); | 988 | tvlv_value_cont_len = ntohs(tvlv_hdr->len); |
989 | tvlv_value = tvlv_hdr + 1; | 989 | tvlv_value = tvlv_hdr + 1; |
990 | tvlv_value_len -= sizeof(*tvlv_hdr); | 990 | tvlv_value_len -= sizeof(*tvlv_hdr); |
991 | 991 | ||
992 | if (tvlv_value_cont_len > tvlv_value_len) | 992 | if (tvlv_value_cont_len > tvlv_value_len) |
993 | break; | 993 | break; |
994 | 994 | ||
995 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, | 995 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, |
996 | tvlv_hdr->type, | 996 | tvlv_hdr->type, |
997 | tvlv_hdr->version); | 997 | tvlv_hdr->version); |
998 | 998 | ||
999 | ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler, | 999 | ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler, |
1000 | ogm_source, orig_node, | 1000 | ogm_source, orig_node, |
1001 | src, dst, tvlv_value, | 1001 | src, dst, tvlv_value, |
1002 | tvlv_value_cont_len); | 1002 | tvlv_value_cont_len); |
1003 | if (tvlv_handler) | 1003 | if (tvlv_handler) |
1004 | batadv_tvlv_handler_free_ref(tvlv_handler); | 1004 | batadv_tvlv_handler_free_ref(tvlv_handler); |
1005 | tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len; | 1005 | tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len; |
1006 | tvlv_value_len -= tvlv_value_cont_len; | 1006 | tvlv_value_len -= tvlv_value_cont_len; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | if (!ogm_source) | 1009 | if (!ogm_source) |
1010 | return ret; | 1010 | return ret; |
1011 | 1011 | ||
1012 | rcu_read_lock(); | 1012 | rcu_read_lock(); |
1013 | hlist_for_each_entry_rcu(tvlv_handler, | 1013 | hlist_for_each_entry_rcu(tvlv_handler, |
1014 | &bat_priv->tvlv.handler_list, list) { | 1014 | &bat_priv->tvlv.handler_list, list) { |
1015 | if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) && | 1015 | if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) && |
1016 | !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED)) | 1016 | !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED)) |
1017 | tvlv_handler->ogm_handler(bat_priv, orig_node, | 1017 | tvlv_handler->ogm_handler(bat_priv, orig_node, |
1018 | cifnotfound, NULL, 0); | 1018 | cifnotfound, NULL, 0); |
1019 | 1019 | ||
1020 | tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED; | 1020 | tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED; |
1021 | } | 1021 | } |
1022 | rcu_read_unlock(); | 1022 | rcu_read_unlock(); |
1023 | 1023 | ||
1024 | return NET_RX_SUCCESS; | 1024 | return NET_RX_SUCCESS; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /** | 1027 | /** |
1028 | * batadv_tvlv_ogm_receive - process an incoming ogm and call the appropriate | 1028 | * batadv_tvlv_ogm_receive - process an incoming ogm and call the appropriate |
1029 | * handlers | 1029 | * handlers |
1030 | * @bat_priv: the bat priv with all the soft interface information | 1030 | * @bat_priv: the bat priv with all the soft interface information |
1031 | * @batadv_ogm_packet: ogm packet containing the tvlv containers | 1031 | * @batadv_ogm_packet: ogm packet containing the tvlv containers |
1032 | * @orig_node: orig node emitting the ogm packet | 1032 | * @orig_node: orig node emitting the ogm packet |
1033 | */ | 1033 | */ |
1034 | void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, | 1034 | void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, |
1035 | struct batadv_ogm_packet *batadv_ogm_packet, | 1035 | struct batadv_ogm_packet *batadv_ogm_packet, |
1036 | struct batadv_orig_node *orig_node) | 1036 | struct batadv_orig_node *orig_node) |
1037 | { | 1037 | { |
1038 | void *tvlv_value; | 1038 | void *tvlv_value; |
1039 | u16 tvlv_value_len; | 1039 | u16 tvlv_value_len; |
1040 | 1040 | ||
1041 | if (!batadv_ogm_packet) | 1041 | if (!batadv_ogm_packet) |
1042 | return; | 1042 | return; |
1043 | 1043 | ||
1044 | tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len); | 1044 | tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len); |
1045 | if (!tvlv_value_len) | 1045 | if (!tvlv_value_len) |
1046 | return; | 1046 | return; |
1047 | 1047 | ||
1048 | tvlv_value = batadv_ogm_packet + 1; | 1048 | tvlv_value = batadv_ogm_packet + 1; |
1049 | 1049 | ||
1050 | batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL, | 1050 | batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL, |
1051 | tvlv_value, tvlv_value_len); | 1051 | tvlv_value, tvlv_value_len); |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | /** | 1054 | /** |
1055 | * batadv_tvlv_handler_register - register tvlv handler based on the provided | 1055 | * batadv_tvlv_handler_register - register tvlv handler based on the provided |
1056 | * type and version (both need to match) for ogm tvlv payload and/or unicast | 1056 | * type and version (both need to match) for ogm tvlv payload and/or unicast |
1057 | * payload | 1057 | * payload |
1058 | * @bat_priv: the bat priv with all the soft interface information | 1058 | * @bat_priv: the bat priv with all the soft interface information |
1059 | * @optr: ogm tvlv handler callback function. This function receives the orig | 1059 | * @optr: ogm tvlv handler callback function. This function receives the orig |
1060 | * node, flags and the tvlv content as argument to process. | 1060 | * node, flags and the tvlv content as argument to process. |
1061 | * @uptr: unicast tvlv handler callback function. This function receives the | 1061 | * @uptr: unicast tvlv handler callback function. This function receives the |
1062 | * source & destination of the unicast packet as well as the tvlv content | 1062 | * source & destination of the unicast packet as well as the tvlv content |
1063 | * to process. | 1063 | * to process. |
1064 | * @type: tvlv handler type to be registered | 1064 | * @type: tvlv handler type to be registered |
1065 | * @version: tvlv handler version to be registered | 1065 | * @version: tvlv handler version to be registered |
1066 | * @flags: flags to enable or disable TVLV API behavior | 1066 | * @flags: flags to enable or disable TVLV API behavior |
1067 | */ | 1067 | */ |
1068 | void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, | 1068 | void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, |
1069 | void (*optr)(struct batadv_priv *bat_priv, | 1069 | void (*optr)(struct batadv_priv *bat_priv, |
1070 | struct batadv_orig_node *orig, | 1070 | struct batadv_orig_node *orig, |
1071 | u8 flags, | 1071 | u8 flags, |
1072 | void *tvlv_value, | 1072 | void *tvlv_value, |
1073 | u16 tvlv_value_len), | 1073 | u16 tvlv_value_len), |
1074 | int (*uptr)(struct batadv_priv *bat_priv, | 1074 | int (*uptr)(struct batadv_priv *bat_priv, |
1075 | u8 *src, u8 *dst, | 1075 | u8 *src, u8 *dst, |
1076 | void *tvlv_value, | 1076 | void *tvlv_value, |
1077 | u16 tvlv_value_len), | 1077 | u16 tvlv_value_len), |
1078 | u8 type, u8 version, u8 flags) | 1078 | u8 type, u8 version, u8 flags) |
1079 | { | 1079 | { |
1080 | struct batadv_tvlv_handler *tvlv_handler; | 1080 | struct batadv_tvlv_handler *tvlv_handler; |
1081 | 1081 | ||
1082 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); | 1082 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); |
1083 | if (tvlv_handler) { | 1083 | if (tvlv_handler) { |
1084 | batadv_tvlv_handler_free_ref(tvlv_handler); | 1084 | batadv_tvlv_handler_free_ref(tvlv_handler); |
1085 | return; | 1085 | return; |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC); | 1088 | tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC); |
1089 | if (!tvlv_handler) | 1089 | if (!tvlv_handler) |
1090 | return; | 1090 | return; |
1091 | 1091 | ||
1092 | tvlv_handler->ogm_handler = optr; | 1092 | tvlv_handler->ogm_handler = optr; |
1093 | tvlv_handler->unicast_handler = uptr; | 1093 | tvlv_handler->unicast_handler = uptr; |
1094 | tvlv_handler->type = type; | 1094 | tvlv_handler->type = type; |
1095 | tvlv_handler->version = version; | 1095 | tvlv_handler->version = version; |
1096 | tvlv_handler->flags = flags; | 1096 | tvlv_handler->flags = flags; |
1097 | atomic_set(&tvlv_handler->refcount, 1); | 1097 | atomic_set(&tvlv_handler->refcount, 1); |
1098 | INIT_HLIST_NODE(&tvlv_handler->list); | 1098 | INIT_HLIST_NODE(&tvlv_handler->list); |
1099 | 1099 | ||
1100 | spin_lock_bh(&bat_priv->tvlv.handler_list_lock); | 1100 | spin_lock_bh(&bat_priv->tvlv.handler_list_lock); |
1101 | hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list); | 1101 | hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list); |
1102 | spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); | 1102 | spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | /** | 1105 | /** |
1106 | * batadv_tvlv_handler_unregister - unregister tvlv handler based on the | 1106 | * batadv_tvlv_handler_unregister - unregister tvlv handler based on the |
1107 | * provided type and version (both need to match) | 1107 | * provided type and version (both need to match) |
1108 | * @bat_priv: the bat priv with all the soft interface information | 1108 | * @bat_priv: the bat priv with all the soft interface information |
1109 | * @type: tvlv handler type to be unregistered | 1109 | * @type: tvlv handler type to be unregistered |
1110 | * @version: tvlv handler version to be unregistered | 1110 | * @version: tvlv handler version to be unregistered |
1111 | */ | 1111 | */ |
1112 | void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, | 1112 | void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, |
1113 | u8 type, u8 version) | 1113 | u8 type, u8 version) |
1114 | { | 1114 | { |
1115 | struct batadv_tvlv_handler *tvlv_handler; | 1115 | struct batadv_tvlv_handler *tvlv_handler; |
1116 | 1116 | ||
1117 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); | 1117 | tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); |
1118 | if (!tvlv_handler) | 1118 | if (!tvlv_handler) |
1119 | return; | 1119 | return; |
1120 | 1120 | ||
1121 | batadv_tvlv_handler_free_ref(tvlv_handler); | 1121 | batadv_tvlv_handler_free_ref(tvlv_handler); |
1122 | spin_lock_bh(&bat_priv->tvlv.handler_list_lock); | 1122 | spin_lock_bh(&bat_priv->tvlv.handler_list_lock); |
1123 | hlist_del_rcu(&tvlv_handler->list); | 1123 | hlist_del_rcu(&tvlv_handler->list); |
1124 | spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); | 1124 | spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); |
1125 | batadv_tvlv_handler_free_ref(tvlv_handler); | 1125 | batadv_tvlv_handler_free_ref(tvlv_handler); |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | /** | 1128 | /** |
1129 | * batadv_tvlv_unicast_send - send a unicast packet with tvlv payload to the | 1129 | * batadv_tvlv_unicast_send - send a unicast packet with tvlv payload to the |
1130 | * specified host | 1130 | * specified host |
1131 | * @bat_priv: the bat priv with all the soft interface information | 1131 | * @bat_priv: the bat priv with all the soft interface information |
1132 | * @src: source mac address of the unicast packet | 1132 | * @src: source mac address of the unicast packet |
1133 | * @dst: destination mac address of the unicast packet | 1133 | * @dst: destination mac address of the unicast packet |
1134 | * @type: tvlv type | 1134 | * @type: tvlv type |
1135 | * @version: tvlv version | 1135 | * @version: tvlv version |
1136 | * @tvlv_value: tvlv content | 1136 | * @tvlv_value: tvlv content |
1137 | * @tvlv_value_len: tvlv content length | 1137 | * @tvlv_value_len: tvlv content length |
1138 | */ | 1138 | */ |
1139 | void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src, | 1139 | void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src, |
1140 | u8 *dst, u8 type, u8 version, | 1140 | u8 *dst, u8 type, u8 version, |
1141 | void *tvlv_value, u16 tvlv_value_len) | 1141 | void *tvlv_value, u16 tvlv_value_len) |
1142 | { | 1142 | { |
1143 | struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; | 1143 | struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; |
1144 | struct batadv_tvlv_hdr *tvlv_hdr; | 1144 | struct batadv_tvlv_hdr *tvlv_hdr; |
1145 | struct batadv_orig_node *orig_node; | 1145 | struct batadv_orig_node *orig_node; |
1146 | struct sk_buff *skb = NULL; | 1146 | struct sk_buff *skb = NULL; |
1147 | unsigned char *tvlv_buff; | 1147 | unsigned char *tvlv_buff; |
1148 | unsigned int tvlv_len; | 1148 | unsigned int tvlv_len; |
1149 | ssize_t hdr_len = sizeof(*unicast_tvlv_packet); | 1149 | ssize_t hdr_len = sizeof(*unicast_tvlv_packet); |
1150 | bool ret = false; | 1150 | bool ret = false; |
1151 | 1151 | ||
1152 | orig_node = batadv_orig_hash_find(bat_priv, dst); | 1152 | orig_node = batadv_orig_hash_find(bat_priv, dst); |
1153 | if (!orig_node) | 1153 | if (!orig_node) |
1154 | goto out; | 1154 | goto out; |
1155 | 1155 | ||
1156 | tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len; | 1156 | tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len; |
1157 | 1157 | ||
1158 | skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len); | 1158 | skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len); |
1159 | if (!skb) | 1159 | if (!skb) |
1160 | goto out; | 1160 | goto out; |
1161 | 1161 | ||
1162 | skb->priority = TC_PRIO_CONTROL; | 1162 | skb->priority = TC_PRIO_CONTROL; |
1163 | skb_reserve(skb, ETH_HLEN); | 1163 | skb_reserve(skb, ETH_HLEN); |
1164 | tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len); | 1164 | tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len); |
1165 | unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff; | 1165 | unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff; |
1166 | unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV; | 1166 | unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV; |
1167 | unicast_tvlv_packet->version = BATADV_COMPAT_VERSION; | 1167 | unicast_tvlv_packet->version = BATADV_COMPAT_VERSION; |
1168 | unicast_tvlv_packet->ttl = BATADV_TTL; | 1168 | unicast_tvlv_packet->ttl = BATADV_TTL; |
1169 | unicast_tvlv_packet->reserved = 0; | 1169 | unicast_tvlv_packet->reserved = 0; |
1170 | unicast_tvlv_packet->tvlv_len = htons(tvlv_len); | 1170 | unicast_tvlv_packet->tvlv_len = htons(tvlv_len); |
1171 | unicast_tvlv_packet->align = 0; | 1171 | unicast_tvlv_packet->align = 0; |
1172 | ether_addr_copy(unicast_tvlv_packet->src, src); | 1172 | ether_addr_copy(unicast_tvlv_packet->src, src); |
1173 | ether_addr_copy(unicast_tvlv_packet->dst, dst); | 1173 | ether_addr_copy(unicast_tvlv_packet->dst, dst); |
1174 | 1174 | ||
1175 | tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); | 1175 | tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); |
1176 | tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; | 1176 | tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; |
1177 | tvlv_hdr->version = version; | 1177 | tvlv_hdr->version = version; |
1178 | tvlv_hdr->type = type; | 1178 | tvlv_hdr->type = type; |
1179 | tvlv_hdr->len = htons(tvlv_value_len); | 1179 | tvlv_hdr->len = htons(tvlv_value_len); |
1180 | tvlv_buff += sizeof(*tvlv_hdr); | 1180 | tvlv_buff += sizeof(*tvlv_hdr); |
1181 | memcpy(tvlv_buff, tvlv_value, tvlv_value_len); | 1181 | memcpy(tvlv_buff, tvlv_value, tvlv_value_len); |
1182 | 1182 | ||
1183 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) | 1183 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) |
1184 | ret = true; | 1184 | ret = true; |
1185 | 1185 | ||
1186 | out: | 1186 | out: |
1187 | if (skb && !ret) | 1187 | if (!ret) |
1188 | kfree_skb(skb); | 1188 | kfree_skb(skb); |
1189 | if (orig_node) | 1189 | if (orig_node) |
1190 | batadv_orig_node_free_ref(orig_node); | 1190 | batadv_orig_node_free_ref(orig_node); |
1191 | } | 1191 | } |
1192 | 1192 | ||
1193 | /** | 1193 | /** |
1194 | * batadv_get_vid - extract the VLAN identifier from skb if any | 1194 | * batadv_get_vid - extract the VLAN identifier from skb if any |
1195 | * @skb: the buffer containing the packet | 1195 | * @skb: the buffer containing the packet |
1196 | * @header_len: length of the batman header preceding the ethernet header | 1196 | * @header_len: length of the batman header preceding the ethernet header |
1197 | * | 1197 | * |
1198 | * If the packet embedded in the skb is vlan tagged this function returns the | 1198 | * If the packet embedded in the skb is vlan tagged this function returns the |
1199 | * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned. | 1199 | * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned. |
1200 | */ | 1200 | */ |
1201 | unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len) | 1201 | unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len) |
1202 | { | 1202 | { |
1203 | struct ethhdr *ethhdr = (struct ethhdr *)(skb->data + header_len); | 1203 | struct ethhdr *ethhdr = (struct ethhdr *)(skb->data + header_len); |
1204 | struct vlan_ethhdr *vhdr; | 1204 | struct vlan_ethhdr *vhdr; |
1205 | unsigned short vid; | 1205 | unsigned short vid; |
1206 | 1206 | ||
1207 | if (ethhdr->h_proto != htons(ETH_P_8021Q)) | 1207 | if (ethhdr->h_proto != htons(ETH_P_8021Q)) |
1208 | return BATADV_NO_FLAGS; | 1208 | return BATADV_NO_FLAGS; |
1209 | 1209 | ||
1210 | if (!pskb_may_pull(skb, header_len + VLAN_ETH_HLEN)) | 1210 | if (!pskb_may_pull(skb, header_len + VLAN_ETH_HLEN)) |
1211 | return BATADV_NO_FLAGS; | 1211 | return BATADV_NO_FLAGS; |
1212 | 1212 | ||
1213 | vhdr = (struct vlan_ethhdr *)(skb->data + header_len); | 1213 | vhdr = (struct vlan_ethhdr *)(skb->data + header_len); |
1214 | vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; | 1214 | vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; |
1215 | vid |= BATADV_VLAN_HAS_TAG; | 1215 | vid |= BATADV_VLAN_HAS_TAG; |
1216 | 1216 | ||
1217 | return vid; | 1217 | return vid; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | /** | 1220 | /** |
1221 | * batadv_vlan_ap_isola_get - return the AP isolation status for the given vlan | 1221 | * batadv_vlan_ap_isola_get - return the AP isolation status for the given vlan |
1222 | * @bat_priv: the bat priv with all the soft interface information | 1222 | * @bat_priv: the bat priv with all the soft interface information |
1223 | * @vid: the VLAN identifier for which the AP isolation attributed as to be | 1223 | * @vid: the VLAN identifier for which the AP isolation attributed as to be |
1224 | * looked up | 1224 | * looked up |
1225 | * | 1225 | * |
1226 | * Returns true if AP isolation is on for the VLAN idenfied by vid, false | 1226 | * Returns true if AP isolation is on for the VLAN idenfied by vid, false |
1227 | * otherwise | 1227 | * otherwise |
1228 | */ | 1228 | */ |
1229 | bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid) | 1229 | bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid) |
1230 | { | 1230 | { |
1231 | bool ap_isolation_enabled = false; | 1231 | bool ap_isolation_enabled = false; |
1232 | struct batadv_softif_vlan *vlan; | 1232 | struct batadv_softif_vlan *vlan; |
1233 | 1233 | ||
1234 | /* if the AP isolation is requested on a VLAN, then check for its | 1234 | /* if the AP isolation is requested on a VLAN, then check for its |
1235 | * setting in the proper VLAN private data structure | 1235 | * setting in the proper VLAN private data structure |
1236 | */ | 1236 | */ |
1237 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 1237 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
1238 | if (vlan) { | 1238 | if (vlan) { |
1239 | ap_isolation_enabled = atomic_read(&vlan->ap_isolation); | 1239 | ap_isolation_enabled = atomic_read(&vlan->ap_isolation); |
1240 | batadv_softif_vlan_free_ref(vlan); | 1240 | batadv_softif_vlan_free_ref(vlan); |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | return ap_isolation_enabled; | 1243 | return ap_isolation_enabled; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) | 1246 | static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) |
1247 | { | 1247 | { |
1248 | struct batadv_algo_ops *bat_algo_ops; | 1248 | struct batadv_algo_ops *bat_algo_ops; |
1249 | char *algo_name = (char *)val; | 1249 | char *algo_name = (char *)val; |
1250 | size_t name_len = strlen(algo_name); | 1250 | size_t name_len = strlen(algo_name); |
1251 | 1251 | ||
1252 | if (name_len > 0 && algo_name[name_len - 1] == '\n') | 1252 | if (name_len > 0 && algo_name[name_len - 1] == '\n') |
1253 | algo_name[name_len - 1] = '\0'; | 1253 | algo_name[name_len - 1] = '\0'; |
1254 | 1254 | ||
1255 | bat_algo_ops = batadv_algo_get(algo_name); | 1255 | bat_algo_ops = batadv_algo_get(algo_name); |
1256 | if (!bat_algo_ops) { | 1256 | if (!bat_algo_ops) { |
1257 | pr_err("Routing algorithm '%s' is not supported\n", algo_name); | 1257 | pr_err("Routing algorithm '%s' is not supported\n", algo_name); |
1258 | return -EINVAL; | 1258 | return -EINVAL; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | return param_set_copystring(algo_name, kp); | 1261 | return param_set_copystring(algo_name, kp); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | static const struct kernel_param_ops batadv_param_ops_ra = { | 1264 | static const struct kernel_param_ops batadv_param_ops_ra = { |
1265 | .set = batadv_param_set_ra, | 1265 | .set = batadv_param_set_ra, |
1266 | .get = param_get_string, | 1266 | .get = param_get_string, |
1267 | }; | 1267 | }; |
1268 | 1268 | ||
1269 | static struct kparam_string batadv_param_string_ra = { | 1269 | static struct kparam_string batadv_param_string_ra = { |
1270 | .maxlen = sizeof(batadv_routing_algo), | 1270 | .maxlen = sizeof(batadv_routing_algo), |
1271 | .string = batadv_routing_algo, | 1271 | .string = batadv_routing_algo, |
1272 | }; | 1272 | }; |
1273 | 1273 | ||
1274 | module_param_cb(routing_algo, &batadv_param_ops_ra, &batadv_param_string_ra, | 1274 | module_param_cb(routing_algo, &batadv_param_ops_ra, &batadv_param_string_ra, |
1275 | 0644); | 1275 | 0644); |
1276 | module_init(batadv_init); | 1276 | module_init(batadv_init); |
1277 | module_exit(batadv_exit); | 1277 | module_exit(batadv_exit); |
1278 | 1278 | ||
1279 | MODULE_LICENSE("GPL"); | 1279 | MODULE_LICENSE("GPL"); |
1280 | 1280 | ||
1281 | MODULE_AUTHOR(BATADV_DRIVER_AUTHOR); | 1281 | MODULE_AUTHOR(BATADV_DRIVER_AUTHOR); |
1282 | MODULE_DESCRIPTION(BATADV_DRIVER_DESC); | 1282 | MODULE_DESCRIPTION(BATADV_DRIVER_DESC); |
1283 | MODULE_SUPPORTED_DEVICE(BATADV_DRIVER_DEVICE); | 1283 | MODULE_SUPPORTED_DEVICE(BATADV_DRIVER_DEVICE); |
1284 | MODULE_VERSION(BATADV_SOURCE_VERSION); | 1284 | MODULE_VERSION(BATADV_SOURCE_VERSION); |
1285 | 1285 |
net/batman-adv/network-coding.c
1 | /* Copyright (C) 2012-2015 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2012-2015 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Martin Hundebรธll, Jeppe Ledet-Pedersen | 3 | * Martin Hundebรธll, Jeppe Ledet-Pedersen |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of version 2 of the GNU General Public |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "network-coding.h" | 18 | #include "network-coding.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | #include <linux/byteorder/generic.h> | 23 | #include <linux/byteorder/generic.h> |
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/if_ether.h> | 29 | #include <linux/if_ether.h> |
30 | #include <linux/if_packet.h> | 30 | #include <linux/if_packet.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/jhash.h> | 32 | #include <linux/jhash.h> |
33 | #include <linux/jiffies.h> | 33 | #include <linux/jiffies.h> |
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/lockdep.h> | 36 | #include <linux/lockdep.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/printk.h> | 38 | #include <linux/printk.h> |
39 | #include <linux/random.h> | 39 | #include <linux/random.h> |
40 | #include <linux/rculist.h> | 40 | #include <linux/rculist.h> |
41 | #include <linux/rcupdate.h> | 41 | #include <linux/rcupdate.h> |
42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
43 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
46 | #include <linux/stat.h> | 46 | #include <linux/stat.h> |
47 | #include <linux/stddef.h> | 47 | #include <linux/stddef.h> |
48 | #include <linux/string.h> | 48 | #include <linux/string.h> |
49 | #include <linux/workqueue.h> | 49 | #include <linux/workqueue.h> |
50 | 50 | ||
51 | #include "hard-interface.h" | 51 | #include "hard-interface.h" |
52 | #include "hash.h" | 52 | #include "hash.h" |
53 | #include "originator.h" | 53 | #include "originator.h" |
54 | #include "packet.h" | 54 | #include "packet.h" |
55 | #include "routing.h" | 55 | #include "routing.h" |
56 | #include "send.h" | 56 | #include "send.h" |
57 | 57 | ||
58 | static struct lock_class_key batadv_nc_coding_hash_lock_class_key; | 58 | static struct lock_class_key batadv_nc_coding_hash_lock_class_key; |
59 | static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; | 59 | static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; |
60 | 60 | ||
61 | static void batadv_nc_worker(struct work_struct *work); | 61 | static void batadv_nc_worker(struct work_struct *work); |
62 | static int batadv_nc_recv_coded_packet(struct sk_buff *skb, | 62 | static int batadv_nc_recv_coded_packet(struct sk_buff *skb, |
63 | struct batadv_hard_iface *recv_if); | 63 | struct batadv_hard_iface *recv_if); |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * batadv_nc_init - one-time initialization for network coding | 66 | * batadv_nc_init - one-time initialization for network coding |
67 | */ | 67 | */ |
68 | int __init batadv_nc_init(void) | 68 | int __init batadv_nc_init(void) |
69 | { | 69 | { |
70 | int ret; | 70 | int ret; |
71 | 71 | ||
72 | /* Register our packet type */ | 72 | /* Register our packet type */ |
73 | ret = batadv_recv_handler_register(BATADV_CODED, | 73 | ret = batadv_recv_handler_register(BATADV_CODED, |
74 | batadv_nc_recv_coded_packet); | 74 | batadv_nc_recv_coded_packet); |
75 | 75 | ||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * batadv_nc_start_timer - initialise the nc periodic worker | 80 | * batadv_nc_start_timer - initialise the nc periodic worker |
81 | * @bat_priv: the bat priv with all the soft interface information | 81 | * @bat_priv: the bat priv with all the soft interface information |
82 | */ | 82 | */ |
83 | static void batadv_nc_start_timer(struct batadv_priv *bat_priv) | 83 | static void batadv_nc_start_timer(struct batadv_priv *bat_priv) |
84 | { | 84 | { |
85 | queue_delayed_work(batadv_event_workqueue, &bat_priv->nc.work, | 85 | queue_delayed_work(batadv_event_workqueue, &bat_priv->nc.work, |
86 | msecs_to_jiffies(10)); | 86 | msecs_to_jiffies(10)); |
87 | } | 87 | } |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * batadv_nc_tvlv_container_update - update the network coding tvlv container | 90 | * batadv_nc_tvlv_container_update - update the network coding tvlv container |
91 | * after network coding setting change | 91 | * after network coding setting change |
92 | * @bat_priv: the bat priv with all the soft interface information | 92 | * @bat_priv: the bat priv with all the soft interface information |
93 | */ | 93 | */ |
94 | static void batadv_nc_tvlv_container_update(struct batadv_priv *bat_priv) | 94 | static void batadv_nc_tvlv_container_update(struct batadv_priv *bat_priv) |
95 | { | 95 | { |
96 | char nc_mode; | 96 | char nc_mode; |
97 | 97 | ||
98 | nc_mode = atomic_read(&bat_priv->network_coding); | 98 | nc_mode = atomic_read(&bat_priv->network_coding); |
99 | 99 | ||
100 | switch (nc_mode) { | 100 | switch (nc_mode) { |
101 | case 0: | 101 | case 0: |
102 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1); | 102 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1); |
103 | break; | 103 | break; |
104 | case 1: | 104 | case 1: |
105 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_NC, 1, | 105 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_NC, 1, |
106 | NULL, 0); | 106 | NULL, 0); |
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * batadv_nc_status_update - update the network coding tvlv container after | 112 | * batadv_nc_status_update - update the network coding tvlv container after |
113 | * network coding setting change | 113 | * network coding setting change |
114 | * @net_dev: the soft interface net device | 114 | * @net_dev: the soft interface net device |
115 | */ | 115 | */ |
116 | void batadv_nc_status_update(struct net_device *net_dev) | 116 | void batadv_nc_status_update(struct net_device *net_dev) |
117 | { | 117 | { |
118 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 118 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
119 | 119 | ||
120 | batadv_nc_tvlv_container_update(bat_priv); | 120 | batadv_nc_tvlv_container_update(bat_priv); |
121 | } | 121 | } |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * batadv_nc_tvlv_ogm_handler_v1 - process incoming nc tvlv container | 124 | * batadv_nc_tvlv_ogm_handler_v1 - process incoming nc tvlv container |
125 | * @bat_priv: the bat priv with all the soft interface information | 125 | * @bat_priv: the bat priv with all the soft interface information |
126 | * @orig: the orig_node of the ogm | 126 | * @orig: the orig_node of the ogm |
127 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) | 127 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) |
128 | * @tvlv_value: tvlv buffer containing the gateway data | 128 | * @tvlv_value: tvlv buffer containing the gateway data |
129 | * @tvlv_value_len: tvlv buffer length | 129 | * @tvlv_value_len: tvlv buffer length |
130 | */ | 130 | */ |
131 | static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | 131 | static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, |
132 | struct batadv_orig_node *orig, | 132 | struct batadv_orig_node *orig, |
133 | u8 flags, | 133 | u8 flags, |
134 | void *tvlv_value, u16 tvlv_value_len) | 134 | void *tvlv_value, u16 tvlv_value_len) |
135 | { | 135 | { |
136 | if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) | 136 | if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) |
137 | clear_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); | 137 | clear_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); |
138 | else | 138 | else |
139 | set_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); | 139 | set_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); |
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * batadv_nc_mesh_init - initialise coding hash table and start house keeping | 143 | * batadv_nc_mesh_init - initialise coding hash table and start house keeping |
144 | * @bat_priv: the bat priv with all the soft interface information | 144 | * @bat_priv: the bat priv with all the soft interface information |
145 | */ | 145 | */ |
146 | int batadv_nc_mesh_init(struct batadv_priv *bat_priv) | 146 | int batadv_nc_mesh_init(struct batadv_priv *bat_priv) |
147 | { | 147 | { |
148 | bat_priv->nc.timestamp_fwd_flush = jiffies; | 148 | bat_priv->nc.timestamp_fwd_flush = jiffies; |
149 | bat_priv->nc.timestamp_sniffed_purge = jiffies; | 149 | bat_priv->nc.timestamp_sniffed_purge = jiffies; |
150 | 150 | ||
151 | if (bat_priv->nc.coding_hash || bat_priv->nc.decoding_hash) | 151 | if (bat_priv->nc.coding_hash || bat_priv->nc.decoding_hash) |
152 | return 0; | 152 | return 0; |
153 | 153 | ||
154 | bat_priv->nc.coding_hash = batadv_hash_new(128); | 154 | bat_priv->nc.coding_hash = batadv_hash_new(128); |
155 | if (!bat_priv->nc.coding_hash) | 155 | if (!bat_priv->nc.coding_hash) |
156 | goto err; | 156 | goto err; |
157 | 157 | ||
158 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, | 158 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, |
159 | &batadv_nc_coding_hash_lock_class_key); | 159 | &batadv_nc_coding_hash_lock_class_key); |
160 | 160 | ||
161 | bat_priv->nc.decoding_hash = batadv_hash_new(128); | 161 | bat_priv->nc.decoding_hash = batadv_hash_new(128); |
162 | if (!bat_priv->nc.decoding_hash) | 162 | if (!bat_priv->nc.decoding_hash) |
163 | goto err; | 163 | goto err; |
164 | 164 | ||
165 | batadv_hash_set_lock_class(bat_priv->nc.decoding_hash, | 165 | batadv_hash_set_lock_class(bat_priv->nc.decoding_hash, |
166 | &batadv_nc_decoding_hash_lock_class_key); | 166 | &batadv_nc_decoding_hash_lock_class_key); |
167 | 167 | ||
168 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); | 168 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); |
169 | batadv_nc_start_timer(bat_priv); | 169 | batadv_nc_start_timer(bat_priv); |
170 | 170 | ||
171 | batadv_tvlv_handler_register(bat_priv, batadv_nc_tvlv_ogm_handler_v1, | 171 | batadv_tvlv_handler_register(bat_priv, batadv_nc_tvlv_ogm_handler_v1, |
172 | NULL, BATADV_TVLV_NC, 1, | 172 | NULL, BATADV_TVLV_NC, 1, |
173 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | 173 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
174 | batadv_nc_tvlv_container_update(bat_priv); | 174 | batadv_nc_tvlv_container_update(bat_priv); |
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | err: | 177 | err: |
178 | return -ENOMEM; | 178 | return -ENOMEM; |
179 | } | 179 | } |
180 | 180 | ||
181 | /** | 181 | /** |
182 | * batadv_nc_init_bat_priv - initialise the nc specific bat_priv variables | 182 | * batadv_nc_init_bat_priv - initialise the nc specific bat_priv variables |
183 | * @bat_priv: the bat priv with all the soft interface information | 183 | * @bat_priv: the bat priv with all the soft interface information |
184 | */ | 184 | */ |
185 | void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) | 185 | void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) |
186 | { | 186 | { |
187 | atomic_set(&bat_priv->network_coding, 0); | 187 | atomic_set(&bat_priv->network_coding, 0); |
188 | bat_priv->nc.min_tq = 200; | 188 | bat_priv->nc.min_tq = 200; |
189 | bat_priv->nc.max_fwd_delay = 10; | 189 | bat_priv->nc.max_fwd_delay = 10; |
190 | bat_priv->nc.max_buffer_time = 200; | 190 | bat_priv->nc.max_buffer_time = 200; |
191 | } | 191 | } |
192 | 192 | ||
193 | /** | 193 | /** |
194 | * batadv_nc_init_orig - initialise the nc fields of an orig_node | 194 | * batadv_nc_init_orig - initialise the nc fields of an orig_node |
195 | * @orig_node: the orig_node which is going to be initialised | 195 | * @orig_node: the orig_node which is going to be initialised |
196 | */ | 196 | */ |
197 | void batadv_nc_init_orig(struct batadv_orig_node *orig_node) | 197 | void batadv_nc_init_orig(struct batadv_orig_node *orig_node) |
198 | { | 198 | { |
199 | INIT_LIST_HEAD(&orig_node->in_coding_list); | 199 | INIT_LIST_HEAD(&orig_node->in_coding_list); |
200 | INIT_LIST_HEAD(&orig_node->out_coding_list); | 200 | INIT_LIST_HEAD(&orig_node->out_coding_list); |
201 | spin_lock_init(&orig_node->in_coding_list_lock); | 201 | spin_lock_init(&orig_node->in_coding_list_lock); |
202 | spin_lock_init(&orig_node->out_coding_list_lock); | 202 | spin_lock_init(&orig_node->out_coding_list_lock); |
203 | } | 203 | } |
204 | 204 | ||
205 | /** | 205 | /** |
206 | * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove | 206 | * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove |
207 | * its refcount on the orig_node | 207 | * its refcount on the orig_node |
208 | * @rcu: rcu pointer of the nc node | 208 | * @rcu: rcu pointer of the nc node |
209 | */ | 209 | */ |
210 | static void batadv_nc_node_free_rcu(struct rcu_head *rcu) | 210 | static void batadv_nc_node_free_rcu(struct rcu_head *rcu) |
211 | { | 211 | { |
212 | struct batadv_nc_node *nc_node; | 212 | struct batadv_nc_node *nc_node; |
213 | 213 | ||
214 | nc_node = container_of(rcu, struct batadv_nc_node, rcu); | 214 | nc_node = container_of(rcu, struct batadv_nc_node, rcu); |
215 | batadv_orig_node_free_ref(nc_node->orig_node); | 215 | batadv_orig_node_free_ref(nc_node->orig_node); |
216 | kfree(nc_node); | 216 | kfree(nc_node); |
217 | } | 217 | } |
218 | 218 | ||
219 | /** | 219 | /** |
220 | * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly | 220 | * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly |
221 | * frees it | 221 | * frees it |
222 | * @nc_node: the nc node to free | 222 | * @nc_node: the nc node to free |
223 | */ | 223 | */ |
224 | static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) | 224 | static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) |
225 | { | 225 | { |
226 | if (atomic_dec_and_test(&nc_node->refcount)) | 226 | if (atomic_dec_and_test(&nc_node->refcount)) |
227 | call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu); | 227 | call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu); |
228 | } | 228 | } |
229 | 229 | ||
230 | /** | 230 | /** |
231 | * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly | 231 | * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly |
232 | * frees it | 232 | * frees it |
233 | * @nc_path: the nc node to free | 233 | * @nc_path: the nc node to free |
234 | */ | 234 | */ |
235 | static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path) | 235 | static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path) |
236 | { | 236 | { |
237 | if (atomic_dec_and_test(&nc_path->refcount)) | 237 | if (atomic_dec_and_test(&nc_path->refcount)) |
238 | kfree_rcu(nc_path, rcu); | 238 | kfree_rcu(nc_path, rcu); |
239 | } | 239 | } |
240 | 240 | ||
241 | /** | 241 | /** |
242 | * batadv_nc_packet_free - frees nc packet | 242 | * batadv_nc_packet_free - frees nc packet |
243 | * @nc_packet: the nc packet to free | 243 | * @nc_packet: the nc packet to free |
244 | */ | 244 | */ |
245 | static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet) | 245 | static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet) |
246 | { | 246 | { |
247 | if (nc_packet->skb) | 247 | kfree_skb(nc_packet->skb); |
248 | kfree_skb(nc_packet->skb); | ||
249 | |||
250 | batadv_nc_path_free_ref(nc_packet->nc_path); | 248 | batadv_nc_path_free_ref(nc_packet->nc_path); |
251 | kfree(nc_packet); | 249 | kfree(nc_packet); |
252 | } | 250 | } |
253 | 251 | ||
254 | /** | 252 | /** |
255 | * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged | 253 | * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged |
256 | * @bat_priv: the bat priv with all the soft interface information | 254 | * @bat_priv: the bat priv with all the soft interface information |
257 | * @nc_node: the nc node to check | 255 | * @nc_node: the nc node to check |
258 | * | 256 | * |
259 | * Returns true if the entry has to be purged now, false otherwise | 257 | * Returns true if the entry has to be purged now, false otherwise |
260 | */ | 258 | */ |
261 | static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv, | 259 | static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv, |
262 | struct batadv_nc_node *nc_node) | 260 | struct batadv_nc_node *nc_node) |
263 | { | 261 | { |
264 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 262 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
265 | return true; | 263 | return true; |
266 | 264 | ||
267 | return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT); | 265 | return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT); |
268 | } | 266 | } |
269 | 267 | ||
270 | /** | 268 | /** |
271 | * batadv_nc_to_purge_nc_path_coding - checks whether an nc path has timed out | 269 | * batadv_nc_to_purge_nc_path_coding - checks whether an nc path has timed out |
272 | * @bat_priv: the bat priv with all the soft interface information | 270 | * @bat_priv: the bat priv with all the soft interface information |
273 | * @nc_path: the nc path to check | 271 | * @nc_path: the nc path to check |
274 | * | 272 | * |
275 | * Returns true if the entry has to be purged now, false otherwise | 273 | * Returns true if the entry has to be purged now, false otherwise |
276 | */ | 274 | */ |
277 | static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv, | 275 | static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv, |
278 | struct batadv_nc_path *nc_path) | 276 | struct batadv_nc_path *nc_path) |
279 | { | 277 | { |
280 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 278 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
281 | return true; | 279 | return true; |
282 | 280 | ||
283 | /* purge the path when no packets has been added for 10 times the | 281 | /* purge the path when no packets has been added for 10 times the |
284 | * max_fwd_delay time | 282 | * max_fwd_delay time |
285 | */ | 283 | */ |
286 | return batadv_has_timed_out(nc_path->last_valid, | 284 | return batadv_has_timed_out(nc_path->last_valid, |
287 | bat_priv->nc.max_fwd_delay * 10); | 285 | bat_priv->nc.max_fwd_delay * 10); |
288 | } | 286 | } |
289 | 287 | ||
290 | /** | 288 | /** |
291 | * batadv_nc_to_purge_nc_path_decoding - checks whether an nc path has timed out | 289 | * batadv_nc_to_purge_nc_path_decoding - checks whether an nc path has timed out |
292 | * @bat_priv: the bat priv with all the soft interface information | 290 | * @bat_priv: the bat priv with all the soft interface information |
293 | * @nc_path: the nc path to check | 291 | * @nc_path: the nc path to check |
294 | * | 292 | * |
295 | * Returns true if the entry has to be purged now, false otherwise | 293 | * Returns true if the entry has to be purged now, false otherwise |
296 | */ | 294 | */ |
297 | static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv, | 295 | static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv, |
298 | struct batadv_nc_path *nc_path) | 296 | struct batadv_nc_path *nc_path) |
299 | { | 297 | { |
300 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 298 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
301 | return true; | 299 | return true; |
302 | 300 | ||
303 | /* purge the path when no packets has been added for 10 times the | 301 | /* purge the path when no packets has been added for 10 times the |
304 | * max_buffer time | 302 | * max_buffer time |
305 | */ | 303 | */ |
306 | return batadv_has_timed_out(nc_path->last_valid, | 304 | return batadv_has_timed_out(nc_path->last_valid, |
307 | bat_priv->nc.max_buffer_time * 10); | 305 | bat_priv->nc.max_buffer_time * 10); |
308 | } | 306 | } |
309 | 307 | ||
310 | /** | 308 | /** |
311 | * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale | 309 | * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale |
312 | * entries | 310 | * entries |
313 | * @bat_priv: the bat priv with all the soft interface information | 311 | * @bat_priv: the bat priv with all the soft interface information |
314 | * @list: list of nc nodes | 312 | * @list: list of nc nodes |
315 | * @lock: nc node list lock | 313 | * @lock: nc node list lock |
316 | * @to_purge: function in charge to decide whether an entry has to be purged or | 314 | * @to_purge: function in charge to decide whether an entry has to be purged or |
317 | * not. This function takes the nc node as argument and has to return | 315 | * not. This function takes the nc node as argument and has to return |
318 | * a boolean value: true if the entry has to be deleted, false | 316 | * a boolean value: true if the entry has to be deleted, false |
319 | * otherwise | 317 | * otherwise |
320 | */ | 318 | */ |
321 | static void | 319 | static void |
322 | batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv, | 320 | batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv, |
323 | struct list_head *list, | 321 | struct list_head *list, |
324 | spinlock_t *lock, | 322 | spinlock_t *lock, |
325 | bool (*to_purge)(struct batadv_priv *, | 323 | bool (*to_purge)(struct batadv_priv *, |
326 | struct batadv_nc_node *)) | 324 | struct batadv_nc_node *)) |
327 | { | 325 | { |
328 | struct batadv_nc_node *nc_node, *nc_node_tmp; | 326 | struct batadv_nc_node *nc_node, *nc_node_tmp; |
329 | 327 | ||
330 | /* For each nc_node in list */ | 328 | /* For each nc_node in list */ |
331 | spin_lock_bh(lock); | 329 | spin_lock_bh(lock); |
332 | list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) { | 330 | list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) { |
333 | /* if an helper function has been passed as parameter, | 331 | /* if an helper function has been passed as parameter, |
334 | * ask it if the entry has to be purged or not | 332 | * ask it if the entry has to be purged or not |
335 | */ | 333 | */ |
336 | if (to_purge && !to_purge(bat_priv, nc_node)) | 334 | if (to_purge && !to_purge(bat_priv, nc_node)) |
337 | continue; | 335 | continue; |
338 | 336 | ||
339 | batadv_dbg(BATADV_DBG_NC, bat_priv, | 337 | batadv_dbg(BATADV_DBG_NC, bat_priv, |
340 | "Removing nc_node %pM -> %pM\n", | 338 | "Removing nc_node %pM -> %pM\n", |
341 | nc_node->addr, nc_node->orig_node->orig); | 339 | nc_node->addr, nc_node->orig_node->orig); |
342 | list_del_rcu(&nc_node->list); | 340 | list_del_rcu(&nc_node->list); |
343 | batadv_nc_node_free_ref(nc_node); | 341 | batadv_nc_node_free_ref(nc_node); |
344 | } | 342 | } |
345 | spin_unlock_bh(lock); | 343 | spin_unlock_bh(lock); |
346 | } | 344 | } |
347 | 345 | ||
348 | /** | 346 | /** |
349 | * batadv_nc_purge_orig - purges all nc node data attached of the given | 347 | * batadv_nc_purge_orig - purges all nc node data attached of the given |
350 | * originator | 348 | * originator |
351 | * @bat_priv: the bat priv with all the soft interface information | 349 | * @bat_priv: the bat priv with all the soft interface information |
352 | * @orig_node: orig_node with the nc node entries to be purged | 350 | * @orig_node: orig_node with the nc node entries to be purged |
353 | * @to_purge: function in charge to decide whether an entry has to be purged or | 351 | * @to_purge: function in charge to decide whether an entry has to be purged or |
354 | * not. This function takes the nc node as argument and has to return | 352 | * not. This function takes the nc node as argument and has to return |
355 | * a boolean value: true is the entry has to be deleted, false | 353 | * a boolean value: true is the entry has to be deleted, false |
356 | * otherwise | 354 | * otherwise |
357 | */ | 355 | */ |
358 | void batadv_nc_purge_orig(struct batadv_priv *bat_priv, | 356 | void batadv_nc_purge_orig(struct batadv_priv *bat_priv, |
359 | struct batadv_orig_node *orig_node, | 357 | struct batadv_orig_node *orig_node, |
360 | bool (*to_purge)(struct batadv_priv *, | 358 | bool (*to_purge)(struct batadv_priv *, |
361 | struct batadv_nc_node *)) | 359 | struct batadv_nc_node *)) |
362 | { | 360 | { |
363 | /* Check ingoing nc_node's of this orig_node */ | 361 | /* Check ingoing nc_node's of this orig_node */ |
364 | batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list, | 362 | batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list, |
365 | &orig_node->in_coding_list_lock, | 363 | &orig_node->in_coding_list_lock, |
366 | to_purge); | 364 | to_purge); |
367 | 365 | ||
368 | /* Check outgoing nc_node's of this orig_node */ | 366 | /* Check outgoing nc_node's of this orig_node */ |
369 | batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list, | 367 | batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list, |
370 | &orig_node->out_coding_list_lock, | 368 | &orig_node->out_coding_list_lock, |
371 | to_purge); | 369 | to_purge); |
372 | } | 370 | } |
373 | 371 | ||
374 | /** | 372 | /** |
375 | * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they | 373 | * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they |
376 | * have timed out nc nodes | 374 | * have timed out nc nodes |
377 | * @bat_priv: the bat priv with all the soft interface information | 375 | * @bat_priv: the bat priv with all the soft interface information |
378 | */ | 376 | */ |
379 | static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv) | 377 | static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv) |
380 | { | 378 | { |
381 | struct batadv_hashtable *hash = bat_priv->orig_hash; | 379 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
382 | struct hlist_head *head; | 380 | struct hlist_head *head; |
383 | struct batadv_orig_node *orig_node; | 381 | struct batadv_orig_node *orig_node; |
384 | u32 i; | 382 | u32 i; |
385 | 383 | ||
386 | if (!hash) | 384 | if (!hash) |
387 | return; | 385 | return; |
388 | 386 | ||
389 | /* For each orig_node */ | 387 | /* For each orig_node */ |
390 | for (i = 0; i < hash->size; i++) { | 388 | for (i = 0; i < hash->size; i++) { |
391 | head = &hash->table[i]; | 389 | head = &hash->table[i]; |
392 | 390 | ||
393 | rcu_read_lock(); | 391 | rcu_read_lock(); |
394 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) | 392 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) |
395 | batadv_nc_purge_orig(bat_priv, orig_node, | 393 | batadv_nc_purge_orig(bat_priv, orig_node, |
396 | batadv_nc_to_purge_nc_node); | 394 | batadv_nc_to_purge_nc_node); |
397 | rcu_read_unlock(); | 395 | rcu_read_unlock(); |
398 | } | 396 | } |
399 | } | 397 | } |
400 | 398 | ||
401 | /** | 399 | /** |
402 | * batadv_nc_purge_paths - traverse all nc paths part of the hash and remove | 400 | * batadv_nc_purge_paths - traverse all nc paths part of the hash and remove |
403 | * unused ones | 401 | * unused ones |
404 | * @bat_priv: the bat priv with all the soft interface information | 402 | * @bat_priv: the bat priv with all the soft interface information |
405 | * @hash: hash table containing the nc paths to check | 403 | * @hash: hash table containing the nc paths to check |
406 | * @to_purge: function in charge to decide whether an entry has to be purged or | 404 | * @to_purge: function in charge to decide whether an entry has to be purged or |
407 | * not. This function takes the nc node as argument and has to return | 405 | * not. This function takes the nc node as argument and has to return |
408 | * a boolean value: true is the entry has to be deleted, false | 406 | * a boolean value: true is the entry has to be deleted, false |
409 | * otherwise | 407 | * otherwise |
410 | */ | 408 | */ |
411 | static void batadv_nc_purge_paths(struct batadv_priv *bat_priv, | 409 | static void batadv_nc_purge_paths(struct batadv_priv *bat_priv, |
412 | struct batadv_hashtable *hash, | 410 | struct batadv_hashtable *hash, |
413 | bool (*to_purge)(struct batadv_priv *, | 411 | bool (*to_purge)(struct batadv_priv *, |
414 | struct batadv_nc_path *)) | 412 | struct batadv_nc_path *)) |
415 | { | 413 | { |
416 | struct hlist_head *head; | 414 | struct hlist_head *head; |
417 | struct hlist_node *node_tmp; | 415 | struct hlist_node *node_tmp; |
418 | struct batadv_nc_path *nc_path; | 416 | struct batadv_nc_path *nc_path; |
419 | spinlock_t *lock; /* Protects lists in hash */ | 417 | spinlock_t *lock; /* Protects lists in hash */ |
420 | u32 i; | 418 | u32 i; |
421 | 419 | ||
422 | for (i = 0; i < hash->size; i++) { | 420 | for (i = 0; i < hash->size; i++) { |
423 | head = &hash->table[i]; | 421 | head = &hash->table[i]; |
424 | lock = &hash->list_locks[i]; | 422 | lock = &hash->list_locks[i]; |
425 | 423 | ||
426 | /* For each nc_path in this bin */ | 424 | /* For each nc_path in this bin */ |
427 | spin_lock_bh(lock); | 425 | spin_lock_bh(lock); |
428 | hlist_for_each_entry_safe(nc_path, node_tmp, head, hash_entry) { | 426 | hlist_for_each_entry_safe(nc_path, node_tmp, head, hash_entry) { |
429 | /* if an helper function has been passed as parameter, | 427 | /* if an helper function has been passed as parameter, |
430 | * ask it if the entry has to be purged or not | 428 | * ask it if the entry has to be purged or not |
431 | */ | 429 | */ |
432 | if (to_purge && !to_purge(bat_priv, nc_path)) | 430 | if (to_purge && !to_purge(bat_priv, nc_path)) |
433 | continue; | 431 | continue; |
434 | 432 | ||
435 | /* purging an non-empty nc_path should never happen, but | 433 | /* purging an non-empty nc_path should never happen, but |
436 | * is observed under high CPU load. Delay the purging | 434 | * is observed under high CPU load. Delay the purging |
437 | * until next iteration to allow the packet_list to be | 435 | * until next iteration to allow the packet_list to be |
438 | * emptied first. | 436 | * emptied first. |
439 | */ | 437 | */ |
440 | if (!unlikely(list_empty(&nc_path->packet_list))) { | 438 | if (!unlikely(list_empty(&nc_path->packet_list))) { |
441 | net_ratelimited_function(printk, | 439 | net_ratelimited_function(printk, |
442 | KERN_WARNING | 440 | KERN_WARNING |
443 | "Skipping free of non-empty nc_path (%pM -> %pM)!\n", | 441 | "Skipping free of non-empty nc_path (%pM -> %pM)!\n", |
444 | nc_path->prev_hop, | 442 | nc_path->prev_hop, |
445 | nc_path->next_hop); | 443 | nc_path->next_hop); |
446 | continue; | 444 | continue; |
447 | } | 445 | } |
448 | 446 | ||
449 | /* nc_path is unused, so remove it */ | 447 | /* nc_path is unused, so remove it */ |
450 | batadv_dbg(BATADV_DBG_NC, bat_priv, | 448 | batadv_dbg(BATADV_DBG_NC, bat_priv, |
451 | "Remove nc_path %pM -> %pM\n", | 449 | "Remove nc_path %pM -> %pM\n", |
452 | nc_path->prev_hop, nc_path->next_hop); | 450 | nc_path->prev_hop, nc_path->next_hop); |
453 | hlist_del_rcu(&nc_path->hash_entry); | 451 | hlist_del_rcu(&nc_path->hash_entry); |
454 | batadv_nc_path_free_ref(nc_path); | 452 | batadv_nc_path_free_ref(nc_path); |
455 | } | 453 | } |
456 | spin_unlock_bh(lock); | 454 | spin_unlock_bh(lock); |
457 | } | 455 | } |
458 | } | 456 | } |
459 | 457 | ||
460 | /** | 458 | /** |
461 | * batadv_nc_hash_key_gen - computes the nc_path hash key | 459 | * batadv_nc_hash_key_gen - computes the nc_path hash key |
462 | * @key: buffer to hold the final hash key | 460 | * @key: buffer to hold the final hash key |
463 | * @src: source ethernet mac address going into the hash key | 461 | * @src: source ethernet mac address going into the hash key |
464 | * @dst: destination ethernet mac address going into the hash key | 462 | * @dst: destination ethernet mac address going into the hash key |
465 | */ | 463 | */ |
466 | static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src, | 464 | static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src, |
467 | const char *dst) | 465 | const char *dst) |
468 | { | 466 | { |
469 | memcpy(key->prev_hop, src, sizeof(key->prev_hop)); | 467 | memcpy(key->prev_hop, src, sizeof(key->prev_hop)); |
470 | memcpy(key->next_hop, dst, sizeof(key->next_hop)); | 468 | memcpy(key->next_hop, dst, sizeof(key->next_hop)); |
471 | } | 469 | } |
472 | 470 | ||
473 | /** | 471 | /** |
474 | * batadv_nc_hash_choose - compute the hash value for an nc path | 472 | * batadv_nc_hash_choose - compute the hash value for an nc path |
475 | * @data: data to hash | 473 | * @data: data to hash |
476 | * @size: size of the hash table | 474 | * @size: size of the hash table |
477 | * | 475 | * |
478 | * Returns the selected index in the hash table for the given data. | 476 | * Returns the selected index in the hash table for the given data. |
479 | */ | 477 | */ |
480 | static u32 batadv_nc_hash_choose(const void *data, u32 size) | 478 | static u32 batadv_nc_hash_choose(const void *data, u32 size) |
481 | { | 479 | { |
482 | const struct batadv_nc_path *nc_path = data; | 480 | const struct batadv_nc_path *nc_path = data; |
483 | u32 hash = 0; | 481 | u32 hash = 0; |
484 | 482 | ||
485 | hash = jhash(&nc_path->prev_hop, sizeof(nc_path->prev_hop), hash); | 483 | hash = jhash(&nc_path->prev_hop, sizeof(nc_path->prev_hop), hash); |
486 | hash = jhash(&nc_path->next_hop, sizeof(nc_path->next_hop), hash); | 484 | hash = jhash(&nc_path->next_hop, sizeof(nc_path->next_hop), hash); |
487 | 485 | ||
488 | return hash % size; | 486 | return hash % size; |
489 | } | 487 | } |
490 | 488 | ||
491 | /** | 489 | /** |
492 | * batadv_nc_hash_compare - comparing function used in the network coding hash | 490 | * batadv_nc_hash_compare - comparing function used in the network coding hash |
493 | * tables | 491 | * tables |
494 | * @node: node in the local table | 492 | * @node: node in the local table |
495 | * @data2: second object to compare the node to | 493 | * @data2: second object to compare the node to |
496 | * | 494 | * |
497 | * Returns 1 if the two entry are the same, 0 otherwise | 495 | * Returns 1 if the two entry are the same, 0 otherwise |
498 | */ | 496 | */ |
499 | static int batadv_nc_hash_compare(const struct hlist_node *node, | 497 | static int batadv_nc_hash_compare(const struct hlist_node *node, |
500 | const void *data2) | 498 | const void *data2) |
501 | { | 499 | { |
502 | const struct batadv_nc_path *nc_path1, *nc_path2; | 500 | const struct batadv_nc_path *nc_path1, *nc_path2; |
503 | 501 | ||
504 | nc_path1 = container_of(node, struct batadv_nc_path, hash_entry); | 502 | nc_path1 = container_of(node, struct batadv_nc_path, hash_entry); |
505 | nc_path2 = data2; | 503 | nc_path2 = data2; |
506 | 504 | ||
507 | /* Return 1 if the two keys are identical */ | 505 | /* Return 1 if the two keys are identical */ |
508 | if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop, | 506 | if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop, |
509 | sizeof(nc_path1->prev_hop)) != 0) | 507 | sizeof(nc_path1->prev_hop)) != 0) |
510 | return 0; | 508 | return 0; |
511 | 509 | ||
512 | if (memcmp(nc_path1->next_hop, nc_path2->next_hop, | 510 | if (memcmp(nc_path1->next_hop, nc_path2->next_hop, |
513 | sizeof(nc_path1->next_hop)) != 0) | 511 | sizeof(nc_path1->next_hop)) != 0) |
514 | return 0; | 512 | return 0; |
515 | 513 | ||
516 | return 1; | 514 | return 1; |
517 | } | 515 | } |
518 | 516 | ||
519 | /** | 517 | /** |
520 | * batadv_nc_hash_find - search for an existing nc path and return it | 518 | * batadv_nc_hash_find - search for an existing nc path and return it |
521 | * @hash: hash table containing the nc path | 519 | * @hash: hash table containing the nc path |
522 | * @data: search key | 520 | * @data: search key |
523 | * | 521 | * |
524 | * Returns the nc_path if found, NULL otherwise. | 522 | * Returns the nc_path if found, NULL otherwise. |
525 | */ | 523 | */ |
526 | static struct batadv_nc_path * | 524 | static struct batadv_nc_path * |
527 | batadv_nc_hash_find(struct batadv_hashtable *hash, | 525 | batadv_nc_hash_find(struct batadv_hashtable *hash, |
528 | void *data) | 526 | void *data) |
529 | { | 527 | { |
530 | struct hlist_head *head; | 528 | struct hlist_head *head; |
531 | struct batadv_nc_path *nc_path, *nc_path_tmp = NULL; | 529 | struct batadv_nc_path *nc_path, *nc_path_tmp = NULL; |
532 | int index; | 530 | int index; |
533 | 531 | ||
534 | if (!hash) | 532 | if (!hash) |
535 | return NULL; | 533 | return NULL; |
536 | 534 | ||
537 | index = batadv_nc_hash_choose(data, hash->size); | 535 | index = batadv_nc_hash_choose(data, hash->size); |
538 | head = &hash->table[index]; | 536 | head = &hash->table[index]; |
539 | 537 | ||
540 | rcu_read_lock(); | 538 | rcu_read_lock(); |
541 | hlist_for_each_entry_rcu(nc_path, head, hash_entry) { | 539 | hlist_for_each_entry_rcu(nc_path, head, hash_entry) { |
542 | if (!batadv_nc_hash_compare(&nc_path->hash_entry, data)) | 540 | if (!batadv_nc_hash_compare(&nc_path->hash_entry, data)) |
543 | continue; | 541 | continue; |
544 | 542 | ||
545 | if (!atomic_inc_not_zero(&nc_path->refcount)) | 543 | if (!atomic_inc_not_zero(&nc_path->refcount)) |
546 | continue; | 544 | continue; |
547 | 545 | ||
548 | nc_path_tmp = nc_path; | 546 | nc_path_tmp = nc_path; |
549 | break; | 547 | break; |
550 | } | 548 | } |
551 | rcu_read_unlock(); | 549 | rcu_read_unlock(); |
552 | 550 | ||
553 | return nc_path_tmp; | 551 | return nc_path_tmp; |
554 | } | 552 | } |
555 | 553 | ||
556 | /** | 554 | /** |
557 | * batadv_nc_send_packet - send non-coded packet and free nc_packet struct | 555 | * batadv_nc_send_packet - send non-coded packet and free nc_packet struct |
558 | * @nc_packet: the nc packet to send | 556 | * @nc_packet: the nc packet to send |
559 | */ | 557 | */ |
560 | static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) | 558 | static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) |
561 | { | 559 | { |
562 | batadv_send_skb_packet(nc_packet->skb, | 560 | batadv_send_skb_packet(nc_packet->skb, |
563 | nc_packet->neigh_node->if_incoming, | 561 | nc_packet->neigh_node->if_incoming, |
564 | nc_packet->nc_path->next_hop); | 562 | nc_packet->nc_path->next_hop); |
565 | nc_packet->skb = NULL; | 563 | nc_packet->skb = NULL; |
566 | batadv_nc_packet_free(nc_packet); | 564 | batadv_nc_packet_free(nc_packet); |
567 | } | 565 | } |
568 | 566 | ||
569 | /** | 567 | /** |
570 | * batadv_nc_sniffed_purge - Checks timestamp of given sniffed nc_packet. | 568 | * batadv_nc_sniffed_purge - Checks timestamp of given sniffed nc_packet. |
571 | * @bat_priv: the bat priv with all the soft interface information | 569 | * @bat_priv: the bat priv with all the soft interface information |
572 | * @nc_path: the nc path the packet belongs to | 570 | * @nc_path: the nc path the packet belongs to |
573 | * @nc_packet: the nc packet to be checked | 571 | * @nc_packet: the nc packet to be checked |
574 | * | 572 | * |
575 | * Checks whether the given sniffed (overheard) nc_packet has hit its buffering | 573 | * Checks whether the given sniffed (overheard) nc_packet has hit its buffering |
576 | * timeout. If so, the packet is no longer kept and the entry deleted from the | 574 | * timeout. If so, the packet is no longer kept and the entry deleted from the |
577 | * queue. Has to be called with the appropriate locks. | 575 | * queue. Has to be called with the appropriate locks. |
578 | * | 576 | * |
579 | * Returns false as soon as the entry in the fifo queue has not been timed out | 577 | * Returns false as soon as the entry in the fifo queue has not been timed out |
580 | * yet and true otherwise. | 578 | * yet and true otherwise. |
581 | */ | 579 | */ |
582 | static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv, | 580 | static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv, |
583 | struct batadv_nc_path *nc_path, | 581 | struct batadv_nc_path *nc_path, |
584 | struct batadv_nc_packet *nc_packet) | 582 | struct batadv_nc_packet *nc_packet) |
585 | { | 583 | { |
586 | unsigned long timeout = bat_priv->nc.max_buffer_time; | 584 | unsigned long timeout = bat_priv->nc.max_buffer_time; |
587 | bool res = false; | 585 | bool res = false; |
588 | 586 | ||
589 | lockdep_assert_held(&nc_path->packet_list_lock); | 587 | lockdep_assert_held(&nc_path->packet_list_lock); |
590 | 588 | ||
591 | /* Packets are added to tail, so the remaining packets did not time | 589 | /* Packets are added to tail, so the remaining packets did not time |
592 | * out and we can stop processing the current queue | 590 | * out and we can stop processing the current queue |
593 | */ | 591 | */ |
594 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE && | 592 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE && |
595 | !batadv_has_timed_out(nc_packet->timestamp, timeout)) | 593 | !batadv_has_timed_out(nc_packet->timestamp, timeout)) |
596 | goto out; | 594 | goto out; |
597 | 595 | ||
598 | /* purge nc packet */ | 596 | /* purge nc packet */ |
599 | list_del(&nc_packet->list); | 597 | list_del(&nc_packet->list); |
600 | batadv_nc_packet_free(nc_packet); | 598 | batadv_nc_packet_free(nc_packet); |
601 | 599 | ||
602 | res = true; | 600 | res = true; |
603 | 601 | ||
604 | out: | 602 | out: |
605 | return res; | 603 | return res; |
606 | } | 604 | } |
607 | 605 | ||
608 | /** | 606 | /** |
609 | * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet. | 607 | * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet. |
610 | * @bat_priv: the bat priv with all the soft interface information | 608 | * @bat_priv: the bat priv with all the soft interface information |
611 | * @nc_path: the nc path the packet belongs to | 609 | * @nc_path: the nc path the packet belongs to |
612 | * @nc_packet: the nc packet to be checked | 610 | * @nc_packet: the nc packet to be checked |
613 | * | 611 | * |
614 | * Checks whether the given nc packet has hit its forward timeout. If so, the | 612 | * Checks whether the given nc packet has hit its forward timeout. If so, the |
615 | * packet is no longer delayed, immediately sent and the entry deleted from the | 613 | * packet is no longer delayed, immediately sent and the entry deleted from the |
616 | * queue. Has to be called with the appropriate locks. | 614 | * queue. Has to be called with the appropriate locks. |
617 | * | 615 | * |
618 | * Returns false as soon as the entry in the fifo queue has not been timed out | 616 | * Returns false as soon as the entry in the fifo queue has not been timed out |
619 | * yet and true otherwise. | 617 | * yet and true otherwise. |
620 | */ | 618 | */ |
621 | static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv, | 619 | static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv, |
622 | struct batadv_nc_path *nc_path, | 620 | struct batadv_nc_path *nc_path, |
623 | struct batadv_nc_packet *nc_packet) | 621 | struct batadv_nc_packet *nc_packet) |
624 | { | 622 | { |
625 | unsigned long timeout = bat_priv->nc.max_fwd_delay; | 623 | unsigned long timeout = bat_priv->nc.max_fwd_delay; |
626 | 624 | ||
627 | lockdep_assert_held(&nc_path->packet_list_lock); | 625 | lockdep_assert_held(&nc_path->packet_list_lock); |
628 | 626 | ||
629 | /* Packets are added to tail, so the remaining packets did not time | 627 | /* Packets are added to tail, so the remaining packets did not time |
630 | * out and we can stop processing the current queue | 628 | * out and we can stop processing the current queue |
631 | */ | 629 | */ |
632 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE && | 630 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE && |
633 | !batadv_has_timed_out(nc_packet->timestamp, timeout)) | 631 | !batadv_has_timed_out(nc_packet->timestamp, timeout)) |
634 | return false; | 632 | return false; |
635 | 633 | ||
636 | /* Send packet */ | 634 | /* Send packet */ |
637 | batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); | 635 | batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); |
638 | batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, | 636 | batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, |
639 | nc_packet->skb->len + ETH_HLEN); | 637 | nc_packet->skb->len + ETH_HLEN); |
640 | list_del(&nc_packet->list); | 638 | list_del(&nc_packet->list); |
641 | batadv_nc_send_packet(nc_packet); | 639 | batadv_nc_send_packet(nc_packet); |
642 | 640 | ||
643 | return true; | 641 | return true; |
644 | } | 642 | } |
645 | 643 | ||
646 | /** | 644 | /** |
647 | * batadv_nc_process_nc_paths - traverse given nc packet pool and free timed out | 645 | * batadv_nc_process_nc_paths - traverse given nc packet pool and free timed out |
648 | * nc packets | 646 | * nc packets |
649 | * @bat_priv: the bat priv with all the soft interface information | 647 | * @bat_priv: the bat priv with all the soft interface information |
650 | * @hash: to be processed hash table | 648 | * @hash: to be processed hash table |
651 | * @process_fn: Function called to process given nc packet. Should return true | 649 | * @process_fn: Function called to process given nc packet. Should return true |
652 | * to encourage this function to proceed with the next packet. | 650 | * to encourage this function to proceed with the next packet. |
653 | * Otherwise the rest of the current queue is skipped. | 651 | * Otherwise the rest of the current queue is skipped. |
654 | */ | 652 | */ |
655 | static void | 653 | static void |
656 | batadv_nc_process_nc_paths(struct batadv_priv *bat_priv, | 654 | batadv_nc_process_nc_paths(struct batadv_priv *bat_priv, |
657 | struct batadv_hashtable *hash, | 655 | struct batadv_hashtable *hash, |
658 | bool (*process_fn)(struct batadv_priv *, | 656 | bool (*process_fn)(struct batadv_priv *, |
659 | struct batadv_nc_path *, | 657 | struct batadv_nc_path *, |
660 | struct batadv_nc_packet *)) | 658 | struct batadv_nc_packet *)) |
661 | { | 659 | { |
662 | struct hlist_head *head; | 660 | struct hlist_head *head; |
663 | struct batadv_nc_packet *nc_packet, *nc_packet_tmp; | 661 | struct batadv_nc_packet *nc_packet, *nc_packet_tmp; |
664 | struct batadv_nc_path *nc_path; | 662 | struct batadv_nc_path *nc_path; |
665 | bool ret; | 663 | bool ret; |
666 | int i; | 664 | int i; |
667 | 665 | ||
668 | if (!hash) | 666 | if (!hash) |
669 | return; | 667 | return; |
670 | 668 | ||
671 | /* Loop hash table bins */ | 669 | /* Loop hash table bins */ |
672 | for (i = 0; i < hash->size; i++) { | 670 | for (i = 0; i < hash->size; i++) { |
673 | head = &hash->table[i]; | 671 | head = &hash->table[i]; |
674 | 672 | ||
675 | /* Loop coding paths */ | 673 | /* Loop coding paths */ |
676 | rcu_read_lock(); | 674 | rcu_read_lock(); |
677 | hlist_for_each_entry_rcu(nc_path, head, hash_entry) { | 675 | hlist_for_each_entry_rcu(nc_path, head, hash_entry) { |
678 | /* Loop packets */ | 676 | /* Loop packets */ |
679 | spin_lock_bh(&nc_path->packet_list_lock); | 677 | spin_lock_bh(&nc_path->packet_list_lock); |
680 | list_for_each_entry_safe(nc_packet, nc_packet_tmp, | 678 | list_for_each_entry_safe(nc_packet, nc_packet_tmp, |
681 | &nc_path->packet_list, list) { | 679 | &nc_path->packet_list, list) { |
682 | ret = process_fn(bat_priv, nc_path, nc_packet); | 680 | ret = process_fn(bat_priv, nc_path, nc_packet); |
683 | if (!ret) | 681 | if (!ret) |
684 | break; | 682 | break; |
685 | } | 683 | } |
686 | spin_unlock_bh(&nc_path->packet_list_lock); | 684 | spin_unlock_bh(&nc_path->packet_list_lock); |
687 | } | 685 | } |
688 | rcu_read_unlock(); | 686 | rcu_read_unlock(); |
689 | } | 687 | } |
690 | } | 688 | } |
691 | 689 | ||
692 | /** | 690 | /** |
693 | * batadv_nc_worker - periodic task for house keeping related to network coding | 691 | * batadv_nc_worker - periodic task for house keeping related to network coding |
694 | * @work: kernel work struct | 692 | * @work: kernel work struct |
695 | */ | 693 | */ |
696 | static void batadv_nc_worker(struct work_struct *work) | 694 | static void batadv_nc_worker(struct work_struct *work) |
697 | { | 695 | { |
698 | struct delayed_work *delayed_work; | 696 | struct delayed_work *delayed_work; |
699 | struct batadv_priv_nc *priv_nc; | 697 | struct batadv_priv_nc *priv_nc; |
700 | struct batadv_priv *bat_priv; | 698 | struct batadv_priv *bat_priv; |
701 | unsigned long timeout; | 699 | unsigned long timeout; |
702 | 700 | ||
703 | delayed_work = container_of(work, struct delayed_work, work); | 701 | delayed_work = container_of(work, struct delayed_work, work); |
704 | priv_nc = container_of(delayed_work, struct batadv_priv_nc, work); | 702 | priv_nc = container_of(delayed_work, struct batadv_priv_nc, work); |
705 | bat_priv = container_of(priv_nc, struct batadv_priv, nc); | 703 | bat_priv = container_of(priv_nc, struct batadv_priv, nc); |
706 | 704 | ||
707 | batadv_nc_purge_orig_hash(bat_priv); | 705 | batadv_nc_purge_orig_hash(bat_priv); |
708 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, | 706 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, |
709 | batadv_nc_to_purge_nc_path_coding); | 707 | batadv_nc_to_purge_nc_path_coding); |
710 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, | 708 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, |
711 | batadv_nc_to_purge_nc_path_decoding); | 709 | batadv_nc_to_purge_nc_path_decoding); |
712 | 710 | ||
713 | timeout = bat_priv->nc.max_fwd_delay; | 711 | timeout = bat_priv->nc.max_fwd_delay; |
714 | 712 | ||
715 | if (batadv_has_timed_out(bat_priv->nc.timestamp_fwd_flush, timeout)) { | 713 | if (batadv_has_timed_out(bat_priv->nc.timestamp_fwd_flush, timeout)) { |
716 | batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.coding_hash, | 714 | batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.coding_hash, |
717 | batadv_nc_fwd_flush); | 715 | batadv_nc_fwd_flush); |
718 | bat_priv->nc.timestamp_fwd_flush = jiffies; | 716 | bat_priv->nc.timestamp_fwd_flush = jiffies; |
719 | } | 717 | } |
720 | 718 | ||
721 | if (batadv_has_timed_out(bat_priv->nc.timestamp_sniffed_purge, | 719 | if (batadv_has_timed_out(bat_priv->nc.timestamp_sniffed_purge, |
722 | bat_priv->nc.max_buffer_time)) { | 720 | bat_priv->nc.max_buffer_time)) { |
723 | batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.decoding_hash, | 721 | batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.decoding_hash, |
724 | batadv_nc_sniffed_purge); | 722 | batadv_nc_sniffed_purge); |
725 | bat_priv->nc.timestamp_sniffed_purge = jiffies; | 723 | bat_priv->nc.timestamp_sniffed_purge = jiffies; |
726 | } | 724 | } |
727 | 725 | ||
728 | /* Schedule a new check */ | 726 | /* Schedule a new check */ |
729 | batadv_nc_start_timer(bat_priv); | 727 | batadv_nc_start_timer(bat_priv); |
730 | } | 728 | } |
731 | 729 | ||
732 | /** | 730 | /** |
733 | * batadv_can_nc_with_orig - checks whether the given orig node is suitable for | 731 | * batadv_can_nc_with_orig - checks whether the given orig node is suitable for |
734 | * coding or not | 732 | * coding or not |
735 | * @bat_priv: the bat priv with all the soft interface information | 733 | * @bat_priv: the bat priv with all the soft interface information |
736 | * @orig_node: neighboring orig node which may be used as nc candidate | 734 | * @orig_node: neighboring orig node which may be used as nc candidate |
737 | * @ogm_packet: incoming ogm packet also used for the checks | 735 | * @ogm_packet: incoming ogm packet also used for the checks |
738 | * | 736 | * |
739 | * Returns true if: | 737 | * Returns true if: |
740 | * 1) The OGM must have the most recent sequence number. | 738 | * 1) The OGM must have the most recent sequence number. |
741 | * 2) The TTL must be decremented by one and only one. | 739 | * 2) The TTL must be decremented by one and only one. |
742 | * 3) The OGM must be received from the first hop from orig_node. | 740 | * 3) The OGM must be received from the first hop from orig_node. |
743 | * 4) The TQ value of the OGM must be above bat_priv->nc.min_tq. | 741 | * 4) The TQ value of the OGM must be above bat_priv->nc.min_tq. |
744 | */ | 742 | */ |
745 | static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv, | 743 | static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv, |
746 | struct batadv_orig_node *orig_node, | 744 | struct batadv_orig_node *orig_node, |
747 | struct batadv_ogm_packet *ogm_packet) | 745 | struct batadv_ogm_packet *ogm_packet) |
748 | { | 746 | { |
749 | struct batadv_orig_ifinfo *orig_ifinfo; | 747 | struct batadv_orig_ifinfo *orig_ifinfo; |
750 | u32 last_real_seqno; | 748 | u32 last_real_seqno; |
751 | u8 last_ttl; | 749 | u8 last_ttl; |
752 | 750 | ||
753 | orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT); | 751 | orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT); |
754 | if (!orig_ifinfo) | 752 | if (!orig_ifinfo) |
755 | return false; | 753 | return false; |
756 | 754 | ||
757 | last_ttl = orig_ifinfo->last_ttl; | 755 | last_ttl = orig_ifinfo->last_ttl; |
758 | last_real_seqno = orig_ifinfo->last_real_seqno; | 756 | last_real_seqno = orig_ifinfo->last_real_seqno; |
759 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | 757 | batadv_orig_ifinfo_free_ref(orig_ifinfo); |
760 | 758 | ||
761 | if (last_real_seqno != ntohl(ogm_packet->seqno)) | 759 | if (last_real_seqno != ntohl(ogm_packet->seqno)) |
762 | return false; | 760 | return false; |
763 | if (last_ttl != ogm_packet->ttl + 1) | 761 | if (last_ttl != ogm_packet->ttl + 1) |
764 | return false; | 762 | return false; |
765 | if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender)) | 763 | if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender)) |
766 | return false; | 764 | return false; |
767 | if (ogm_packet->tq < bat_priv->nc.min_tq) | 765 | if (ogm_packet->tq < bat_priv->nc.min_tq) |
768 | return false; | 766 | return false; |
769 | 767 | ||
770 | return true; | 768 | return true; |
771 | } | 769 | } |
772 | 770 | ||
773 | /** | 771 | /** |
774 | * batadv_nc_find_nc_node - search for an existing nc node and return it | 772 | * batadv_nc_find_nc_node - search for an existing nc node and return it |
775 | * @orig_node: orig node originating the ogm packet | 773 | * @orig_node: orig node originating the ogm packet |
776 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet | 774 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet |
777 | * (can be equal to orig_node) | 775 | * (can be equal to orig_node) |
778 | * @in_coding: traverse incoming or outgoing network coding list | 776 | * @in_coding: traverse incoming or outgoing network coding list |
779 | * | 777 | * |
780 | * Returns the nc_node if found, NULL otherwise. | 778 | * Returns the nc_node if found, NULL otherwise. |
781 | */ | 779 | */ |
782 | static struct batadv_nc_node | 780 | static struct batadv_nc_node |
783 | *batadv_nc_find_nc_node(struct batadv_orig_node *orig_node, | 781 | *batadv_nc_find_nc_node(struct batadv_orig_node *orig_node, |
784 | struct batadv_orig_node *orig_neigh_node, | 782 | struct batadv_orig_node *orig_neigh_node, |
785 | bool in_coding) | 783 | bool in_coding) |
786 | { | 784 | { |
787 | struct batadv_nc_node *nc_node, *nc_node_out = NULL; | 785 | struct batadv_nc_node *nc_node, *nc_node_out = NULL; |
788 | struct list_head *list; | 786 | struct list_head *list; |
789 | 787 | ||
790 | if (in_coding) | 788 | if (in_coding) |
791 | list = &orig_neigh_node->in_coding_list; | 789 | list = &orig_neigh_node->in_coding_list; |
792 | else | 790 | else |
793 | list = &orig_neigh_node->out_coding_list; | 791 | list = &orig_neigh_node->out_coding_list; |
794 | 792 | ||
795 | /* Traverse list of nc_nodes to orig_node */ | 793 | /* Traverse list of nc_nodes to orig_node */ |
796 | rcu_read_lock(); | 794 | rcu_read_lock(); |
797 | list_for_each_entry_rcu(nc_node, list, list) { | 795 | list_for_each_entry_rcu(nc_node, list, list) { |
798 | if (!batadv_compare_eth(nc_node->addr, orig_node->orig)) | 796 | if (!batadv_compare_eth(nc_node->addr, orig_node->orig)) |
799 | continue; | 797 | continue; |
800 | 798 | ||
801 | if (!atomic_inc_not_zero(&nc_node->refcount)) | 799 | if (!atomic_inc_not_zero(&nc_node->refcount)) |
802 | continue; | 800 | continue; |
803 | 801 | ||
804 | /* Found a match */ | 802 | /* Found a match */ |
805 | nc_node_out = nc_node; | 803 | nc_node_out = nc_node; |
806 | break; | 804 | break; |
807 | } | 805 | } |
808 | rcu_read_unlock(); | 806 | rcu_read_unlock(); |
809 | 807 | ||
810 | return nc_node_out; | 808 | return nc_node_out; |
811 | } | 809 | } |
812 | 810 | ||
813 | /** | 811 | /** |
814 | * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was | 812 | * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was |
815 | * not found | 813 | * not found |
816 | * @bat_priv: the bat priv with all the soft interface information | 814 | * @bat_priv: the bat priv with all the soft interface information |
817 | * @orig_node: orig node originating the ogm packet | 815 | * @orig_node: orig node originating the ogm packet |
818 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet | 816 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet |
819 | * (can be equal to orig_node) | 817 | * (can be equal to orig_node) |
820 | * @in_coding: traverse incoming or outgoing network coding list | 818 | * @in_coding: traverse incoming or outgoing network coding list |
821 | * | 819 | * |
822 | * Returns the nc_node if found or created, NULL in case of an error. | 820 | * Returns the nc_node if found or created, NULL in case of an error. |
823 | */ | 821 | */ |
824 | static struct batadv_nc_node | 822 | static struct batadv_nc_node |
825 | *batadv_nc_get_nc_node(struct batadv_priv *bat_priv, | 823 | *batadv_nc_get_nc_node(struct batadv_priv *bat_priv, |
826 | struct batadv_orig_node *orig_node, | 824 | struct batadv_orig_node *orig_node, |
827 | struct batadv_orig_node *orig_neigh_node, | 825 | struct batadv_orig_node *orig_neigh_node, |
828 | bool in_coding) | 826 | bool in_coding) |
829 | { | 827 | { |
830 | struct batadv_nc_node *nc_node; | 828 | struct batadv_nc_node *nc_node; |
831 | spinlock_t *lock; /* Used to lock list selected by "int in_coding" */ | 829 | spinlock_t *lock; /* Used to lock list selected by "int in_coding" */ |
832 | struct list_head *list; | 830 | struct list_head *list; |
833 | 831 | ||
834 | /* Check if nc_node is already added */ | 832 | /* Check if nc_node is already added */ |
835 | nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding); | 833 | nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding); |
836 | 834 | ||
837 | /* Node found */ | 835 | /* Node found */ |
838 | if (nc_node) | 836 | if (nc_node) |
839 | return nc_node; | 837 | return nc_node; |
840 | 838 | ||
841 | nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC); | 839 | nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC); |
842 | if (!nc_node) | 840 | if (!nc_node) |
843 | return NULL; | 841 | return NULL; |
844 | 842 | ||
845 | if (!atomic_inc_not_zero(&orig_neigh_node->refcount)) | 843 | if (!atomic_inc_not_zero(&orig_neigh_node->refcount)) |
846 | goto free; | 844 | goto free; |
847 | 845 | ||
848 | /* Initialize nc_node */ | 846 | /* Initialize nc_node */ |
849 | INIT_LIST_HEAD(&nc_node->list); | 847 | INIT_LIST_HEAD(&nc_node->list); |
850 | ether_addr_copy(nc_node->addr, orig_node->orig); | 848 | ether_addr_copy(nc_node->addr, orig_node->orig); |
851 | nc_node->orig_node = orig_neigh_node; | 849 | nc_node->orig_node = orig_neigh_node; |
852 | atomic_set(&nc_node->refcount, 2); | 850 | atomic_set(&nc_node->refcount, 2); |
853 | 851 | ||
854 | /* Select ingoing or outgoing coding node */ | 852 | /* Select ingoing or outgoing coding node */ |
855 | if (in_coding) { | 853 | if (in_coding) { |
856 | lock = &orig_neigh_node->in_coding_list_lock; | 854 | lock = &orig_neigh_node->in_coding_list_lock; |
857 | list = &orig_neigh_node->in_coding_list; | 855 | list = &orig_neigh_node->in_coding_list; |
858 | } else { | 856 | } else { |
859 | lock = &orig_neigh_node->out_coding_list_lock; | 857 | lock = &orig_neigh_node->out_coding_list_lock; |
860 | list = &orig_neigh_node->out_coding_list; | 858 | list = &orig_neigh_node->out_coding_list; |
861 | } | 859 | } |
862 | 860 | ||
863 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n", | 861 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n", |
864 | nc_node->addr, nc_node->orig_node->orig); | 862 | nc_node->addr, nc_node->orig_node->orig); |
865 | 863 | ||
866 | /* Add nc_node to orig_node */ | 864 | /* Add nc_node to orig_node */ |
867 | spin_lock_bh(lock); | 865 | spin_lock_bh(lock); |
868 | list_add_tail_rcu(&nc_node->list, list); | 866 | list_add_tail_rcu(&nc_node->list, list); |
869 | spin_unlock_bh(lock); | 867 | spin_unlock_bh(lock); |
870 | 868 | ||
871 | return nc_node; | 869 | return nc_node; |
872 | 870 | ||
873 | free: | 871 | free: |
874 | kfree(nc_node); | 872 | kfree(nc_node); |
875 | return NULL; | 873 | return NULL; |
876 | } | 874 | } |
877 | 875 | ||
878 | /** | 876 | /** |
879 | * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node | 877 | * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node |
880 | * structs (best called on incoming OGMs) | 878 | * structs (best called on incoming OGMs) |
881 | * @bat_priv: the bat priv with all the soft interface information | 879 | * @bat_priv: the bat priv with all the soft interface information |
882 | * @orig_node: orig node originating the ogm packet | 880 | * @orig_node: orig node originating the ogm packet |
883 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet | 881 | * @orig_neigh_node: neighboring orig node from which we received the ogm packet |
884 | * (can be equal to orig_node) | 882 | * (can be equal to orig_node) |
885 | * @ogm_packet: incoming ogm packet | 883 | * @ogm_packet: incoming ogm packet |
886 | * @is_single_hop_neigh: orig_node is a single hop neighbor | 884 | * @is_single_hop_neigh: orig_node is a single hop neighbor |
887 | */ | 885 | */ |
888 | void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, | 886 | void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, |
889 | struct batadv_orig_node *orig_node, | 887 | struct batadv_orig_node *orig_node, |
890 | struct batadv_orig_node *orig_neigh_node, | 888 | struct batadv_orig_node *orig_neigh_node, |
891 | struct batadv_ogm_packet *ogm_packet, | 889 | struct batadv_ogm_packet *ogm_packet, |
892 | int is_single_hop_neigh) | 890 | int is_single_hop_neigh) |
893 | { | 891 | { |
894 | struct batadv_nc_node *in_nc_node = NULL; | 892 | struct batadv_nc_node *in_nc_node = NULL; |
895 | struct batadv_nc_node *out_nc_node = NULL; | 893 | struct batadv_nc_node *out_nc_node = NULL; |
896 | 894 | ||
897 | /* Check if network coding is enabled */ | 895 | /* Check if network coding is enabled */ |
898 | if (!atomic_read(&bat_priv->network_coding)) | 896 | if (!atomic_read(&bat_priv->network_coding)) |
899 | goto out; | 897 | goto out; |
900 | 898 | ||
901 | /* check if orig node is network coding enabled */ | 899 | /* check if orig node is network coding enabled */ |
902 | if (!test_bit(BATADV_ORIG_CAPA_HAS_NC, &orig_node->capabilities)) | 900 | if (!test_bit(BATADV_ORIG_CAPA_HAS_NC, &orig_node->capabilities)) |
903 | goto out; | 901 | goto out; |
904 | 902 | ||
905 | /* accept ogms from 'good' neighbors and single hop neighbors */ | 903 | /* accept ogms from 'good' neighbors and single hop neighbors */ |
906 | if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) && | 904 | if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) && |
907 | !is_single_hop_neigh) | 905 | !is_single_hop_neigh) |
908 | goto out; | 906 | goto out; |
909 | 907 | ||
910 | /* Add orig_node as in_nc_node on hop */ | 908 | /* Add orig_node as in_nc_node on hop */ |
911 | in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node, | 909 | in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node, |
912 | orig_neigh_node, true); | 910 | orig_neigh_node, true); |
913 | if (!in_nc_node) | 911 | if (!in_nc_node) |
914 | goto out; | 912 | goto out; |
915 | 913 | ||
916 | in_nc_node->last_seen = jiffies; | 914 | in_nc_node->last_seen = jiffies; |
917 | 915 | ||
918 | /* Add hop as out_nc_node on orig_node */ | 916 | /* Add hop as out_nc_node on orig_node */ |
919 | out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node, | 917 | out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node, |
920 | orig_node, false); | 918 | orig_node, false); |
921 | if (!out_nc_node) | 919 | if (!out_nc_node) |
922 | goto out; | 920 | goto out; |
923 | 921 | ||
924 | out_nc_node->last_seen = jiffies; | 922 | out_nc_node->last_seen = jiffies; |
925 | 923 | ||
926 | out: | 924 | out: |
927 | if (in_nc_node) | 925 | if (in_nc_node) |
928 | batadv_nc_node_free_ref(in_nc_node); | 926 | batadv_nc_node_free_ref(in_nc_node); |
929 | if (out_nc_node) | 927 | if (out_nc_node) |
930 | batadv_nc_node_free_ref(out_nc_node); | 928 | batadv_nc_node_free_ref(out_nc_node); |
931 | } | 929 | } |
932 | 930 | ||
933 | /** | 931 | /** |
934 | * batadv_nc_get_path - get existing nc_path or allocate a new one | 932 | * batadv_nc_get_path - get existing nc_path or allocate a new one |
935 | * @bat_priv: the bat priv with all the soft interface information | 933 | * @bat_priv: the bat priv with all the soft interface information |
936 | * @hash: hash table containing the nc path | 934 | * @hash: hash table containing the nc path |
937 | * @src: ethernet source address - first half of the nc path search key | 935 | * @src: ethernet source address - first half of the nc path search key |
938 | * @dst: ethernet destination address - second half of the nc path search key | 936 | * @dst: ethernet destination address - second half of the nc path search key |
939 | * | 937 | * |
940 | * Returns pointer to nc_path if the path was found or created, returns NULL | 938 | * Returns pointer to nc_path if the path was found or created, returns NULL |
941 | * on error. | 939 | * on error. |
942 | */ | 940 | */ |
943 | static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, | 941 | static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, |
944 | struct batadv_hashtable *hash, | 942 | struct batadv_hashtable *hash, |
945 | u8 *src, | 943 | u8 *src, |
946 | u8 *dst) | 944 | u8 *dst) |
947 | { | 945 | { |
948 | int hash_added; | 946 | int hash_added; |
949 | struct batadv_nc_path *nc_path, nc_path_key; | 947 | struct batadv_nc_path *nc_path, nc_path_key; |
950 | 948 | ||
951 | batadv_nc_hash_key_gen(&nc_path_key, src, dst); | 949 | batadv_nc_hash_key_gen(&nc_path_key, src, dst); |
952 | 950 | ||
953 | /* Search for existing nc_path */ | 951 | /* Search for existing nc_path */ |
954 | nc_path = batadv_nc_hash_find(hash, (void *)&nc_path_key); | 952 | nc_path = batadv_nc_hash_find(hash, (void *)&nc_path_key); |
955 | 953 | ||
956 | if (nc_path) { | 954 | if (nc_path) { |
957 | /* Set timestamp to delay removal of nc_path */ | 955 | /* Set timestamp to delay removal of nc_path */ |
958 | nc_path->last_valid = jiffies; | 956 | nc_path->last_valid = jiffies; |
959 | return nc_path; | 957 | return nc_path; |
960 | } | 958 | } |
961 | 959 | ||
962 | /* No existing nc_path was found; create a new */ | 960 | /* No existing nc_path was found; create a new */ |
963 | nc_path = kzalloc(sizeof(*nc_path), GFP_ATOMIC); | 961 | nc_path = kzalloc(sizeof(*nc_path), GFP_ATOMIC); |
964 | 962 | ||
965 | if (!nc_path) | 963 | if (!nc_path) |
966 | return NULL; | 964 | return NULL; |
967 | 965 | ||
968 | /* Initialize nc_path */ | 966 | /* Initialize nc_path */ |
969 | INIT_LIST_HEAD(&nc_path->packet_list); | 967 | INIT_LIST_HEAD(&nc_path->packet_list); |
970 | spin_lock_init(&nc_path->packet_list_lock); | 968 | spin_lock_init(&nc_path->packet_list_lock); |
971 | atomic_set(&nc_path->refcount, 2); | 969 | atomic_set(&nc_path->refcount, 2); |
972 | nc_path->last_valid = jiffies; | 970 | nc_path->last_valid = jiffies; |
973 | ether_addr_copy(nc_path->next_hop, dst); | 971 | ether_addr_copy(nc_path->next_hop, dst); |
974 | ether_addr_copy(nc_path->prev_hop, src); | 972 | ether_addr_copy(nc_path->prev_hop, src); |
975 | 973 | ||
976 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n", | 974 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n", |
977 | nc_path->prev_hop, | 975 | nc_path->prev_hop, |
978 | nc_path->next_hop); | 976 | nc_path->next_hop); |
979 | 977 | ||
980 | /* Add nc_path to hash table */ | 978 | /* Add nc_path to hash table */ |
981 | hash_added = batadv_hash_add(hash, batadv_nc_hash_compare, | 979 | hash_added = batadv_hash_add(hash, batadv_nc_hash_compare, |
982 | batadv_nc_hash_choose, &nc_path_key, | 980 | batadv_nc_hash_choose, &nc_path_key, |
983 | &nc_path->hash_entry); | 981 | &nc_path->hash_entry); |
984 | 982 | ||
985 | if (hash_added < 0) { | 983 | if (hash_added < 0) { |
986 | kfree(nc_path); | 984 | kfree(nc_path); |
987 | return NULL; | 985 | return NULL; |
988 | } | 986 | } |
989 | 987 | ||
990 | return nc_path; | 988 | return nc_path; |
991 | } | 989 | } |
992 | 990 | ||
993 | /** | 991 | /** |
994 | * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair | 992 | * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair |
995 | * selection of a receiver with slightly lower TQ than the other | 993 | * selection of a receiver with slightly lower TQ than the other |
996 | * @tq: to be weighted tq value | 994 | * @tq: to be weighted tq value |
997 | */ | 995 | */ |
998 | static u8 batadv_nc_random_weight_tq(u8 tq) | 996 | static u8 batadv_nc_random_weight_tq(u8 tq) |
999 | { | 997 | { |
1000 | u8 rand_val, rand_tq; | 998 | u8 rand_val, rand_tq; |
1001 | 999 | ||
1002 | get_random_bytes(&rand_val, sizeof(rand_val)); | 1000 | get_random_bytes(&rand_val, sizeof(rand_val)); |
1003 | 1001 | ||
1004 | /* randomize the estimated packet loss (max TQ - estimated TQ) */ | 1002 | /* randomize the estimated packet loss (max TQ - estimated TQ) */ |
1005 | rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq); | 1003 | rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq); |
1006 | 1004 | ||
1007 | /* normalize the randomized packet loss */ | 1005 | /* normalize the randomized packet loss */ |
1008 | rand_tq /= BATADV_TQ_MAX_VALUE; | 1006 | rand_tq /= BATADV_TQ_MAX_VALUE; |
1009 | 1007 | ||
1010 | /* convert to (randomized) estimated tq again */ | 1008 | /* convert to (randomized) estimated tq again */ |
1011 | return BATADV_TQ_MAX_VALUE - rand_tq; | 1009 | return BATADV_TQ_MAX_VALUE - rand_tq; |
1012 | } | 1010 | } |
1013 | 1011 | ||
1014 | /** | 1012 | /** |
1015 | * batadv_nc_memxor - XOR destination with source | 1013 | * batadv_nc_memxor - XOR destination with source |
1016 | * @dst: byte array to XOR into | 1014 | * @dst: byte array to XOR into |
1017 | * @src: byte array to XOR from | 1015 | * @src: byte array to XOR from |
1018 | * @len: length of destination array | 1016 | * @len: length of destination array |
1019 | */ | 1017 | */ |
1020 | static void batadv_nc_memxor(char *dst, const char *src, unsigned int len) | 1018 | static void batadv_nc_memxor(char *dst, const char *src, unsigned int len) |
1021 | { | 1019 | { |
1022 | unsigned int i; | 1020 | unsigned int i; |
1023 | 1021 | ||
1024 | for (i = 0; i < len; ++i) | 1022 | for (i = 0; i < len; ++i) |
1025 | dst[i] ^= src[i]; | 1023 | dst[i] ^= src[i]; |
1026 | } | 1024 | } |
1027 | 1025 | ||
1028 | /** | 1026 | /** |
1029 | * batadv_nc_code_packets - code a received unicast_packet with an nc packet | 1027 | * batadv_nc_code_packets - code a received unicast_packet with an nc packet |
1030 | * into a coded_packet and send it | 1028 | * into a coded_packet and send it |
1031 | * @bat_priv: the bat priv with all the soft interface information | 1029 | * @bat_priv: the bat priv with all the soft interface information |
1032 | * @skb: data skb to forward | 1030 | * @skb: data skb to forward |
1033 | * @ethhdr: pointer to the ethernet header inside the skb | 1031 | * @ethhdr: pointer to the ethernet header inside the skb |
1034 | * @nc_packet: structure containing the packet to the skb can be coded with | 1032 | * @nc_packet: structure containing the packet to the skb can be coded with |
1035 | * @neigh_node: next hop to forward packet to | 1033 | * @neigh_node: next hop to forward packet to |
1036 | * | 1034 | * |
1037 | * Returns true if both packets are consumed, false otherwise. | 1035 | * Returns true if both packets are consumed, false otherwise. |
1038 | */ | 1036 | */ |
1039 | static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | 1037 | static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, |
1040 | struct sk_buff *skb, | 1038 | struct sk_buff *skb, |
1041 | struct ethhdr *ethhdr, | 1039 | struct ethhdr *ethhdr, |
1042 | struct batadv_nc_packet *nc_packet, | 1040 | struct batadv_nc_packet *nc_packet, |
1043 | struct batadv_neigh_node *neigh_node) | 1041 | struct batadv_neigh_node *neigh_node) |
1044 | { | 1042 | { |
1045 | u8 tq_weighted_neigh, tq_weighted_coding, tq_tmp; | 1043 | u8 tq_weighted_neigh, tq_weighted_coding, tq_tmp; |
1046 | struct sk_buff *skb_dest, *skb_src; | 1044 | struct sk_buff *skb_dest, *skb_src; |
1047 | struct batadv_unicast_packet *packet1; | 1045 | struct batadv_unicast_packet *packet1; |
1048 | struct batadv_unicast_packet *packet2; | 1046 | struct batadv_unicast_packet *packet2; |
1049 | struct batadv_coded_packet *coded_packet; | 1047 | struct batadv_coded_packet *coded_packet; |
1050 | struct batadv_neigh_node *neigh_tmp, *router_neigh; | 1048 | struct batadv_neigh_node *neigh_tmp, *router_neigh; |
1051 | struct batadv_neigh_node *router_coding = NULL; | 1049 | struct batadv_neigh_node *router_coding = NULL; |
1052 | struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; | 1050 | struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; |
1053 | struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; | 1051 | struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; |
1054 | u8 *first_source, *first_dest, *second_source, *second_dest; | 1052 | u8 *first_source, *first_dest, *second_source, *second_dest; |
1055 | __be32 packet_id1, packet_id2; | 1053 | __be32 packet_id1, packet_id2; |
1056 | size_t count; | 1054 | size_t count; |
1057 | bool res = false; | 1055 | bool res = false; |
1058 | int coding_len; | 1056 | int coding_len; |
1059 | int unicast_size = sizeof(*packet1); | 1057 | int unicast_size = sizeof(*packet1); |
1060 | int coded_size = sizeof(*coded_packet); | 1058 | int coded_size = sizeof(*coded_packet); |
1061 | int header_add = coded_size - unicast_size; | 1059 | int header_add = coded_size - unicast_size; |
1062 | 1060 | ||
1063 | /* TODO: do we need to consider the outgoing interface for | 1061 | /* TODO: do we need to consider the outgoing interface for |
1064 | * coded packets? | 1062 | * coded packets? |
1065 | */ | 1063 | */ |
1066 | router_neigh = batadv_orig_router_get(neigh_node->orig_node, | 1064 | router_neigh = batadv_orig_router_get(neigh_node->orig_node, |
1067 | BATADV_IF_DEFAULT); | 1065 | BATADV_IF_DEFAULT); |
1068 | if (!router_neigh) | 1066 | if (!router_neigh) |
1069 | goto out; | 1067 | goto out; |
1070 | 1068 | ||
1071 | router_neigh_ifinfo = batadv_neigh_ifinfo_get(router_neigh, | 1069 | router_neigh_ifinfo = batadv_neigh_ifinfo_get(router_neigh, |
1072 | BATADV_IF_DEFAULT); | 1070 | BATADV_IF_DEFAULT); |
1073 | if (!router_neigh_ifinfo) | 1071 | if (!router_neigh_ifinfo) |
1074 | goto out; | 1072 | goto out; |
1075 | 1073 | ||
1076 | neigh_tmp = nc_packet->neigh_node; | 1074 | neigh_tmp = nc_packet->neigh_node; |
1077 | router_coding = batadv_orig_router_get(neigh_tmp->orig_node, | 1075 | router_coding = batadv_orig_router_get(neigh_tmp->orig_node, |
1078 | BATADV_IF_DEFAULT); | 1076 | BATADV_IF_DEFAULT); |
1079 | if (!router_coding) | 1077 | if (!router_coding) |
1080 | goto out; | 1078 | goto out; |
1081 | 1079 | ||
1082 | router_coding_ifinfo = batadv_neigh_ifinfo_get(router_coding, | 1080 | router_coding_ifinfo = batadv_neigh_ifinfo_get(router_coding, |
1083 | BATADV_IF_DEFAULT); | 1081 | BATADV_IF_DEFAULT); |
1084 | if (!router_coding_ifinfo) | 1082 | if (!router_coding_ifinfo) |
1085 | goto out; | 1083 | goto out; |
1086 | 1084 | ||
1087 | tq_tmp = router_neigh_ifinfo->bat_iv.tq_avg; | 1085 | tq_tmp = router_neigh_ifinfo->bat_iv.tq_avg; |
1088 | tq_weighted_neigh = batadv_nc_random_weight_tq(tq_tmp); | 1086 | tq_weighted_neigh = batadv_nc_random_weight_tq(tq_tmp); |
1089 | tq_tmp = router_coding_ifinfo->bat_iv.tq_avg; | 1087 | tq_tmp = router_coding_ifinfo->bat_iv.tq_avg; |
1090 | tq_weighted_coding = batadv_nc_random_weight_tq(tq_tmp); | 1088 | tq_weighted_coding = batadv_nc_random_weight_tq(tq_tmp); |
1091 | 1089 | ||
1092 | /* Select one destination for the MAC-header dst-field based on | 1090 | /* Select one destination for the MAC-header dst-field based on |
1093 | * weighted TQ-values. | 1091 | * weighted TQ-values. |
1094 | */ | 1092 | */ |
1095 | if (tq_weighted_neigh >= tq_weighted_coding) { | 1093 | if (tq_weighted_neigh >= tq_weighted_coding) { |
1096 | /* Destination from nc_packet is selected for MAC-header */ | 1094 | /* Destination from nc_packet is selected for MAC-header */ |
1097 | first_dest = nc_packet->nc_path->next_hop; | 1095 | first_dest = nc_packet->nc_path->next_hop; |
1098 | first_source = nc_packet->nc_path->prev_hop; | 1096 | first_source = nc_packet->nc_path->prev_hop; |
1099 | second_dest = neigh_node->addr; | 1097 | second_dest = neigh_node->addr; |
1100 | second_source = ethhdr->h_source; | 1098 | second_source = ethhdr->h_source; |
1101 | packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data; | 1099 | packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data; |
1102 | packet2 = (struct batadv_unicast_packet *)skb->data; | 1100 | packet2 = (struct batadv_unicast_packet *)skb->data; |
1103 | packet_id1 = nc_packet->packet_id; | 1101 | packet_id1 = nc_packet->packet_id; |
1104 | packet_id2 = batadv_skb_crc32(skb, | 1102 | packet_id2 = batadv_skb_crc32(skb, |
1105 | skb->data + sizeof(*packet2)); | 1103 | skb->data + sizeof(*packet2)); |
1106 | } else { | 1104 | } else { |
1107 | /* Destination for skb is selected for MAC-header */ | 1105 | /* Destination for skb is selected for MAC-header */ |
1108 | first_dest = neigh_node->addr; | 1106 | first_dest = neigh_node->addr; |
1109 | first_source = ethhdr->h_source; | 1107 | first_source = ethhdr->h_source; |
1110 | second_dest = nc_packet->nc_path->next_hop; | 1108 | second_dest = nc_packet->nc_path->next_hop; |
1111 | second_source = nc_packet->nc_path->prev_hop; | 1109 | second_source = nc_packet->nc_path->prev_hop; |
1112 | packet1 = (struct batadv_unicast_packet *)skb->data; | 1110 | packet1 = (struct batadv_unicast_packet *)skb->data; |
1113 | packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data; | 1111 | packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data; |
1114 | packet_id1 = batadv_skb_crc32(skb, | 1112 | packet_id1 = batadv_skb_crc32(skb, |
1115 | skb->data + sizeof(*packet1)); | 1113 | skb->data + sizeof(*packet1)); |
1116 | packet_id2 = nc_packet->packet_id; | 1114 | packet_id2 = nc_packet->packet_id; |
1117 | } | 1115 | } |
1118 | 1116 | ||
1119 | /* Instead of zero padding the smallest data buffer, we | 1117 | /* Instead of zero padding the smallest data buffer, we |
1120 | * code into the largest. | 1118 | * code into the largest. |
1121 | */ | 1119 | */ |
1122 | if (skb->len <= nc_packet->skb->len) { | 1120 | if (skb->len <= nc_packet->skb->len) { |
1123 | skb_dest = nc_packet->skb; | 1121 | skb_dest = nc_packet->skb; |
1124 | skb_src = skb; | 1122 | skb_src = skb; |
1125 | } else { | 1123 | } else { |
1126 | skb_dest = skb; | 1124 | skb_dest = skb; |
1127 | skb_src = nc_packet->skb; | 1125 | skb_src = nc_packet->skb; |
1128 | } | 1126 | } |
1129 | 1127 | ||
1130 | /* coding_len is used when decoding the packet shorter packet */ | 1128 | /* coding_len is used when decoding the packet shorter packet */ |
1131 | coding_len = skb_src->len - unicast_size; | 1129 | coding_len = skb_src->len - unicast_size; |
1132 | 1130 | ||
1133 | if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0) | 1131 | if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0) |
1134 | goto out; | 1132 | goto out; |
1135 | 1133 | ||
1136 | skb_push(skb_dest, header_add); | 1134 | skb_push(skb_dest, header_add); |
1137 | 1135 | ||
1138 | coded_packet = (struct batadv_coded_packet *)skb_dest->data; | 1136 | coded_packet = (struct batadv_coded_packet *)skb_dest->data; |
1139 | skb_reset_mac_header(skb_dest); | 1137 | skb_reset_mac_header(skb_dest); |
1140 | 1138 | ||
1141 | coded_packet->packet_type = BATADV_CODED; | 1139 | coded_packet->packet_type = BATADV_CODED; |
1142 | coded_packet->version = BATADV_COMPAT_VERSION; | 1140 | coded_packet->version = BATADV_COMPAT_VERSION; |
1143 | coded_packet->ttl = packet1->ttl; | 1141 | coded_packet->ttl = packet1->ttl; |
1144 | 1142 | ||
1145 | /* Info about first unicast packet */ | 1143 | /* Info about first unicast packet */ |
1146 | ether_addr_copy(coded_packet->first_source, first_source); | 1144 | ether_addr_copy(coded_packet->first_source, first_source); |
1147 | ether_addr_copy(coded_packet->first_orig_dest, packet1->dest); | 1145 | ether_addr_copy(coded_packet->first_orig_dest, packet1->dest); |
1148 | coded_packet->first_crc = packet_id1; | 1146 | coded_packet->first_crc = packet_id1; |
1149 | coded_packet->first_ttvn = packet1->ttvn; | 1147 | coded_packet->first_ttvn = packet1->ttvn; |
1150 | 1148 | ||
1151 | /* Info about second unicast packet */ | 1149 | /* Info about second unicast packet */ |
1152 | ether_addr_copy(coded_packet->second_dest, second_dest); | 1150 | ether_addr_copy(coded_packet->second_dest, second_dest); |
1153 | ether_addr_copy(coded_packet->second_source, second_source); | 1151 | ether_addr_copy(coded_packet->second_source, second_source); |
1154 | ether_addr_copy(coded_packet->second_orig_dest, packet2->dest); | 1152 | ether_addr_copy(coded_packet->second_orig_dest, packet2->dest); |
1155 | coded_packet->second_crc = packet_id2; | 1153 | coded_packet->second_crc = packet_id2; |
1156 | coded_packet->second_ttl = packet2->ttl; | 1154 | coded_packet->second_ttl = packet2->ttl; |
1157 | coded_packet->second_ttvn = packet2->ttvn; | 1155 | coded_packet->second_ttvn = packet2->ttvn; |
1158 | coded_packet->coded_len = htons(coding_len); | 1156 | coded_packet->coded_len = htons(coding_len); |
1159 | 1157 | ||
1160 | /* This is where the magic happens: Code skb_src into skb_dest */ | 1158 | /* This is where the magic happens: Code skb_src into skb_dest */ |
1161 | batadv_nc_memxor(skb_dest->data + coded_size, | 1159 | batadv_nc_memxor(skb_dest->data + coded_size, |
1162 | skb_src->data + unicast_size, coding_len); | 1160 | skb_src->data + unicast_size, coding_len); |
1163 | 1161 | ||
1164 | /* Update counters accordingly */ | 1162 | /* Update counters accordingly */ |
1165 | if (BATADV_SKB_CB(skb_src)->decoded && | 1163 | if (BATADV_SKB_CB(skb_src)->decoded && |
1166 | BATADV_SKB_CB(skb_dest)->decoded) { | 1164 | BATADV_SKB_CB(skb_dest)->decoded) { |
1167 | /* Both packets are recoded */ | 1165 | /* Both packets are recoded */ |
1168 | count = skb_src->len + ETH_HLEN; | 1166 | count = skb_src->len + ETH_HLEN; |
1169 | count += skb_dest->len + ETH_HLEN; | 1167 | count += skb_dest->len + ETH_HLEN; |
1170 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2); | 1168 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2); |
1171 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count); | 1169 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count); |
1172 | } else if (!BATADV_SKB_CB(skb_src)->decoded && | 1170 | } else if (!BATADV_SKB_CB(skb_src)->decoded && |
1173 | !BATADV_SKB_CB(skb_dest)->decoded) { | 1171 | !BATADV_SKB_CB(skb_dest)->decoded) { |
1174 | /* Both packets are newly coded */ | 1172 | /* Both packets are newly coded */ |
1175 | count = skb_src->len + ETH_HLEN; | 1173 | count = skb_src->len + ETH_HLEN; |
1176 | count += skb_dest->len + ETH_HLEN; | 1174 | count += skb_dest->len + ETH_HLEN; |
1177 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2); | 1175 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2); |
1178 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count); | 1176 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count); |
1179 | } else if (BATADV_SKB_CB(skb_src)->decoded && | 1177 | } else if (BATADV_SKB_CB(skb_src)->decoded && |
1180 | !BATADV_SKB_CB(skb_dest)->decoded) { | 1178 | !BATADV_SKB_CB(skb_dest)->decoded) { |
1181 | /* skb_src recoded and skb_dest is newly coded */ | 1179 | /* skb_src recoded and skb_dest is newly coded */ |
1182 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE); | 1180 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE); |
1183 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, | 1181 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, |
1184 | skb_src->len + ETH_HLEN); | 1182 | skb_src->len + ETH_HLEN); |
1185 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE); | 1183 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE); |
1186 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, | 1184 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, |
1187 | skb_dest->len + ETH_HLEN); | 1185 | skb_dest->len + ETH_HLEN); |
1188 | } else if (!BATADV_SKB_CB(skb_src)->decoded && | 1186 | } else if (!BATADV_SKB_CB(skb_src)->decoded && |
1189 | BATADV_SKB_CB(skb_dest)->decoded) { | 1187 | BATADV_SKB_CB(skb_dest)->decoded) { |
1190 | /* skb_src is newly coded and skb_dest is recoded */ | 1188 | /* skb_src is newly coded and skb_dest is recoded */ |
1191 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE); | 1189 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE); |
1192 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, | 1190 | batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, |
1193 | skb_src->len + ETH_HLEN); | 1191 | skb_src->len + ETH_HLEN); |
1194 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE); | 1192 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE); |
1195 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, | 1193 | batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, |
1196 | skb_dest->len + ETH_HLEN); | 1194 | skb_dest->len + ETH_HLEN); |
1197 | } | 1195 | } |
1198 | 1196 | ||
1199 | /* skb_src is now coded into skb_dest, so free it */ | 1197 | /* skb_src is now coded into skb_dest, so free it */ |
1200 | kfree_skb(skb_src); | 1198 | kfree_skb(skb_src); |
1201 | 1199 | ||
1202 | /* avoid duplicate free of skb from nc_packet */ | 1200 | /* avoid duplicate free of skb from nc_packet */ |
1203 | nc_packet->skb = NULL; | 1201 | nc_packet->skb = NULL; |
1204 | batadv_nc_packet_free(nc_packet); | 1202 | batadv_nc_packet_free(nc_packet); |
1205 | 1203 | ||
1206 | /* Send the coded packet and return true */ | 1204 | /* Send the coded packet and return true */ |
1207 | batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest); | 1205 | batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest); |
1208 | res = true; | 1206 | res = true; |
1209 | out: | 1207 | out: |
1210 | if (router_neigh) | 1208 | if (router_neigh) |
1211 | batadv_neigh_node_free_ref(router_neigh); | 1209 | batadv_neigh_node_free_ref(router_neigh); |
1212 | if (router_coding) | 1210 | if (router_coding) |
1213 | batadv_neigh_node_free_ref(router_coding); | 1211 | batadv_neigh_node_free_ref(router_coding); |
1214 | if (router_neigh_ifinfo) | 1212 | if (router_neigh_ifinfo) |
1215 | batadv_neigh_ifinfo_free_ref(router_neigh_ifinfo); | 1213 | batadv_neigh_ifinfo_free_ref(router_neigh_ifinfo); |
1216 | if (router_coding_ifinfo) | 1214 | if (router_coding_ifinfo) |
1217 | batadv_neigh_ifinfo_free_ref(router_coding_ifinfo); | 1215 | batadv_neigh_ifinfo_free_ref(router_coding_ifinfo); |
1218 | return res; | 1216 | return res; |
1219 | } | 1217 | } |
1220 | 1218 | ||
1221 | /** | 1219 | /** |
1222 | * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst. | 1220 | * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst. |
1223 | * @skb: data skb to forward | 1221 | * @skb: data skb to forward |
1224 | * @dst: destination mac address of the other skb to code with | 1222 | * @dst: destination mac address of the other skb to code with |
1225 | * @src: source mac address of skb | 1223 | * @src: source mac address of skb |
1226 | * | 1224 | * |
1227 | * Whenever we network code a packet we have to check whether we received it in | 1225 | * Whenever we network code a packet we have to check whether we received it in |
1228 | * a network coded form. If so, we may not be able to use it for coding because | 1226 | * a network coded form. If so, we may not be able to use it for coding because |
1229 | * some neighbors may also have received (overheard) the packet in the network | 1227 | * some neighbors may also have received (overheard) the packet in the network |
1230 | * coded form without being able to decode it. It is hard to know which of the | 1228 | * coded form without being able to decode it. It is hard to know which of the |
1231 | * neighboring nodes was able to decode the packet, therefore we can only | 1229 | * neighboring nodes was able to decode the packet, therefore we can only |
1232 | * re-code the packet if the source of the previous encoded packet is involved. | 1230 | * re-code the packet if the source of the previous encoded packet is involved. |
1233 | * Since the source encoded the packet we can be certain it has all necessary | 1231 | * Since the source encoded the packet we can be certain it has all necessary |
1234 | * decode information. | 1232 | * decode information. |
1235 | * | 1233 | * |
1236 | * Returns true if coding of a decoded packet is allowed. | 1234 | * Returns true if coding of a decoded packet is allowed. |
1237 | */ | 1235 | */ |
1238 | static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, u8 *dst, u8 *src) | 1236 | static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, u8 *dst, u8 *src) |
1239 | { | 1237 | { |
1240 | if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src)) | 1238 | if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src)) |
1241 | return false; | 1239 | return false; |
1242 | return true; | 1240 | return true; |
1243 | } | 1241 | } |
1244 | 1242 | ||
1245 | /** | 1243 | /** |
1246 | * batadv_nc_path_search - Find the coding path matching in_nc_node and | 1244 | * batadv_nc_path_search - Find the coding path matching in_nc_node and |
1247 | * out_nc_node to retrieve a buffered packet that can be used for coding. | 1245 | * out_nc_node to retrieve a buffered packet that can be used for coding. |
1248 | * @bat_priv: the bat priv with all the soft interface information | 1246 | * @bat_priv: the bat priv with all the soft interface information |
1249 | * @in_nc_node: pointer to skb next hop's neighbor nc node | 1247 | * @in_nc_node: pointer to skb next hop's neighbor nc node |
1250 | * @out_nc_node: pointer to skb source's neighbor nc node | 1248 | * @out_nc_node: pointer to skb source's neighbor nc node |
1251 | * @skb: data skb to forward | 1249 | * @skb: data skb to forward |
1252 | * @eth_dst: next hop mac address of skb | 1250 | * @eth_dst: next hop mac address of skb |
1253 | * | 1251 | * |
1254 | * Returns true if coding of a decoded skb is allowed. | 1252 | * Returns true if coding of a decoded skb is allowed. |
1255 | */ | 1253 | */ |
1256 | static struct batadv_nc_packet * | 1254 | static struct batadv_nc_packet * |
1257 | batadv_nc_path_search(struct batadv_priv *bat_priv, | 1255 | batadv_nc_path_search(struct batadv_priv *bat_priv, |
1258 | struct batadv_nc_node *in_nc_node, | 1256 | struct batadv_nc_node *in_nc_node, |
1259 | struct batadv_nc_node *out_nc_node, | 1257 | struct batadv_nc_node *out_nc_node, |
1260 | struct sk_buff *skb, | 1258 | struct sk_buff *skb, |
1261 | u8 *eth_dst) | 1259 | u8 *eth_dst) |
1262 | { | 1260 | { |
1263 | struct batadv_nc_path *nc_path, nc_path_key; | 1261 | struct batadv_nc_path *nc_path, nc_path_key; |
1264 | struct batadv_nc_packet *nc_packet_out = NULL; | 1262 | struct batadv_nc_packet *nc_packet_out = NULL; |
1265 | struct batadv_nc_packet *nc_packet, *nc_packet_tmp; | 1263 | struct batadv_nc_packet *nc_packet, *nc_packet_tmp; |
1266 | struct batadv_hashtable *hash = bat_priv->nc.coding_hash; | 1264 | struct batadv_hashtable *hash = bat_priv->nc.coding_hash; |
1267 | int idx; | 1265 | int idx; |
1268 | 1266 | ||
1269 | if (!hash) | 1267 | if (!hash) |
1270 | return NULL; | 1268 | return NULL; |
1271 | 1269 | ||
1272 | /* Create almost path key */ | 1270 | /* Create almost path key */ |
1273 | batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr, | 1271 | batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr, |
1274 | out_nc_node->addr); | 1272 | out_nc_node->addr); |
1275 | idx = batadv_nc_hash_choose(&nc_path_key, hash->size); | 1273 | idx = batadv_nc_hash_choose(&nc_path_key, hash->size); |
1276 | 1274 | ||
1277 | /* Check for coding opportunities in this nc_path */ | 1275 | /* Check for coding opportunities in this nc_path */ |
1278 | rcu_read_lock(); | 1276 | rcu_read_lock(); |
1279 | hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) { | 1277 | hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) { |
1280 | if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr)) | 1278 | if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr)) |
1281 | continue; | 1279 | continue; |
1282 | 1280 | ||
1283 | if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr)) | 1281 | if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr)) |
1284 | continue; | 1282 | continue; |
1285 | 1283 | ||
1286 | spin_lock_bh(&nc_path->packet_list_lock); | 1284 | spin_lock_bh(&nc_path->packet_list_lock); |
1287 | if (list_empty(&nc_path->packet_list)) { | 1285 | if (list_empty(&nc_path->packet_list)) { |
1288 | spin_unlock_bh(&nc_path->packet_list_lock); | 1286 | spin_unlock_bh(&nc_path->packet_list_lock); |
1289 | continue; | 1287 | continue; |
1290 | } | 1288 | } |
1291 | 1289 | ||
1292 | list_for_each_entry_safe(nc_packet, nc_packet_tmp, | 1290 | list_for_each_entry_safe(nc_packet, nc_packet_tmp, |
1293 | &nc_path->packet_list, list) { | 1291 | &nc_path->packet_list, list) { |
1294 | if (!batadv_nc_skb_coding_possible(nc_packet->skb, | 1292 | if (!batadv_nc_skb_coding_possible(nc_packet->skb, |
1295 | eth_dst, | 1293 | eth_dst, |
1296 | in_nc_node->addr)) | 1294 | in_nc_node->addr)) |
1297 | continue; | 1295 | continue; |
1298 | 1296 | ||
1299 | /* Coding opportunity is found! */ | 1297 | /* Coding opportunity is found! */ |
1300 | list_del(&nc_packet->list); | 1298 | list_del(&nc_packet->list); |
1301 | nc_packet_out = nc_packet; | 1299 | nc_packet_out = nc_packet; |
1302 | break; | 1300 | break; |
1303 | } | 1301 | } |
1304 | 1302 | ||
1305 | spin_unlock_bh(&nc_path->packet_list_lock); | 1303 | spin_unlock_bh(&nc_path->packet_list_lock); |
1306 | break; | 1304 | break; |
1307 | } | 1305 | } |
1308 | rcu_read_unlock(); | 1306 | rcu_read_unlock(); |
1309 | 1307 | ||
1310 | return nc_packet_out; | 1308 | return nc_packet_out; |
1311 | } | 1309 | } |
1312 | 1310 | ||
1313 | /** | 1311 | /** |
1314 | * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the | 1312 | * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the |
1315 | * skb's sender (may be equal to the originator). | 1313 | * skb's sender (may be equal to the originator). |
1316 | * @bat_priv: the bat priv with all the soft interface information | 1314 | * @bat_priv: the bat priv with all the soft interface information |
1317 | * @skb: data skb to forward | 1315 | * @skb: data skb to forward |
1318 | * @eth_dst: next hop mac address of skb | 1316 | * @eth_dst: next hop mac address of skb |
1319 | * @eth_src: source mac address of skb | 1317 | * @eth_src: source mac address of skb |
1320 | * @in_nc_node: pointer to skb next hop's neighbor nc node | 1318 | * @in_nc_node: pointer to skb next hop's neighbor nc node |
1321 | * | 1319 | * |
1322 | * Returns an nc packet if a suitable coding packet was found, NULL otherwise. | 1320 | * Returns an nc packet if a suitable coding packet was found, NULL otherwise. |
1323 | */ | 1321 | */ |
1324 | static struct batadv_nc_packet * | 1322 | static struct batadv_nc_packet * |
1325 | batadv_nc_skb_src_search(struct batadv_priv *bat_priv, | 1323 | batadv_nc_skb_src_search(struct batadv_priv *bat_priv, |
1326 | struct sk_buff *skb, | 1324 | struct sk_buff *skb, |
1327 | u8 *eth_dst, | 1325 | u8 *eth_dst, |
1328 | u8 *eth_src, | 1326 | u8 *eth_src, |
1329 | struct batadv_nc_node *in_nc_node) | 1327 | struct batadv_nc_node *in_nc_node) |
1330 | { | 1328 | { |
1331 | struct batadv_orig_node *orig_node; | 1329 | struct batadv_orig_node *orig_node; |
1332 | struct batadv_nc_node *out_nc_node; | 1330 | struct batadv_nc_node *out_nc_node; |
1333 | struct batadv_nc_packet *nc_packet = NULL; | 1331 | struct batadv_nc_packet *nc_packet = NULL; |
1334 | 1332 | ||
1335 | orig_node = batadv_orig_hash_find(bat_priv, eth_src); | 1333 | orig_node = batadv_orig_hash_find(bat_priv, eth_src); |
1336 | if (!orig_node) | 1334 | if (!orig_node) |
1337 | return NULL; | 1335 | return NULL; |
1338 | 1336 | ||
1339 | rcu_read_lock(); | 1337 | rcu_read_lock(); |
1340 | list_for_each_entry_rcu(out_nc_node, | 1338 | list_for_each_entry_rcu(out_nc_node, |
1341 | &orig_node->out_coding_list, list) { | 1339 | &orig_node->out_coding_list, list) { |
1342 | /* Check if the skb is decoded and if recoding is possible */ | 1340 | /* Check if the skb is decoded and if recoding is possible */ |
1343 | if (!batadv_nc_skb_coding_possible(skb, | 1341 | if (!batadv_nc_skb_coding_possible(skb, |
1344 | out_nc_node->addr, eth_src)) | 1342 | out_nc_node->addr, eth_src)) |
1345 | continue; | 1343 | continue; |
1346 | 1344 | ||
1347 | /* Search for an opportunity in this nc_path */ | 1345 | /* Search for an opportunity in this nc_path */ |
1348 | nc_packet = batadv_nc_path_search(bat_priv, in_nc_node, | 1346 | nc_packet = batadv_nc_path_search(bat_priv, in_nc_node, |
1349 | out_nc_node, skb, eth_dst); | 1347 | out_nc_node, skb, eth_dst); |
1350 | if (nc_packet) | 1348 | if (nc_packet) |
1351 | break; | 1349 | break; |
1352 | } | 1350 | } |
1353 | rcu_read_unlock(); | 1351 | rcu_read_unlock(); |
1354 | 1352 | ||
1355 | batadv_orig_node_free_ref(orig_node); | 1353 | batadv_orig_node_free_ref(orig_node); |
1356 | return nc_packet; | 1354 | return nc_packet; |
1357 | } | 1355 | } |
1358 | 1356 | ||
1359 | /** | 1357 | /** |
1360 | * batadv_nc_skb_store_before_coding - set the ethernet src and dst of the | 1358 | * batadv_nc_skb_store_before_coding - set the ethernet src and dst of the |
1361 | * unicast skb before it is stored for use in later decoding | 1359 | * unicast skb before it is stored for use in later decoding |
1362 | * @bat_priv: the bat priv with all the soft interface information | 1360 | * @bat_priv: the bat priv with all the soft interface information |
1363 | * @skb: data skb to store | 1361 | * @skb: data skb to store |
1364 | * @eth_dst_new: new destination mac address of skb | 1362 | * @eth_dst_new: new destination mac address of skb |
1365 | */ | 1363 | */ |
1366 | static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, | 1364 | static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, |
1367 | struct sk_buff *skb, | 1365 | struct sk_buff *skb, |
1368 | u8 *eth_dst_new) | 1366 | u8 *eth_dst_new) |
1369 | { | 1367 | { |
1370 | struct ethhdr *ethhdr; | 1368 | struct ethhdr *ethhdr; |
1371 | 1369 | ||
1372 | /* Copy skb header to change the mac header */ | 1370 | /* Copy skb header to change the mac header */ |
1373 | skb = pskb_copy_for_clone(skb, GFP_ATOMIC); | 1371 | skb = pskb_copy_for_clone(skb, GFP_ATOMIC); |
1374 | if (!skb) | 1372 | if (!skb) |
1375 | return; | 1373 | return; |
1376 | 1374 | ||
1377 | /* Set the mac header as if we actually sent the packet uncoded */ | 1375 | /* Set the mac header as if we actually sent the packet uncoded */ |
1378 | ethhdr = eth_hdr(skb); | 1376 | ethhdr = eth_hdr(skb); |
1379 | ether_addr_copy(ethhdr->h_source, ethhdr->h_dest); | 1377 | ether_addr_copy(ethhdr->h_source, ethhdr->h_dest); |
1380 | ether_addr_copy(ethhdr->h_dest, eth_dst_new); | 1378 | ether_addr_copy(ethhdr->h_dest, eth_dst_new); |
1381 | 1379 | ||
1382 | /* Set data pointer to MAC header to mimic packets from our tx path */ | 1380 | /* Set data pointer to MAC header to mimic packets from our tx path */ |
1383 | skb_push(skb, ETH_HLEN); | 1381 | skb_push(skb, ETH_HLEN); |
1384 | 1382 | ||
1385 | /* Add the packet to the decoding packet pool */ | 1383 | /* Add the packet to the decoding packet pool */ |
1386 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | 1384 | batadv_nc_skb_store_for_decoding(bat_priv, skb); |
1387 | 1385 | ||
1388 | /* batadv_nc_skb_store_for_decoding() clones the skb, so we must free | 1386 | /* batadv_nc_skb_store_for_decoding() clones the skb, so we must free |
1389 | * our ref | 1387 | * our ref |
1390 | */ | 1388 | */ |
1391 | kfree_skb(skb); | 1389 | kfree_skb(skb); |
1392 | } | 1390 | } |
1393 | 1391 | ||
1394 | /** | 1392 | /** |
1395 | * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst. | 1393 | * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst. |
1396 | * @skb: data skb to forward | 1394 | * @skb: data skb to forward |
1397 | * @neigh_node: next hop to forward packet to | 1395 | * @neigh_node: next hop to forward packet to |
1398 | * @ethhdr: pointer to the ethernet header inside the skb | 1396 | * @ethhdr: pointer to the ethernet header inside the skb |
1399 | * | 1397 | * |
1400 | * Loops through list of neighboring nodes the next hop has a good connection to | 1398 | * Loops through list of neighboring nodes the next hop has a good connection to |
1401 | * (receives OGMs with a sufficient quality). We need to find a neighbor of our | 1399 | * (receives OGMs with a sufficient quality). We need to find a neighbor of our |
1402 | * next hop that potentially sent a packet which our next hop also received | 1400 | * next hop that potentially sent a packet which our next hop also received |
1403 | * (overheard) and has stored for later decoding. | 1401 | * (overheard) and has stored for later decoding. |
1404 | * | 1402 | * |
1405 | * Returns true if the skb was consumed (encoded packet sent) or false otherwise | 1403 | * Returns true if the skb was consumed (encoded packet sent) or false otherwise |
1406 | */ | 1404 | */ |
1407 | static bool batadv_nc_skb_dst_search(struct sk_buff *skb, | 1405 | static bool batadv_nc_skb_dst_search(struct sk_buff *skb, |
1408 | struct batadv_neigh_node *neigh_node, | 1406 | struct batadv_neigh_node *neigh_node, |
1409 | struct ethhdr *ethhdr) | 1407 | struct ethhdr *ethhdr) |
1410 | { | 1408 | { |
1411 | struct net_device *netdev = neigh_node->if_incoming->soft_iface; | 1409 | struct net_device *netdev = neigh_node->if_incoming->soft_iface; |
1412 | struct batadv_priv *bat_priv = netdev_priv(netdev); | 1410 | struct batadv_priv *bat_priv = netdev_priv(netdev); |
1413 | struct batadv_orig_node *orig_node = neigh_node->orig_node; | 1411 | struct batadv_orig_node *orig_node = neigh_node->orig_node; |
1414 | struct batadv_nc_node *nc_node; | 1412 | struct batadv_nc_node *nc_node; |
1415 | struct batadv_nc_packet *nc_packet = NULL; | 1413 | struct batadv_nc_packet *nc_packet = NULL; |
1416 | 1414 | ||
1417 | rcu_read_lock(); | 1415 | rcu_read_lock(); |
1418 | list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) { | 1416 | list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) { |
1419 | /* Search for coding opportunity with this in_nc_node */ | 1417 | /* Search for coding opportunity with this in_nc_node */ |
1420 | nc_packet = batadv_nc_skb_src_search(bat_priv, skb, | 1418 | nc_packet = batadv_nc_skb_src_search(bat_priv, skb, |
1421 | neigh_node->addr, | 1419 | neigh_node->addr, |
1422 | ethhdr->h_source, nc_node); | 1420 | ethhdr->h_source, nc_node); |
1423 | 1421 | ||
1424 | /* Opportunity was found, so stop searching */ | 1422 | /* Opportunity was found, so stop searching */ |
1425 | if (nc_packet) | 1423 | if (nc_packet) |
1426 | break; | 1424 | break; |
1427 | } | 1425 | } |
1428 | rcu_read_unlock(); | 1426 | rcu_read_unlock(); |
1429 | 1427 | ||
1430 | if (!nc_packet) | 1428 | if (!nc_packet) |
1431 | return false; | 1429 | return false; |
1432 | 1430 | ||
1433 | /* Save packets for later decoding */ | 1431 | /* Save packets for later decoding */ |
1434 | batadv_nc_skb_store_before_coding(bat_priv, skb, | 1432 | batadv_nc_skb_store_before_coding(bat_priv, skb, |
1435 | neigh_node->addr); | 1433 | neigh_node->addr); |
1436 | batadv_nc_skb_store_before_coding(bat_priv, nc_packet->skb, | 1434 | batadv_nc_skb_store_before_coding(bat_priv, nc_packet->skb, |
1437 | nc_packet->neigh_node->addr); | 1435 | nc_packet->neigh_node->addr); |
1438 | 1436 | ||
1439 | /* Code and send packets */ | 1437 | /* Code and send packets */ |
1440 | if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet, | 1438 | if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet, |
1441 | neigh_node)) | 1439 | neigh_node)) |
1442 | return true; | 1440 | return true; |
1443 | 1441 | ||
1444 | /* out of mem ? Coding failed - we have to free the buffered packet | 1442 | /* out of mem ? Coding failed - we have to free the buffered packet |
1445 | * to avoid memleaks. The skb passed as argument will be dealt with | 1443 | * to avoid memleaks. The skb passed as argument will be dealt with |
1446 | * by the calling function. | 1444 | * by the calling function. |
1447 | */ | 1445 | */ |
1448 | batadv_nc_send_packet(nc_packet); | 1446 | batadv_nc_send_packet(nc_packet); |
1449 | return false; | 1447 | return false; |
1450 | } | 1448 | } |
1451 | 1449 | ||
1452 | /** | 1450 | /** |
1453 | * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding | 1451 | * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding |
1454 | * @skb: skb to add to path | 1452 | * @skb: skb to add to path |
1455 | * @nc_path: path to add skb to | 1453 | * @nc_path: path to add skb to |
1456 | * @neigh_node: next hop to forward packet to | 1454 | * @neigh_node: next hop to forward packet to |
1457 | * @packet_id: checksum to identify packet | 1455 | * @packet_id: checksum to identify packet |
1458 | * | 1456 | * |
1459 | * Returns true if the packet was buffered or false in case of an error. | 1457 | * Returns true if the packet was buffered or false in case of an error. |
1460 | */ | 1458 | */ |
1461 | static bool batadv_nc_skb_add_to_path(struct sk_buff *skb, | 1459 | static bool batadv_nc_skb_add_to_path(struct sk_buff *skb, |
1462 | struct batadv_nc_path *nc_path, | 1460 | struct batadv_nc_path *nc_path, |
1463 | struct batadv_neigh_node *neigh_node, | 1461 | struct batadv_neigh_node *neigh_node, |
1464 | __be32 packet_id) | 1462 | __be32 packet_id) |
1465 | { | 1463 | { |
1466 | struct batadv_nc_packet *nc_packet; | 1464 | struct batadv_nc_packet *nc_packet; |
1467 | 1465 | ||
1468 | nc_packet = kzalloc(sizeof(*nc_packet), GFP_ATOMIC); | 1466 | nc_packet = kzalloc(sizeof(*nc_packet), GFP_ATOMIC); |
1469 | if (!nc_packet) | 1467 | if (!nc_packet) |
1470 | return false; | 1468 | return false; |
1471 | 1469 | ||
1472 | /* Initialize nc_packet */ | 1470 | /* Initialize nc_packet */ |
1473 | nc_packet->timestamp = jiffies; | 1471 | nc_packet->timestamp = jiffies; |
1474 | nc_packet->packet_id = packet_id; | 1472 | nc_packet->packet_id = packet_id; |
1475 | nc_packet->skb = skb; | 1473 | nc_packet->skb = skb; |
1476 | nc_packet->neigh_node = neigh_node; | 1474 | nc_packet->neigh_node = neigh_node; |
1477 | nc_packet->nc_path = nc_path; | 1475 | nc_packet->nc_path = nc_path; |
1478 | 1476 | ||
1479 | /* Add coding packet to list */ | 1477 | /* Add coding packet to list */ |
1480 | spin_lock_bh(&nc_path->packet_list_lock); | 1478 | spin_lock_bh(&nc_path->packet_list_lock); |
1481 | list_add_tail(&nc_packet->list, &nc_path->packet_list); | 1479 | list_add_tail(&nc_packet->list, &nc_path->packet_list); |
1482 | spin_unlock_bh(&nc_path->packet_list_lock); | 1480 | spin_unlock_bh(&nc_path->packet_list_lock); |
1483 | 1481 | ||
1484 | return true; | 1482 | return true; |
1485 | } | 1483 | } |
1486 | 1484 | ||
1487 | /** | 1485 | /** |
1488 | * batadv_nc_skb_forward - try to code a packet or add it to the coding packet | 1486 | * batadv_nc_skb_forward - try to code a packet or add it to the coding packet |
1489 | * buffer | 1487 | * buffer |
1490 | * @skb: data skb to forward | 1488 | * @skb: data skb to forward |
1491 | * @neigh_node: next hop to forward packet to | 1489 | * @neigh_node: next hop to forward packet to |
1492 | * | 1490 | * |
1493 | * Returns true if the skb was consumed (encoded packet sent) or false otherwise | 1491 | * Returns true if the skb was consumed (encoded packet sent) or false otherwise |
1494 | */ | 1492 | */ |
1495 | bool batadv_nc_skb_forward(struct sk_buff *skb, | 1493 | bool batadv_nc_skb_forward(struct sk_buff *skb, |
1496 | struct batadv_neigh_node *neigh_node) | 1494 | struct batadv_neigh_node *neigh_node) |
1497 | { | 1495 | { |
1498 | const struct net_device *netdev = neigh_node->if_incoming->soft_iface; | 1496 | const struct net_device *netdev = neigh_node->if_incoming->soft_iface; |
1499 | struct batadv_priv *bat_priv = netdev_priv(netdev); | 1497 | struct batadv_priv *bat_priv = netdev_priv(netdev); |
1500 | struct batadv_unicast_packet *packet; | 1498 | struct batadv_unicast_packet *packet; |
1501 | struct batadv_nc_path *nc_path; | 1499 | struct batadv_nc_path *nc_path; |
1502 | struct ethhdr *ethhdr = eth_hdr(skb); | 1500 | struct ethhdr *ethhdr = eth_hdr(skb); |
1503 | __be32 packet_id; | 1501 | __be32 packet_id; |
1504 | u8 *payload; | 1502 | u8 *payload; |
1505 | 1503 | ||
1506 | /* Check if network coding is enabled */ | 1504 | /* Check if network coding is enabled */ |
1507 | if (!atomic_read(&bat_priv->network_coding)) | 1505 | if (!atomic_read(&bat_priv->network_coding)) |
1508 | goto out; | 1506 | goto out; |
1509 | 1507 | ||
1510 | /* We only handle unicast packets */ | 1508 | /* We only handle unicast packets */ |
1511 | payload = skb_network_header(skb); | 1509 | payload = skb_network_header(skb); |
1512 | packet = (struct batadv_unicast_packet *)payload; | 1510 | packet = (struct batadv_unicast_packet *)payload; |
1513 | if (packet->packet_type != BATADV_UNICAST) | 1511 | if (packet->packet_type != BATADV_UNICAST) |
1514 | goto out; | 1512 | goto out; |
1515 | 1513 | ||
1516 | /* Try to find a coding opportunity and send the skb if one is found */ | 1514 | /* Try to find a coding opportunity and send the skb if one is found */ |
1517 | if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr)) | 1515 | if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr)) |
1518 | return true; | 1516 | return true; |
1519 | 1517 | ||
1520 | /* Find or create a nc_path for this src-dst pair */ | 1518 | /* Find or create a nc_path for this src-dst pair */ |
1521 | nc_path = batadv_nc_get_path(bat_priv, | 1519 | nc_path = batadv_nc_get_path(bat_priv, |
1522 | bat_priv->nc.coding_hash, | 1520 | bat_priv->nc.coding_hash, |
1523 | ethhdr->h_source, | 1521 | ethhdr->h_source, |
1524 | neigh_node->addr); | 1522 | neigh_node->addr); |
1525 | 1523 | ||
1526 | if (!nc_path) | 1524 | if (!nc_path) |
1527 | goto out; | 1525 | goto out; |
1528 | 1526 | ||
1529 | /* Add skb to nc_path */ | 1527 | /* Add skb to nc_path */ |
1530 | packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet)); | 1528 | packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet)); |
1531 | if (!batadv_nc_skb_add_to_path(skb, nc_path, neigh_node, packet_id)) | 1529 | if (!batadv_nc_skb_add_to_path(skb, nc_path, neigh_node, packet_id)) |
1532 | goto free_nc_path; | 1530 | goto free_nc_path; |
1533 | 1531 | ||
1534 | /* Packet is consumed */ | 1532 | /* Packet is consumed */ |
1535 | return true; | 1533 | return true; |
1536 | 1534 | ||
1537 | free_nc_path: | 1535 | free_nc_path: |
1538 | batadv_nc_path_free_ref(nc_path); | 1536 | batadv_nc_path_free_ref(nc_path); |
1539 | out: | 1537 | out: |
1540 | /* Packet is not consumed */ | 1538 | /* Packet is not consumed */ |
1541 | return false; | 1539 | return false; |
1542 | } | 1540 | } |
1543 | 1541 | ||
1544 | /** | 1542 | /** |
1545 | * batadv_nc_skb_store_for_decoding - save a clone of the skb which can be used | 1543 | * batadv_nc_skb_store_for_decoding - save a clone of the skb which can be used |
1546 | * when decoding coded packets | 1544 | * when decoding coded packets |
1547 | * @bat_priv: the bat priv with all the soft interface information | 1545 | * @bat_priv: the bat priv with all the soft interface information |
1548 | * @skb: data skb to store | 1546 | * @skb: data skb to store |
1549 | */ | 1547 | */ |
1550 | void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, | 1548 | void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, |
1551 | struct sk_buff *skb) | 1549 | struct sk_buff *skb) |
1552 | { | 1550 | { |
1553 | struct batadv_unicast_packet *packet; | 1551 | struct batadv_unicast_packet *packet; |
1554 | struct batadv_nc_path *nc_path; | 1552 | struct batadv_nc_path *nc_path; |
1555 | struct ethhdr *ethhdr = eth_hdr(skb); | 1553 | struct ethhdr *ethhdr = eth_hdr(skb); |
1556 | __be32 packet_id; | 1554 | __be32 packet_id; |
1557 | u8 *payload; | 1555 | u8 *payload; |
1558 | 1556 | ||
1559 | /* Check if network coding is enabled */ | 1557 | /* Check if network coding is enabled */ |
1560 | if (!atomic_read(&bat_priv->network_coding)) | 1558 | if (!atomic_read(&bat_priv->network_coding)) |
1561 | goto out; | 1559 | goto out; |
1562 | 1560 | ||
1563 | /* Check for supported packet type */ | 1561 | /* Check for supported packet type */ |
1564 | payload = skb_network_header(skb); | 1562 | payload = skb_network_header(skb); |
1565 | packet = (struct batadv_unicast_packet *)payload; | 1563 | packet = (struct batadv_unicast_packet *)payload; |
1566 | if (packet->packet_type != BATADV_UNICAST) | 1564 | if (packet->packet_type != BATADV_UNICAST) |
1567 | goto out; | 1565 | goto out; |
1568 | 1566 | ||
1569 | /* Find existing nc_path or create a new */ | 1567 | /* Find existing nc_path or create a new */ |
1570 | nc_path = batadv_nc_get_path(bat_priv, | 1568 | nc_path = batadv_nc_get_path(bat_priv, |
1571 | bat_priv->nc.decoding_hash, | 1569 | bat_priv->nc.decoding_hash, |
1572 | ethhdr->h_source, | 1570 | ethhdr->h_source, |
1573 | ethhdr->h_dest); | 1571 | ethhdr->h_dest); |
1574 | 1572 | ||
1575 | if (!nc_path) | 1573 | if (!nc_path) |
1576 | goto out; | 1574 | goto out; |
1577 | 1575 | ||
1578 | /* Clone skb and adjust skb->data to point at batman header */ | 1576 | /* Clone skb and adjust skb->data to point at batman header */ |
1579 | skb = skb_clone(skb, GFP_ATOMIC); | 1577 | skb = skb_clone(skb, GFP_ATOMIC); |
1580 | if (unlikely(!skb)) | 1578 | if (unlikely(!skb)) |
1581 | goto free_nc_path; | 1579 | goto free_nc_path; |
1582 | 1580 | ||
1583 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | 1581 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) |
1584 | goto free_skb; | 1582 | goto free_skb; |
1585 | 1583 | ||
1586 | if (unlikely(!skb_pull_rcsum(skb, ETH_HLEN))) | 1584 | if (unlikely(!skb_pull_rcsum(skb, ETH_HLEN))) |
1587 | goto free_skb; | 1585 | goto free_skb; |
1588 | 1586 | ||
1589 | /* Add skb to nc_path */ | 1587 | /* Add skb to nc_path */ |
1590 | packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet)); | 1588 | packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet)); |
1591 | if (!batadv_nc_skb_add_to_path(skb, nc_path, NULL, packet_id)) | 1589 | if (!batadv_nc_skb_add_to_path(skb, nc_path, NULL, packet_id)) |
1592 | goto free_skb; | 1590 | goto free_skb; |
1593 | 1591 | ||
1594 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_BUFFER); | 1592 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_BUFFER); |
1595 | return; | 1593 | return; |
1596 | 1594 | ||
1597 | free_skb: | 1595 | free_skb: |
1598 | kfree_skb(skb); | 1596 | kfree_skb(skb); |
1599 | free_nc_path: | 1597 | free_nc_path: |
1600 | batadv_nc_path_free_ref(nc_path); | 1598 | batadv_nc_path_free_ref(nc_path); |
1601 | out: | 1599 | out: |
1602 | return; | 1600 | return; |
1603 | } | 1601 | } |
1604 | 1602 | ||
1605 | /** | 1603 | /** |
1606 | * batadv_nc_skb_store_sniffed_unicast - check if a received unicast packet | 1604 | * batadv_nc_skb_store_sniffed_unicast - check if a received unicast packet |
1607 | * should be saved in the decoding buffer and, if so, store it there | 1605 | * should be saved in the decoding buffer and, if so, store it there |
1608 | * @bat_priv: the bat priv with all the soft interface information | 1606 | * @bat_priv: the bat priv with all the soft interface information |
1609 | * @skb: unicast skb to store | 1607 | * @skb: unicast skb to store |
1610 | */ | 1608 | */ |
1611 | void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, | 1609 | void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, |
1612 | struct sk_buff *skb) | 1610 | struct sk_buff *skb) |
1613 | { | 1611 | { |
1614 | struct ethhdr *ethhdr = eth_hdr(skb); | 1612 | struct ethhdr *ethhdr = eth_hdr(skb); |
1615 | 1613 | ||
1616 | if (batadv_is_my_mac(bat_priv, ethhdr->h_dest)) | 1614 | if (batadv_is_my_mac(bat_priv, ethhdr->h_dest)) |
1617 | return; | 1615 | return; |
1618 | 1616 | ||
1619 | /* Set data pointer to MAC header to mimic packets from our tx path */ | 1617 | /* Set data pointer to MAC header to mimic packets from our tx path */ |
1620 | skb_push(skb, ETH_HLEN); | 1618 | skb_push(skb, ETH_HLEN); |
1621 | 1619 | ||
1622 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | 1620 | batadv_nc_skb_store_for_decoding(bat_priv, skb); |
1623 | } | 1621 | } |
1624 | 1622 | ||
1625 | /** | 1623 | /** |
1626 | * batadv_nc_skb_decode_packet - decode given skb using the decode data stored | 1624 | * batadv_nc_skb_decode_packet - decode given skb using the decode data stored |
1627 | * in nc_packet | 1625 | * in nc_packet |
1628 | * @bat_priv: the bat priv with all the soft interface information | 1626 | * @bat_priv: the bat priv with all the soft interface information |
1629 | * @skb: unicast skb to decode | 1627 | * @skb: unicast skb to decode |
1630 | * @nc_packet: decode data needed to decode the skb | 1628 | * @nc_packet: decode data needed to decode the skb |
1631 | * | 1629 | * |
1632 | * Returns pointer to decoded unicast packet if the packet was decoded or NULL | 1630 | * Returns pointer to decoded unicast packet if the packet was decoded or NULL |
1633 | * in case of an error. | 1631 | * in case of an error. |
1634 | */ | 1632 | */ |
1635 | static struct batadv_unicast_packet * | 1633 | static struct batadv_unicast_packet * |
1636 | batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | 1634 | batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, |
1637 | struct batadv_nc_packet *nc_packet) | 1635 | struct batadv_nc_packet *nc_packet) |
1638 | { | 1636 | { |
1639 | const int h_size = sizeof(struct batadv_unicast_packet); | 1637 | const int h_size = sizeof(struct batadv_unicast_packet); |
1640 | const int h_diff = sizeof(struct batadv_coded_packet) - h_size; | 1638 | const int h_diff = sizeof(struct batadv_coded_packet) - h_size; |
1641 | struct batadv_unicast_packet *unicast_packet; | 1639 | struct batadv_unicast_packet *unicast_packet; |
1642 | struct batadv_coded_packet coded_packet_tmp; | 1640 | struct batadv_coded_packet coded_packet_tmp; |
1643 | struct ethhdr *ethhdr, ethhdr_tmp; | 1641 | struct ethhdr *ethhdr, ethhdr_tmp; |
1644 | u8 *orig_dest, ttl, ttvn; | 1642 | u8 *orig_dest, ttl, ttvn; |
1645 | unsigned int coding_len; | 1643 | unsigned int coding_len; |
1646 | int err; | 1644 | int err; |
1647 | 1645 | ||
1648 | /* Save headers temporarily */ | 1646 | /* Save headers temporarily */ |
1649 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); | 1647 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); |
1650 | memcpy(ðhdr_tmp, skb_mac_header(skb), sizeof(ethhdr_tmp)); | 1648 | memcpy(ðhdr_tmp, skb_mac_header(skb), sizeof(ethhdr_tmp)); |
1651 | 1649 | ||
1652 | if (skb_cow(skb, 0) < 0) | 1650 | if (skb_cow(skb, 0) < 0) |
1653 | return NULL; | 1651 | return NULL; |
1654 | 1652 | ||
1655 | if (unlikely(!skb_pull_rcsum(skb, h_diff))) | 1653 | if (unlikely(!skb_pull_rcsum(skb, h_diff))) |
1656 | return NULL; | 1654 | return NULL; |
1657 | 1655 | ||
1658 | /* Data points to batman header, so set mac header 14 bytes before | 1656 | /* Data points to batman header, so set mac header 14 bytes before |
1659 | * and network to data | 1657 | * and network to data |
1660 | */ | 1658 | */ |
1661 | skb_set_mac_header(skb, -ETH_HLEN); | 1659 | skb_set_mac_header(skb, -ETH_HLEN); |
1662 | skb_reset_network_header(skb); | 1660 | skb_reset_network_header(skb); |
1663 | 1661 | ||
1664 | /* Reconstruct original mac header */ | 1662 | /* Reconstruct original mac header */ |
1665 | ethhdr = eth_hdr(skb); | 1663 | ethhdr = eth_hdr(skb); |
1666 | *ethhdr = ethhdr_tmp; | 1664 | *ethhdr = ethhdr_tmp; |
1667 | 1665 | ||
1668 | /* Select the correct unicast header information based on the location | 1666 | /* Select the correct unicast header information based on the location |
1669 | * of our mac address in the coded_packet header | 1667 | * of our mac address in the coded_packet header |
1670 | */ | 1668 | */ |
1671 | if (batadv_is_my_mac(bat_priv, coded_packet_tmp.second_dest)) { | 1669 | if (batadv_is_my_mac(bat_priv, coded_packet_tmp.second_dest)) { |
1672 | /* If we are the second destination the packet was overheard, | 1670 | /* If we are the second destination the packet was overheard, |
1673 | * so the Ethernet address must be copied to h_dest and | 1671 | * so the Ethernet address must be copied to h_dest and |
1674 | * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST | 1672 | * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST |
1675 | */ | 1673 | */ |
1676 | ether_addr_copy(ethhdr->h_dest, coded_packet_tmp.second_dest); | 1674 | ether_addr_copy(ethhdr->h_dest, coded_packet_tmp.second_dest); |
1677 | skb->pkt_type = PACKET_HOST; | 1675 | skb->pkt_type = PACKET_HOST; |
1678 | 1676 | ||
1679 | orig_dest = coded_packet_tmp.second_orig_dest; | 1677 | orig_dest = coded_packet_tmp.second_orig_dest; |
1680 | ttl = coded_packet_tmp.second_ttl; | 1678 | ttl = coded_packet_tmp.second_ttl; |
1681 | ttvn = coded_packet_tmp.second_ttvn; | 1679 | ttvn = coded_packet_tmp.second_ttvn; |
1682 | } else { | 1680 | } else { |
1683 | orig_dest = coded_packet_tmp.first_orig_dest; | 1681 | orig_dest = coded_packet_tmp.first_orig_dest; |
1684 | ttl = coded_packet_tmp.ttl; | 1682 | ttl = coded_packet_tmp.ttl; |
1685 | ttvn = coded_packet_tmp.first_ttvn; | 1683 | ttvn = coded_packet_tmp.first_ttvn; |
1686 | } | 1684 | } |
1687 | 1685 | ||
1688 | coding_len = ntohs(coded_packet_tmp.coded_len); | 1686 | coding_len = ntohs(coded_packet_tmp.coded_len); |
1689 | 1687 | ||
1690 | if (coding_len > skb->len) | 1688 | if (coding_len > skb->len) |
1691 | return NULL; | 1689 | return NULL; |
1692 | 1690 | ||
1693 | /* Here the magic is reversed: | 1691 | /* Here the magic is reversed: |
1694 | * extract the missing packet from the received coded packet | 1692 | * extract the missing packet from the received coded packet |
1695 | */ | 1693 | */ |
1696 | batadv_nc_memxor(skb->data + h_size, | 1694 | batadv_nc_memxor(skb->data + h_size, |
1697 | nc_packet->skb->data + h_size, | 1695 | nc_packet->skb->data + h_size, |
1698 | coding_len); | 1696 | coding_len); |
1699 | 1697 | ||
1700 | /* Resize decoded skb if decoded with larger packet */ | 1698 | /* Resize decoded skb if decoded with larger packet */ |
1701 | if (nc_packet->skb->len > coding_len + h_size) { | 1699 | if (nc_packet->skb->len > coding_len + h_size) { |
1702 | err = pskb_trim_rcsum(skb, coding_len + h_size); | 1700 | err = pskb_trim_rcsum(skb, coding_len + h_size); |
1703 | if (err) | 1701 | if (err) |
1704 | return NULL; | 1702 | return NULL; |
1705 | } | 1703 | } |
1706 | 1704 | ||
1707 | /* Create decoded unicast packet */ | 1705 | /* Create decoded unicast packet */ |
1708 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 1706 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
1709 | unicast_packet->packet_type = BATADV_UNICAST; | 1707 | unicast_packet->packet_type = BATADV_UNICAST; |
1710 | unicast_packet->version = BATADV_COMPAT_VERSION; | 1708 | unicast_packet->version = BATADV_COMPAT_VERSION; |
1711 | unicast_packet->ttl = ttl; | 1709 | unicast_packet->ttl = ttl; |
1712 | ether_addr_copy(unicast_packet->dest, orig_dest); | 1710 | ether_addr_copy(unicast_packet->dest, orig_dest); |
1713 | unicast_packet->ttvn = ttvn; | 1711 | unicast_packet->ttvn = ttvn; |
1714 | 1712 | ||
1715 | batadv_nc_packet_free(nc_packet); | 1713 | batadv_nc_packet_free(nc_packet); |
1716 | return unicast_packet; | 1714 | return unicast_packet; |
1717 | } | 1715 | } |
1718 | 1716 | ||
1719 | /** | 1717 | /** |
1720 | * batadv_nc_find_decoding_packet - search through buffered decoding data to | 1718 | * batadv_nc_find_decoding_packet - search through buffered decoding data to |
1721 | * find the data needed to decode the coded packet | 1719 | * find the data needed to decode the coded packet |
1722 | * @bat_priv: the bat priv with all the soft interface information | 1720 | * @bat_priv: the bat priv with all the soft interface information |
1723 | * @ethhdr: pointer to the ethernet header inside the coded packet | 1721 | * @ethhdr: pointer to the ethernet header inside the coded packet |
1724 | * @coded: coded packet we try to find decode data for | 1722 | * @coded: coded packet we try to find decode data for |
1725 | * | 1723 | * |
1726 | * Returns pointer to nc packet if the needed data was found or NULL otherwise. | 1724 | * Returns pointer to nc packet if the needed data was found or NULL otherwise. |
1727 | */ | 1725 | */ |
1728 | static struct batadv_nc_packet * | 1726 | static struct batadv_nc_packet * |
1729 | batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv, | 1727 | batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv, |
1730 | struct ethhdr *ethhdr, | 1728 | struct ethhdr *ethhdr, |
1731 | struct batadv_coded_packet *coded) | 1729 | struct batadv_coded_packet *coded) |
1732 | { | 1730 | { |
1733 | struct batadv_hashtable *hash = bat_priv->nc.decoding_hash; | 1731 | struct batadv_hashtable *hash = bat_priv->nc.decoding_hash; |
1734 | struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL; | 1732 | struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL; |
1735 | struct batadv_nc_path *nc_path, nc_path_key; | 1733 | struct batadv_nc_path *nc_path, nc_path_key; |
1736 | u8 *dest, *source; | 1734 | u8 *dest, *source; |
1737 | __be32 packet_id; | 1735 | __be32 packet_id; |
1738 | int index; | 1736 | int index; |
1739 | 1737 | ||
1740 | if (!hash) | 1738 | if (!hash) |
1741 | return NULL; | 1739 | return NULL; |
1742 | 1740 | ||
1743 | /* Select the correct packet id based on the location of our mac-addr */ | 1741 | /* Select the correct packet id based on the location of our mac-addr */ |
1744 | dest = ethhdr->h_source; | 1742 | dest = ethhdr->h_source; |
1745 | if (!batadv_is_my_mac(bat_priv, coded->second_dest)) { | 1743 | if (!batadv_is_my_mac(bat_priv, coded->second_dest)) { |
1746 | source = coded->second_source; | 1744 | source = coded->second_source; |
1747 | packet_id = coded->second_crc; | 1745 | packet_id = coded->second_crc; |
1748 | } else { | 1746 | } else { |
1749 | source = coded->first_source; | 1747 | source = coded->first_source; |
1750 | packet_id = coded->first_crc; | 1748 | packet_id = coded->first_crc; |
1751 | } | 1749 | } |
1752 | 1750 | ||
1753 | batadv_nc_hash_key_gen(&nc_path_key, source, dest); | 1751 | batadv_nc_hash_key_gen(&nc_path_key, source, dest); |
1754 | index = batadv_nc_hash_choose(&nc_path_key, hash->size); | 1752 | index = batadv_nc_hash_choose(&nc_path_key, hash->size); |
1755 | 1753 | ||
1756 | /* Search for matching coding path */ | 1754 | /* Search for matching coding path */ |
1757 | rcu_read_lock(); | 1755 | rcu_read_lock(); |
1758 | hlist_for_each_entry_rcu(nc_path, &hash->table[index], hash_entry) { | 1756 | hlist_for_each_entry_rcu(nc_path, &hash->table[index], hash_entry) { |
1759 | /* Find matching nc_packet */ | 1757 | /* Find matching nc_packet */ |
1760 | spin_lock_bh(&nc_path->packet_list_lock); | 1758 | spin_lock_bh(&nc_path->packet_list_lock); |
1761 | list_for_each_entry(tmp_nc_packet, | 1759 | list_for_each_entry(tmp_nc_packet, |
1762 | &nc_path->packet_list, list) { | 1760 | &nc_path->packet_list, list) { |
1763 | if (packet_id == tmp_nc_packet->packet_id) { | 1761 | if (packet_id == tmp_nc_packet->packet_id) { |
1764 | list_del(&tmp_nc_packet->list); | 1762 | list_del(&tmp_nc_packet->list); |
1765 | 1763 | ||
1766 | nc_packet = tmp_nc_packet; | 1764 | nc_packet = tmp_nc_packet; |
1767 | break; | 1765 | break; |
1768 | } | 1766 | } |
1769 | } | 1767 | } |
1770 | spin_unlock_bh(&nc_path->packet_list_lock); | 1768 | spin_unlock_bh(&nc_path->packet_list_lock); |
1771 | 1769 | ||
1772 | if (nc_packet) | 1770 | if (nc_packet) |
1773 | break; | 1771 | break; |
1774 | } | 1772 | } |
1775 | rcu_read_unlock(); | 1773 | rcu_read_unlock(); |
1776 | 1774 | ||
1777 | if (!nc_packet) | 1775 | if (!nc_packet) |
1778 | batadv_dbg(BATADV_DBG_NC, bat_priv, | 1776 | batadv_dbg(BATADV_DBG_NC, bat_priv, |
1779 | "No decoding packet found for %u\n", packet_id); | 1777 | "No decoding packet found for %u\n", packet_id); |
1780 | 1778 | ||
1781 | return nc_packet; | 1779 | return nc_packet; |
1782 | } | 1780 | } |
1783 | 1781 | ||
1784 | /** | 1782 | /** |
1785 | * batadv_nc_recv_coded_packet - try to decode coded packet and enqueue the | 1783 | * batadv_nc_recv_coded_packet - try to decode coded packet and enqueue the |
1786 | * resulting unicast packet | 1784 | * resulting unicast packet |
1787 | * @skb: incoming coded packet | 1785 | * @skb: incoming coded packet |
1788 | * @recv_if: pointer to interface this packet was received on | 1786 | * @recv_if: pointer to interface this packet was received on |
1789 | */ | 1787 | */ |
1790 | static int batadv_nc_recv_coded_packet(struct sk_buff *skb, | 1788 | static int batadv_nc_recv_coded_packet(struct sk_buff *skb, |
1791 | struct batadv_hard_iface *recv_if) | 1789 | struct batadv_hard_iface *recv_if) |
1792 | { | 1790 | { |
1793 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 1791 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1794 | struct batadv_unicast_packet *unicast_packet; | 1792 | struct batadv_unicast_packet *unicast_packet; |
1795 | struct batadv_coded_packet *coded_packet; | 1793 | struct batadv_coded_packet *coded_packet; |
1796 | struct batadv_nc_packet *nc_packet; | 1794 | struct batadv_nc_packet *nc_packet; |
1797 | struct ethhdr *ethhdr; | 1795 | struct ethhdr *ethhdr; |
1798 | int hdr_size = sizeof(*coded_packet); | 1796 | int hdr_size = sizeof(*coded_packet); |
1799 | 1797 | ||
1800 | /* Check if network coding is enabled */ | 1798 | /* Check if network coding is enabled */ |
1801 | if (!atomic_read(&bat_priv->network_coding)) | 1799 | if (!atomic_read(&bat_priv->network_coding)) |
1802 | return NET_RX_DROP; | 1800 | return NET_RX_DROP; |
1803 | 1801 | ||
1804 | /* Make sure we can access (and remove) header */ | 1802 | /* Make sure we can access (and remove) header */ |
1805 | if (unlikely(!pskb_may_pull(skb, hdr_size))) | 1803 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
1806 | return NET_RX_DROP; | 1804 | return NET_RX_DROP; |
1807 | 1805 | ||
1808 | coded_packet = (struct batadv_coded_packet *)skb->data; | 1806 | coded_packet = (struct batadv_coded_packet *)skb->data; |
1809 | ethhdr = eth_hdr(skb); | 1807 | ethhdr = eth_hdr(skb); |
1810 | 1808 | ||
1811 | /* Verify frame is destined for us */ | 1809 | /* Verify frame is destined for us */ |
1812 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) && | 1810 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) && |
1813 | !batadv_is_my_mac(bat_priv, coded_packet->second_dest)) | 1811 | !batadv_is_my_mac(bat_priv, coded_packet->second_dest)) |
1814 | return NET_RX_DROP; | 1812 | return NET_RX_DROP; |
1815 | 1813 | ||
1816 | /* Update stat counter */ | 1814 | /* Update stat counter */ |
1817 | if (batadv_is_my_mac(bat_priv, coded_packet->second_dest)) | 1815 | if (batadv_is_my_mac(bat_priv, coded_packet->second_dest)) |
1818 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_SNIFFED); | 1816 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_SNIFFED); |
1819 | 1817 | ||
1820 | nc_packet = batadv_nc_find_decoding_packet(bat_priv, ethhdr, | 1818 | nc_packet = batadv_nc_find_decoding_packet(bat_priv, ethhdr, |
1821 | coded_packet); | 1819 | coded_packet); |
1822 | if (!nc_packet) { | 1820 | if (!nc_packet) { |
1823 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED); | 1821 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED); |
1824 | return NET_RX_DROP; | 1822 | return NET_RX_DROP; |
1825 | } | 1823 | } |
1826 | 1824 | ||
1827 | /* Make skb's linear, because decoding accesses the entire buffer */ | 1825 | /* Make skb's linear, because decoding accesses the entire buffer */ |
1828 | if (skb_linearize(skb) < 0) | 1826 | if (skb_linearize(skb) < 0) |
1829 | goto free_nc_packet; | 1827 | goto free_nc_packet; |
1830 | 1828 | ||
1831 | if (skb_linearize(nc_packet->skb) < 0) | 1829 | if (skb_linearize(nc_packet->skb) < 0) |
1832 | goto free_nc_packet; | 1830 | goto free_nc_packet; |
1833 | 1831 | ||
1834 | /* Decode the packet */ | 1832 | /* Decode the packet */ |
1835 | unicast_packet = batadv_nc_skb_decode_packet(bat_priv, skb, nc_packet); | 1833 | unicast_packet = batadv_nc_skb_decode_packet(bat_priv, skb, nc_packet); |
1836 | if (!unicast_packet) { | 1834 | if (!unicast_packet) { |
1837 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED); | 1835 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED); |
1838 | goto free_nc_packet; | 1836 | goto free_nc_packet; |
1839 | } | 1837 | } |
1840 | 1838 | ||
1841 | /* Mark packet as decoded to do correct recoding when forwarding */ | 1839 | /* Mark packet as decoded to do correct recoding when forwarding */ |
1842 | BATADV_SKB_CB(skb)->decoded = true; | 1840 | BATADV_SKB_CB(skb)->decoded = true; |
1843 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE); | 1841 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE); |
1844 | batadv_add_counter(bat_priv, BATADV_CNT_NC_DECODE_BYTES, | 1842 | batadv_add_counter(bat_priv, BATADV_CNT_NC_DECODE_BYTES, |
1845 | skb->len + ETH_HLEN); | 1843 | skb->len + ETH_HLEN); |
1846 | return batadv_recv_unicast_packet(skb, recv_if); | 1844 | return batadv_recv_unicast_packet(skb, recv_if); |
1847 | 1845 | ||
1848 | free_nc_packet: | 1846 | free_nc_packet: |
1849 | batadv_nc_packet_free(nc_packet); | 1847 | batadv_nc_packet_free(nc_packet); |
1850 | return NET_RX_DROP; | 1848 | return NET_RX_DROP; |
1851 | } | 1849 | } |
1852 | 1850 | ||
1853 | /** | 1851 | /** |
1854 | * batadv_nc_mesh_free - clean up network coding memory | 1852 | * batadv_nc_mesh_free - clean up network coding memory |
1855 | * @bat_priv: the bat priv with all the soft interface information | 1853 | * @bat_priv: the bat priv with all the soft interface information |
1856 | */ | 1854 | */ |
1857 | void batadv_nc_mesh_free(struct batadv_priv *bat_priv) | 1855 | void batadv_nc_mesh_free(struct batadv_priv *bat_priv) |
1858 | { | 1856 | { |
1859 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1); | 1857 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1); |
1860 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_NC, 1); | 1858 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_NC, 1); |
1861 | cancel_delayed_work_sync(&bat_priv->nc.work); | 1859 | cancel_delayed_work_sync(&bat_priv->nc.work); |
1862 | 1860 | ||
1863 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); | 1861 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); |
1864 | batadv_hash_destroy(bat_priv->nc.coding_hash); | 1862 | batadv_hash_destroy(bat_priv->nc.coding_hash); |
1865 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, NULL); | 1863 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, NULL); |
1866 | batadv_hash_destroy(bat_priv->nc.decoding_hash); | 1864 | batadv_hash_destroy(bat_priv->nc.decoding_hash); |
1867 | } | 1865 | } |
1868 | 1866 | ||
1869 | /** | 1867 | /** |
1870 | * batadv_nc_nodes_seq_print_text - print the nc node information | 1868 | * batadv_nc_nodes_seq_print_text - print the nc node information |
1871 | * @seq: seq file to print on | 1869 | * @seq: seq file to print on |
1872 | * @offset: not used | 1870 | * @offset: not used |
1873 | */ | 1871 | */ |
1874 | int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset) | 1872 | int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset) |
1875 | { | 1873 | { |
1876 | struct net_device *net_dev = (struct net_device *)seq->private; | 1874 | struct net_device *net_dev = (struct net_device *)seq->private; |
1877 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 1875 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
1878 | struct batadv_hashtable *hash = bat_priv->orig_hash; | 1876 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
1879 | struct batadv_hard_iface *primary_if; | 1877 | struct batadv_hard_iface *primary_if; |
1880 | struct hlist_head *head; | 1878 | struct hlist_head *head; |
1881 | struct batadv_orig_node *orig_node; | 1879 | struct batadv_orig_node *orig_node; |
1882 | struct batadv_nc_node *nc_node; | 1880 | struct batadv_nc_node *nc_node; |
1883 | int i; | 1881 | int i; |
1884 | 1882 | ||
1885 | primary_if = batadv_seq_print_text_primary_if_get(seq); | 1883 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
1886 | if (!primary_if) | 1884 | if (!primary_if) |
1887 | goto out; | 1885 | goto out; |
1888 | 1886 | ||
1889 | /* Traverse list of originators */ | 1887 | /* Traverse list of originators */ |
1890 | for (i = 0; i < hash->size; i++) { | 1888 | for (i = 0; i < hash->size; i++) { |
1891 | head = &hash->table[i]; | 1889 | head = &hash->table[i]; |
1892 | 1890 | ||
1893 | /* For each orig_node in this bin */ | 1891 | /* For each orig_node in this bin */ |
1894 | rcu_read_lock(); | 1892 | rcu_read_lock(); |
1895 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { | 1893 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { |
1896 | /* no need to print the orig node if it does not have | 1894 | /* no need to print the orig node if it does not have |
1897 | * network coding neighbors | 1895 | * network coding neighbors |
1898 | */ | 1896 | */ |
1899 | if (list_empty(&orig_node->in_coding_list) && | 1897 | if (list_empty(&orig_node->in_coding_list) && |
1900 | list_empty(&orig_node->out_coding_list)) | 1898 | list_empty(&orig_node->out_coding_list)) |
1901 | continue; | 1899 | continue; |
1902 | 1900 | ||
1903 | seq_printf(seq, "Node: %pM\n", orig_node->orig); | 1901 | seq_printf(seq, "Node: %pM\n", orig_node->orig); |
1904 | 1902 | ||
1905 | seq_puts(seq, " Ingoing: "); | 1903 | seq_puts(seq, " Ingoing: "); |
1906 | /* For each in_nc_node to this orig_node */ | 1904 | /* For each in_nc_node to this orig_node */ |
1907 | list_for_each_entry_rcu(nc_node, | 1905 | list_for_each_entry_rcu(nc_node, |
1908 | &orig_node->in_coding_list, | 1906 | &orig_node->in_coding_list, |
1909 | list) | 1907 | list) |
1910 | seq_printf(seq, "%pM ", | 1908 | seq_printf(seq, "%pM ", |
1911 | nc_node->addr); | 1909 | nc_node->addr); |
1912 | seq_puts(seq, "\n"); | 1910 | seq_puts(seq, "\n"); |
1913 | 1911 | ||
1914 | seq_puts(seq, " Outgoing: "); | 1912 | seq_puts(seq, " Outgoing: "); |
1915 | /* For out_nc_node to this orig_node */ | 1913 | /* For out_nc_node to this orig_node */ |
1916 | list_for_each_entry_rcu(nc_node, | 1914 | list_for_each_entry_rcu(nc_node, |
1917 | &orig_node->out_coding_list, | 1915 | &orig_node->out_coding_list, |
1918 | list) | 1916 | list) |
1919 | seq_printf(seq, "%pM ", | 1917 | seq_printf(seq, "%pM ", |
1920 | nc_node->addr); | 1918 | nc_node->addr); |
1921 | seq_puts(seq, "\n\n"); | 1919 | seq_puts(seq, "\n\n"); |
1922 | } | 1920 | } |
1923 | rcu_read_unlock(); | 1921 | rcu_read_unlock(); |
1924 | } | 1922 | } |
1925 | 1923 | ||
1926 | out: | 1924 | out: |
1927 | if (primary_if) | 1925 | if (primary_if) |
1928 | batadv_hardif_free_ref(primary_if); | 1926 | batadv_hardif_free_ref(primary_if); |
1929 | return 0; | 1927 | return 0; |
1930 | } | 1928 | } |
1931 | 1929 | ||
1932 | /** | 1930 | /** |
1933 | * batadv_nc_init_debugfs - create nc folder and related files in debugfs | 1931 | * batadv_nc_init_debugfs - create nc folder and related files in debugfs |
1934 | * @bat_priv: the bat priv with all the soft interface information | 1932 | * @bat_priv: the bat priv with all the soft interface information |
1935 | */ | 1933 | */ |
1936 | int batadv_nc_init_debugfs(struct batadv_priv *bat_priv) | 1934 | int batadv_nc_init_debugfs(struct batadv_priv *bat_priv) |
1937 | { | 1935 | { |
1938 | struct dentry *nc_dir, *file; | 1936 | struct dentry *nc_dir, *file; |
1939 | 1937 | ||
1940 | nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir); | 1938 | nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir); |
1941 | if (!nc_dir) | 1939 | if (!nc_dir) |
1942 | goto out; | 1940 | goto out; |
1943 | 1941 | ||
1944 | file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir, | 1942 | file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir, |
1945 | &bat_priv->nc.min_tq); | 1943 | &bat_priv->nc.min_tq); |
1946 | if (!file) | 1944 | if (!file) |
1947 | goto out; | 1945 | goto out; |
1948 | 1946 | ||
1949 | file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir, | 1947 | file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir, |
1950 | &bat_priv->nc.max_fwd_delay); | 1948 | &bat_priv->nc.max_fwd_delay); |
1951 | if (!file) | 1949 | if (!file) |
1952 | goto out; | 1950 | goto out; |
1953 | 1951 | ||
1954 | file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir, | 1952 | file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir, |
1955 | &bat_priv->nc.max_buffer_time); | 1953 | &bat_priv->nc.max_buffer_time); |
1956 | if (!file) | 1954 | if (!file) |
1957 | goto out; | 1955 | goto out; |
1958 | 1956 | ||
1959 | return 0; | 1957 | return 0; |
1960 | 1958 | ||
1961 | out: | 1959 | out: |
1962 | return -ENOMEM; | 1960 | return -ENOMEM; |
1963 | } | 1961 | } |
1964 | 1962 |
net/batman-adv/send.c
1 | /* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of version 2 of the GNU General Public |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "send.h" | 18 | #include "send.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/byteorder/generic.h> | 22 | #include <linux/byteorder/generic.h> |
23 | #include <linux/etherdevice.h> | 23 | #include <linux/etherdevice.h> |
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/if_ether.h> | 25 | #include <linux/if_ether.h> |
26 | #include <linux/if.h> | 26 | #include <linux/if.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/printk.h> | 31 | #include <linux/printk.h> |
32 | #include <linux/rculist.h> | 32 | #include <linux/rculist.h> |
33 | #include <linux/rcupdate.h> | 33 | #include <linux/rcupdate.h> |
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
37 | #include <linux/stddef.h> | 37 | #include <linux/stddef.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | 39 | ||
40 | #include "distributed-arp-table.h" | 40 | #include "distributed-arp-table.h" |
41 | #include "fragmentation.h" | 41 | #include "fragmentation.h" |
42 | #include "gateway_client.h" | 42 | #include "gateway_client.h" |
43 | #include "hard-interface.h" | 43 | #include "hard-interface.h" |
44 | #include "network-coding.h" | 44 | #include "network-coding.h" |
45 | #include "originator.h" | 45 | #include "originator.h" |
46 | #include "routing.h" | 46 | #include "routing.h" |
47 | #include "soft-interface.h" | 47 | #include "soft-interface.h" |
48 | #include "translation-table.h" | 48 | #include "translation-table.h" |
49 | 49 | ||
50 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); | 50 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); |
51 | 51 | ||
52 | /* send out an already prepared packet to the given address via the | 52 | /* send out an already prepared packet to the given address via the |
53 | * specified batman interface | 53 | * specified batman interface |
54 | */ | 54 | */ |
55 | int batadv_send_skb_packet(struct sk_buff *skb, | 55 | int batadv_send_skb_packet(struct sk_buff *skb, |
56 | struct batadv_hard_iface *hard_iface, | 56 | struct batadv_hard_iface *hard_iface, |
57 | const u8 *dst_addr) | 57 | const u8 *dst_addr) |
58 | { | 58 | { |
59 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 59 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
60 | struct ethhdr *ethhdr; | 60 | struct ethhdr *ethhdr; |
61 | 61 | ||
62 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | 62 | if (hard_iface->if_status != BATADV_IF_ACTIVE) |
63 | goto send_skb_err; | 63 | goto send_skb_err; |
64 | 64 | ||
65 | if (unlikely(!hard_iface->net_dev)) | 65 | if (unlikely(!hard_iface->net_dev)) |
66 | goto send_skb_err; | 66 | goto send_skb_err; |
67 | 67 | ||
68 | if (!(hard_iface->net_dev->flags & IFF_UP)) { | 68 | if (!(hard_iface->net_dev->flags & IFF_UP)) { |
69 | pr_warn("Interface %s is not up - can't send packet via that interface!\n", | 69 | pr_warn("Interface %s is not up - can't send packet via that interface!\n", |
70 | hard_iface->net_dev->name); | 70 | hard_iface->net_dev->name); |
71 | goto send_skb_err; | 71 | goto send_skb_err; |
72 | } | 72 | } |
73 | 73 | ||
74 | /* push to the ethernet header. */ | 74 | /* push to the ethernet header. */ |
75 | if (batadv_skb_head_push(skb, ETH_HLEN) < 0) | 75 | if (batadv_skb_head_push(skb, ETH_HLEN) < 0) |
76 | goto send_skb_err; | 76 | goto send_skb_err; |
77 | 77 | ||
78 | skb_reset_mac_header(skb); | 78 | skb_reset_mac_header(skb); |
79 | 79 | ||
80 | ethhdr = eth_hdr(skb); | 80 | ethhdr = eth_hdr(skb); |
81 | ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr); | 81 | ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr); |
82 | ether_addr_copy(ethhdr->h_dest, dst_addr); | 82 | ether_addr_copy(ethhdr->h_dest, dst_addr); |
83 | ethhdr->h_proto = htons(ETH_P_BATMAN); | 83 | ethhdr->h_proto = htons(ETH_P_BATMAN); |
84 | 84 | ||
85 | skb_set_network_header(skb, ETH_HLEN); | 85 | skb_set_network_header(skb, ETH_HLEN); |
86 | skb->protocol = htons(ETH_P_BATMAN); | 86 | skb->protocol = htons(ETH_P_BATMAN); |
87 | 87 | ||
88 | skb->dev = hard_iface->net_dev; | 88 | skb->dev = hard_iface->net_dev; |
89 | 89 | ||
90 | /* Save a clone of the skb to use when decoding coded packets */ | 90 | /* Save a clone of the skb to use when decoding coded packets */ |
91 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | 91 | batadv_nc_skb_store_for_decoding(bat_priv, skb); |
92 | 92 | ||
93 | /* dev_queue_xmit() returns a negative result on error. However on | 93 | /* dev_queue_xmit() returns a negative result on error. However on |
94 | * congestion and traffic shaping, it drops and returns NET_XMIT_DROP | 94 | * congestion and traffic shaping, it drops and returns NET_XMIT_DROP |
95 | * (which is > 0). This will not be treated as an error. | 95 | * (which is > 0). This will not be treated as an error. |
96 | */ | 96 | */ |
97 | return dev_queue_xmit(skb); | 97 | return dev_queue_xmit(skb); |
98 | send_skb_err: | 98 | send_skb_err: |
99 | kfree_skb(skb); | 99 | kfree_skb(skb); |
100 | return NET_XMIT_DROP; | 100 | return NET_XMIT_DROP; |
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * batadv_send_skb_to_orig - Lookup next-hop and transmit skb. | 104 | * batadv_send_skb_to_orig - Lookup next-hop and transmit skb. |
105 | * @skb: Packet to be transmitted. | 105 | * @skb: Packet to be transmitted. |
106 | * @orig_node: Final destination of the packet. | 106 | * @orig_node: Final destination of the packet. |
107 | * @recv_if: Interface used when receiving the packet (can be NULL). | 107 | * @recv_if: Interface used when receiving the packet (can be NULL). |
108 | * | 108 | * |
109 | * Looks up the best next-hop towards the passed originator and passes the | 109 | * Looks up the best next-hop towards the passed originator and passes the |
110 | * skb on for preparation of MAC header. If the packet originated from this | 110 | * skb on for preparation of MAC header. If the packet originated from this |
111 | * host, NULL can be passed as recv_if and no interface alternating is | 111 | * host, NULL can be passed as recv_if and no interface alternating is |
112 | * attempted. | 112 | * attempted. |
113 | * | 113 | * |
114 | * Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or | 114 | * Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or |
115 | * NET_XMIT_POLICED if the skb is buffered for later transmit. | 115 | * NET_XMIT_POLICED if the skb is buffered for later transmit. |
116 | */ | 116 | */ |
117 | int batadv_send_skb_to_orig(struct sk_buff *skb, | 117 | int batadv_send_skb_to_orig(struct sk_buff *skb, |
118 | struct batadv_orig_node *orig_node, | 118 | struct batadv_orig_node *orig_node, |
119 | struct batadv_hard_iface *recv_if) | 119 | struct batadv_hard_iface *recv_if) |
120 | { | 120 | { |
121 | struct batadv_priv *bat_priv = orig_node->bat_priv; | 121 | struct batadv_priv *bat_priv = orig_node->bat_priv; |
122 | struct batadv_neigh_node *neigh_node; | 122 | struct batadv_neigh_node *neigh_node; |
123 | int ret = NET_XMIT_DROP; | 123 | int ret = NET_XMIT_DROP; |
124 | 124 | ||
125 | /* batadv_find_router() increases neigh_nodes refcount if found. */ | 125 | /* batadv_find_router() increases neigh_nodes refcount if found. */ |
126 | neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); | 126 | neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); |
127 | if (!neigh_node) | 127 | if (!neigh_node) |
128 | goto out; | 128 | goto out; |
129 | 129 | ||
130 | /* Check if the skb is too large to send in one piece and fragment | 130 | /* Check if the skb is too large to send in one piece and fragment |
131 | * it if needed. | 131 | * it if needed. |
132 | */ | 132 | */ |
133 | if (atomic_read(&bat_priv->fragmentation) && | 133 | if (atomic_read(&bat_priv->fragmentation) && |
134 | skb->len > neigh_node->if_incoming->net_dev->mtu) { | 134 | skb->len > neigh_node->if_incoming->net_dev->mtu) { |
135 | /* Fragment and send packet. */ | 135 | /* Fragment and send packet. */ |
136 | if (batadv_frag_send_packet(skb, orig_node, neigh_node)) | 136 | if (batadv_frag_send_packet(skb, orig_node, neigh_node)) |
137 | ret = NET_XMIT_SUCCESS; | 137 | ret = NET_XMIT_SUCCESS; |
138 | 138 | ||
139 | goto out; | 139 | goto out; |
140 | } | 140 | } |
141 | 141 | ||
142 | /* try to network code the packet, if it is received on an interface | 142 | /* try to network code the packet, if it is received on an interface |
143 | * (i.e. being forwarded). If the packet originates from this node or if | 143 | * (i.e. being forwarded). If the packet originates from this node or if |
144 | * network coding fails, then send the packet as usual. | 144 | * network coding fails, then send the packet as usual. |
145 | */ | 145 | */ |
146 | if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) { | 146 | if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) { |
147 | ret = NET_XMIT_POLICED; | 147 | ret = NET_XMIT_POLICED; |
148 | } else { | 148 | } else { |
149 | batadv_send_skb_packet(skb, neigh_node->if_incoming, | 149 | batadv_send_skb_packet(skb, neigh_node->if_incoming, |
150 | neigh_node->addr); | 150 | neigh_node->addr); |
151 | ret = NET_XMIT_SUCCESS; | 151 | ret = NET_XMIT_SUCCESS; |
152 | } | 152 | } |
153 | 153 | ||
154 | out: | 154 | out: |
155 | if (neigh_node) | 155 | if (neigh_node) |
156 | batadv_neigh_node_free_ref(neigh_node); | 156 | batadv_neigh_node_free_ref(neigh_node); |
157 | 157 | ||
158 | return ret; | 158 | return ret; |
159 | } | 159 | } |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the | 162 | * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the |
163 | * common fields for unicast packets | 163 | * common fields for unicast packets |
164 | * @skb: the skb carrying the unicast header to initialize | 164 | * @skb: the skb carrying the unicast header to initialize |
165 | * @hdr_size: amount of bytes to push at the beginning of the skb | 165 | * @hdr_size: amount of bytes to push at the beginning of the skb |
166 | * @orig_node: the destination node | 166 | * @orig_node: the destination node |
167 | * | 167 | * |
168 | * Returns false if the buffer extension was not possible or true otherwise. | 168 | * Returns false if the buffer extension was not possible or true otherwise. |
169 | */ | 169 | */ |
170 | static bool | 170 | static bool |
171 | batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, | 171 | batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, |
172 | struct batadv_orig_node *orig_node) | 172 | struct batadv_orig_node *orig_node) |
173 | { | 173 | { |
174 | struct batadv_unicast_packet *unicast_packet; | 174 | struct batadv_unicast_packet *unicast_packet; |
175 | u8 ttvn = (u8)atomic_read(&orig_node->last_ttvn); | 175 | u8 ttvn = (u8)atomic_read(&orig_node->last_ttvn); |
176 | 176 | ||
177 | if (batadv_skb_head_push(skb, hdr_size) < 0) | 177 | if (batadv_skb_head_push(skb, hdr_size) < 0) |
178 | return false; | 178 | return false; |
179 | 179 | ||
180 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 180 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
181 | unicast_packet->version = BATADV_COMPAT_VERSION; | 181 | unicast_packet->version = BATADV_COMPAT_VERSION; |
182 | /* batman packet type: unicast */ | 182 | /* batman packet type: unicast */ |
183 | unicast_packet->packet_type = BATADV_UNICAST; | 183 | unicast_packet->packet_type = BATADV_UNICAST; |
184 | /* set unicast ttl */ | 184 | /* set unicast ttl */ |
185 | unicast_packet->ttl = BATADV_TTL; | 185 | unicast_packet->ttl = BATADV_TTL; |
186 | /* copy the destination for faster routing */ | 186 | /* copy the destination for faster routing */ |
187 | ether_addr_copy(unicast_packet->dest, orig_node->orig); | 187 | ether_addr_copy(unicast_packet->dest, orig_node->orig); |
188 | /* set the destination tt version number */ | 188 | /* set the destination tt version number */ |
189 | unicast_packet->ttvn = ttvn; | 189 | unicast_packet->ttvn = ttvn; |
190 | 190 | ||
191 | return true; | 191 | return true; |
192 | } | 192 | } |
193 | 193 | ||
194 | /** | 194 | /** |
195 | * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header | 195 | * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header |
196 | * @skb: the skb containing the payload to encapsulate | 196 | * @skb: the skb containing the payload to encapsulate |
197 | * @orig_node: the destination node | 197 | * @orig_node: the destination node |
198 | * | 198 | * |
199 | * Returns false if the payload could not be encapsulated or true otherwise. | 199 | * Returns false if the payload could not be encapsulated or true otherwise. |
200 | */ | 200 | */ |
201 | static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, | 201 | static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, |
202 | struct batadv_orig_node *orig_node) | 202 | struct batadv_orig_node *orig_node) |
203 | { | 203 | { |
204 | size_t uni_size = sizeof(struct batadv_unicast_packet); | 204 | size_t uni_size = sizeof(struct batadv_unicast_packet); |
205 | 205 | ||
206 | return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node); | 206 | return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node); |
207 | } | 207 | } |
208 | 208 | ||
209 | /** | 209 | /** |
210 | * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a | 210 | * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a |
211 | * unicast 4addr header | 211 | * unicast 4addr header |
212 | * @bat_priv: the bat priv with all the soft interface information | 212 | * @bat_priv: the bat priv with all the soft interface information |
213 | * @skb: the skb containing the payload to encapsulate | 213 | * @skb: the skb containing the payload to encapsulate |
214 | * @orig_node: the destination node | 214 | * @orig_node: the destination node |
215 | * @packet_subtype: the unicast 4addr packet subtype to use | 215 | * @packet_subtype: the unicast 4addr packet subtype to use |
216 | * | 216 | * |
217 | * Returns false if the payload could not be encapsulated or true otherwise. | 217 | * Returns false if the payload could not be encapsulated or true otherwise. |
218 | */ | 218 | */ |
219 | bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, | 219 | bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, |
220 | struct sk_buff *skb, | 220 | struct sk_buff *skb, |
221 | struct batadv_orig_node *orig, | 221 | struct batadv_orig_node *orig, |
222 | int packet_subtype) | 222 | int packet_subtype) |
223 | { | 223 | { |
224 | struct batadv_hard_iface *primary_if; | 224 | struct batadv_hard_iface *primary_if; |
225 | struct batadv_unicast_4addr_packet *uc_4addr_packet; | 225 | struct batadv_unicast_4addr_packet *uc_4addr_packet; |
226 | bool ret = false; | 226 | bool ret = false; |
227 | 227 | ||
228 | primary_if = batadv_primary_if_get_selected(bat_priv); | 228 | primary_if = batadv_primary_if_get_selected(bat_priv); |
229 | if (!primary_if) | 229 | if (!primary_if) |
230 | goto out; | 230 | goto out; |
231 | 231 | ||
232 | /* Pull the header space and fill the unicast_packet substructure. | 232 | /* Pull the header space and fill the unicast_packet substructure. |
233 | * We can do that because the first member of the uc_4addr_packet | 233 | * We can do that because the first member of the uc_4addr_packet |
234 | * is of type struct unicast_packet | 234 | * is of type struct unicast_packet |
235 | */ | 235 | */ |
236 | if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet), | 236 | if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet), |
237 | orig)) | 237 | orig)) |
238 | goto out; | 238 | goto out; |
239 | 239 | ||
240 | uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | 240 | uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; |
241 | uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; | 241 | uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; |
242 | ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr); | 242 | ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr); |
243 | uc_4addr_packet->subtype = packet_subtype; | 243 | uc_4addr_packet->subtype = packet_subtype; |
244 | uc_4addr_packet->reserved = 0; | 244 | uc_4addr_packet->reserved = 0; |
245 | 245 | ||
246 | ret = true; | 246 | ret = true; |
247 | out: | 247 | out: |
248 | if (primary_if) | 248 | if (primary_if) |
249 | batadv_hardif_free_ref(primary_if); | 249 | batadv_hardif_free_ref(primary_if); |
250 | return ret; | 250 | return ret; |
251 | } | 251 | } |
252 | 252 | ||
253 | /** | 253 | /** |
254 | * batadv_send_skb_unicast - encapsulate and send an skb via unicast | 254 | * batadv_send_skb_unicast - encapsulate and send an skb via unicast |
255 | * @bat_priv: the bat priv with all the soft interface information | 255 | * @bat_priv: the bat priv with all the soft interface information |
256 | * @skb: payload to send | 256 | * @skb: payload to send |
257 | * @packet_type: the batman unicast packet type to use | 257 | * @packet_type: the batman unicast packet type to use |
258 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast | 258 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast |
259 | * 4addr packets) | 259 | * 4addr packets) |
260 | * @orig_node: the originator to send the packet to | 260 | * @orig_node: the originator to send the packet to |
261 | * @vid: the vid to be used to search the translation table | 261 | * @vid: the vid to be used to search the translation table |
262 | * | 262 | * |
263 | * Wrap the given skb into a batman-adv unicast or unicast-4addr header | 263 | * Wrap the given skb into a batman-adv unicast or unicast-4addr header |
264 | * depending on whether BATADV_UNICAST or BATADV_UNICAST_4ADDR was supplied | 264 | * depending on whether BATADV_UNICAST or BATADV_UNICAST_4ADDR was supplied |
265 | * as packet_type. Then send this frame to the given orig_node and release a | 265 | * as packet_type. Then send this frame to the given orig_node and release a |
266 | * reference to this orig_node. | 266 | * reference to this orig_node. |
267 | * | 267 | * |
268 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. | 268 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. |
269 | */ | 269 | */ |
270 | int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | 270 | int batadv_send_skb_unicast(struct batadv_priv *bat_priv, |
271 | struct sk_buff *skb, int packet_type, | 271 | struct sk_buff *skb, int packet_type, |
272 | int packet_subtype, | 272 | int packet_subtype, |
273 | struct batadv_orig_node *orig_node, | 273 | struct batadv_orig_node *orig_node, |
274 | unsigned short vid) | 274 | unsigned short vid) |
275 | { | 275 | { |
276 | struct batadv_unicast_packet *unicast_packet; | 276 | struct batadv_unicast_packet *unicast_packet; |
277 | struct ethhdr *ethhdr; | 277 | struct ethhdr *ethhdr; |
278 | int ret = NET_XMIT_DROP; | 278 | int ret = NET_XMIT_DROP; |
279 | 279 | ||
280 | if (!orig_node) | 280 | if (!orig_node) |
281 | goto out; | 281 | goto out; |
282 | 282 | ||
283 | switch (packet_type) { | 283 | switch (packet_type) { |
284 | case BATADV_UNICAST: | 284 | case BATADV_UNICAST: |
285 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) | 285 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) |
286 | goto out; | 286 | goto out; |
287 | break; | 287 | break; |
288 | case BATADV_UNICAST_4ADDR: | 288 | case BATADV_UNICAST_4ADDR: |
289 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, | 289 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, |
290 | orig_node, | 290 | orig_node, |
291 | packet_subtype)) | 291 | packet_subtype)) |
292 | goto out; | 292 | goto out; |
293 | break; | 293 | break; |
294 | default: | 294 | default: |
295 | /* this function supports UNICAST and UNICAST_4ADDR only. It | 295 | /* this function supports UNICAST and UNICAST_4ADDR only. It |
296 | * should never be invoked with any other packet type | 296 | * should never be invoked with any other packet type |
297 | */ | 297 | */ |
298 | goto out; | 298 | goto out; |
299 | } | 299 | } |
300 | 300 | ||
301 | /* skb->data might have been reallocated by | 301 | /* skb->data might have been reallocated by |
302 | * batadv_send_skb_prepare_unicast{,_4addr}() | 302 | * batadv_send_skb_prepare_unicast{,_4addr}() |
303 | */ | 303 | */ |
304 | ethhdr = eth_hdr(skb); | 304 | ethhdr = eth_hdr(skb); |
305 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 305 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
306 | 306 | ||
307 | /* inform the destination node that we are still missing a correct route | 307 | /* inform the destination node that we are still missing a correct route |
308 | * for this client. The destination will receive this packet and will | 308 | * for this client. The destination will receive this packet and will |
309 | * try to reroute it because the ttvn contained in the header is less | 309 | * try to reroute it because the ttvn contained in the header is less |
310 | * than the current one | 310 | * than the current one |
311 | */ | 311 | */ |
312 | if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) | 312 | if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) |
313 | unicast_packet->ttvn = unicast_packet->ttvn - 1; | 313 | unicast_packet->ttvn = unicast_packet->ttvn - 1; |
314 | 314 | ||
315 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) | 315 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) |
316 | ret = NET_XMIT_SUCCESS; | 316 | ret = NET_XMIT_SUCCESS; |
317 | 317 | ||
318 | out: | 318 | out: |
319 | if (orig_node) | 319 | if (orig_node) |
320 | batadv_orig_node_free_ref(orig_node); | 320 | batadv_orig_node_free_ref(orig_node); |
321 | if (ret == NET_XMIT_DROP) | 321 | if (ret == NET_XMIT_DROP) |
322 | kfree_skb(skb); | 322 | kfree_skb(skb); |
323 | return ret; | 323 | return ret; |
324 | } | 324 | } |
325 | 325 | ||
326 | /** | 326 | /** |
327 | * batadv_send_skb_via_tt_generic - send an skb via TT lookup | 327 | * batadv_send_skb_via_tt_generic - send an skb via TT lookup |
328 | * @bat_priv: the bat priv with all the soft interface information | 328 | * @bat_priv: the bat priv with all the soft interface information |
329 | * @skb: payload to send | 329 | * @skb: payload to send |
330 | * @packet_type: the batman unicast packet type to use | 330 | * @packet_type: the batman unicast packet type to use |
331 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast | 331 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast |
332 | * 4addr packets) | 332 | * 4addr packets) |
333 | * @dst_hint: can be used to override the destination contained in the skb | 333 | * @dst_hint: can be used to override the destination contained in the skb |
334 | * @vid: the vid to be used to search the translation table | 334 | * @vid: the vid to be used to search the translation table |
335 | * | 335 | * |
336 | * Look up the recipient node for the destination address in the ethernet | 336 | * Look up the recipient node for the destination address in the ethernet |
337 | * header via the translation table. Wrap the given skb into a batman-adv | 337 | * header via the translation table. Wrap the given skb into a batman-adv |
338 | * unicast or unicast-4addr header depending on whether BATADV_UNICAST or | 338 | * unicast or unicast-4addr header depending on whether BATADV_UNICAST or |
339 | * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame | 339 | * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame |
340 | * to the according destination node. | 340 | * to the according destination node. |
341 | * | 341 | * |
342 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. | 342 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. |
343 | */ | 343 | */ |
344 | int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, | 344 | int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, |
345 | struct sk_buff *skb, int packet_type, | 345 | struct sk_buff *skb, int packet_type, |
346 | int packet_subtype, u8 *dst_hint, | 346 | int packet_subtype, u8 *dst_hint, |
347 | unsigned short vid) | 347 | unsigned short vid) |
348 | { | 348 | { |
349 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 349 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
350 | struct batadv_orig_node *orig_node; | 350 | struct batadv_orig_node *orig_node; |
351 | u8 *src, *dst; | 351 | u8 *src, *dst; |
352 | 352 | ||
353 | src = ethhdr->h_source; | 353 | src = ethhdr->h_source; |
354 | dst = ethhdr->h_dest; | 354 | dst = ethhdr->h_dest; |
355 | 355 | ||
356 | /* if we got an hint! let's send the packet to this client (if any) */ | 356 | /* if we got an hint! let's send the packet to this client (if any) */ |
357 | if (dst_hint) { | 357 | if (dst_hint) { |
358 | src = NULL; | 358 | src = NULL; |
359 | dst = dst_hint; | 359 | dst = dst_hint; |
360 | } | 360 | } |
361 | orig_node = batadv_transtable_search(bat_priv, src, dst, vid); | 361 | orig_node = batadv_transtable_search(bat_priv, src, dst, vid); |
362 | 362 | ||
363 | return batadv_send_skb_unicast(bat_priv, skb, packet_type, | 363 | return batadv_send_skb_unicast(bat_priv, skb, packet_type, |
364 | packet_subtype, orig_node, vid); | 364 | packet_subtype, orig_node, vid); |
365 | } | 365 | } |
366 | 366 | ||
367 | /** | 367 | /** |
368 | * batadv_send_skb_via_gw - send an skb via gateway lookup | 368 | * batadv_send_skb_via_gw - send an skb via gateway lookup |
369 | * @bat_priv: the bat priv with all the soft interface information | 369 | * @bat_priv: the bat priv with all the soft interface information |
370 | * @skb: payload to send | 370 | * @skb: payload to send |
371 | * @vid: the vid to be used to search the translation table | 371 | * @vid: the vid to be used to search the translation table |
372 | * | 372 | * |
373 | * Look up the currently selected gateway. Wrap the given skb into a batman-adv | 373 | * Look up the currently selected gateway. Wrap the given skb into a batman-adv |
374 | * unicast header and send this frame to this gateway node. | 374 | * unicast header and send this frame to this gateway node. |
375 | * | 375 | * |
376 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. | 376 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. |
377 | */ | 377 | */ |
378 | int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, | 378 | int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, |
379 | unsigned short vid) | 379 | unsigned short vid) |
380 | { | 380 | { |
381 | struct batadv_orig_node *orig_node; | 381 | struct batadv_orig_node *orig_node; |
382 | 382 | ||
383 | orig_node = batadv_gw_get_selected_orig(bat_priv); | 383 | orig_node = batadv_gw_get_selected_orig(bat_priv); |
384 | return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0, | 384 | return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0, |
385 | orig_node, vid); | 385 | orig_node, vid); |
386 | } | 386 | } |
387 | 387 | ||
388 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) | 388 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) |
389 | { | 389 | { |
390 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 390 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
391 | 391 | ||
392 | if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || | 392 | if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || |
393 | (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) | 393 | (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) |
394 | return; | 394 | return; |
395 | 395 | ||
396 | /* the interface gets activated here to avoid race conditions between | 396 | /* the interface gets activated here to avoid race conditions between |
397 | * the moment of activating the interface in | 397 | * the moment of activating the interface in |
398 | * hardif_activate_interface() where the originator mac is set and | 398 | * hardif_activate_interface() where the originator mac is set and |
399 | * outdated packets (especially uninitialized mac addresses) in the | 399 | * outdated packets (especially uninitialized mac addresses) in the |
400 | * packet queue | 400 | * packet queue |
401 | */ | 401 | */ |
402 | if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) | 402 | if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) |
403 | hard_iface->if_status = BATADV_IF_ACTIVE; | 403 | hard_iface->if_status = BATADV_IF_ACTIVE; |
404 | 404 | ||
405 | bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface); | 405 | bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface); |
406 | } | 406 | } |
407 | 407 | ||
408 | static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) | 408 | static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) |
409 | { | 409 | { |
410 | if (forw_packet->skb) | 410 | kfree_skb(forw_packet->skb); |
411 | kfree_skb(forw_packet->skb); | ||
412 | if (forw_packet->if_incoming) | 411 | if (forw_packet->if_incoming) |
413 | batadv_hardif_free_ref(forw_packet->if_incoming); | 412 | batadv_hardif_free_ref(forw_packet->if_incoming); |
414 | if (forw_packet->if_outgoing) | 413 | if (forw_packet->if_outgoing) |
415 | batadv_hardif_free_ref(forw_packet->if_outgoing); | 414 | batadv_hardif_free_ref(forw_packet->if_outgoing); |
416 | kfree(forw_packet); | 415 | kfree(forw_packet); |
417 | } | 416 | } |
418 | 417 | ||
419 | static void | 418 | static void |
420 | _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, | 419 | _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, |
421 | struct batadv_forw_packet *forw_packet, | 420 | struct batadv_forw_packet *forw_packet, |
422 | unsigned long send_time) | 421 | unsigned long send_time) |
423 | { | 422 | { |
424 | /* add new packet to packet list */ | 423 | /* add new packet to packet list */ |
425 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 424 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
426 | hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); | 425 | hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); |
427 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 426 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
428 | 427 | ||
429 | /* start timer for this packet */ | 428 | /* start timer for this packet */ |
430 | queue_delayed_work(batadv_event_workqueue, &forw_packet->delayed_work, | 429 | queue_delayed_work(batadv_event_workqueue, &forw_packet->delayed_work, |
431 | send_time); | 430 | send_time); |
432 | } | 431 | } |
433 | 432 | ||
434 | /* add a broadcast packet to the queue and setup timers. broadcast packets | 433 | /* add a broadcast packet to the queue and setup timers. broadcast packets |
435 | * are sent multiple times to increase probability for being received. | 434 | * are sent multiple times to increase probability for being received. |
436 | * | 435 | * |
437 | * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on | 436 | * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on |
438 | * errors. | 437 | * errors. |
439 | * | 438 | * |
440 | * The skb is not consumed, so the caller should make sure that the | 439 | * The skb is not consumed, so the caller should make sure that the |
441 | * skb is freed. | 440 | * skb is freed. |
442 | */ | 441 | */ |
443 | int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, | 442 | int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, |
444 | const struct sk_buff *skb, | 443 | const struct sk_buff *skb, |
445 | unsigned long delay) | 444 | unsigned long delay) |
446 | { | 445 | { |
447 | struct batadv_hard_iface *primary_if = NULL; | 446 | struct batadv_hard_iface *primary_if = NULL; |
448 | struct batadv_forw_packet *forw_packet; | 447 | struct batadv_forw_packet *forw_packet; |
449 | struct batadv_bcast_packet *bcast_packet; | 448 | struct batadv_bcast_packet *bcast_packet; |
450 | struct sk_buff *newskb; | 449 | struct sk_buff *newskb; |
451 | 450 | ||
452 | if (!batadv_atomic_dec_not_zero(&bat_priv->bcast_queue_left)) { | 451 | if (!batadv_atomic_dec_not_zero(&bat_priv->bcast_queue_left)) { |
453 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 452 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
454 | "bcast packet queue full\n"); | 453 | "bcast packet queue full\n"); |
455 | goto out; | 454 | goto out; |
456 | } | 455 | } |
457 | 456 | ||
458 | primary_if = batadv_primary_if_get_selected(bat_priv); | 457 | primary_if = batadv_primary_if_get_selected(bat_priv); |
459 | if (!primary_if) | 458 | if (!primary_if) |
460 | goto out_and_inc; | 459 | goto out_and_inc; |
461 | 460 | ||
462 | forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC); | 461 | forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC); |
463 | 462 | ||
464 | if (!forw_packet) | 463 | if (!forw_packet) |
465 | goto out_and_inc; | 464 | goto out_and_inc; |
466 | 465 | ||
467 | newskb = skb_copy(skb, GFP_ATOMIC); | 466 | newskb = skb_copy(skb, GFP_ATOMIC); |
468 | if (!newskb) | 467 | if (!newskb) |
469 | goto packet_free; | 468 | goto packet_free; |
470 | 469 | ||
471 | /* as we have a copy now, it is safe to decrease the TTL */ | 470 | /* as we have a copy now, it is safe to decrease the TTL */ |
472 | bcast_packet = (struct batadv_bcast_packet *)newskb->data; | 471 | bcast_packet = (struct batadv_bcast_packet *)newskb->data; |
473 | bcast_packet->ttl--; | 472 | bcast_packet->ttl--; |
474 | 473 | ||
475 | skb_reset_mac_header(newskb); | 474 | skb_reset_mac_header(newskb); |
476 | 475 | ||
477 | forw_packet->skb = newskb; | 476 | forw_packet->skb = newskb; |
478 | forw_packet->if_incoming = primary_if; | 477 | forw_packet->if_incoming = primary_if; |
479 | forw_packet->if_outgoing = NULL; | 478 | forw_packet->if_outgoing = NULL; |
480 | 479 | ||
481 | /* how often did we send the bcast packet ? */ | 480 | /* how often did we send the bcast packet ? */ |
482 | forw_packet->num_packets = 0; | 481 | forw_packet->num_packets = 0; |
483 | 482 | ||
484 | INIT_DELAYED_WORK(&forw_packet->delayed_work, | 483 | INIT_DELAYED_WORK(&forw_packet->delayed_work, |
485 | batadv_send_outstanding_bcast_packet); | 484 | batadv_send_outstanding_bcast_packet); |
486 | 485 | ||
487 | _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay); | 486 | _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay); |
488 | return NETDEV_TX_OK; | 487 | return NETDEV_TX_OK; |
489 | 488 | ||
490 | packet_free: | 489 | packet_free: |
491 | kfree(forw_packet); | 490 | kfree(forw_packet); |
492 | out_and_inc: | 491 | out_and_inc: |
493 | atomic_inc(&bat_priv->bcast_queue_left); | 492 | atomic_inc(&bat_priv->bcast_queue_left); |
494 | out: | 493 | out: |
495 | if (primary_if) | 494 | if (primary_if) |
496 | batadv_hardif_free_ref(primary_if); | 495 | batadv_hardif_free_ref(primary_if); |
497 | return NETDEV_TX_BUSY; | 496 | return NETDEV_TX_BUSY; |
498 | } | 497 | } |
499 | 498 | ||
500 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work) | 499 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work) |
501 | { | 500 | { |
502 | struct batadv_hard_iface *hard_iface; | 501 | struct batadv_hard_iface *hard_iface; |
503 | struct delayed_work *delayed_work; | 502 | struct delayed_work *delayed_work; |
504 | struct batadv_forw_packet *forw_packet; | 503 | struct batadv_forw_packet *forw_packet; |
505 | struct sk_buff *skb1; | 504 | struct sk_buff *skb1; |
506 | struct net_device *soft_iface; | 505 | struct net_device *soft_iface; |
507 | struct batadv_priv *bat_priv; | 506 | struct batadv_priv *bat_priv; |
508 | 507 | ||
509 | delayed_work = container_of(work, struct delayed_work, work); | 508 | delayed_work = container_of(work, struct delayed_work, work); |
510 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | 509 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, |
511 | delayed_work); | 510 | delayed_work); |
512 | soft_iface = forw_packet->if_incoming->soft_iface; | 511 | soft_iface = forw_packet->if_incoming->soft_iface; |
513 | bat_priv = netdev_priv(soft_iface); | 512 | bat_priv = netdev_priv(soft_iface); |
514 | 513 | ||
515 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 514 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
516 | hlist_del(&forw_packet->list); | 515 | hlist_del(&forw_packet->list); |
517 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 516 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
518 | 517 | ||
519 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) | 518 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) |
520 | goto out; | 519 | goto out; |
521 | 520 | ||
522 | if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) | 521 | if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) |
523 | goto out; | 522 | goto out; |
524 | 523 | ||
525 | /* rebroadcast packet */ | 524 | /* rebroadcast packet */ |
526 | rcu_read_lock(); | 525 | rcu_read_lock(); |
527 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 526 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { |
528 | if (hard_iface->soft_iface != soft_iface) | 527 | if (hard_iface->soft_iface != soft_iface) |
529 | continue; | 528 | continue; |
530 | 529 | ||
531 | if (forw_packet->num_packets >= hard_iface->num_bcasts) | 530 | if (forw_packet->num_packets >= hard_iface->num_bcasts) |
532 | continue; | 531 | continue; |
533 | 532 | ||
534 | /* send a copy of the saved skb */ | 533 | /* send a copy of the saved skb */ |
535 | skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); | 534 | skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); |
536 | if (skb1) | 535 | if (skb1) |
537 | batadv_send_skb_packet(skb1, hard_iface, | 536 | batadv_send_skb_packet(skb1, hard_iface, |
538 | batadv_broadcast_addr); | 537 | batadv_broadcast_addr); |
539 | } | 538 | } |
540 | rcu_read_unlock(); | 539 | rcu_read_unlock(); |
541 | 540 | ||
542 | forw_packet->num_packets++; | 541 | forw_packet->num_packets++; |
543 | 542 | ||
544 | /* if we still have some more bcasts to send */ | 543 | /* if we still have some more bcasts to send */ |
545 | if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) { | 544 | if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) { |
546 | _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, | 545 | _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, |
547 | msecs_to_jiffies(5)); | 546 | msecs_to_jiffies(5)); |
548 | return; | 547 | return; |
549 | } | 548 | } |
550 | 549 | ||
551 | out: | 550 | out: |
552 | batadv_forw_packet_free(forw_packet); | 551 | batadv_forw_packet_free(forw_packet); |
553 | atomic_inc(&bat_priv->bcast_queue_left); | 552 | atomic_inc(&bat_priv->bcast_queue_left); |
554 | } | 553 | } |
555 | 554 | ||
556 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) | 555 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) |
557 | { | 556 | { |
558 | struct delayed_work *delayed_work; | 557 | struct delayed_work *delayed_work; |
559 | struct batadv_forw_packet *forw_packet; | 558 | struct batadv_forw_packet *forw_packet; |
560 | struct batadv_priv *bat_priv; | 559 | struct batadv_priv *bat_priv; |
561 | 560 | ||
562 | delayed_work = container_of(work, struct delayed_work, work); | 561 | delayed_work = container_of(work, struct delayed_work, work); |
563 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | 562 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, |
564 | delayed_work); | 563 | delayed_work); |
565 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); | 564 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); |
566 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | 565 | spin_lock_bh(&bat_priv->forw_bat_list_lock); |
567 | hlist_del(&forw_packet->list); | 566 | hlist_del(&forw_packet->list); |
568 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 567 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
569 | 568 | ||
570 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) | 569 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) |
571 | goto out; | 570 | goto out; |
572 | 571 | ||
573 | bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet); | 572 | bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet); |
574 | 573 | ||
575 | /* we have to have at least one packet in the queue to determine the | 574 | /* we have to have at least one packet in the queue to determine the |
576 | * queues wake up time unless we are shutting down. | 575 | * queues wake up time unless we are shutting down. |
577 | * | 576 | * |
578 | * only re-schedule if this is the "original" copy, e.g. the OGM of the | 577 | * only re-schedule if this is the "original" copy, e.g. the OGM of the |
579 | * primary interface should only be rescheduled once per period, but | 578 | * primary interface should only be rescheduled once per period, but |
580 | * this function will be called for the forw_packet instances of the | 579 | * this function will be called for the forw_packet instances of the |
581 | * other secondary interfaces as well. | 580 | * other secondary interfaces as well. |
582 | */ | 581 | */ |
583 | if (forw_packet->own && | 582 | if (forw_packet->own && |
584 | forw_packet->if_incoming == forw_packet->if_outgoing) | 583 | forw_packet->if_incoming == forw_packet->if_outgoing) |
585 | batadv_schedule_bat_ogm(forw_packet->if_incoming); | 584 | batadv_schedule_bat_ogm(forw_packet->if_incoming); |
586 | 585 | ||
587 | out: | 586 | out: |
588 | /* don't count own packet */ | 587 | /* don't count own packet */ |
589 | if (!forw_packet->own) | 588 | if (!forw_packet->own) |
590 | atomic_inc(&bat_priv->batman_queue_left); | 589 | atomic_inc(&bat_priv->batman_queue_left); |
591 | 590 | ||
592 | batadv_forw_packet_free(forw_packet); | 591 | batadv_forw_packet_free(forw_packet); |
593 | } | 592 | } |
594 | 593 | ||
595 | void | 594 | void |
596 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | 595 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, |
597 | const struct batadv_hard_iface *hard_iface) | 596 | const struct batadv_hard_iface *hard_iface) |
598 | { | 597 | { |
599 | struct batadv_forw_packet *forw_packet; | 598 | struct batadv_forw_packet *forw_packet; |
600 | struct hlist_node *safe_tmp_node; | 599 | struct hlist_node *safe_tmp_node; |
601 | bool pending; | 600 | bool pending; |
602 | 601 | ||
603 | if (hard_iface) | 602 | if (hard_iface) |
604 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 603 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
605 | "purge_outstanding_packets(): %s\n", | 604 | "purge_outstanding_packets(): %s\n", |
606 | hard_iface->net_dev->name); | 605 | hard_iface->net_dev->name); |
607 | else | 606 | else |
608 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 607 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
609 | "purge_outstanding_packets()\n"); | 608 | "purge_outstanding_packets()\n"); |
610 | 609 | ||
611 | /* free bcast list */ | 610 | /* free bcast list */ |
612 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 611 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
613 | hlist_for_each_entry_safe(forw_packet, safe_tmp_node, | 612 | hlist_for_each_entry_safe(forw_packet, safe_tmp_node, |
614 | &bat_priv->forw_bcast_list, list) { | 613 | &bat_priv->forw_bcast_list, list) { |
615 | /* if purge_outstanding_packets() was called with an argument | 614 | /* if purge_outstanding_packets() was called with an argument |
616 | * we delete only packets belonging to the given interface | 615 | * we delete only packets belonging to the given interface |
617 | */ | 616 | */ |
618 | if ((hard_iface) && | 617 | if ((hard_iface) && |
619 | (forw_packet->if_incoming != hard_iface) && | 618 | (forw_packet->if_incoming != hard_iface) && |
620 | (forw_packet->if_outgoing != hard_iface)) | 619 | (forw_packet->if_outgoing != hard_iface)) |
621 | continue; | 620 | continue; |
622 | 621 | ||
623 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 622 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
624 | 623 | ||
625 | /* batadv_send_outstanding_bcast_packet() will lock the list to | 624 | /* batadv_send_outstanding_bcast_packet() will lock the list to |
626 | * delete the item from the list | 625 | * delete the item from the list |
627 | */ | 626 | */ |
628 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); | 627 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
629 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 628 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
630 | 629 | ||
631 | if (pending) { | 630 | if (pending) { |
632 | hlist_del(&forw_packet->list); | 631 | hlist_del(&forw_packet->list); |
633 | batadv_forw_packet_free(forw_packet); | 632 | batadv_forw_packet_free(forw_packet); |
634 | } | 633 | } |
635 | } | 634 | } |
636 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 635 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
637 | 636 | ||
638 | /* free batman packet list */ | 637 | /* free batman packet list */ |
639 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | 638 | spin_lock_bh(&bat_priv->forw_bat_list_lock); |
640 | hlist_for_each_entry_safe(forw_packet, safe_tmp_node, | 639 | hlist_for_each_entry_safe(forw_packet, safe_tmp_node, |
641 | &bat_priv->forw_bat_list, list) { | 640 | &bat_priv->forw_bat_list, list) { |
642 | /* if purge_outstanding_packets() was called with an argument | 641 | /* if purge_outstanding_packets() was called with an argument |
643 | * we delete only packets belonging to the given interface | 642 | * we delete only packets belonging to the given interface |
644 | */ | 643 | */ |
645 | if ((hard_iface) && | 644 | if ((hard_iface) && |
646 | (forw_packet->if_incoming != hard_iface) && | 645 | (forw_packet->if_incoming != hard_iface) && |
647 | (forw_packet->if_outgoing != hard_iface)) | 646 | (forw_packet->if_outgoing != hard_iface)) |
648 | continue; | 647 | continue; |
649 | 648 | ||
650 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 649 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
651 | 650 | ||
652 | /* send_outstanding_bat_packet() will lock the list to | 651 | /* send_outstanding_bat_packet() will lock the list to |
653 | * delete the item from the list | 652 | * delete the item from the list |
654 | */ | 653 | */ |
655 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); | 654 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
656 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | 655 | spin_lock_bh(&bat_priv->forw_bat_list_lock); |
657 | 656 | ||
658 | if (pending) { | 657 | if (pending) { |
659 | hlist_del(&forw_packet->list); | 658 | hlist_del(&forw_packet->list); |
660 | batadv_forw_packet_free(forw_packet); | 659 | batadv_forw_packet_free(forw_packet); |
661 | } | 660 | } |
662 | } | 661 | } |
663 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 662 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
664 | } | 663 | } |
665 | 664 |