aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
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
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')
-rw-r--r--net/batman-adv/hard-interface.c113
-rw-r--r--net/batman-adv/main.c121
-rw-r--r--net/batman-adv/main.h6
3 files changed, 127 insertions, 113 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 47c79d724ba3..95f869c7ca04 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -32,12 +32,6 @@
32 32
33#include <linux/if_arp.h> 33#include <linux/if_arp.h>
34 34
35
36static int batman_skb_recv(struct sk_buff *skb,
37 struct net_device *dev,
38 struct packet_type *ptype,
39 struct net_device *orig_dev);
40
41void hardif_free_rcu(struct rcu_head *rcu) 35void hardif_free_rcu(struct rcu_head *rcu)
42{ 36{
43 struct hard_iface *hard_iface; 37 struct hard_iface *hard_iface;
@@ -551,113 +545,6 @@ out:
551 return NOTIFY_DONE; 545 return NOTIFY_DONE;
552} 546}
553 547
554/* incoming packets with the batman ethertype received on any active hard
555 * interface */
556static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
557 struct packet_type *ptype,
558 struct net_device *orig_dev)
559{
560 struct bat_priv *bat_priv;
561 struct batman_ogm_packet *batman_ogm_packet;
562 struct hard_iface *hard_iface;
563 int ret;
564
565 hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
566 skb = skb_share_check(skb, GFP_ATOMIC);
567
568 /* skb was released by skb_share_check() */
569 if (!skb)
570 goto err_out;
571
572 /* packet should hold at least type and version */
573 if (unlikely(!pskb_may_pull(skb, 2)))
574 goto err_free;
575
576 /* expect a valid ethernet header here. */
577 if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
578 goto err_free;
579
580 if (!hard_iface->soft_iface)
581 goto err_free;
582
583 bat_priv = netdev_priv(hard_iface->soft_iface);
584
585 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
586 goto err_free;
587
588 /* discard frames on not active interfaces */
589 if (hard_iface->if_status != IF_ACTIVE)
590 goto err_free;
591
592 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
593
594 if (batman_ogm_packet->header.version != COMPAT_VERSION) {
595 bat_dbg(DBG_BATMAN, bat_priv,
596 "Drop packet: incompatible batman version (%i)\n",
597 batman_ogm_packet->header.version);
598 goto err_free;
599 }
600
601 /* all receive handlers return whether they received or reused
602 * the supplied skb. if not, we have to free the skb. */
603
604 switch (batman_ogm_packet->header.packet_type) {
605 /* batman originator packet */
606 case BAT_IV_OGM:
607 ret = recv_bat_ogm_packet(skb, hard_iface);
608 break;
609
610 /* batman icmp packet */
611 case BAT_ICMP:
612 ret = recv_icmp_packet(skb, hard_iface);
613 break;
614
615 /* unicast packet */
616 case BAT_UNICAST:
617 ret = recv_unicast_packet(skb, hard_iface);
618 break;
619
620 /* fragmented unicast packet */
621 case BAT_UNICAST_FRAG:
622 ret = recv_ucast_frag_packet(skb, hard_iface);
623 break;
624
625 /* broadcast packet */
626 case BAT_BCAST:
627 ret = recv_bcast_packet(skb, hard_iface);
628 break;
629
630 /* vis packet */
631 case BAT_VIS:
632 ret = recv_vis_packet(skb, hard_iface);
633 break;
634 /* Translation table query (request or response) */
635 case BAT_TT_QUERY:
636 ret = recv_tt_query(skb, hard_iface);
637 break;
638 /* Roaming advertisement */
639 case BAT_ROAM_ADV:
640 ret = recv_roam_adv(skb, hard_iface);
641 break;
642 default:
643 ret = NET_RX_DROP;
644 }
645
646 if (ret == NET_RX_DROP)
647 kfree_skb(skb);
648
649 /* return NET_RX_SUCCESS in any case as we
650 * most probably dropped the packet for
651 * routing-logical reasons. */
652
653 return NET_RX_SUCCESS;
654
655err_free:
656 kfree_skb(skb);
657err_out:
658 return NET_RX_DROP;
659}
660
661/* This function returns true if the interface represented by ifindex is a 548/* This function returns true if the interface represented by ifindex is a
662 * 802.11 wireless device */ 549 * 802.11 wireless device */
663bool is_wifi_iface(int ifindex) 550bool is_wifi_iface(int ifindex)
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;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index d9832acf558d..fd83acd48b28 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -155,6 +155,12 @@ void mesh_free(struct net_device *soft_iface);
155void inc_module_count(void); 155void inc_module_count(void);
156void dec_module_count(void); 156void dec_module_count(void);
157int is_my_mac(const uint8_t *addr); 157int is_my_mac(const uint8_t *addr);
158int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
159 struct packet_type *ptype, struct net_device *orig_dev);
160int recv_handler_register(uint8_t packet_type,
161 int (*recv_handler)(struct sk_buff *,
162 struct hard_iface *));
163void recv_handler_unregister(uint8_t packet_type);
158int bat_algo_register(struct bat_algo_ops *bat_algo_ops); 164int bat_algo_register(struct bat_algo_ops *bat_algo_ops);
159int bat_algo_select(struct bat_priv *bat_priv, char *name); 165int bat_algo_select(struct bat_priv *bat_priv, char *name);
160int bat_algo_seq_print_text(struct seq_file *seq, void *offset); 166int bat_algo_seq_print_text(struct seq_file *seq, void *offset);