diff options
Diffstat (limited to 'net/batman-adv/hard-interface.c')
-rw-r--r-- | net/batman-adv/hard-interface.c | 170 |
1 files changed, 31 insertions, 139 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 377897701a85..dc334fa89847 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -28,15 +28,10 @@ | |||
28 | #include "bat_sysfs.h" | 28 | #include "bat_sysfs.h" |
29 | #include "originator.h" | 29 | #include "originator.h" |
30 | #include "hash.h" | 30 | #include "hash.h" |
31 | #include "bridge_loop_avoidance.h" | ||
31 | 32 | ||
32 | #include <linux/if_arp.h> | 33 | #include <linux/if_arp.h> |
33 | 34 | ||
34 | |||
35 | static int batman_skb_recv(struct sk_buff *skb, | ||
36 | struct net_device *dev, | ||
37 | struct packet_type *ptype, | ||
38 | struct net_device *orig_dev); | ||
39 | |||
40 | void hardif_free_rcu(struct rcu_head *rcu) | 35 | void hardif_free_rcu(struct rcu_head *rcu) |
41 | { | 36 | { |
42 | struct hard_iface *hard_iface; | 37 | struct hard_iface *hard_iface; |
@@ -107,7 +102,8 @@ out: | |||
107 | return hard_iface; | 102 | return hard_iface; |
108 | } | 103 | } |
109 | 104 | ||
110 | static void primary_if_update_addr(struct bat_priv *bat_priv) | 105 | static void primary_if_update_addr(struct bat_priv *bat_priv, |
106 | struct hard_iface *oldif) | ||
111 | { | 107 | { |
112 | struct vis_packet *vis_packet; | 108 | struct vis_packet *vis_packet; |
113 | struct hard_iface *primary_if; | 109 | struct hard_iface *primary_if; |
@@ -122,6 +118,7 @@ static void primary_if_update_addr(struct bat_priv *bat_priv) | |||
122 | memcpy(vis_packet->sender_orig, | 118 | memcpy(vis_packet->sender_orig, |
123 | primary_if->net_dev->dev_addr, ETH_ALEN); | 119 | primary_if->net_dev->dev_addr, ETH_ALEN); |
124 | 120 | ||
121 | bla_update_orig_address(bat_priv, primary_if, oldif); | ||
125 | out: | 122 | out: |
126 | if (primary_if) | 123 | if (primary_if) |
127 | hardif_free_ref(primary_if); | 124 | hardif_free_ref(primary_if); |
@@ -140,14 +137,15 @@ static void primary_if_select(struct bat_priv *bat_priv, | |||
140 | curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); | 137 | curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); |
141 | rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); | 138 | rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); |
142 | 139 | ||
143 | if (curr_hard_iface) | ||
144 | hardif_free_ref(curr_hard_iface); | ||
145 | |||
146 | if (!new_hard_iface) | 140 | if (!new_hard_iface) |
147 | return; | 141 | goto out; |
142 | |||
143 | bat_priv->bat_algo_ops->bat_primary_iface_set(new_hard_iface); | ||
144 | primary_if_update_addr(bat_priv, curr_hard_iface); | ||
148 | 145 | ||
149 | bat_priv->bat_algo_ops->bat_ogm_init_primary(new_hard_iface); | 146 | out: |
150 | primary_if_update_addr(bat_priv); | 147 | if (curr_hard_iface) |
148 | hardif_free_ref(curr_hard_iface); | ||
151 | } | 149 | } |
152 | 150 | ||
153 | static bool hardif_is_iface_up(const struct hard_iface *hard_iface) | 151 | static bool hardif_is_iface_up(const struct hard_iface *hard_iface) |
@@ -175,9 +173,9 @@ static void check_known_mac_addr(const struct net_device *net_dev) | |||
175 | net_dev->dev_addr)) | 173 | net_dev->dev_addr)) |
176 | continue; | 174 | continue; |
177 | 175 | ||
178 | pr_warning("The newly added mac address (%pM) already exists on: %s\n", | 176 | pr_warn("The newly added mac address (%pM) already exists on: %s\n", |
179 | net_dev->dev_addr, hard_iface->net_dev->name); | 177 | net_dev->dev_addr, hard_iface->net_dev->name); |
180 | pr_warning("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); | 178 | pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); |
181 | } | 179 | } |
182 | rcu_read_unlock(); | 180 | rcu_read_unlock(); |
183 | } | 181 | } |
@@ -230,7 +228,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) | |||
230 | 228 | ||
231 | bat_priv = netdev_priv(hard_iface->soft_iface); | 229 | bat_priv = netdev_priv(hard_iface->soft_iface); |
232 | 230 | ||
233 | bat_priv->bat_algo_ops->bat_ogm_update_mac(hard_iface); | 231 | bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface); |
234 | hard_iface->if_status = IF_TO_BE_ACTIVATED; | 232 | hard_iface->if_status = IF_TO_BE_ACTIVATED; |
235 | 233 | ||
236 | /** | 234 | /** |
@@ -300,22 +298,17 @@ int hardif_enable_interface(struct hard_iface *hard_iface, | |||
300 | if (!softif_is_valid(soft_iface)) { | 298 | if (!softif_is_valid(soft_iface)) { |
301 | pr_err("Can't create batman mesh interface %s: already exists as regular interface\n", | 299 | pr_err("Can't create batman mesh interface %s: already exists as regular interface\n", |
302 | soft_iface->name); | 300 | soft_iface->name); |
303 | dev_put(soft_iface); | ||
304 | ret = -EINVAL; | 301 | ret = -EINVAL; |
305 | goto err; | 302 | goto err_dev; |
306 | } | 303 | } |
307 | 304 | ||
308 | hard_iface->soft_iface = soft_iface; | 305 | hard_iface->soft_iface = soft_iface; |
309 | bat_priv = netdev_priv(hard_iface->soft_iface); | 306 | bat_priv = netdev_priv(hard_iface->soft_iface); |
310 | 307 | ||
311 | bat_priv->bat_algo_ops->bat_ogm_init(hard_iface); | 308 | ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); |
312 | 309 | if (ret < 0) { | |
313 | if (!hard_iface->packet_buff) { | ||
314 | bat_err(hard_iface->soft_iface, | ||
315 | "Can't add interface packet (%s): out of memory\n", | ||
316 | hard_iface->net_dev->name); | ||
317 | ret = -ENOMEM; | 310 | ret = -ENOMEM; |
318 | goto err; | 311 | goto err_dev; |
319 | } | 312 | } |
320 | 313 | ||
321 | hard_iface->if_num = bat_priv->num_ifaces; | 314 | hard_iface->if_num = bat_priv->num_ifaces; |
@@ -328,7 +321,6 @@ int hardif_enable_interface(struct hard_iface *hard_iface, | |||
328 | hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; | 321 | hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; |
329 | dev_add_pack(&hard_iface->batman_adv_ptype); | 322 | dev_add_pack(&hard_iface->batman_adv_ptype); |
330 | 323 | ||
331 | atomic_set(&hard_iface->seqno, 1); | ||
332 | atomic_set(&hard_iface->frag_seqno, 1); | 324 | atomic_set(&hard_iface->frag_seqno, 1); |
333 | bat_info(hard_iface->soft_iface, "Adding interface: %s\n", | 325 | bat_info(hard_iface->soft_iface, "Adding interface: %s\n", |
334 | hard_iface->net_dev->name); | 326 | hard_iface->net_dev->name); |
@@ -360,6 +352,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface, | |||
360 | out: | 352 | out: |
361 | return 0; | 353 | return 0; |
362 | 354 | ||
355 | err_dev: | ||
356 | dev_put(soft_iface); | ||
363 | err: | 357 | err: |
364 | hardif_free_ref(hard_iface); | 358 | hardif_free_ref(hard_iface); |
365 | return ret; | 359 | return ret; |
@@ -394,8 +388,7 @@ void hardif_disable_interface(struct hard_iface *hard_iface) | |||
394 | hardif_free_ref(new_if); | 388 | hardif_free_ref(new_if); |
395 | } | 389 | } |
396 | 390 | ||
397 | kfree(hard_iface->packet_buff); | 391 | bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); |
398 | hard_iface->packet_buff = NULL; | ||
399 | hard_iface->if_status = IF_NOT_IN_USE; | 392 | hard_iface->if_status = IF_NOT_IN_USE; |
400 | 393 | ||
401 | /* delete all references to this hard_iface */ | 394 | /* delete all references to this hard_iface */ |
@@ -447,6 +440,13 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
447 | check_known_mac_addr(hard_iface->net_dev); | 440 | check_known_mac_addr(hard_iface->net_dev); |
448 | list_add_tail_rcu(&hard_iface->list, &hardif_list); | 441 | list_add_tail_rcu(&hard_iface->list, &hardif_list); |
449 | 442 | ||
443 | /** | ||
444 | * This can't be called via a bat_priv callback because | ||
445 | * we have no bat_priv yet. | ||
446 | */ | ||
447 | atomic_set(&hard_iface->seqno, 1); | ||
448 | hard_iface->packet_buff = NULL; | ||
449 | |||
450 | return hard_iface; | 450 | return hard_iface; |
451 | 451 | ||
452 | free_if: | 452 | free_if: |
@@ -524,14 +524,14 @@ static int hard_if_event(struct notifier_block *this, | |||
524 | check_known_mac_addr(hard_iface->net_dev); | 524 | check_known_mac_addr(hard_iface->net_dev); |
525 | 525 | ||
526 | bat_priv = netdev_priv(hard_iface->soft_iface); | 526 | bat_priv = netdev_priv(hard_iface->soft_iface); |
527 | bat_priv->bat_algo_ops->bat_ogm_update_mac(hard_iface); | 527 | bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface); |
528 | 528 | ||
529 | primary_if = primary_if_get_selected(bat_priv); | 529 | primary_if = primary_if_get_selected(bat_priv); |
530 | if (!primary_if) | 530 | if (!primary_if) |
531 | goto hardif_put; | 531 | goto hardif_put; |
532 | 532 | ||
533 | if (hard_iface == primary_if) | 533 | if (hard_iface == primary_if) |
534 | primary_if_update_addr(bat_priv); | 534 | primary_if_update_addr(bat_priv, NULL); |
535 | break; | 535 | break; |
536 | default: | 536 | default: |
537 | break; | 537 | break; |
@@ -545,114 +545,6 @@ out: | |||
545 | return NOTIFY_DONE; | 545 | return NOTIFY_DONE; |
546 | } | 546 | } |
547 | 547 | ||
548 | /* incoming packets with the batman ethertype received on any active hard | ||
549 | * interface */ | ||
550 | static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | ||
551 | struct packet_type *ptype, | ||
552 | struct net_device *orig_dev) | ||
553 | { | ||
554 | struct bat_priv *bat_priv; | ||
555 | struct batman_ogm_packet *batman_ogm_packet; | ||
556 | struct hard_iface *hard_iface; | ||
557 | int ret; | ||
558 | |||
559 | hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype); | ||
560 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
561 | |||
562 | /* skb was released by skb_share_check() */ | ||
563 | if (!skb) | ||
564 | goto err_out; | ||
565 | |||
566 | /* packet should hold at least type and version */ | ||
567 | if (unlikely(!pskb_may_pull(skb, 2))) | ||
568 | goto err_free; | ||
569 | |||
570 | /* expect a valid ethernet header here. */ | ||
571 | if (unlikely(skb->mac_len != sizeof(struct ethhdr) || | ||
572 | !skb_mac_header(skb))) | ||
573 | goto err_free; | ||
574 | |||
575 | if (!hard_iface->soft_iface) | ||
576 | goto err_free; | ||
577 | |||
578 | bat_priv = netdev_priv(hard_iface->soft_iface); | ||
579 | |||
580 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) | ||
581 | goto err_free; | ||
582 | |||
583 | /* discard frames on not active interfaces */ | ||
584 | if (hard_iface->if_status != IF_ACTIVE) | ||
585 | goto err_free; | ||
586 | |||
587 | batman_ogm_packet = (struct batman_ogm_packet *)skb->data; | ||
588 | |||
589 | if (batman_ogm_packet->header.version != COMPAT_VERSION) { | ||
590 | bat_dbg(DBG_BATMAN, bat_priv, | ||
591 | "Drop packet: incompatible batman version (%i)\n", | ||
592 | batman_ogm_packet->header.version); | ||
593 | goto err_free; | ||
594 | } | ||
595 | |||
596 | /* all receive handlers return whether they received or reused | ||
597 | * the supplied skb. if not, we have to free the skb. */ | ||
598 | |||
599 | switch (batman_ogm_packet->header.packet_type) { | ||
600 | /* batman originator packet */ | ||
601 | case BAT_OGM: | ||
602 | ret = recv_bat_ogm_packet(skb, hard_iface); | ||
603 | break; | ||
604 | |||
605 | /* batman icmp packet */ | ||
606 | case BAT_ICMP: | ||
607 | ret = recv_icmp_packet(skb, hard_iface); | ||
608 | break; | ||
609 | |||
610 | /* unicast packet */ | ||
611 | case BAT_UNICAST: | ||
612 | ret = recv_unicast_packet(skb, hard_iface); | ||
613 | break; | ||
614 | |||
615 | /* fragmented unicast packet */ | ||
616 | case BAT_UNICAST_FRAG: | ||
617 | ret = recv_ucast_frag_packet(skb, hard_iface); | ||
618 | break; | ||
619 | |||
620 | /* broadcast packet */ | ||
621 | case BAT_BCAST: | ||
622 | ret = recv_bcast_packet(skb, hard_iface); | ||
623 | break; | ||
624 | |||
625 | /* vis packet */ | ||
626 | case BAT_VIS: | ||
627 | ret = recv_vis_packet(skb, hard_iface); | ||
628 | break; | ||
629 | /* Translation table query (request or response) */ | ||
630 | case BAT_TT_QUERY: | ||
631 | ret = recv_tt_query(skb, hard_iface); | ||
632 | break; | ||
633 | /* Roaming advertisement */ | ||
634 | case BAT_ROAM_ADV: | ||
635 | ret = recv_roam_adv(skb, hard_iface); | ||
636 | break; | ||
637 | default: | ||
638 | ret = NET_RX_DROP; | ||
639 | } | ||
640 | |||
641 | if (ret == NET_RX_DROP) | ||
642 | kfree_skb(skb); | ||
643 | |||
644 | /* return NET_RX_SUCCESS in any case as we | ||
645 | * most probably dropped the packet for | ||
646 | * routing-logical reasons. */ | ||
647 | |||
648 | return NET_RX_SUCCESS; | ||
649 | |||
650 | err_free: | ||
651 | kfree_skb(skb); | ||
652 | err_out: | ||
653 | return NET_RX_DROP; | ||
654 | } | ||
655 | |||
656 | /* 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 |
657 | * 802.11 wireless device */ | 549 | * 802.11 wireless device */ |
658 | bool is_wifi_iface(int ifindex) | 550 | bool is_wifi_iface(int ifindex) |