diff options
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 194 |
1 files changed, 93 insertions, 101 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f212abe745bc..b7d43caaa9c8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv, | |||
87 | struct neigh_node *neigh_node, | 87 | struct neigh_node *neigh_node, |
88 | unsigned char *hna_buff, int hna_buff_len) | 88 | unsigned char *hna_buff, int hna_buff_len) |
89 | { | 89 | { |
90 | struct neigh_node *neigh_node_tmp; | 90 | struct neigh_node *curr_router; |
91 | |||
92 | curr_router = orig_node_get_router(orig_node); | ||
91 | 93 | ||
92 | /* route deleted */ | 94 | /* route deleted */ |
93 | if ((orig_node->router) && (!neigh_node)) { | 95 | if ((curr_router) && (!neigh_node)) { |
94 | 96 | ||
95 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 97 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
96 | orig_node->orig); | 98 | orig_node->orig); |
97 | hna_global_del_orig(bat_priv, orig_node, | 99 | hna_global_del_orig(bat_priv, orig_node, |
98 | "originator timed out"); | 100 | "originator timed out"); |
99 | 101 | ||
100 | /* route added */ | 102 | /* route added */ |
101 | } else if ((!orig_node->router) && (neigh_node)) { | 103 | } else if ((!curr_router) && (neigh_node)) { |
102 | 104 | ||
103 | bat_dbg(DBG_ROUTES, bat_priv, | 105 | bat_dbg(DBG_ROUTES, bat_priv, |
104 | "Adding route towards: %pM (via %pM)\n", | 106 | "Adding route towards: %pM (via %pM)\n", |
@@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv, | |||
106 | hna_global_add_orig(bat_priv, orig_node, | 108 | hna_global_add_orig(bat_priv, orig_node, |
107 | hna_buff, hna_buff_len); | 109 | hna_buff, hna_buff_len); |
108 | 110 | ||
109 | /* route changed */ | 111 | /* route changed */ |
110 | } else { | 112 | } else { |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 113 | bat_dbg(DBG_ROUTES, bat_priv, |
112 | "Changing route towards: %pM " | 114 | "Changing route towards: %pM " |
113 | "(now via %pM - was via %pM)\n", | 115 | "(now via %pM - was via %pM)\n", |
114 | orig_node->orig, neigh_node->addr, | 116 | orig_node->orig, neigh_node->addr, |
115 | orig_node->router->addr); | 117 | curr_router->addr); |
116 | } | 118 | } |
117 | 119 | ||
120 | if (curr_router) | ||
121 | neigh_node_free_ref(curr_router); | ||
122 | |||
123 | /* increase refcount of new best neighbor */ | ||
118 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) | 124 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) |
119 | neigh_node = NULL; | 125 | neigh_node = NULL; |
120 | neigh_node_tmp = orig_node->router; | 126 | |
121 | orig_node->router = neigh_node; | 127 | spin_lock_bh(&orig_node->neigh_list_lock); |
122 | if (neigh_node_tmp) | 128 | rcu_assign_pointer(orig_node->router, neigh_node); |
123 | neigh_node_free_ref(neigh_node_tmp); | 129 | spin_unlock_bh(&orig_node->neigh_list_lock); |
130 | |||
131 | /* decrease refcount of previous best neighbor */ | ||
132 | if (curr_router) | ||
133 | neigh_node_free_ref(curr_router); | ||
124 | } | 134 | } |
125 | 135 | ||
126 | 136 | ||
@@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
128 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 138 | struct neigh_node *neigh_node, unsigned char *hna_buff, |
129 | int hna_buff_len) | 139 | int hna_buff_len) |
130 | { | 140 | { |
141 | struct neigh_node *router = NULL; | ||
131 | 142 | ||
132 | if (!orig_node) | 143 | if (!orig_node) |
133 | return; | 144 | goto out; |
145 | |||
146 | router = orig_node_get_router(orig_node); | ||
134 | 147 | ||
135 | if (orig_node->router != neigh_node) | 148 | if (router != neigh_node) |
136 | update_route(bat_priv, orig_node, neigh_node, | 149 | update_route(bat_priv, orig_node, neigh_node, |
137 | hna_buff, hna_buff_len); | 150 | hna_buff, hna_buff_len); |
138 | /* may be just HNA changed */ | 151 | /* may be just HNA changed */ |
139 | else | 152 | else |
140 | update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); | 153 | update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); |
154 | |||
155 | out: | ||
156 | if (router) | ||
157 | neigh_node_free_ref(router); | ||
141 | } | 158 | } |
142 | 159 | ||
143 | static int is_bidirectional_neigh(struct orig_node *orig_node, | 160 | static int is_bidirectional_neigh(struct orig_node *orig_node, |
@@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
288 | struct neigh_node *neigh_node) | 305 | struct neigh_node *neigh_node) |
289 | { | 306 | { |
290 | struct hlist_node *node; | 307 | struct hlist_node *node; |
291 | struct neigh_node *tmp_neigh_node; | 308 | struct neigh_node *tmp_neigh_node, *router = NULL; |
292 | uint8_t best_tq, interference_candidate = 0; | 309 | uint8_t interference_candidate = 0; |
293 | 310 | ||
294 | spin_lock_bh(&orig_node->neigh_list_lock); | 311 | spin_lock_bh(&orig_node->neigh_list_lock); |
295 | 312 | ||
@@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
298 | neigh_node->orig_node->primary_addr)) | 315 | neigh_node->orig_node->primary_addr)) |
299 | goto candidate_del; | 316 | goto candidate_del; |
300 | 317 | ||
301 | if (!orig_node->router) | 318 | router = orig_node_get_router(orig_node); |
319 | if (!router) | ||
302 | goto candidate_del; | 320 | goto candidate_del; |
303 | 321 | ||
304 | best_tq = orig_node->router->tq_avg; | ||
305 | |||
306 | /* ... and is good enough to be considered */ | 322 | /* ... and is good enough to be considered */ |
307 | if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) | 323 | if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) |
308 | goto candidate_del; | 324 | goto candidate_del; |
309 | 325 | ||
310 | /** | 326 | /** |
@@ -350,7 +366,9 @@ candidate_del: | |||
350 | 366 | ||
351 | out: | 367 | out: |
352 | spin_unlock_bh(&orig_node->neigh_list_lock); | 368 | spin_unlock_bh(&orig_node->neigh_list_lock); |
353 | return; | 369 | |
370 | if (router) | ||
371 | neigh_node_free_ref(router); | ||
354 | } | 372 | } |
355 | 373 | ||
356 | /* copy primary address for bonding */ | 374 | /* copy primary address for bonding */ |
@@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv, | |||
373 | char is_duplicate) | 391 | char is_duplicate) |
374 | { | 392 | { |
375 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 393 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
394 | struct neigh_node *router = NULL; | ||
376 | struct orig_node *orig_node_tmp; | 395 | struct orig_node *orig_node_tmp; |
377 | struct hlist_node *node; | 396 | struct hlist_node *node; |
378 | int tmp_hna_buff_len; | 397 | int tmp_hna_buff_len; |
@@ -441,19 +460,18 @@ static void update_orig(struct bat_priv *bat_priv, | |||
441 | 460 | ||
442 | /* if this neighbor already is our next hop there is nothing | 461 | /* if this neighbor already is our next hop there is nothing |
443 | * to change */ | 462 | * to change */ |
444 | if (orig_node->router == neigh_node) | 463 | router = orig_node_get_router(orig_node); |
464 | if (router == neigh_node) | ||
445 | goto update_hna; | 465 | goto update_hna; |
446 | 466 | ||
447 | /* if this neighbor does not offer a better TQ we won't consider it */ | 467 | /* if this neighbor does not offer a better TQ we won't consider it */ |
448 | if ((orig_node->router) && | 468 | if (router && (router->tq_avg > neigh_node->tq_avg)) |
449 | (orig_node->router->tq_avg > neigh_node->tq_avg)) | ||
450 | goto update_hna; | 469 | goto update_hna; |
451 | 470 | ||
452 | /* if the TQ is the same and the link not more symetric we | 471 | /* if the TQ is the same and the link not more symetric we |
453 | * won't consider it either */ | 472 | * won't consider it either */ |
454 | if ((orig_node->router) && | 473 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
455 | (neigh_node->tq_avg == orig_node->router->tq_avg)) { | 474 | orig_node_tmp = router->orig_node; |
456 | orig_node_tmp = orig_node->router->orig_node; | ||
457 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 475 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
458 | bcast_own_sum_orig = | 476 | bcast_own_sum_orig = |
459 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | 477 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
@@ -474,7 +492,7 @@ static void update_orig(struct bat_priv *bat_priv, | |||
474 | goto update_gw; | 492 | goto update_gw; |
475 | 493 | ||
476 | update_hna: | 494 | update_hna: |
477 | update_routes(bat_priv, orig_node, orig_node->router, | 495 | update_routes(bat_priv, orig_node, router, |
478 | hna_buff, tmp_hna_buff_len); | 496 | hna_buff, tmp_hna_buff_len); |
479 | 497 | ||
480 | update_gw: | 498 | update_gw: |
@@ -496,6 +514,8 @@ unlock: | |||
496 | out: | 514 | out: |
497 | if (neigh_node) | 515 | if (neigh_node) |
498 | neigh_node_free_ref(neigh_node); | 516 | neigh_node_free_ref(neigh_node); |
517 | if (router) | ||
518 | neigh_node_free_ref(router); | ||
499 | } | 519 | } |
500 | 520 | ||
501 | /* checks whether the host restarted and is in the protection time. | 521 | /* checks whether the host restarted and is in the protection time. |
@@ -603,6 +623,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 623 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
604 | struct hard_iface *hard_iface; | 624 | struct hard_iface *hard_iface; |
605 | struct orig_node *orig_neigh_node, *orig_node; | 625 | struct orig_node *orig_neigh_node, *orig_node; |
626 | struct neigh_node *router = NULL, *router_router = NULL; | ||
627 | struct neigh_node *orig_neigh_router = NULL; | ||
606 | char has_directlink_flag; | 628 | char has_directlink_flag; |
607 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 629 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
608 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; | 630 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; |
@@ -747,14 +769,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
747 | goto out; | 769 | goto out; |
748 | } | 770 | } |
749 | 771 | ||
772 | router = orig_node_get_router(orig_node); | ||
773 | if (router) | ||
774 | router_router = orig_node_get_router(router->orig_node); | ||
775 | |||
750 | /* avoid temporary routing loops */ | 776 | /* avoid temporary routing loops */ |
751 | if ((orig_node->router) && | 777 | if (router && router_router && |
752 | (orig_node->router->orig_node->router) && | 778 | (compare_eth(router->addr, batman_packet->prev_sender)) && |
753 | (compare_eth(orig_node->router->addr, | ||
754 | batman_packet->prev_sender)) && | ||
755 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && | 779 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && |
756 | (compare_eth(orig_node->router->addr, | 780 | (compare_eth(router->addr, router_router->addr))) { |
757 | orig_node->router->orig_node->router->addr))) { | ||
758 | bat_dbg(DBG_BATMAN, bat_priv, | 781 | bat_dbg(DBG_BATMAN, bat_priv, |
759 | "Drop packet: ignoring all rebroadcast packets that " | 782 | "Drop packet: ignoring all rebroadcast packets that " |
760 | "may make me loop (sender: %pM)\n", ethhdr->h_source); | 783 | "may make me loop (sender: %pM)\n", ethhdr->h_source); |
@@ -769,9 +792,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
769 | if (!orig_neigh_node) | 792 | if (!orig_neigh_node) |
770 | goto out; | 793 | goto out; |
771 | 794 | ||
795 | orig_neigh_router = orig_node_get_router(orig_neigh_node); | ||
796 | |||
772 | /* drop packet if sender is not a direct neighbor and if we | 797 | /* drop packet if sender is not a direct neighbor and if we |
773 | * don't route towards it */ | 798 | * don't route towards it */ |
774 | if (!is_single_hop_neigh && (!orig_neigh_node->router)) { | 799 | if (!is_single_hop_neigh && (!orig_neigh_router)) { |
775 | bat_dbg(DBG_BATMAN, bat_priv, | 800 | bat_dbg(DBG_BATMAN, bat_priv, |
776 | "Drop packet: OGM via unknown neighbor!\n"); | 801 | "Drop packet: OGM via unknown neighbor!\n"); |
777 | goto out_neigh; | 802 | goto out_neigh; |
@@ -825,6 +850,13 @@ out_neigh: | |||
825 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 850 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
826 | orig_node_free_ref(orig_neigh_node); | 851 | orig_node_free_ref(orig_neigh_node); |
827 | out: | 852 | out: |
853 | if (router) | ||
854 | neigh_node_free_ref(router); | ||
855 | if (router_router) | ||
856 | neigh_node_free_ref(router_router); | ||
857 | if (orig_neigh_router) | ||
858 | neigh_node_free_ref(orig_neigh_router); | ||
859 | |||
828 | orig_node_free_ref(orig_node); | 860 | orig_node_free_ref(orig_node); |
829 | } | 861 | } |
830 | 862 | ||
@@ -869,7 +901,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
869 | struct sk_buff *skb, size_t icmp_len) | 901 | struct sk_buff *skb, size_t icmp_len) |
870 | { | 902 | { |
871 | struct orig_node *orig_node = NULL; | 903 | struct orig_node *orig_node = NULL; |
872 | struct neigh_node *neigh_node = NULL; | 904 | struct neigh_node *router = NULL; |
873 | struct icmp_packet_rr *icmp_packet; | 905 | struct icmp_packet_rr *icmp_packet; |
874 | int ret = NET_RX_DROP; | 906 | int ret = NET_RX_DROP; |
875 | 907 | ||
@@ -886,23 +918,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
886 | 918 | ||
887 | /* answer echo request (ping) */ | 919 | /* answer echo request (ping) */ |
888 | /* get routing information */ | 920 | /* get routing information */ |
889 | rcu_read_lock(); | ||
890 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 921 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
891 | |||
892 | if (!orig_node) | 922 | if (!orig_node) |
893 | goto unlock; | 923 | goto out; |
894 | |||
895 | neigh_node = orig_node->router; | ||
896 | |||
897 | if (!neigh_node) | ||
898 | goto unlock; | ||
899 | |||
900 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
901 | neigh_node = NULL; | ||
902 | goto unlock; | ||
903 | } | ||
904 | 924 | ||
905 | rcu_read_unlock(); | 925 | router = orig_node_get_router(orig_node); |
926 | if (!router) | ||
927 | goto out; | ||
906 | 928 | ||
907 | /* create a copy of the skb, if needed, to modify it. */ | 929 | /* create a copy of the skb, if needed, to modify it. */ |
908 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 930 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -916,15 +938,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
916 | icmp_packet->msg_type = ECHO_REPLY; | 938 | icmp_packet->msg_type = ECHO_REPLY; |
917 | icmp_packet->ttl = TTL; | 939 | icmp_packet->ttl = TTL; |
918 | 940 | ||
919 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 941 | send_skb_packet(skb, router->if_incoming, router->addr); |
920 | ret = NET_RX_SUCCESS; | 942 | ret = NET_RX_SUCCESS; |
921 | goto out; | ||
922 | 943 | ||
923 | unlock: | ||
924 | rcu_read_unlock(); | ||
925 | out: | 944 | out: |
926 | if (neigh_node) | 945 | if (router) |
927 | neigh_node_free_ref(neigh_node); | 946 | neigh_node_free_ref(router); |
928 | if (orig_node) | 947 | if (orig_node) |
929 | orig_node_free_ref(orig_node); | 948 | orig_node_free_ref(orig_node); |
930 | return ret; | 949 | return ret; |
@@ -934,7 +953,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
934 | struct sk_buff *skb) | 953 | struct sk_buff *skb) |
935 | { | 954 | { |
936 | struct orig_node *orig_node = NULL; | 955 | struct orig_node *orig_node = NULL; |
937 | struct neigh_node *neigh_node = NULL; | 956 | struct neigh_node *router = NULL; |
938 | struct icmp_packet *icmp_packet; | 957 | struct icmp_packet *icmp_packet; |
939 | int ret = NET_RX_DROP; | 958 | int ret = NET_RX_DROP; |
940 | 959 | ||
@@ -952,23 +971,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
952 | goto out; | 971 | goto out; |
953 | 972 | ||
954 | /* get routing information */ | 973 | /* get routing information */ |
955 | rcu_read_lock(); | ||
956 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 974 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
957 | |||
958 | if (!orig_node) | 975 | if (!orig_node) |
959 | goto unlock; | 976 | goto out; |
960 | |||
961 | neigh_node = orig_node->router; | ||
962 | |||
963 | if (!neigh_node) | ||
964 | goto unlock; | ||
965 | |||
966 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
967 | neigh_node = NULL; | ||
968 | goto unlock; | ||
969 | } | ||
970 | 977 | ||
971 | rcu_read_unlock(); | 978 | router = orig_node_get_router(orig_node); |
979 | if (!router) | ||
980 | goto out; | ||
972 | 981 | ||
973 | /* create a copy of the skb, if needed, to modify it. */ | 982 | /* create a copy of the skb, if needed, to modify it. */ |
974 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 983 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -982,15 +991,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
982 | icmp_packet->msg_type = TTL_EXCEEDED; | 991 | icmp_packet->msg_type = TTL_EXCEEDED; |
983 | icmp_packet->ttl = TTL; | 992 | icmp_packet->ttl = TTL; |
984 | 993 | ||
985 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 994 | send_skb_packet(skb, router->if_incoming, router->addr); |
986 | ret = NET_RX_SUCCESS; | 995 | ret = NET_RX_SUCCESS; |
987 | goto out; | ||
988 | 996 | ||
989 | unlock: | ||
990 | rcu_read_unlock(); | ||
991 | out: | 997 | out: |
992 | if (neigh_node) | 998 | if (router) |
993 | neigh_node_free_ref(neigh_node); | 999 | neigh_node_free_ref(router); |
994 | if (orig_node) | 1000 | if (orig_node) |
995 | orig_node_free_ref(orig_node); | 1001 | orig_node_free_ref(orig_node); |
996 | return ret; | 1002 | return ret; |
@@ -1003,7 +1009,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1003 | struct icmp_packet_rr *icmp_packet; | 1009 | struct icmp_packet_rr *icmp_packet; |
1004 | struct ethhdr *ethhdr; | 1010 | struct ethhdr *ethhdr; |
1005 | struct orig_node *orig_node = NULL; | 1011 | struct orig_node *orig_node = NULL; |
1006 | struct neigh_node *neigh_node = NULL; | 1012 | struct neigh_node *router = NULL; |
1007 | int hdr_size = sizeof(struct icmp_packet); | 1013 | int hdr_size = sizeof(struct icmp_packet); |
1008 | int ret = NET_RX_DROP; | 1014 | int ret = NET_RX_DROP; |
1009 | 1015 | ||
@@ -1050,23 +1056,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1050 | return recv_icmp_ttl_exceeded(bat_priv, skb); | 1056 | return recv_icmp_ttl_exceeded(bat_priv, skb); |
1051 | 1057 | ||
1052 | /* get routing information */ | 1058 | /* get routing information */ |
1053 | rcu_read_lock(); | ||
1054 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 1059 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
1055 | |||
1056 | if (!orig_node) | 1060 | if (!orig_node) |
1057 | goto unlock; | 1061 | goto out; |
1058 | |||
1059 | neigh_node = orig_node->router; | ||
1060 | |||
1061 | if (!neigh_node) | ||
1062 | goto unlock; | ||
1063 | |||
1064 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
1065 | neigh_node = NULL; | ||
1066 | goto unlock; | ||
1067 | } | ||
1068 | 1062 | ||
1069 | rcu_read_unlock(); | 1063 | router = orig_node_get_router(orig_node); |
1064 | if (!router) | ||
1065 | goto out; | ||
1070 | 1066 | ||
1071 | /* create a copy of the skb, if needed, to modify it. */ | 1067 | /* create a copy of the skb, if needed, to modify it. */ |
1072 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 1068 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -1078,15 +1074,12 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1078 | icmp_packet->ttl--; | 1074 | icmp_packet->ttl--; |
1079 | 1075 | ||
1080 | /* route it */ | 1076 | /* route it */ |
1081 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1077 | send_skb_packet(skb, router->if_incoming, router->addr); |
1082 | ret = NET_RX_SUCCESS; | 1078 | ret = NET_RX_SUCCESS; |
1083 | goto out; | ||
1084 | 1079 | ||
1085 | unlock: | ||
1086 | rcu_read_unlock(); | ||
1087 | out: | 1080 | out: |
1088 | if (neigh_node) | 1081 | if (router) |
1089 | neigh_node_free_ref(neigh_node); | 1082 | neigh_node_free_ref(router); |
1090 | if (orig_node) | 1083 | if (orig_node) |
1091 | orig_node_free_ref(orig_node); | 1084 | orig_node_free_ref(orig_node); |
1092 | return ret; | 1085 | return ret; |
@@ -1208,7 +1201,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1208 | if (!orig_node) | 1201 | if (!orig_node) |
1209 | return NULL; | 1202 | return NULL; |
1210 | 1203 | ||
1211 | if (!orig_node->router) | 1204 | router = orig_node_get_router(orig_node); |
1205 | if (!router) | ||
1212 | return NULL; | 1206 | return NULL; |
1213 | 1207 | ||
1214 | /* without bonding, the first node should | 1208 | /* without bonding, the first node should |
@@ -1217,9 +1211,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1217 | 1211 | ||
1218 | rcu_read_lock(); | 1212 | rcu_read_lock(); |
1219 | /* select default router to output */ | 1213 | /* select default router to output */ |
1220 | router = orig_node->router; | 1214 | router_orig = router->orig_node; |
1221 | router_orig = orig_node->router->orig_node; | 1215 | if (!router_orig) { |
1222 | if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { | ||
1223 | rcu_read_unlock(); | 1216 | rcu_read_unlock(); |
1224 | return NULL; | 1217 | return NULL; |
1225 | } | 1218 | } |
@@ -1251,7 +1244,6 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1251 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) | 1244 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) |
1252 | goto return_router; | 1245 | goto return_router; |
1253 | 1246 | ||
1254 | |||
1255 | /* all nodes between should choose a candidate which | 1247 | /* all nodes between should choose a candidate which |
1256 | * is is not on the interface where the packet came | 1248 | * is is not on the interface where the packet came |
1257 | * in. */ | 1249 | * in. */ |