diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2012-03-01 02:35:17 -0500 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2012-05-11 04:08:10 -0400 |
commit | ffa995e036bef734ea40cbbccda574d1df3a8a58 (patch) | |
tree | 396d7c202f1b0d82dce905e7d70c32708886f404 /net/batman-adv | |
parent | 75cd33f86396c446f84c4bb620be70c36a2a54f6 (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.c | 113 | ||||
-rw-r--r-- | net/batman-adv/main.c | 121 | ||||
-rw-r--r-- | net/batman-adv/main.h | 6 |
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 | |||
36 | static 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 | |||
41 | void hardif_free_rcu(struct rcu_head *rcu) | 35 | void 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 */ | ||
556 | static 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 | |||
655 | err_free: | ||
656 | kfree_skb(skb); | ||
657 | err_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 */ |
663 | bool is_wifi_iface(int ifindex) | 550 | bool 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 */ |
41 | struct list_head hardif_list; | 41 | struct list_head hardif_list; |
42 | static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *); | ||
42 | char bat_routing_algo[20] = "BATMAN IV"; | 43 | char bat_routing_algo[20] = "BATMAN IV"; |
43 | static struct hlist_head bat_algo_list; | 44 | static struct hlist_head bat_algo_list; |
44 | 45 | ||
@@ -46,11 +47,15 @@ unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||
46 | 47 | ||
47 | struct workqueue_struct *bat_event_workqueue; | 48 | struct workqueue_struct *bat_event_workqueue; |
48 | 49 | ||
50 | static void recv_handler_init(void); | ||
51 | |||
49 | static int __init batman_init(void) | 52 | static 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 | ||
187 | static 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 | */ | ||
196 | int 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 | |||
256 | err_free: | ||
257 | kfree_skb(skb); | ||
258 | err_out: | ||
259 | return NET_RX_DROP; | ||
260 | } | ||
261 | |||
262 | static 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 | |||
287 | int 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 | |||
298 | void recv_handler_unregister(uint8_t packet_type) | ||
299 | { | ||
300 | recv_packet_handler[packet_type] = recv_unhandled_packet; | ||
301 | } | ||
302 | |||
182 | static struct bat_algo_ops *bat_algo_get(char *name) | 303 | static 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); | |||
155 | void inc_module_count(void); | 155 | void inc_module_count(void); |
156 | void dec_module_count(void); | 156 | void dec_module_count(void); |
157 | int is_my_mac(const uint8_t *addr); | 157 | int is_my_mac(const uint8_t *addr); |
158 | int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | ||
159 | struct packet_type *ptype, struct net_device *orig_dev); | ||
160 | int recv_handler_register(uint8_t packet_type, | ||
161 | int (*recv_handler)(struct sk_buff *, | ||
162 | struct hard_iface *)); | ||
163 | void recv_handler_unregister(uint8_t packet_type); | ||
158 | int bat_algo_register(struct bat_algo_ops *bat_algo_ops); | 164 | int bat_algo_register(struct bat_algo_ops *bat_algo_ops); |
159 | int bat_algo_select(struct bat_priv *bat_priv, char *name); | 165 | int bat_algo_select(struct bat_priv *bat_priv, char *name); |
160 | int bat_algo_seq_print_text(struct seq_file *seq, void *offset); | 166 | int bat_algo_seq_print_text(struct seq_file *seq, void *offset); |