diff options
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 252 |
1 files changed, 204 insertions, 48 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index eb6fb7d2d368..8b0f8330b06d 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,27 +64,56 @@ 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 | const 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 | spin_lock_bh(&bat_priv->tt_ghash_lock); | ||
94 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); | ||
95 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | ||
96 | } else { | ||
97 | /* if we missed more than one change or our tables are not | ||
98 | * in sync anymore -> request fresh tt data */ | ||
99 | if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { | ||
100 | request_table: | ||
101 | bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. " | ||
102 | "Need to retrieve the correct information " | ||
103 | "(ttvn: %u last_ttvn: %u crc: %u last_crc: " | ||
104 | "%u num_changes: %u)\n", orig_node->orig, ttvn, | ||
105 | orig_ttvn, tt_crc, orig_node->tt_crc, | ||
106 | tt_num_changes); | ||
107 | send_tt_request(bat_priv, orig_node, ttvn, tt_crc, | ||
108 | full_table); | ||
109 | return; | ||
110 | } | ||
82 | } | 111 | } |
83 | } | 112 | } |
84 | 113 | ||
85 | static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, | 114 | static void update_route(struct bat_priv *bat_priv, |
86 | struct neigh_node *neigh_node, | 115 | struct orig_node *orig_node, |
87 | const unsigned char *tt_buff, int tt_buff_len) | 116 | struct neigh_node *neigh_node) |
88 | { | 117 | { |
89 | struct neigh_node *curr_router; | 118 | struct neigh_node *curr_router; |
90 | 119 | ||
@@ -92,11 +121,10 @@ static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
92 | 121 | ||
93 | /* route deleted */ | 122 | /* route deleted */ |
94 | if ((curr_router) && (!neigh_node)) { | 123 | if ((curr_router) && (!neigh_node)) { |
95 | |||
96 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 124 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
97 | orig_node->orig); | 125 | orig_node->orig); |
98 | tt_global_del_orig(bat_priv, orig_node, | 126 | tt_global_del_orig(bat_priv, orig_node, |
99 | "originator timed out"); | 127 | "Deleted route towards originator"); |
100 | 128 | ||
101 | /* route added */ | 129 | /* route added */ |
102 | } else if ((!curr_router) && (neigh_node)) { | 130 | } else if ((!curr_router) && (neigh_node)) { |
@@ -104,9 +132,6 @@ static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
104 | bat_dbg(DBG_ROUTES, bat_priv, | 132 | bat_dbg(DBG_ROUTES, bat_priv, |
105 | "Adding route towards: %pM (via %pM)\n", | 133 | "Adding route towards: %pM (via %pM)\n", |
106 | orig_node->orig, neigh_node->addr); | 134 | orig_node->orig, neigh_node->addr); |
107 | tt_global_add_orig(bat_priv, orig_node, | ||
108 | tt_buff, tt_buff_len); | ||
109 | |||
110 | /* route changed */ | 135 | /* route changed */ |
111 | } else if (neigh_node && curr_router) { | 136 | } else if (neigh_node && curr_router) { |
112 | bat_dbg(DBG_ROUTES, bat_priv, | 137 | bat_dbg(DBG_ROUTES, bat_priv, |
@@ -133,8 +158,7 @@ static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
133 | } | 158 | } |
134 | 159 | ||
135 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 160 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
136 | struct neigh_node *neigh_node, const unsigned char *tt_buff, | 161 | struct neigh_node *neigh_node) |
137 | int tt_buff_len) | ||
138 | { | 162 | { |
139 | struct neigh_node *router = NULL; | 163 | struct neigh_node *router = NULL; |
140 | 164 | ||
@@ -144,11 +168,7 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
144 | router = orig_node_get_router(orig_node); | 168 | router = orig_node_get_router(orig_node); |
145 | 169 | ||
146 | if (router != neigh_node) | 170 | if (router != neigh_node) |
147 | update_route(bat_priv, orig_node, neigh_node, | 171 | update_route(bat_priv, orig_node, neigh_node); |
148 | tt_buff, tt_buff_len); | ||
149 | /* may be just TT changed */ | ||
150 | else | ||
151 | update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); | ||
152 | 172 | ||
153 | out: | 173 | out: |
154 | if (router) | 174 | if (router) |
@@ -360,14 +380,12 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
360 | const struct ethhdr *ethhdr, | 380 | const struct ethhdr *ethhdr, |
361 | const struct batman_packet *batman_packet, | 381 | const struct batman_packet *batman_packet, |
362 | struct hard_iface *if_incoming, | 382 | struct hard_iface *if_incoming, |
363 | const unsigned char *tt_buff, int tt_buff_len, | 383 | const unsigned char *tt_buff, int is_duplicate) |
364 | int is_duplicate) | ||
365 | { | 384 | { |
366 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 385 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
367 | struct neigh_node *router = NULL; | 386 | struct neigh_node *router = NULL; |
368 | struct orig_node *orig_node_tmp; | 387 | struct orig_node *orig_node_tmp; |
369 | struct hlist_node *node; | 388 | struct hlist_node *node; |
370 | int tmp_tt_buff_len; | ||
371 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 389 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; |
372 | 390 | ||
373 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 391 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
@@ -432,9 +450,6 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
432 | 450 | ||
433 | bonding_candidate_add(orig_node, neigh_node); | 451 | bonding_candidate_add(orig_node, neigh_node); |
434 | 452 | ||
435 | tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? | ||
436 | batman_packet->num_tt * ETH_ALEN : tt_buff_len); | ||
437 | |||
438 | /* if this neighbor already is our next hop there is nothing | 453 | /* if this neighbor already is our next hop there is nothing |
439 | * to change */ | 454 | * to change */ |
440 | router = orig_node_get_router(orig_node); | 455 | router = orig_node_get_router(orig_node); |
@@ -464,15 +479,19 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
464 | goto update_tt; | 479 | goto update_tt; |
465 | } | 480 | } |
466 | 481 | ||
467 | update_routes(bat_priv, orig_node, neigh_node, | 482 | update_routes(bat_priv, orig_node, neigh_node); |
468 | tt_buff, tmp_tt_buff_len); | ||
469 | goto update_gw; | ||
470 | 483 | ||
471 | update_tt: | 484 | update_tt: |
472 | update_routes(bat_priv, orig_node, router, | 485 | /* I have to check for transtable changes only if the OGM has been |
473 | tt_buff, tmp_tt_buff_len); | 486 | * sent through a primary interface */ |
487 | if (((batman_packet->orig != ethhdr->h_source) && | ||
488 | (batman_packet->ttl > 2)) || | ||
489 | (batman_packet->flags & PRIMARIES_FIRST_HOP)) | ||
490 | update_transtable(bat_priv, orig_node, tt_buff, | ||
491 | batman_packet->tt_num_changes, | ||
492 | batman_packet->ttvn, | ||
493 | batman_packet->tt_crc); | ||
474 | 494 | ||
475 | update_gw: | ||
476 | if (orig_node->gw_flags != batman_packet->gw_flags) | 495 | if (orig_node->gw_flags != batman_packet->gw_flags) |
477 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); | 496 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); |
478 | 497 | ||
@@ -594,7 +613,7 @@ out: | |||
594 | 613 | ||
595 | void receive_bat_packet(const struct ethhdr *ethhdr, | 614 | void receive_bat_packet(const struct ethhdr *ethhdr, |
596 | struct batman_packet *batman_packet, | 615 | struct batman_packet *batman_packet, |
597 | const unsigned char *tt_buff, int tt_buff_len, | 616 | const unsigned char *tt_buff, |
598 | struct hard_iface *if_incoming) | 617 | struct hard_iface *if_incoming) |
599 | { | 618 | { |
600 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 619 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
@@ -633,12 +652,14 @@ void receive_bat_packet(const struct ethhdr *ethhdr, | |||
633 | 652 | ||
634 | bat_dbg(DBG_BATMAN, bat_priv, | 653 | bat_dbg(DBG_BATMAN, bat_priv, |
635 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] " | 654 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] " |
636 | "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, " | 655 | "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, " |
637 | "TTL %d, V %d, IDF %d)\n", | 656 | "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", |
638 | ethhdr->h_source, if_incoming->net_dev->name, | 657 | ethhdr->h_source, if_incoming->net_dev->name, |
639 | if_incoming->net_dev->dev_addr, batman_packet->orig, | 658 | if_incoming->net_dev->dev_addr, batman_packet->orig, |
640 | batman_packet->prev_sender, batman_packet->seqno, | 659 | batman_packet->prev_sender, batman_packet->seqno, |
641 | batman_packet->tq, batman_packet->ttl, batman_packet->version, | 660 | batman_packet->ttvn, batman_packet->tt_crc, |
661 | batman_packet->tt_num_changes, batman_packet->tq, | ||
662 | batman_packet->ttl, batman_packet->version, | ||
642 | has_directlink_flag); | 663 | has_directlink_flag); |
643 | 664 | ||
644 | rcu_read_lock(); | 665 | rcu_read_lock(); |
@@ -790,14 +811,14 @@ void receive_bat_packet(const struct ethhdr *ethhdr, | |||
790 | ((orig_node->last_real_seqno == batman_packet->seqno) && | 811 | ((orig_node->last_real_seqno == batman_packet->seqno) && |
791 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) | 812 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) |
792 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, | 813 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, |
793 | if_incoming, tt_buff, tt_buff_len, is_duplicate); | 814 | if_incoming, tt_buff, is_duplicate); |
794 | 815 | ||
795 | /* is single hop (direct) neighbor */ | 816 | /* is single hop (direct) neighbor */ |
796 | if (is_single_hop_neigh) { | 817 | if (is_single_hop_neigh) { |
797 | 818 | ||
798 | /* mark direct link on incoming interface */ | 819 | /* mark direct link on incoming interface */ |
799 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 820 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
800 | 1, tt_buff_len, if_incoming); | 821 | 1, if_incoming); |
801 | 822 | ||
802 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " | 823 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " |
803 | "rebroadcast neighbor packet with direct link flag\n"); | 824 | "rebroadcast neighbor packet with direct link flag\n"); |
@@ -820,7 +841,7 @@ void receive_bat_packet(const struct ethhdr *ethhdr, | |||
820 | bat_dbg(DBG_BATMAN, bat_priv, | 841 | bat_dbg(DBG_BATMAN, bat_priv, |
821 | "Forwarding packet: rebroadcast originator packet\n"); | 842 | "Forwarding packet: rebroadcast originator packet\n"); |
822 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 843 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
823 | 0, tt_buff_len, if_incoming); | 844 | 0, if_incoming); |
824 | 845 | ||
825 | out_neigh: | 846 | out_neigh: |
826 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 847 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
@@ -1167,6 +1188,70 @@ static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | |||
1167 | return router; | 1188 | return router; |
1168 | } | 1189 | } |
1169 | 1190 | ||
1191 | int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) | ||
1192 | { | ||
1193 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
1194 | struct tt_query_packet *tt_query; | ||
1195 | struct ethhdr *ethhdr; | ||
1196 | |||
1197 | /* drop packet if it has not necessary minimum size */ | ||
1198 | if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet)))) | ||
1199 | goto out; | ||
1200 | |||
1201 | /* I could need to modify it */ | ||
1202 | if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0) | ||
1203 | goto out; | ||
1204 | |||
1205 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1206 | |||
1207 | /* packet with unicast indication but broadcast recipient */ | ||
1208 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | ||
1209 | goto out; | ||
1210 | |||
1211 | /* packet with broadcast sender address */ | ||
1212 | if (is_broadcast_ether_addr(ethhdr->h_source)) | ||
1213 | goto out; | ||
1214 | |||
1215 | tt_query = (struct tt_query_packet *)skb->data; | ||
1216 | |||
1217 | tt_query->tt_data = ntohs(tt_query->tt_data); | ||
1218 | |||
1219 | switch (tt_query->flags & TT_QUERY_TYPE_MASK) { | ||
1220 | case TT_REQUEST: | ||
1221 | /* If we cannot provide an answer the tt_request is | ||
1222 | * forwarded */ | ||
1223 | if (!send_tt_response(bat_priv, tt_query)) { | ||
1224 | bat_dbg(DBG_TT, bat_priv, | ||
1225 | "Routing TT_REQUEST to %pM [%c]\n", | ||
1226 | tt_query->dst, | ||
1227 | (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); | ||
1228 | tt_query->tt_data = htons(tt_query->tt_data); | ||
1229 | return route_unicast_packet(skb, recv_if); | ||
1230 | } | ||
1231 | break; | ||
1232 | case TT_RESPONSE: | ||
1233 | /* packet needs to be linearised to access the TT changes */ | ||
1234 | if (skb_linearize(skb) < 0) | ||
1235 | goto out; | ||
1236 | |||
1237 | if (is_my_mac(tt_query->dst)) | ||
1238 | handle_tt_response(bat_priv, tt_query); | ||
1239 | else { | ||
1240 | bat_dbg(DBG_TT, bat_priv, | ||
1241 | "Routing TT_RESPONSE to %pM [%c]\n", | ||
1242 | tt_query->dst, | ||
1243 | (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); | ||
1244 | tt_query->tt_data = htons(tt_query->tt_data); | ||
1245 | return route_unicast_packet(skb, recv_if); | ||
1246 | } | ||
1247 | break; | ||
1248 | } | ||
1249 | |||
1250 | out: | ||
1251 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | ||
1252 | return NET_RX_DROP; | ||
1253 | } | ||
1254 | |||
1170 | /* find a suitable router for this originator, and use | 1255 | /* find a suitable router for this originator, and use |
1171 | * bonding if possible. increases the found neighbors | 1256 | * bonding if possible. increases the found neighbors |
1172 | * refcount.*/ | 1257 | * refcount.*/ |
@@ -1353,14 +1438,82 @@ out: | |||
1353 | return ret; | 1438 | return ret; |
1354 | } | 1439 | } |
1355 | 1440 | ||
1441 | static int check_unicast_ttvn(struct bat_priv *bat_priv, | ||
1442 | struct sk_buff *skb) { | ||
1443 | uint8_t curr_ttvn; | ||
1444 | struct orig_node *orig_node; | ||
1445 | struct ethhdr *ethhdr; | ||
1446 | struct hard_iface *primary_if; | ||
1447 | struct unicast_packet *unicast_packet; | ||
1448 | |||
1449 | /* I could need to modify it */ | ||
1450 | if (skb_cow(skb, sizeof(struct unicast_packet)) < 0) | ||
1451 | return 0; | ||
1452 | |||
1453 | unicast_packet = (struct unicast_packet *)skb->data; | ||
1454 | |||
1455 | if (is_my_mac(unicast_packet->dest)) | ||
1456 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | ||
1457 | else { | ||
1458 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); | ||
1459 | |||
1460 | if (!orig_node) | ||
1461 | return 0; | ||
1462 | |||
1463 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
1464 | orig_node_free_ref(orig_node); | ||
1465 | } | ||
1466 | |||
1467 | /* Check whether I have to reroute the packet */ | ||
1468 | if (seq_before(unicast_packet->ttvn, curr_ttvn)) { | ||
1469 | /* Linearize the skb before accessing it */ | ||
1470 | if (skb_linearize(skb) < 0) | ||
1471 | return 0; | ||
1472 | |||
1473 | ethhdr = (struct ethhdr *)(skb->data + | ||
1474 | sizeof(struct unicast_packet)); | ||
1475 | |||
1476 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | ||
1477 | |||
1478 | if (!orig_node) { | ||
1479 | if (!is_my_client(bat_priv, ethhdr->h_dest)) | ||
1480 | return 0; | ||
1481 | primary_if = primary_if_get_selected(bat_priv); | ||
1482 | if (!primary_if) | ||
1483 | return 0; | ||
1484 | memcpy(unicast_packet->dest, | ||
1485 | primary_if->net_dev->dev_addr, ETH_ALEN); | ||
1486 | hardif_free_ref(primary_if); | ||
1487 | } else { | ||
1488 | memcpy(unicast_packet->dest, orig_node->orig, | ||
1489 | ETH_ALEN); | ||
1490 | curr_ttvn = (uint8_t) | ||
1491 | atomic_read(&orig_node->last_ttvn); | ||
1492 | orig_node_free_ref(orig_node); | ||
1493 | } | ||
1494 | |||
1495 | bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u " | ||
1496 | "new_ttvn %u)! Rerouting unicast packet (for %pM) to " | ||
1497 | "%pM\n", unicast_packet->ttvn, curr_ttvn, | ||
1498 | ethhdr->h_dest, unicast_packet->dest); | ||
1499 | |||
1500 | unicast_packet->ttvn = curr_ttvn; | ||
1501 | } | ||
1502 | return 1; | ||
1503 | } | ||
1504 | |||
1356 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | 1505 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
1357 | { | 1506 | { |
1507 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
1358 | struct unicast_packet *unicast_packet; | 1508 | struct unicast_packet *unicast_packet; |
1359 | int hdr_size = sizeof(*unicast_packet); | 1509 | int hdr_size = sizeof(*unicast_packet); |
1360 | 1510 | ||
1361 | if (check_unicast_packet(skb, hdr_size) < 0) | 1511 | if (check_unicast_packet(skb, hdr_size) < 0) |
1362 | return NET_RX_DROP; | 1512 | return NET_RX_DROP; |
1363 | 1513 | ||
1514 | if (!check_unicast_ttvn(bat_priv, skb)) | ||
1515 | return NET_RX_DROP; | ||
1516 | |||
1364 | unicast_packet = (struct unicast_packet *)skb->data; | 1517 | unicast_packet = (struct unicast_packet *)skb->data; |
1365 | 1518 | ||
1366 | /* packet for me */ | 1519 | /* packet for me */ |
@@ -1383,6 +1536,9 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1383 | if (check_unicast_packet(skb, hdr_size) < 0) | 1536 | if (check_unicast_packet(skb, hdr_size) < 0) |
1384 | return NET_RX_DROP; | 1537 | return NET_RX_DROP; |
1385 | 1538 | ||
1539 | if (!check_unicast_ttvn(bat_priv, skb)) | ||
1540 | return NET_RX_DROP; | ||
1541 | |||
1386 | unicast_packet = (struct unicast_frag_packet *)skb->data; | 1542 | unicast_packet = (struct unicast_frag_packet *)skb->data; |
1387 | 1543 | ||
1388 | /* packet for me */ | 1544 | /* packet for me */ |