diff options
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 376 |
1 files changed, 297 insertions, 79 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index bb1c3ec7e3f..0f32c818874 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,28 +64,69 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, | 67 | static void update_transtable(struct bat_priv *bat_priv, |
68 | unsigned char *tt_buff, int tt_buff_len) | 68 | struct orig_node *orig_node, |
69 | const unsigned char *tt_buff, | ||
70 | uint8_t tt_num_changes, uint8_t ttvn, | ||
71 | uint16_t tt_crc) | ||
69 | { | 72 | { |
70 | if ((tt_buff_len != orig_node->tt_buff_len) || | 73 | uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
71 | ((tt_buff_len > 0) && | 74 | bool full_table = true; |
72 | (orig_node->tt_buff_len > 0) && | 75 | |
73 | (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { | 76 | /* the ttvn increased by one -> we can apply the attached changes */ |
74 | 77 | if (ttvn - orig_ttvn == 1) { | |
75 | if (orig_node->tt_buff_len > 0) | 78 | /* the OGM could not contain the changes because they were too |
76 | tt_global_del_orig(bat_priv, orig_node, | 79 | * many to fit in one frame or because they have already been |
77 | "originator changed tt"); | 80 | * sent TT_OGM_APPEND_MAX times. In this case send a tt |
78 | 81 | * request */ | |
79 | if ((tt_buff_len > 0) && (tt_buff)) | 82 | if (!tt_num_changes) { |
80 | tt_global_add_orig(bat_priv, orig_node, | 83 | full_table = false; |
81 | tt_buff, tt_buff_len); | 84 | goto request_table; |
85 | } | ||
86 | |||
87 | tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, | ||
88 | (struct tt_change *)tt_buff); | ||
89 | |||
90 | /* Even if we received the crc into the OGM, we prefer | ||
91 | * to recompute it to spot any possible inconsistency | ||
92 | * in the global table */ | ||
93 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); | ||
94 | |||
95 | /* The ttvn alone is not enough to guarantee consistency | ||
96 | * because a single value could repesent different states | ||
97 | * (due to the wrap around). Thus a node has to check whether | ||
98 | * the resulting table (after applying the changes) is still | ||
99 | * consistent or not. E.g. a node could disconnect while its | ||
100 | * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case | ||
101 | * checking the CRC value is mandatory to detect the | ||
102 | * inconsistency */ | ||
103 | if (orig_node->tt_crc != tt_crc) | ||
104 | goto request_table; | ||
105 | |||
106 | /* Roaming phase is over: tables are in sync again. I can | ||
107 | * unset the flag */ | ||
108 | orig_node->tt_poss_change = false; | ||
109 | } else { | ||
110 | /* if we missed more than one change or our tables are not | ||
111 | * in sync anymore -> request fresh tt data */ | ||
112 | if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { | ||
113 | request_table: | ||
114 | bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. " | ||
115 | "Need to retrieve the correct information " | ||
116 | "(ttvn: %u last_ttvn: %u crc: %u last_crc: " | ||
117 | "%u num_changes: %u)\n", orig_node->orig, ttvn, | ||
118 | orig_ttvn, tt_crc, orig_node->tt_crc, | ||
119 | tt_num_changes); | ||
120 | send_tt_request(bat_priv, orig_node, ttvn, tt_crc, | ||
121 | full_table); | ||
122 | return; | ||
123 | } | ||
82 | } | 124 | } |
83 | } | 125 | } |
84 | 126 | ||
85 | static void update_route(struct bat_priv *bat_priv, | 127 | static void update_route(struct bat_priv *bat_priv, |
86 | struct orig_node *orig_node, | 128 | struct orig_node *orig_node, |
87 | struct neigh_node *neigh_node, | 129 | struct neigh_node *neigh_node) |
88 | unsigned char *tt_buff, int tt_buff_len) | ||
89 | { | 130 | { |
90 | struct neigh_node *curr_router; | 131 | struct neigh_node *curr_router; |
91 | 132 | ||
@@ -93,11 +134,10 @@ static void update_route(struct bat_priv *bat_priv, | |||
93 | 134 | ||
94 | /* route deleted */ | 135 | /* route deleted */ |
95 | if ((curr_router) && (!neigh_node)) { | 136 | if ((curr_router) && (!neigh_node)) { |
96 | |||
97 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 137 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
98 | orig_node->orig); | 138 | orig_node->orig); |
99 | tt_global_del_orig(bat_priv, orig_node, | 139 | tt_global_del_orig(bat_priv, orig_node, |
100 | "originator timed out"); | 140 | "Deleted route towards originator"); |
101 | 141 | ||
102 | /* route added */ | 142 | /* route added */ |
103 | } else if ((!curr_router) && (neigh_node)) { | 143 | } else if ((!curr_router) && (neigh_node)) { |
@@ -105,11 +145,8 @@ static void update_route(struct bat_priv *bat_priv, | |||
105 | bat_dbg(DBG_ROUTES, bat_priv, | 145 | bat_dbg(DBG_ROUTES, bat_priv, |
106 | "Adding route towards: %pM (via %pM)\n", | 146 | "Adding route towards: %pM (via %pM)\n", |
107 | orig_node->orig, neigh_node->addr); | 147 | orig_node->orig, neigh_node->addr); |
108 | tt_global_add_orig(bat_priv, orig_node, | ||
109 | tt_buff, tt_buff_len); | ||
110 | |||
111 | /* route changed */ | 148 | /* route changed */ |
112 | } else { | 149 | } else if (neigh_node && curr_router) { |
113 | bat_dbg(DBG_ROUTES, bat_priv, | 150 | bat_dbg(DBG_ROUTES, bat_priv, |
114 | "Changing route towards: %pM " | 151 | "Changing route towards: %pM " |
115 | "(now via %pM - was via %pM)\n", | 152 | "(now via %pM - was via %pM)\n", |
@@ -133,10 +170,8 @@ static void update_route(struct bat_priv *bat_priv, | |||
133 | neigh_node_free_ref(curr_router); | 170 | neigh_node_free_ref(curr_router); |
134 | } | 171 | } |
135 | 172 | ||
136 | |||
137 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 173 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
138 | struct neigh_node *neigh_node, unsigned char *tt_buff, | 174 | struct neigh_node *neigh_node) |
139 | int tt_buff_len) | ||
140 | { | 175 | { |
141 | struct neigh_node *router = NULL; | 176 | struct neigh_node *router = NULL; |
142 | 177 | ||
@@ -146,11 +181,7 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
146 | router = orig_node_get_router(orig_node); | 181 | router = orig_node_get_router(orig_node); |
147 | 182 | ||
148 | if (router != neigh_node) | 183 | if (router != neigh_node) |
149 | update_route(bat_priv, orig_node, neigh_node, | 184 | update_route(bat_priv, orig_node, neigh_node); |
150 | tt_buff, tt_buff_len); | ||
151 | /* may be just TT changed */ | ||
152 | else | ||
153 | update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); | ||
154 | 185 | ||
155 | out: | 186 | out: |
156 | if (router) | 187 | if (router) |
@@ -165,7 +196,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
165 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 196 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
166 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node; | 197 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node; |
167 | struct hlist_node *node; | 198 | struct hlist_node *node; |
168 | unsigned char total_count; | 199 | uint8_t total_count; |
169 | uint8_t orig_eq_count, neigh_rq_count, tq_own; | 200 | uint8_t orig_eq_count, neigh_rq_count, tq_own; |
170 | int tq_asym_penalty, ret = 0; | 201 | int tq_asym_penalty, ret = 0; |
171 | 202 | ||
@@ -348,9 +379,9 @@ out: | |||
348 | } | 379 | } |
349 | 380 | ||
350 | /* copy primary address for bonding */ | 381 | /* copy primary address for bonding */ |
351 | static void bonding_save_primary(struct orig_node *orig_node, | 382 | static void bonding_save_primary(const struct orig_node *orig_node, |
352 | struct orig_node *orig_neigh_node, | 383 | struct orig_node *orig_neigh_node, |
353 | struct batman_packet *batman_packet) | 384 | const struct batman_packet *batman_packet) |
354 | { | 385 | { |
355 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) | 386 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) |
356 | return; | 387 | return; |
@@ -358,19 +389,16 @@ static void bonding_save_primary(struct orig_node *orig_node, | |||
358 | memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); | 389 | memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); |
359 | } | 390 | } |
360 | 391 | ||
361 | static void update_orig(struct bat_priv *bat_priv, | 392 | static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, |
362 | struct orig_node *orig_node, | 393 | const struct ethhdr *ethhdr, |
363 | struct ethhdr *ethhdr, | 394 | const struct batman_packet *batman_packet, |
364 | struct batman_packet *batman_packet, | ||
365 | struct hard_iface *if_incoming, | 395 | struct hard_iface *if_incoming, |
366 | unsigned char *tt_buff, int tt_buff_len, | 396 | const unsigned char *tt_buff, int is_duplicate) |
367 | char is_duplicate) | ||
368 | { | 397 | { |
369 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 398 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
370 | struct neigh_node *router = NULL; | 399 | struct neigh_node *router = NULL; |
371 | struct orig_node *orig_node_tmp; | 400 | struct orig_node *orig_node_tmp; |
372 | struct hlist_node *node; | 401 | struct hlist_node *node; |
373 | int tmp_tt_buff_len; | ||
374 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 402 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; |
375 | 403 | ||
376 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 404 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
@@ -435,9 +463,6 @@ static void update_orig(struct bat_priv *bat_priv, | |||
435 | 463 | ||
436 | bonding_candidate_add(orig_node, neigh_node); | 464 | bonding_candidate_add(orig_node, neigh_node); |
437 | 465 | ||
438 | tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? | ||
439 | batman_packet->num_tt * ETH_ALEN : tt_buff_len); | ||
440 | |||
441 | /* if this neighbor already is our next hop there is nothing | 466 | /* if this neighbor already is our next hop there is nothing |
442 | * to change */ | 467 | * to change */ |
443 | router = orig_node_get_router(orig_node); | 468 | router = orig_node_get_router(orig_node); |
@@ -467,15 +492,19 @@ static void update_orig(struct bat_priv *bat_priv, | |||
467 | goto update_tt; | 492 | goto update_tt; |
468 | } | 493 | } |
469 | 494 | ||
470 | update_routes(bat_priv, orig_node, neigh_node, | 495 | update_routes(bat_priv, orig_node, neigh_node); |
471 | tt_buff, tmp_tt_buff_len); | ||
472 | goto update_gw; | ||
473 | 496 | ||
474 | update_tt: | 497 | update_tt: |
475 | update_routes(bat_priv, orig_node, router, | 498 | /* I have to check for transtable changes only if the OGM has been |
476 | tt_buff, tmp_tt_buff_len); | 499 | * sent through a primary interface */ |
500 | if (((batman_packet->orig != ethhdr->h_source) && | ||
501 | (batman_packet->ttl > 2)) || | ||
502 | (batman_packet->flags & PRIMARIES_FIRST_HOP)) | ||
503 | update_transtable(bat_priv, orig_node, tt_buff, | ||
504 | batman_packet->tt_num_changes, | ||
505 | batman_packet->ttvn, | ||
506 | batman_packet->tt_crc); | ||
477 | 507 | ||
478 | update_gw: | ||
479 | if (orig_node->gw_flags != batman_packet->gw_flags) | 508 | if (orig_node->gw_flags != batman_packet->gw_flags) |
480 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); | 509 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); |
481 | 510 | ||
@@ -531,15 +560,15 @@ static int window_protected(struct bat_priv *bat_priv, | |||
531 | * -1 the packet is old and has been received while the seqno window | 560 | * -1 the packet is old and has been received while the seqno window |
532 | * was protected. Caller should drop it. | 561 | * was protected. Caller should drop it. |
533 | */ | 562 | */ |
534 | static char count_real_packets(struct ethhdr *ethhdr, | 563 | static int count_real_packets(const struct ethhdr *ethhdr, |
535 | struct batman_packet *batman_packet, | 564 | const struct batman_packet *batman_packet, |
536 | struct hard_iface *if_incoming) | 565 | const struct hard_iface *if_incoming) |
537 | { | 566 | { |
538 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 567 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
539 | struct orig_node *orig_node; | 568 | struct orig_node *orig_node; |
540 | struct neigh_node *tmp_neigh_node; | 569 | struct neigh_node *tmp_neigh_node; |
541 | struct hlist_node *node; | 570 | struct hlist_node *node; |
542 | char is_duplicate = 0; | 571 | int is_duplicate = 0; |
543 | int32_t seq_diff; | 572 | int32_t seq_diff; |
544 | int need_update = 0; | 573 | int need_update = 0; |
545 | int set_mark, ret = -1; | 574 | int set_mark, ret = -1; |
@@ -595,9 +624,9 @@ out: | |||
595 | return ret; | 624 | return ret; |
596 | } | 625 | } |
597 | 626 | ||
598 | void receive_bat_packet(struct ethhdr *ethhdr, | 627 | void receive_bat_packet(const struct ethhdr *ethhdr, |
599 | struct batman_packet *batman_packet, | 628 | struct batman_packet *batman_packet, |
600 | unsigned char *tt_buff, int tt_buff_len, | 629 | const unsigned char *tt_buff, |
601 | struct hard_iface *if_incoming) | 630 | struct hard_iface *if_incoming) |
602 | { | 631 | { |
603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 632 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
@@ -605,10 +634,10 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
605 | struct orig_node *orig_neigh_node, *orig_node; | 634 | struct orig_node *orig_neigh_node, *orig_node; |
606 | struct neigh_node *router = NULL, *router_router = NULL; | 635 | struct neigh_node *router = NULL, *router_router = NULL; |
607 | struct neigh_node *orig_neigh_router = NULL; | 636 | struct neigh_node *orig_neigh_router = NULL; |
608 | char has_directlink_flag; | 637 | int has_directlink_flag; |
609 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 638 | int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
610 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; | 639 | int is_broadcast = 0, is_bidirectional, is_single_hop_neigh; |
611 | char is_duplicate; | 640 | int is_duplicate; |
612 | uint32_t if_incoming_seqno; | 641 | uint32_t if_incoming_seqno; |
613 | 642 | ||
614 | /* Silently drop when the batman packet is actually not a | 643 | /* Silently drop when the batman packet is actually not a |
@@ -636,12 +665,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
636 | 665 | ||
637 | bat_dbg(DBG_BATMAN, bat_priv, | 666 | bat_dbg(DBG_BATMAN, bat_priv, |
638 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] " | 667 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] " |
639 | "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, " | 668 | "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, " |
640 | "TTL %d, V %d, IDF %d)\n", | 669 | "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", |
641 | ethhdr->h_source, if_incoming->net_dev->name, | 670 | ethhdr->h_source, if_incoming->net_dev->name, |
642 | if_incoming->net_dev->dev_addr, batman_packet->orig, | 671 | if_incoming->net_dev->dev_addr, batman_packet->orig, |
643 | batman_packet->prev_sender, batman_packet->seqno, | 672 | batman_packet->prev_sender, batman_packet->seqno, |
644 | batman_packet->tq, batman_packet->ttl, batman_packet->version, | 673 | batman_packet->ttvn, batman_packet->tt_crc, |
674 | batman_packet->tt_num_changes, batman_packet->tq, | ||
675 | batman_packet->ttl, batman_packet->version, | ||
645 | has_directlink_flag); | 676 | has_directlink_flag); |
646 | 677 | ||
647 | rcu_read_lock(); | 678 | rcu_read_lock(); |
@@ -664,7 +695,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
664 | hard_iface->net_dev->dev_addr)) | 695 | hard_iface->net_dev->dev_addr)) |
665 | is_my_oldorig = 1; | 696 | is_my_oldorig = 1; |
666 | 697 | ||
667 | if (compare_eth(ethhdr->h_source, broadcast_addr)) | 698 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
668 | is_broadcast = 1; | 699 | is_broadcast = 1; |
669 | } | 700 | } |
670 | rcu_read_unlock(); | 701 | rcu_read_unlock(); |
@@ -701,17 +732,16 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
701 | 732 | ||
702 | /* neighbor has to indicate direct link and it has to | 733 | /* neighbor has to indicate direct link and it has to |
703 | * come via the corresponding interface */ | 734 | * come via the corresponding interface */ |
704 | /* if received seqno equals last send seqno save new | 735 | /* save packet seqno for bidirectional check */ |
705 | * seqno for bidirectional check */ | ||
706 | if (has_directlink_flag && | 736 | if (has_directlink_flag && |
707 | compare_eth(if_incoming->net_dev->dev_addr, | 737 | compare_eth(if_incoming->net_dev->dev_addr, |
708 | batman_packet->orig) && | 738 | batman_packet->orig)) { |
709 | (batman_packet->seqno - if_incoming_seqno + 2 == 0)) { | ||
710 | offset = if_incoming->if_num * NUM_WORDS; | 739 | offset = if_incoming->if_num * NUM_WORDS; |
711 | 740 | ||
712 | spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); | 741 | spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); |
713 | word = &(orig_neigh_node->bcast_own[offset]); | 742 | word = &(orig_neigh_node->bcast_own[offset]); |
714 | bit_mark(word, 0); | 743 | bit_mark(word, |
744 | if_incoming_seqno - batman_packet->seqno - 2); | ||
715 | orig_neigh_node->bcast_own_sum[if_incoming->if_num] = | 745 | orig_neigh_node->bcast_own_sum[if_incoming->if_num] = |
716 | bit_packet_count(word); | 746 | bit_packet_count(word); |
717 | spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); | 747 | spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); |
@@ -794,14 +824,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
794 | ((orig_node->last_real_seqno == batman_packet->seqno) && | 824 | ((orig_node->last_real_seqno == batman_packet->seqno) && |
795 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) | 825 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) |
796 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, | 826 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, |
797 | if_incoming, tt_buff, tt_buff_len, is_duplicate); | 827 | if_incoming, tt_buff, is_duplicate); |
798 | 828 | ||
799 | /* is single hop (direct) neighbor */ | 829 | /* is single hop (direct) neighbor */ |
800 | if (is_single_hop_neigh) { | 830 | if (is_single_hop_neigh) { |
801 | 831 | ||
802 | /* mark direct link on incoming interface */ | 832 | /* mark direct link on incoming interface */ |
803 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 833 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
804 | 1, tt_buff_len, if_incoming); | 834 | 1, if_incoming); |
805 | 835 | ||
806 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " | 836 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " |
807 | "rebroadcast neighbor packet with direct link flag\n"); | 837 | "rebroadcast neighbor packet with direct link flag\n"); |
@@ -824,7 +854,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
824 | bat_dbg(DBG_BATMAN, bat_priv, | 854 | bat_dbg(DBG_BATMAN, bat_priv, |
825 | "Forwarding packet: rebroadcast originator packet\n"); | 855 | "Forwarding packet: rebroadcast originator packet\n"); |
826 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 856 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
827 | 0, tt_buff_len, if_incoming); | 857 | 0, if_incoming); |
828 | 858 | ||
829 | out_neigh: | 859 | out_neigh: |
830 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 860 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
@@ -1077,7 +1107,7 @@ out: | |||
1077 | * This method rotates the bonding list and increases the | 1107 | * This method rotates the bonding list and increases the |
1078 | * returned router's refcount. */ | 1108 | * returned router's refcount. */ |
1079 | static struct neigh_node *find_bond_router(struct orig_node *primary_orig, | 1109 | static struct neigh_node *find_bond_router(struct orig_node *primary_orig, |
1080 | struct hard_iface *recv_if) | 1110 | const struct hard_iface *recv_if) |
1081 | { | 1111 | { |
1082 | struct neigh_node *tmp_neigh_node; | 1112 | struct neigh_node *tmp_neigh_node; |
1083 | struct neigh_node *router = NULL, *first_candidate = NULL; | 1113 | struct neigh_node *router = NULL, *first_candidate = NULL; |
@@ -1128,7 +1158,7 @@ out: | |||
1128 | * | 1158 | * |
1129 | * Increases the returned router's refcount */ | 1159 | * Increases the returned router's refcount */ |
1130 | static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | 1160 | static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, |
1131 | struct hard_iface *recv_if) | 1161 | const struct hard_iface *recv_if) |
1132 | { | 1162 | { |
1133 | struct neigh_node *tmp_neigh_node; | 1163 | struct neigh_node *tmp_neigh_node; |
1134 | struct neigh_node *router = NULL, *first_candidate = NULL; | 1164 | struct neigh_node *router = NULL, *first_candidate = NULL; |
@@ -1171,12 +1201,124 @@ static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | |||
1171 | return router; | 1201 | return router; |
1172 | } | 1202 | } |
1173 | 1203 | ||
1204 | int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) | ||
1205 | { | ||
1206 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
1207 | struct tt_query_packet *tt_query; | ||
1208 | struct ethhdr *ethhdr; | ||
1209 | |||
1210 | /* drop packet if it has not necessary minimum size */ | ||
1211 | if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet)))) | ||
1212 | goto out; | ||
1213 | |||
1214 | /* I could need to modify it */ | ||
1215 | if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0) | ||
1216 | goto out; | ||
1217 | |||
1218 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1219 | |||
1220 | /* packet with unicast indication but broadcast recipient */ | ||
1221 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | ||
1222 | goto out; | ||
1223 | |||
1224 | /* packet with broadcast sender address */ | ||
1225 | if (is_broadcast_ether_addr(ethhdr->h_source)) | ||
1226 | goto out; | ||
1227 | |||
1228 | tt_query = (struct tt_query_packet *)skb->data; | ||
1229 | |||
1230 | tt_query->tt_data = ntohs(tt_query->tt_data); | ||
1231 | |||
1232 | switch (tt_query->flags & TT_QUERY_TYPE_MASK) { | ||
1233 | case TT_REQUEST: | ||
1234 | /* If we cannot provide an answer the tt_request is | ||
1235 | * forwarded */ | ||
1236 | if (!send_tt_response(bat_priv, tt_query)) { | ||
1237 | bat_dbg(DBG_TT, bat_priv, | ||
1238 | "Routing TT_REQUEST to %pM [%c]\n", | ||
1239 | tt_query->dst, | ||
1240 | (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); | ||
1241 | tt_query->tt_data = htons(tt_query->tt_data); | ||
1242 | return route_unicast_packet(skb, recv_if); | ||
1243 | } | ||
1244 | break; | ||
1245 | case TT_RESPONSE: | ||
1246 | /* packet needs to be linearised to access the TT changes */ | ||
1247 | if (skb_linearize(skb) < 0) | ||
1248 | goto out; | ||
1249 | |||
1250 | if (is_my_mac(tt_query->dst)) | ||
1251 | handle_tt_response(bat_priv, tt_query); | ||
1252 | else { | ||
1253 | bat_dbg(DBG_TT, bat_priv, | ||
1254 | "Routing TT_RESPONSE to %pM [%c]\n", | ||
1255 | tt_query->dst, | ||
1256 | (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); | ||
1257 | tt_query->tt_data = htons(tt_query->tt_data); | ||
1258 | return route_unicast_packet(skb, recv_if); | ||
1259 | } | ||
1260 | break; | ||
1261 | } | ||
1262 | |||
1263 | out: | ||
1264 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | ||
1265 | return NET_RX_DROP; | ||
1266 | } | ||
1267 | |||
1268 | int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) | ||
1269 | { | ||
1270 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
1271 | struct roam_adv_packet *roam_adv_packet; | ||
1272 | struct orig_node *orig_node; | ||
1273 | struct ethhdr *ethhdr; | ||
1274 | |||
1275 | /* drop packet if it has not necessary minimum size */ | ||
1276 | if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet)))) | ||
1277 | goto out; | ||
1278 | |||
1279 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1280 | |||
1281 | /* packet with unicast indication but broadcast recipient */ | ||
1282 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | ||
1283 | goto out; | ||
1284 | |||
1285 | /* packet with broadcast sender address */ | ||
1286 | if (is_broadcast_ether_addr(ethhdr->h_source)) | ||
1287 | goto out; | ||
1288 | |||
1289 | roam_adv_packet = (struct roam_adv_packet *)skb->data; | ||
1290 | |||
1291 | if (!is_my_mac(roam_adv_packet->dst)) | ||
1292 | return route_unicast_packet(skb, recv_if); | ||
1293 | |||
1294 | orig_node = orig_hash_find(bat_priv, roam_adv_packet->src); | ||
1295 | if (!orig_node) | ||
1296 | goto out; | ||
1297 | |||
1298 | bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM " | ||
1299 | "(client %pM)\n", roam_adv_packet->src, | ||
1300 | roam_adv_packet->client); | ||
1301 | |||
1302 | tt_global_add(bat_priv, orig_node, roam_adv_packet->client, | ||
1303 | atomic_read(&orig_node->last_ttvn) + 1, true); | ||
1304 | |||
1305 | /* Roaming phase starts: I have new information but the ttvn has not | ||
1306 | * been incremented yet. This flag will make me check all the incoming | ||
1307 | * packets for the correct destination. */ | ||
1308 | bat_priv->tt_poss_change = true; | ||
1309 | |||
1310 | orig_node_free_ref(orig_node); | ||
1311 | out: | ||
1312 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | ||
1313 | return NET_RX_DROP; | ||
1314 | } | ||
1315 | |||
1174 | /* find a suitable router for this originator, and use | 1316 | /* find a suitable router for this originator, and use |
1175 | * bonding if possible. increases the found neighbors | 1317 | * bonding if possible. increases the found neighbors |
1176 | * refcount.*/ | 1318 | * refcount.*/ |
1177 | struct neigh_node *find_router(struct bat_priv *bat_priv, | 1319 | struct neigh_node *find_router(struct bat_priv *bat_priv, |
1178 | struct orig_node *orig_node, | 1320 | struct orig_node *orig_node, |
1179 | struct hard_iface *recv_if) | 1321 | const struct hard_iface *recv_if) |
1180 | { | 1322 | { |
1181 | struct orig_node *primary_orig_node; | 1323 | struct orig_node *primary_orig_node; |
1182 | struct orig_node *router_orig; | 1324 | struct orig_node *router_orig; |
@@ -1240,6 +1382,9 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1240 | router = find_ifalter_router(primary_orig_node, recv_if); | 1382 | router = find_ifalter_router(primary_orig_node, recv_if); |
1241 | 1383 | ||
1242 | return_router: | 1384 | return_router: |
1385 | if (router && router->if_incoming->if_status != IF_ACTIVE) | ||
1386 | goto err_unlock; | ||
1387 | |||
1243 | rcu_read_unlock(); | 1388 | rcu_read_unlock(); |
1244 | return router; | 1389 | return router; |
1245 | err_unlock: | 1390 | err_unlock: |
@@ -1354,14 +1499,84 @@ out: | |||
1354 | return ret; | 1499 | return ret; |
1355 | } | 1500 | } |
1356 | 1501 | ||
1502 | static int check_unicast_ttvn(struct bat_priv *bat_priv, | ||
1503 | struct sk_buff *skb) { | ||
1504 | uint8_t curr_ttvn; | ||
1505 | struct orig_node *orig_node; | ||
1506 | struct ethhdr *ethhdr; | ||
1507 | struct hard_iface *primary_if; | ||
1508 | struct unicast_packet *unicast_packet; | ||
1509 | bool tt_poss_change; | ||
1510 | |||
1511 | /* I could need to modify it */ | ||
1512 | if (skb_cow(skb, sizeof(struct unicast_packet)) < 0) | ||
1513 | return 0; | ||
1514 | |||
1515 | unicast_packet = (struct unicast_packet *)skb->data; | ||
1516 | |||
1517 | if (is_my_mac(unicast_packet->dest)) { | ||
1518 | tt_poss_change = bat_priv->tt_poss_change; | ||
1519 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | ||
1520 | } else { | ||
1521 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); | ||
1522 | |||
1523 | if (!orig_node) | ||
1524 | return 0; | ||
1525 | |||
1526 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
1527 | tt_poss_change = orig_node->tt_poss_change; | ||
1528 | orig_node_free_ref(orig_node); | ||
1529 | } | ||
1530 | |||
1531 | /* Check whether I have to reroute the packet */ | ||
1532 | if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) { | ||
1533 | /* Linearize the skb before accessing it */ | ||
1534 | if (skb_linearize(skb) < 0) | ||
1535 | return 0; | ||
1536 | |||
1537 | ethhdr = (struct ethhdr *)(skb->data + | ||
1538 | sizeof(struct unicast_packet)); | ||
1539 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | ||
1540 | |||
1541 | if (!orig_node) { | ||
1542 | if (!is_my_client(bat_priv, ethhdr->h_dest)) | ||
1543 | return 0; | ||
1544 | primary_if = primary_if_get_selected(bat_priv); | ||
1545 | if (!primary_if) | ||
1546 | return 0; | ||
1547 | memcpy(unicast_packet->dest, | ||
1548 | primary_if->net_dev->dev_addr, ETH_ALEN); | ||
1549 | hardif_free_ref(primary_if); | ||
1550 | } else { | ||
1551 | memcpy(unicast_packet->dest, orig_node->orig, | ||
1552 | ETH_ALEN); | ||
1553 | curr_ttvn = (uint8_t) | ||
1554 | atomic_read(&orig_node->last_ttvn); | ||
1555 | orig_node_free_ref(orig_node); | ||
1556 | } | ||
1557 | |||
1558 | bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u " | ||
1559 | "new_ttvn %u)! Rerouting unicast packet (for %pM) to " | ||
1560 | "%pM\n", unicast_packet->ttvn, curr_ttvn, | ||
1561 | ethhdr->h_dest, unicast_packet->dest); | ||
1562 | |||
1563 | unicast_packet->ttvn = curr_ttvn; | ||
1564 | } | ||
1565 | return 1; | ||
1566 | } | ||
1567 | |||
1357 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | 1568 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
1358 | { | 1569 | { |
1570 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
1359 | struct unicast_packet *unicast_packet; | 1571 | struct unicast_packet *unicast_packet; |
1360 | int hdr_size = sizeof(struct unicast_packet); | 1572 | int hdr_size = sizeof(*unicast_packet); |
1361 | 1573 | ||
1362 | if (check_unicast_packet(skb, hdr_size) < 0) | 1574 | if (check_unicast_packet(skb, hdr_size) < 0) |
1363 | return NET_RX_DROP; | 1575 | return NET_RX_DROP; |
1364 | 1576 | ||
1577 | if (!check_unicast_ttvn(bat_priv, skb)) | ||
1578 | return NET_RX_DROP; | ||
1579 | |||
1365 | unicast_packet = (struct unicast_packet *)skb->data; | 1580 | unicast_packet = (struct unicast_packet *)skb->data; |
1366 | 1581 | ||
1367 | /* packet for me */ | 1582 | /* packet for me */ |
@@ -1377,13 +1592,16 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1377 | { | 1592 | { |
1378 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 1593 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1379 | struct unicast_frag_packet *unicast_packet; | 1594 | struct unicast_frag_packet *unicast_packet; |
1380 | int hdr_size = sizeof(struct unicast_frag_packet); | 1595 | int hdr_size = sizeof(*unicast_packet); |
1381 | struct sk_buff *new_skb = NULL; | 1596 | struct sk_buff *new_skb = NULL; |
1382 | int ret; | 1597 | int ret; |
1383 | 1598 | ||
1384 | if (check_unicast_packet(skb, hdr_size) < 0) | 1599 | if (check_unicast_packet(skb, hdr_size) < 0) |
1385 | return NET_RX_DROP; | 1600 | return NET_RX_DROP; |
1386 | 1601 | ||
1602 | if (!check_unicast_ttvn(bat_priv, skb)) | ||
1603 | return NET_RX_DROP; | ||
1604 | |||
1387 | unicast_packet = (struct unicast_frag_packet *)skb->data; | 1605 | unicast_packet = (struct unicast_frag_packet *)skb->data; |
1388 | 1606 | ||
1389 | /* packet for me */ | 1607 | /* packet for me */ |
@@ -1413,7 +1631,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1413 | struct orig_node *orig_node = NULL; | 1631 | struct orig_node *orig_node = NULL; |
1414 | struct bcast_packet *bcast_packet; | 1632 | struct bcast_packet *bcast_packet; |
1415 | struct ethhdr *ethhdr; | 1633 | struct ethhdr *ethhdr; |
1416 | int hdr_size = sizeof(struct bcast_packet); | 1634 | int hdr_size = sizeof(*bcast_packet); |
1417 | int ret = NET_RX_DROP; | 1635 | int ret = NET_RX_DROP; |
1418 | int32_t seq_diff; | 1636 | int32_t seq_diff; |
1419 | 1637 | ||
@@ -1471,7 +1689,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1471 | spin_unlock_bh(&orig_node->bcast_seqno_lock); | 1689 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1472 | 1690 | ||
1473 | /* rebroadcast packet */ | 1691 | /* rebroadcast packet */ |
1474 | add_bcast_packet_to_list(bat_priv, skb); | 1692 | add_bcast_packet_to_list(bat_priv, skb, 1); |
1475 | 1693 | ||
1476 | /* broadcast for me */ | 1694 | /* broadcast for me */ |
1477 | interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); | 1695 | interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); |
@@ -1491,7 +1709,7 @@ int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1491 | struct vis_packet *vis_packet; | 1709 | struct vis_packet *vis_packet; |
1492 | struct ethhdr *ethhdr; | 1710 | struct ethhdr *ethhdr; |
1493 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 1711 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1494 | int hdr_size = sizeof(struct vis_packet); | 1712 | int hdr_size = sizeof(*vis_packet); |
1495 | 1713 | ||
1496 | /* keep skb linear */ | 1714 | /* keep skb linear */ |
1497 | if (skb_linearize(skb) < 0) | 1715 | if (skb_linearize(skb) < 0) |