aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c252
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
67static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, 67static 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) {
100request_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
85static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, 114static 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
135void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, 160void 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
153out: 173out:
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
471update_tt: 484update_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
475update_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
595void receive_bat_packet(const struct ethhdr *ethhdr, 614void 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
825out_neigh: 846out_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
1191int 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
1250out:
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
1441static 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
1356int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) 1505int 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 */