aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/main.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2012-03-01 02:35:17 -0500
committerAntonio Quartulli <ordex@autistici.org>2012-05-11 04:08:10 -0400
commitffa995e036bef734ea40cbbccda574d1df3a8a58 (patch)
tree396d7c202f1b0d82dce905e7d70c32708886f404 /net/batman-adv/main.c
parent75cd33f86396c446f84c4bb620be70c36a2a54f6 (diff)
batman-adv: introduce packet type handler array for incoming packets
The packet handler array replaces the growing switch statement, thus dealing with incoming packets in a more efficient way. It also adds to possibility to register packet handlers on the fly. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv/main.c')
-rw-r--r--net/batman-adv/main.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 791327219531..d19b93575d56 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -39,6 +39,7 @@
39/* List manipulations on hardif_list have to be rtnl_lock()'ed, 39/* List manipulations on hardif_list have to be rtnl_lock()'ed,
40 * list traversals just rcu-locked */ 40 * list traversals just rcu-locked */
41struct list_head hardif_list; 41struct list_head hardif_list;
42static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *);
42char bat_routing_algo[20] = "BATMAN IV"; 43char bat_routing_algo[20] = "BATMAN IV";
43static struct hlist_head bat_algo_list; 44static struct hlist_head bat_algo_list;
44 45
@@ -46,11 +47,15 @@ unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
46 47
47struct workqueue_struct *bat_event_workqueue; 48struct workqueue_struct *bat_event_workqueue;
48 49
50static void recv_handler_init(void);
51
49static int __init batman_init(void) 52static int __init batman_init(void)
50{ 53{
51 INIT_LIST_HEAD(&hardif_list); 54 INIT_LIST_HEAD(&hardif_list);
52 INIT_HLIST_HEAD(&bat_algo_list); 55 INIT_HLIST_HEAD(&bat_algo_list);
53 56
57 recv_handler_init();
58
54 bat_iv_init(); 59 bat_iv_init();
55 60
56 /* the name should not be longer than 10 chars - see 61 /* the name should not be longer than 10 chars - see
@@ -179,6 +184,122 @@ int is_my_mac(const uint8_t *addr)
179 return 0; 184 return 0;
180} 185}
181 186
187static int recv_unhandled_packet(struct sk_buff *skb,
188 struct hard_iface *recv_if)
189{
190 return NET_RX_DROP;
191}
192
193/* incoming packets with the batman ethertype received on any active hard
194 * interface
195 */
196int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
197 struct packet_type *ptype, struct net_device *orig_dev)
198{
199 struct bat_priv *bat_priv;
200 struct batman_ogm_packet *batman_ogm_packet;
201 struct hard_iface *hard_iface;
202 uint8_t idx;
203 int ret;
204
205 hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
206 skb = skb_share_check(skb, GFP_ATOMIC);
207
208 /* skb was released by skb_share_check() */
209 if (!skb)
210 goto err_out;
211
212 /* packet should hold at least type and version */
213 if (unlikely(!pskb_may_pull(skb, 2)))
214 goto err_free;
215
216 /* expect a valid ethernet header here. */
217 if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
218 goto err_free;
219
220 if (!hard_iface->soft_iface)
221 goto err_free;
222
223 bat_priv = netdev_priv(hard_iface->soft_iface);
224
225 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
226 goto err_free;
227
228 /* discard frames on not active interfaces */
229 if (hard_iface->if_status != IF_ACTIVE)
230 goto err_free;
231
232 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
233
234 if (batman_ogm_packet->header.version != COMPAT_VERSION) {
235 bat_dbg(DBG_BATMAN, bat_priv,
236 "Drop packet: incompatible batman version (%i)\n",
237 batman_ogm_packet->header.version);
238 goto err_free;
239 }
240
241 /* all receive handlers return whether they received or reused
242 * the supplied skb. if not, we have to free the skb.
243 */
244 idx = batman_ogm_packet->header.packet_type;
245 ret = (*recv_packet_handler[idx])(skb, hard_iface);
246
247 if (ret == NET_RX_DROP)
248 kfree_skb(skb);
249
250 /* return NET_RX_SUCCESS in any case as we
251 * most probably dropped the packet for
252 * routing-logical reasons.
253 */
254 return NET_RX_SUCCESS;
255
256err_free:
257 kfree_skb(skb);
258err_out:
259 return NET_RX_DROP;
260}
261
262static void recv_handler_init(void)
263{
264 int i;
265
266 for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
267 recv_packet_handler[i] = recv_unhandled_packet;
268
269 /* batman originator packet */
270 recv_packet_handler[BAT_IV_OGM] = recv_bat_ogm_packet;
271 /* batman icmp packet */
272 recv_packet_handler[BAT_ICMP] = recv_icmp_packet;
273 /* unicast packet */
274 recv_packet_handler[BAT_UNICAST] = recv_unicast_packet;
275 /* fragmented unicast packet */
276 recv_packet_handler[BAT_UNICAST_FRAG] = recv_ucast_frag_packet;
277 /* broadcast packet */
278 recv_packet_handler[BAT_BCAST] = recv_bcast_packet;
279 /* vis packet */
280 recv_packet_handler[BAT_VIS] = recv_vis_packet;
281 /* Translation table query (request or response) */
282 recv_packet_handler[BAT_TT_QUERY] = recv_tt_query;
283 /* Roaming advertisement */
284 recv_packet_handler[BAT_ROAM_ADV] = recv_roam_adv;
285}
286
287int recv_handler_register(uint8_t packet_type,
288 int (*recv_handler)(struct sk_buff *,
289 struct hard_iface *))
290{
291 if (recv_packet_handler[packet_type] != &recv_unhandled_packet)
292 return -EBUSY;
293
294 recv_packet_handler[packet_type] = recv_handler;
295 return 0;
296}
297
298void recv_handler_unregister(uint8_t packet_type)
299{
300 recv_packet_handler[packet_type] = recv_unhandled_packet;
301}
302
182static struct bat_algo_ops *bat_algo_get(char *name) 303static struct bat_algo_ops *bat_algo_get(char *name)
183{ 304{
184 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; 305 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;