aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-11 16:28:55 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-11 16:28:55 -0400
commit29b67c39dc6e7ec4fdf78c620675de761971cd28 (patch)
treeecc7076fc3dce7d2c5f917bca2b0c8c60cf7d520 /net
parent58308451e91974267e1f4a618346055342019e02 (diff)
parent18c68d5960c8dfeb2db113f4b871bab259cfd565 (diff)
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes: - update emails for A. Quartulli and M. Lindner in MAINTAINERS - switch to the next on-the-wire protocol version - introduce the T(ype) V(ersion) L(ength) V(alue) framework - adjust the existing components to make them use the new TVLV code - make the TT component use CRC32 instead of CRC16 - totally remove the VIS functionality (has been moved to userspace) - reorder packet types and flags - add static checks on packet format - remove __packed from batadv_ogm_packet
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/Makefile1
-rw-r--r--net/batman-adv/bat_iv_ogm.c111
-rw-r--r--net/batman-adv/debugfs.c9
-rw-r--r--net/batman-adv/distributed-arp-table.c64
-rw-r--r--net/batman-adv/distributed-arp-table.h5
-rw-r--r--net/batman-adv/gateway_client.c187
-rw-r--r--net/batman-adv/gateway_client.h2
-rw-r--r--net/batman-adv/gateway_common.c230
-rw-r--r--net/batman-adv/gateway_common.h14
-rw-r--r--net/batman-adv/hard-interface.c9
-rw-r--r--net/batman-adv/main.c623
-rw-r--r--net/batman-adv/main.h37
-rw-r--r--net/batman-adv/network-coding.c63
-rw-r--r--net/batman-adv/network-coding.h5
-rw-r--r--net/batman-adv/originator.c4
-rw-r--r--net/batman-adv/packet.h248
-rw-r--r--net/batman-adv/routing.c247
-rw-r--r--net/batman-adv/routing.h6
-rw-r--r--net/batman-adv/send.c1
-rw-r--r--net/batman-adv/soft-interface.c4
-rw-r--r--net/batman-adv/sysfs.c96
-rw-r--r--net/batman-adv/translation-table.c905
-rw-r--r--net/batman-adv/translation-table.h13
-rw-r--r--net/batman-adv/types.h178
-rw-r--r--net/batman-adv/vis.c938
-rw-r--r--net/batman-adv/vis.h36
26 files changed, 1964 insertions, 2072 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 489bb36f1b94..8ddbfe66d637 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -38,4 +38,3 @@ batman-adv-y += soft-interface.o
38batman-adv-y += sysfs.o 38batman-adv-y += sysfs.o
39batman-adv-y += translation-table.o 39batman-adv-y += translation-table.o
40batman-adv-y += unicast.o 40batman-adv-y += unicast.o
41batman-adv-y += vis.o
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 0a8a80cd4bf1..97b42d3c4bef 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -135,9 +135,8 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
135 batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; 135 batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
136 batadv_ogm_packet->header.ttl = 2; 136 batadv_ogm_packet->header.ttl = 2;
137 batadv_ogm_packet->flags = BATADV_NO_FLAGS; 137 batadv_ogm_packet->flags = BATADV_NO_FLAGS;
138 batadv_ogm_packet->reserved = 0;
138 batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; 139 batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
139 batadv_ogm_packet->tt_num_changes = 0;
140 batadv_ogm_packet->ttvn = 0;
141 140
142 res = 0; 141 res = 0;
143 142
@@ -207,12 +206,12 @@ static uint8_t batadv_hop_penalty(uint8_t tq,
207 206
208/* is there another aggregated packet here? */ 207/* is there another aggregated packet here? */
209static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, 208static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
210 int tt_num_changes) 209 __be16 tvlv_len)
211{ 210{
212 int next_buff_pos = 0; 211 int next_buff_pos = 0;
213 212
214 next_buff_pos += buff_pos + BATADV_OGM_HLEN; 213 next_buff_pos += buff_pos + BATADV_OGM_HLEN;
215 next_buff_pos += batadv_tt_len(tt_num_changes); 214 next_buff_pos += ntohs(tvlv_len);
216 215
217 return (next_buff_pos <= packet_len) && 216 return (next_buff_pos <= packet_len) &&
218 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); 217 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -240,7 +239,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
240 239
241 /* adjust all flags and log packets */ 240 /* adjust all flags and log packets */
242 while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, 241 while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
243 batadv_ogm_packet->tt_num_changes)) { 242 batadv_ogm_packet->tvlv_len)) {
244 /* we might have aggregated direct link packets with an 243 /* we might have aggregated direct link packets with an
245 * ordinary base packet 244 * ordinary base packet
246 */ 245 */
@@ -256,18 +255,18 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
256 fwd_str = "Sending own"; 255 fwd_str = "Sending own";
257 256
258 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 257 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
259 "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", 258 "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s) on interface %s [%pM]\n",
260 fwd_str, (packet_num > 0 ? "aggregated " : ""), 259 fwd_str, (packet_num > 0 ? "aggregated " : ""),
261 batadv_ogm_packet->orig, 260 batadv_ogm_packet->orig,
262 ntohl(batadv_ogm_packet->seqno), 261 ntohl(batadv_ogm_packet->seqno),
263 batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl, 262 batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
264 (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 263 (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
265 "on" : "off"), 264 "on" : "off"),
266 batadv_ogm_packet->ttvn, hard_iface->net_dev->name, 265 hard_iface->net_dev->name,
267 hard_iface->net_dev->dev_addr); 266 hard_iface->net_dev->dev_addr);
268 267
269 buff_pos += BATADV_OGM_HLEN; 268 buff_pos += BATADV_OGM_HLEN;
270 buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 269 buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
271 packet_num++; 270 packet_num++;
272 packet_pos = forw_packet->skb->data + buff_pos; 271 packet_pos = forw_packet->skb->data + buff_pos;
273 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; 272 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
@@ -601,7 +600,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
601 struct batadv_hard_iface *if_incoming) 600 struct batadv_hard_iface *if_incoming)
602{ 601{
603 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 602 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
604 uint8_t tt_num_changes; 603 uint16_t tvlv_len;
605 604
606 if (batadv_ogm_packet->header.ttl <= 1) { 605 if (batadv_ogm_packet->header.ttl <= 1) {
607 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n"); 606 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
@@ -621,7 +620,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
621 return; 620 return;
622 } 621 }
623 622
624 tt_num_changes = batadv_ogm_packet->tt_num_changes; 623 tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
625 624
626 batadv_ogm_packet->header.ttl--; 625 batadv_ogm_packet->header.ttl--;
627 memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); 626 memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
@@ -642,7 +641,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
642 batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; 641 batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
643 642
644 batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, 643 batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet,
645 BATADV_OGM_HLEN + batadv_tt_len(tt_num_changes), 644 BATADV_OGM_HLEN + tvlv_len,
646 if_incoming, 0, batadv_iv_ogm_fwd_send_time()); 645 if_incoming, 0, batadv_iv_ogm_fwd_send_time());
647} 646}
648 647
@@ -688,43 +687,29 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
688 struct batadv_ogm_packet *batadv_ogm_packet; 687 struct batadv_ogm_packet *batadv_ogm_packet;
689 struct batadv_hard_iface *primary_if; 688 struct batadv_hard_iface *primary_if;
690 int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; 689 int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
691 int vis_server, tt_num_changes = 0;
692 uint32_t seqno; 690 uint32_t seqno;
693 uint8_t bandwidth; 691 uint16_t tvlv_len = 0;
694 692
695 vis_server = atomic_read(&bat_priv->vis_mode);
696 primary_if = batadv_primary_if_get_selected(bat_priv); 693 primary_if = batadv_primary_if_get_selected(bat_priv);
697 694
698 if (hard_iface == primary_if) 695 if (hard_iface == primary_if) {
699 tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff, 696 /* tt changes have to be committed before the tvlv data is
700 ogm_buff_len, 697 * appended as it may alter the tt tvlv container
701 BATADV_OGM_HLEN); 698 */
699 batadv_tt_local_commit_changes(bat_priv);
700 tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
701 ogm_buff_len,
702 BATADV_OGM_HLEN);
703 }
702 704
703 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); 705 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
706 batadv_ogm_packet->tvlv_len = htons(tvlv_len);
704 707
705 /* change sequence number to network order */ 708 /* change sequence number to network order */
706 seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno); 709 seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
707 batadv_ogm_packet->seqno = htonl(seqno); 710 batadv_ogm_packet->seqno = htonl(seqno);
708 atomic_inc(&hard_iface->bat_iv.ogm_seqno); 711 atomic_inc(&hard_iface->bat_iv.ogm_seqno);
709 712
710 batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
711 batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
712 if (tt_num_changes >= 0)
713 batadv_ogm_packet->tt_num_changes = tt_num_changes;
714
715 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC)
716 batadv_ogm_packet->flags |= BATADV_VIS_SERVER;
717 else
718 batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
719
720 if (hard_iface == primary_if &&
721 atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) {
722 bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
723 batadv_ogm_packet->gw_flags = bandwidth;
724 } else {
725 batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
726 }
727
728 batadv_iv_ogm_slide_own_bcast_window(hard_iface); 713 batadv_iv_ogm_slide_own_bcast_window(hard_iface);
729 batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, 714 batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
730 hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, 715 hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
@@ -798,7 +783,6 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
798 783
799 rcu_read_unlock(); 784 rcu_read_unlock();
800 785
801 orig_node->flags = batadv_ogm_packet->flags;
802 neigh_node->last_seen = jiffies; 786 neigh_node->last_seen = jiffies;
803 787
804 spin_lock_bh(&neigh_node->lq_update_lock); 788 spin_lock_bh(&neigh_node->lq_update_lock);
@@ -820,11 +804,11 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
820 */ 804 */
821 router = batadv_orig_node_get_router(orig_node); 805 router = batadv_orig_node_get_router(orig_node);
822 if (router == neigh_node) 806 if (router == neigh_node)
823 goto update_tt; 807 goto out;
824 808
825 /* if this neighbor does not offer a better TQ we won't consider it */ 809 /* if this neighbor does not offer a better TQ we won't consider it */
826 if (router && (router->tq_avg > neigh_node->tq_avg)) 810 if (router && (router->tq_avg > neigh_node->tq_avg))
827 goto update_tt; 811 goto out;
828 812
829 /* if the TQ is the same and the link not more symmetric we 813 /* if the TQ is the same and the link not more symmetric we
830 * won't consider it either 814 * won't consider it either
@@ -843,35 +827,10 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
843 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); 827 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
844 828
845 if (sum_orig >= sum_neigh) 829 if (sum_orig >= sum_neigh)
846 goto update_tt; 830 goto out;
847 } 831 }
848 832
849 batadv_update_route(bat_priv, orig_node, neigh_node); 833 batadv_update_route(bat_priv, orig_node, neigh_node);
850
851update_tt:
852 /* I have to check for transtable changes only if the OGM has been
853 * sent through a primary interface
854 */
855 if (((batadv_ogm_packet->orig != ethhdr->h_source) &&
856 (batadv_ogm_packet->header.ttl > 2)) ||
857 (batadv_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP))
858 batadv_tt_update_orig(bat_priv, orig_node, tt_buff,
859 batadv_ogm_packet->tt_num_changes,
860 batadv_ogm_packet->ttvn,
861 ntohs(batadv_ogm_packet->tt_crc));
862
863 if (orig_node->gw_flags != batadv_ogm_packet->gw_flags)
864 batadv_gw_node_update(bat_priv, orig_node,
865 batadv_ogm_packet->gw_flags);
866
867 orig_node->gw_flags = batadv_ogm_packet->gw_flags;
868
869 /* restart gateway selection if fast or late switching was enabled */
870 if ((orig_node->gw_flags) &&
871 (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
872 (atomic_read(&bat_priv->gw_sel_class) > 2))
873 batadv_gw_check_election(bat_priv, orig_node);
874
875 goto out; 834 goto out;
876 835
877unlock: 836unlock:
@@ -1122,13 +1081,11 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1122 is_single_hop_neigh = true; 1081 is_single_hop_neigh = true;
1123 1082
1124 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1083 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1125 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %#.4x, changes %u, tq %d, TTL %d, V %d, IDF %d)\n", 1084 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
1126 ethhdr->h_source, if_incoming->net_dev->name, 1085 ethhdr->h_source, if_incoming->net_dev->name,
1127 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig, 1086 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
1128 batadv_ogm_packet->prev_sender, 1087 batadv_ogm_packet->prev_sender,
1129 ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->ttvn, 1088 ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
1130 ntohs(batadv_ogm_packet->tt_crc),
1131 batadv_ogm_packet->tt_num_changes, batadv_ogm_packet->tq,
1132 batadv_ogm_packet->header.ttl, 1089 batadv_ogm_packet->header.ttl,
1133 batadv_ogm_packet->header.version, has_directlink_flag); 1090 batadv_ogm_packet->header.version, has_directlink_flag);
1134 1091
@@ -1254,6 +1211,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1254 goto out; 1211 goto out;
1255 } 1212 }
1256 1213
1214 batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node);
1215
1257 /* if sender is a direct neighbor the sender mac equals 1216 /* if sender is a direct neighbor the sender mac equals
1258 * originator mac 1217 * originator mac
1259 */ 1218 */
@@ -1350,9 +1309,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1350 struct batadv_ogm_packet *batadv_ogm_packet; 1309 struct batadv_ogm_packet *batadv_ogm_packet;
1351 struct ethhdr *ethhdr; 1310 struct ethhdr *ethhdr;
1352 int buff_pos = 0, packet_len; 1311 int buff_pos = 0, packet_len;
1353 unsigned char *tt_buff, *packet_buff; 1312 unsigned char *tvlv_buff, *packet_buff;
1354 bool ret;
1355 uint8_t *packet_pos; 1313 uint8_t *packet_pos;
1314 bool ret;
1356 1315
1357 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); 1316 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
1358 if (!ret) 1317 if (!ret)
@@ -1375,14 +1334,14 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1375 1334
1376 /* unpack the aggregated packets and process them one by one */ 1335 /* unpack the aggregated packets and process them one by one */
1377 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, 1336 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
1378 batadv_ogm_packet->tt_num_changes)) { 1337 batadv_ogm_packet->tvlv_len)) {
1379 tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; 1338 tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
1380 1339
1381 batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, 1340 batadv_iv_ogm_process(ethhdr, batadv_ogm_packet,
1382 if_incoming); 1341 tvlv_buff, if_incoming);
1383 1342
1384 buff_pos += BATADV_OGM_HLEN; 1343 buff_pos += BATADV_OGM_HLEN;
1385 buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 1344 buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
1386 1345
1387 packet_pos = packet_buff + buff_pos; 1346 packet_pos = packet_buff + buff_pos;
1388 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; 1347 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index f186a55b23c3..049a7a2ac5b6 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -28,7 +28,6 @@
28#include "gateway_common.h" 28#include "gateway_common.h"
29#include "gateway_client.h" 29#include "gateway_client.h"
30#include "soft-interface.h" 30#include "soft-interface.h"
31#include "vis.h"
32#include "icmp_socket.h" 31#include "icmp_socket.h"
33#include "bridge_loop_avoidance.h" 32#include "bridge_loop_avoidance.h"
34#include "distributed-arp-table.h" 33#include "distributed-arp-table.h"
@@ -300,12 +299,6 @@ static int batadv_transtable_local_open(struct inode *inode, struct file *file)
300 return single_open(file, batadv_tt_local_seq_print_text, net_dev); 299 return single_open(file, batadv_tt_local_seq_print_text, net_dev);
301} 300}
302 301
303static int batadv_vis_data_open(struct inode *inode, struct file *file)
304{
305 struct net_device *net_dev = (struct net_device *)inode->i_private;
306 return single_open(file, batadv_vis_seq_print_text, net_dev);
307}
308
309struct batadv_debuginfo { 302struct batadv_debuginfo {
310 struct attribute attr; 303 struct attribute attr;
311 const struct file_operations fops; 304 const struct file_operations fops;
@@ -356,7 +349,6 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
356#endif 349#endif
357static BATADV_DEBUGINFO(transtable_local, S_IRUGO, 350static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
358 batadv_transtable_local_open); 351 batadv_transtable_local_open);
359static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
360#ifdef CONFIG_BATMAN_ADV_NC 352#ifdef CONFIG_BATMAN_ADV_NC
361static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); 353static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
362#endif 354#endif
@@ -373,7 +365,6 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
373 &batadv_debuginfo_dat_cache, 365 &batadv_debuginfo_dat_cache,
374#endif 366#endif
375 &batadv_debuginfo_transtable_local, 367 &batadv_debuginfo_transtable_local,
376 &batadv_debuginfo_vis_data,
377#ifdef CONFIG_BATMAN_ADV_NC 368#ifdef CONFIG_BATMAN_ADV_NC
378 &batadv_debuginfo_nc_nodes, 369 &batadv_debuginfo_nc_nodes,
379#endif 370#endif
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 06345d401588..f07ec320dc01 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -419,6 +419,10 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
419 bool ret = false; 419 bool ret = false;
420 int j; 420 int j;
421 421
422 /* check if orig node candidate is running DAT */
423 if (!(candidate->capabilities & BATADV_ORIG_CAPA_HAS_DAT))
424 goto out;
425
422 /* Check if this node has already been selected... */ 426 /* Check if this node has already been selected... */
423 for (j = 0; j < select; j++) 427 for (j = 0; j < select; j++)
424 if (res[j].orig_node == candidate) 428 if (res[j].orig_node == candidate)
@@ -626,6 +630,59 @@ out:
626} 630}
627 631
628/** 632/**
633 * batadv_dat_tvlv_container_update - update the dat tvlv container after dat
634 * setting change
635 * @bat_priv: the bat priv with all the soft interface information
636 */
637static void batadv_dat_tvlv_container_update(struct batadv_priv *bat_priv)
638{
639 char dat_mode;
640
641 dat_mode = atomic_read(&bat_priv->distributed_arp_table);
642
643 switch (dat_mode) {
644 case 0:
645 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1);
646 break;
647 case 1:
648 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_DAT, 1,
649 NULL, 0);
650 break;
651 }
652}
653
654/**
655 * batadv_dat_status_update - update the dat tvlv container after dat
656 * setting change
657 * @net_dev: the soft interface net device
658 */
659void batadv_dat_status_update(struct net_device *net_dev)
660{
661 struct batadv_priv *bat_priv = netdev_priv(net_dev);
662 batadv_dat_tvlv_container_update(bat_priv);
663}
664
665/**
666 * batadv_gw_tvlv_ogm_handler_v1 - process incoming dat tvlv container
667 * @bat_priv: the bat priv with all the soft interface information
668 * @orig: the orig_node of the ogm
669 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
670 * @tvlv_value: tvlv buffer containing the gateway data
671 * @tvlv_value_len: tvlv buffer length
672 */
673static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
674 struct batadv_orig_node *orig,
675 uint8_t flags,
676 void *tvlv_value,
677 uint16_t tvlv_value_len)
678{
679 if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
680 orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT;
681 else
682 orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT;
683}
684
685/**
629 * batadv_dat_hash_free - free the local DAT hash table 686 * batadv_dat_hash_free - free the local DAT hash table
630 * @bat_priv: the bat priv with all the soft interface information 687 * @bat_priv: the bat priv with all the soft interface information
631 */ 688 */
@@ -657,6 +714,10 @@ int batadv_dat_init(struct batadv_priv *bat_priv)
657 714
658 batadv_dat_start_timer(bat_priv); 715 batadv_dat_start_timer(bat_priv);
659 716
717 batadv_tvlv_handler_register(bat_priv, batadv_dat_tvlv_ogm_handler_v1,
718 NULL, BATADV_TVLV_DAT, 1,
719 BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
720 batadv_dat_tvlv_container_update(bat_priv);
660 return 0; 721 return 0;
661} 722}
662 723
@@ -666,6 +727,9 @@ int batadv_dat_init(struct batadv_priv *bat_priv)
666 */ 727 */
667void batadv_dat_free(struct batadv_priv *bat_priv) 728void batadv_dat_free(struct batadv_priv *bat_priv)
668{ 729{
730 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1);
731 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_DAT, 1);
732
669 cancel_delayed_work_sync(&bat_priv->dat.work); 733 cancel_delayed_work_sync(&bat_priv->dat.work);
670 734
671 batadv_dat_hash_free(bat_priv); 735 batadv_dat_hash_free(bat_priv);
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
index 125c8c6fcfad..60d853beb8d8 100644
--- a/net/batman-adv/distributed-arp-table.h
+++ b/net/batman-adv/distributed-arp-table.h
@@ -29,6 +29,7 @@
29 29
30#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) 30#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
31 31
32void batadv_dat_status_update(struct net_device *net_dev);
32bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, 33bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
33 struct sk_buff *skb); 34 struct sk_buff *skb);
34bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, 35bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
@@ -98,6 +99,10 @@ static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
98 99
99#else 100#else
100 101
102static inline void batadv_dat_status_update(struct net_device *net_dev)
103{
104}
105
101static inline bool 106static inline bool
102batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, 107batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
103 struct sk_buff *skb) 108 struct sk_buff *skb)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 1ce4b8763ef2..1bce63aa5f5f 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -118,7 +118,6 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
118 uint32_t max_gw_factor = 0, tmp_gw_factor = 0; 118 uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
119 uint32_t gw_divisor; 119 uint32_t gw_divisor;
120 uint8_t max_tq = 0; 120 uint8_t max_tq = 0;
121 int down, up;
122 uint8_t tq_avg; 121 uint8_t tq_avg;
123 struct batadv_orig_node *orig_node; 122 struct batadv_orig_node *orig_node;
124 123
@@ -142,10 +141,9 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
142 141
143 switch (atomic_read(&bat_priv->gw_sel_class)) { 142 switch (atomic_read(&bat_priv->gw_sel_class)) {
144 case 1: /* fast connection */ 143 case 1: /* fast connection */
145 batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, 144 tmp_gw_factor = tq_avg * tq_avg;
146 &down, &up); 145 tmp_gw_factor *= gw_node->bandwidth_down;
147 146 tmp_gw_factor *= 100 * 100;
148 tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100;
149 tmp_gw_factor /= gw_divisor; 147 tmp_gw_factor /= gw_divisor;
150 148
151 if ((tmp_gw_factor > max_gw_factor) || 149 if ((tmp_gw_factor > max_gw_factor) ||
@@ -258,16 +256,22 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
258 NULL); 256 NULL);
259 } else if ((!curr_gw) && (next_gw)) { 257 } else if ((!curr_gw) && (next_gw)) {
260 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 258 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
261 "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n", 259 "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
262 next_gw->orig_node->orig, 260 next_gw->orig_node->orig,
263 next_gw->orig_node->gw_flags, router->tq_avg); 261 next_gw->bandwidth_down / 10,
262 next_gw->bandwidth_down % 10,
263 next_gw->bandwidth_up / 10,
264 next_gw->bandwidth_up % 10, router->tq_avg);
264 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, 265 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD,
265 gw_addr); 266 gw_addr);
266 } else { 267 } else {
267 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 268 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
268 "Changing route to gateway %pM (gw_flags: %i, tq: %i)\n", 269 "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
269 next_gw->orig_node->orig, 270 next_gw->orig_node->orig,
270 next_gw->orig_node->gw_flags, router->tq_avg); 271 next_gw->bandwidth_down / 10,
272 next_gw->bandwidth_down % 10,
273 next_gw->bandwidth_up / 10,
274 next_gw->bandwidth_up % 10, router->tq_avg);
271 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, 275 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE,
272 gw_addr); 276 gw_addr);
273 } 277 }
@@ -337,12 +341,20 @@ out:
337 return; 341 return;
338} 342}
339 343
344/**
345 * batadv_gw_node_add - add gateway node to list of available gateways
346 * @bat_priv: the bat priv with all the soft interface information
347 * @orig_node: originator announcing gateway capabilities
348 * @gateway: announced bandwidth information
349 */
340static void batadv_gw_node_add(struct batadv_priv *bat_priv, 350static void batadv_gw_node_add(struct batadv_priv *bat_priv,
341 struct batadv_orig_node *orig_node, 351 struct batadv_orig_node *orig_node,
342 uint8_t new_gwflags) 352 struct batadv_tvlv_gateway_data *gateway)
343{ 353{
344 struct batadv_gw_node *gw_node; 354 struct batadv_gw_node *gw_node;
345 int down, up; 355
356 if (gateway->bandwidth_down == 0)
357 return;
346 358
347 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); 359 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
348 if (!gw_node) 360 if (!gw_node)
@@ -356,73 +368,116 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
356 hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); 368 hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
357 spin_unlock_bh(&bat_priv->gw.list_lock); 369 spin_unlock_bh(&bat_priv->gw.list_lock);
358 370
359 batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up);
360 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 371 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
361 "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", 372 "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
362 orig_node->orig, new_gwflags, 373 orig_node->orig,
363 (down > 2048 ? down / 1024 : down), 374 ntohl(gateway->bandwidth_down) / 10,
364 (down > 2048 ? "MBit" : "KBit"), 375 ntohl(gateway->bandwidth_down) % 10,
365 (up > 2048 ? up / 1024 : up), 376 ntohl(gateway->bandwidth_up) / 10,
366 (up > 2048 ? "MBit" : "KBit")); 377 ntohl(gateway->bandwidth_up) % 10);
367} 378}
368 379
369void batadv_gw_node_update(struct batadv_priv *bat_priv, 380/**
370 struct batadv_orig_node *orig_node, 381 * batadv_gw_node_get - retrieve gateway node from list of available gateways
371 uint8_t new_gwflags) 382 * @bat_priv: the bat priv with all the soft interface information
383 * @orig_node: originator announcing gateway capabilities
384 *
385 * Returns gateway node if found or NULL otherwise.
386 */
387static struct batadv_gw_node *
388batadv_gw_node_get(struct batadv_priv *bat_priv,
389 struct batadv_orig_node *orig_node)
372{ 390{
373 struct batadv_gw_node *gw_node, *curr_gw; 391 struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
374
375 /* Note: We don't need a NULL check here, since curr_gw never gets
376 * dereferenced. If curr_gw is NULL we also should not exit as we may
377 * have this gateway in our list (duplication check!) even though we
378 * have no currently selected gateway.
379 */
380 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
381 392
382 rcu_read_lock(); 393 rcu_read_lock();
383 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { 394 hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) {
384 if (gw_node->orig_node != orig_node) 395 if (gw_node_tmp->orig_node != orig_node)
385 continue; 396 continue;
386 397
387 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 398 if (gw_node_tmp->deleted)
388 "Gateway class of originator %pM changed from %i to %i\n", 399 continue;
389 orig_node->orig, gw_node->orig_node->gw_flags,
390 new_gwflags);
391 400
392 gw_node->deleted = 0; 401 if (!atomic_inc_not_zero(&gw_node_tmp->refcount))
402 continue;
393 403
394 if (new_gwflags == BATADV_NO_FLAGS) { 404 gw_node = gw_node_tmp;
395 gw_node->deleted = jiffies; 405 break;
396 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 406 }
397 "Gateway %pM removed from gateway list\n", 407 rcu_read_unlock();
398 orig_node->orig);
399 408
400 if (gw_node == curr_gw) 409 return gw_node;
401 goto deselect; 410}
402 }
403 411
404 goto unlock; 412/**
413 * batadv_gw_node_update - update list of available gateways with changed
414 * bandwidth information
415 * @bat_priv: the bat priv with all the soft interface information
416 * @orig_node: originator announcing gateway capabilities
417 * @gateway: announced bandwidth information
418 */
419void batadv_gw_node_update(struct batadv_priv *bat_priv,
420 struct batadv_orig_node *orig_node,
421 struct batadv_tvlv_gateway_data *gateway)
422{
423 struct batadv_gw_node *gw_node, *curr_gw = NULL;
424
425 gw_node = batadv_gw_node_get(bat_priv, orig_node);
426 if (!gw_node) {
427 batadv_gw_node_add(bat_priv, orig_node, gateway);
428 goto out;
405 } 429 }
406 430
407 if (new_gwflags == BATADV_NO_FLAGS) 431 if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) &&
408 goto unlock; 432 (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up)))
433 goto out;
409 434
410 batadv_gw_node_add(bat_priv, orig_node, new_gwflags); 435 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
411 goto unlock; 436 "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n",
437 orig_node->orig,
438 gw_node->bandwidth_down / 10,
439 gw_node->bandwidth_down % 10,
440 gw_node->bandwidth_up / 10,
441 gw_node->bandwidth_up % 10,
442 ntohl(gateway->bandwidth_down) / 10,
443 ntohl(gateway->bandwidth_down) % 10,
444 ntohl(gateway->bandwidth_up) / 10,
445 ntohl(gateway->bandwidth_up) % 10);
446
447 gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
448 gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
449
450 gw_node->deleted = 0;
451 if (ntohl(gateway->bandwidth_down) == 0) {
452 gw_node->deleted = jiffies;
453 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
454 "Gateway %pM removed from gateway list\n",
455 orig_node->orig);
412 456
413deselect: 457 /* Note: We don't need a NULL check here, since curr_gw never
414 batadv_gw_deselect(bat_priv); 458 * gets dereferenced.
415unlock: 459 */
416 rcu_read_unlock(); 460 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
461 if (gw_node == curr_gw)
462 batadv_gw_deselect(bat_priv);
463 }
417 464
465out:
418 if (curr_gw) 466 if (curr_gw)
419 batadv_gw_node_free_ref(curr_gw); 467 batadv_gw_node_free_ref(curr_gw);
468 if (gw_node)
469 batadv_gw_node_free_ref(gw_node);
420} 470}
421 471
422void batadv_gw_node_delete(struct batadv_priv *bat_priv, 472void batadv_gw_node_delete(struct batadv_priv *bat_priv,
423 struct batadv_orig_node *orig_node) 473 struct batadv_orig_node *orig_node)
424{ 474{
425 batadv_gw_node_update(bat_priv, orig_node, 0); 475 struct batadv_tvlv_gateway_data gateway;
476
477 gateway.bandwidth_down = 0;
478 gateway.bandwidth_up = 0;
479
480 batadv_gw_node_update(bat_priv, orig_node, &gateway);
426} 481}
427 482
428void batadv_gw_node_purge(struct batadv_priv *bat_priv) 483void batadv_gw_node_purge(struct batadv_priv *bat_priv)
@@ -467,9 +522,7 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
467{ 522{
468 struct batadv_gw_node *curr_gw; 523 struct batadv_gw_node *curr_gw;
469 struct batadv_neigh_node *router; 524 struct batadv_neigh_node *router;
470 int down, up, ret = -1; 525 int ret = -1;
471
472 batadv_gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
473 526
474 router = batadv_orig_node_get_router(gw_node->orig_node); 527 router = batadv_orig_node_get_router(gw_node->orig_node);
475 if (!router) 528 if (!router)
@@ -477,16 +530,15 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
477 530
478 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 531 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
479 532
480 ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", 533 ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n",
481 (curr_gw == gw_node ? "=>" : " "), 534 (curr_gw == gw_node ? "=>" : " "),
482 gw_node->orig_node->orig, 535 gw_node->orig_node->orig,
483 router->tq_avg, router->addr, 536 router->tq_avg, router->addr,
484 router->if_incoming->net_dev->name, 537 router->if_incoming->net_dev->name,
485 gw_node->orig_node->gw_flags, 538 gw_node->bandwidth_down / 10,
486 (down > 2048 ? down / 1024 : down), 539 gw_node->bandwidth_down % 10,
487 (down > 2048 ? "MBit" : "KBit"), 540 gw_node->bandwidth_up / 10,
488 (up > 2048 ? up / 1024 : up), 541 gw_node->bandwidth_up % 10);
489 (up > 2048 ? "MBit" : "KBit"));
490 542
491 batadv_neigh_node_free_ref(router); 543 batadv_neigh_node_free_ref(router);
492 if (curr_gw) 544 if (curr_gw)
@@ -508,7 +560,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
508 goto out; 560 goto out;
509 561
510 seq_printf(seq, 562 seq_printf(seq,
511 " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", 563 " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
512 "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", 564 "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF",
513 BATADV_SOURCE_VERSION, primary_if->net_dev->name, 565 BATADV_SOURCE_VERSION, primary_if->net_dev->name,
514 primary_if->net_dev->dev_addr, net_dev->name); 566 primary_if->net_dev->dev_addr, net_dev->name);
@@ -675,7 +727,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
675{ 727{
676 struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; 728 struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
677 struct batadv_orig_node *orig_dst_node = NULL; 729 struct batadv_orig_node *orig_dst_node = NULL;
678 struct batadv_gw_node *curr_gw = NULL; 730 struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL;
679 struct ethhdr *ethhdr; 731 struct ethhdr *ethhdr;
680 bool ret, out_of_range = false; 732 bool ret, out_of_range = false;
681 unsigned int header_len = 0; 733 unsigned int header_len = 0;
@@ -691,7 +743,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
691 if (!orig_dst_node) 743 if (!orig_dst_node)
692 goto out; 744 goto out;
693 745
694 if (!orig_dst_node->gw_flags) 746 gw_node = batadv_gw_node_get(bat_priv, orig_dst_node);
747 if (!gw_node->bandwidth_down == 0)
695 goto out; 748 goto out;
696 749
697 ret = batadv_is_type_dhcprequest(skb, header_len); 750 ret = batadv_is_type_dhcprequest(skb, header_len);
@@ -742,6 +795,8 @@ out:
742 batadv_orig_node_free_ref(orig_dst_node); 795 batadv_orig_node_free_ref(orig_dst_node);
743 if (curr_gw) 796 if (curr_gw)
744 batadv_gw_node_free_ref(curr_gw); 797 batadv_gw_node_free_ref(curr_gw);
798 if (gw_node)
799 batadv_gw_node_free_ref(gw_node);
745 if (neigh_old) 800 if (neigh_old)
746 batadv_neigh_node_free_ref(neigh_old); 801 batadv_neigh_node_free_ref(neigh_old);
747 if (neigh_curr) 802 if (neigh_curr)
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index ceef4ebe8bcd..d95c2d23195e 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -29,7 +29,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
29 struct batadv_orig_node *orig_node); 29 struct batadv_orig_node *orig_node);
30void batadv_gw_node_update(struct batadv_priv *bat_priv, 30void batadv_gw_node_update(struct batadv_priv *bat_priv,
31 struct batadv_orig_node *orig_node, 31 struct batadv_orig_node *orig_node,
32 uint8_t new_gwflags); 32 struct batadv_tvlv_gateway_data *gateway);
33void batadv_gw_node_delete(struct batadv_priv *bat_priv, 33void batadv_gw_node_delete(struct batadv_priv *bat_priv,
34 struct batadv_orig_node *orig_node); 34 struct batadv_orig_node *orig_node);
35void batadv_gw_node_purge(struct batadv_priv *bat_priv); 35void batadv_gw_node_purge(struct batadv_priv *bat_priv);
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 84bb2b18d711..b211b0f9cb78 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -21,64 +21,23 @@
21#include "gateway_common.h" 21#include "gateway_common.h"
22#include "gateway_client.h" 22#include "gateway_client.h"
23 23
24/* calculates the gateway class from kbit */ 24/**
25static void batadv_kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class) 25 * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download
26{ 26 * and upload bandwidth information
27 int mdown = 0, tdown, tup, difference; 27 * @net_dev: the soft interface net device
28 uint8_t sbit, part; 28 * @buff: string buffer to parse
29 29 * @down: pointer holding the returned download bandwidth information
30 *gw_srv_class = 0; 30 * @up: pointer holding the returned upload bandwidth information
31 difference = 0x0FFFFFFF; 31 *
32 32 * Returns false on parse error and true otherwise.
33 /* test all downspeeds */ 33 */
34 for (sbit = 0; sbit < 2; sbit++) {
35 for (part = 0; part < 16; part++) {
36 tdown = 32 * (sbit + 2) * (1 << part);
37
38 if (abs(tdown - down) < difference) {
39 *gw_srv_class = (sbit << 7) + (part << 3);
40 difference = abs(tdown - down);
41 mdown = tdown;
42 }
43 }
44 }
45
46 /* test all upspeeds */
47 difference = 0x0FFFFFFF;
48
49 for (part = 0; part < 8; part++) {
50 tup = ((part + 1) * (mdown)) / 8;
51
52 if (abs(tup - up) < difference) {
53 *gw_srv_class = (*gw_srv_class & 0xF8) | part;
54 difference = abs(tup - up);
55 }
56 }
57}
58
59/* returns the up and downspeeds in kbit, calculated from the class */
60void batadv_gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
61{
62 int sbit = (gw_srv_class & 0x80) >> 7;
63 int dpart = (gw_srv_class & 0x78) >> 3;
64 int upart = (gw_srv_class & 0x07);
65
66 if (!gw_srv_class) {
67 *down = 0;
68 *up = 0;
69 return;
70 }
71
72 *down = 32 * (sbit + 2) * (1 << dpart);
73 *up = ((upart + 1) * (*down)) / 8;
74}
75
76static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, 34static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
77 int *up, int *down) 35 uint32_t *down, uint32_t *up)
78{ 36{
79 int ret, multi = 1; 37 enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT;
80 char *slash_ptr, *tmp_ptr; 38 char *slash_ptr, *tmp_ptr;
81 long ldown, lup; 39 long ldown, lup;
40 int ret;
82 41
83 slash_ptr = strchr(buff, '/'); 42 slash_ptr = strchr(buff, '/');
84 if (slash_ptr) 43 if (slash_ptr)
@@ -88,10 +47,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
88 tmp_ptr = buff + strlen(buff) - 4; 47 tmp_ptr = buff + strlen(buff) - 4;
89 48
90 if (strnicmp(tmp_ptr, "mbit", 4) == 0) 49 if (strnicmp(tmp_ptr, "mbit", 4) == 0)
91 multi = 1024; 50 bw_unit_type = BATADV_BW_UNIT_MBIT;
92 51
93 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || 52 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
94 (multi > 1)) 53 (bw_unit_type == BATADV_BW_UNIT_MBIT))
95 *tmp_ptr = '\0'; 54 *tmp_ptr = '\0';
96 } 55 }
97 56
@@ -103,20 +62,28 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
103 return false; 62 return false;
104 } 63 }
105 64
106 *down = ldown * multi; 65 switch (bw_unit_type) {
66 case BATADV_BW_UNIT_MBIT:
67 *down = ldown * 10;
68 break;
69 case BATADV_BW_UNIT_KBIT:
70 default:
71 *down = ldown / 100;
72 break;
73 }
107 74
108 /* we also got some upload info */ 75 /* we also got some upload info */
109 if (slash_ptr) { 76 if (slash_ptr) {
110 multi = 1; 77 bw_unit_type = BATADV_BW_UNIT_KBIT;
111 78
112 if (strlen(slash_ptr + 1) > 4) { 79 if (strlen(slash_ptr + 1) > 4) {
113 tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); 80 tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1);
114 81
115 if (strnicmp(tmp_ptr, "mbit", 4) == 0) 82 if (strnicmp(tmp_ptr, "mbit", 4) == 0)
116 multi = 1024; 83 bw_unit_type = BATADV_BW_UNIT_MBIT;
117 84
118 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || 85 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
119 (multi > 1)) 86 (bw_unit_type == BATADV_BW_UNIT_MBIT))
120 *tmp_ptr = '\0'; 87 *tmp_ptr = '\0';
121 } 88 }
122 89
@@ -128,52 +95,149 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
128 return false; 95 return false;
129 } 96 }
130 97
131 *up = lup * multi; 98 switch (bw_unit_type) {
99 case BATADV_BW_UNIT_MBIT:
100 *up = lup * 10;
101 break;
102 case BATADV_BW_UNIT_KBIT:
103 default:
104 *up = lup / 100;
105 break;
106 }
132 } 107 }
133 108
134 return true; 109 return true;
135} 110}
136 111
112/**
113 * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway
114 * setting change
115 * @bat_priv: the bat priv with all the soft interface information
116 */
117void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
118{
119 struct batadv_tvlv_gateway_data gw;
120 uint32_t down, up;
121 char gw_mode;
122
123 gw_mode = atomic_read(&bat_priv->gw_mode);
124
125 switch (gw_mode) {
126 case BATADV_GW_MODE_OFF:
127 case BATADV_GW_MODE_CLIENT:
128 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
129 break;
130 case BATADV_GW_MODE_SERVER:
131 down = atomic_read(&bat_priv->gw.bandwidth_down);
132 up = atomic_read(&bat_priv->gw.bandwidth_up);
133 gw.bandwidth_down = htonl(down);
134 gw.bandwidth_up = htonl(up);
135 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1,
136 &gw, sizeof(gw));
137 break;
138 }
139}
140
137ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, 141ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
138 size_t count) 142 size_t count)
139{ 143{
140 struct batadv_priv *bat_priv = netdev_priv(net_dev); 144 struct batadv_priv *bat_priv = netdev_priv(net_dev);
141 long gw_bandwidth_tmp = 0; 145 uint32_t down_curr, up_curr, down_new = 0, up_new = 0;
142 int up = 0, down = 0;
143 bool ret; 146 bool ret;
144 147
145 ret = batadv_parse_gw_bandwidth(net_dev, buff, &up, &down); 148 down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down);
149 up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up);
150
151 ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new);
146 if (!ret) 152 if (!ret)
147 goto end; 153 goto end;
148 154
149 if ((!down) || (down < 256)) 155 if (!down_new)
150 down = 2000; 156 down_new = 1;
151
152 if (!up)
153 up = down / 5;
154 157
155 batadv_kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp); 158 if (!up_new)
159 up_new = down_new / 5;
156 160
157 /* the gw bandwidth we guessed above might not match the given 161 if (!up_new)
158 * speeds, hence we need to calculate it back to show the number 162 up_new = 1;
159 * that is going to be propagated
160 */
161 batadv_gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up);
162 163
163 if (atomic_read(&bat_priv->gw_bandwidth) == gw_bandwidth_tmp) 164 if ((down_curr == down_new) && (up_curr == up_new))
164 return count; 165 return count;
165 166
166 batadv_gw_deselect(bat_priv); 167 batadv_gw_deselect(bat_priv);
167 batadv_info(net_dev, 168 batadv_info(net_dev,
168 "Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n", 169 "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n",
169 atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp, 170 down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10,
170 (down > 2048 ? down / 1024 : down), 171 down_new / 10, down_new % 10, up_new / 10, up_new % 10);
171 (down > 2048 ? "MBit" : "KBit"),
172 (up > 2048 ? up / 1024 : up),
173 (up > 2048 ? "MBit" : "KBit"));
174 172
175 atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp); 173 atomic_set(&bat_priv->gw.bandwidth_down, down_new);
174 atomic_set(&bat_priv->gw.bandwidth_up, up_new);
175 batadv_gw_tvlv_container_update(bat_priv);
176 176
177end: 177end:
178 return count; 178 return count;
179} 179}
180
181/**
182 * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container
183 * @bat_priv: the bat priv with all the soft interface information
184 * @orig: the orig_node of the ogm
185 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
186 * @tvlv_value: tvlv buffer containing the gateway data
187 * @tvlv_value_len: tvlv buffer length
188 */
189static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
190 struct batadv_orig_node *orig,
191 uint8_t flags,
192 void *tvlv_value,
193 uint16_t tvlv_value_len)
194{
195 struct batadv_tvlv_gateway_data gateway, *gateway_ptr;
196
197 /* only fetch the tvlv value if the handler wasn't called via the
198 * CIFNOTFND flag and if there is data to fetch
199 */
200 if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) ||
201 (tvlv_value_len < sizeof(gateway))) {
202 gateway.bandwidth_down = 0;
203 gateway.bandwidth_up = 0;
204 } else {
205 gateway_ptr = tvlv_value;
206 gateway.bandwidth_down = gateway_ptr->bandwidth_down;
207 gateway.bandwidth_up = gateway_ptr->bandwidth_up;
208 if ((gateway.bandwidth_down == 0) ||
209 (gateway.bandwidth_up == 0)) {
210 gateway.bandwidth_down = 0;
211 gateway.bandwidth_up = 0;
212 }
213 }
214
215 batadv_gw_node_update(bat_priv, orig, &gateway);
216
217 /* restart gateway selection if fast or late switching was enabled */
218 if ((gateway.bandwidth_down != 0) &&
219 (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
220 (atomic_read(&bat_priv->gw_sel_class) > 2))
221 batadv_gw_check_election(bat_priv, orig);
222}
223
224/**
225 * batadv_gw_init - initialise the gateway handling internals
226 * @bat_priv: the bat priv with all the soft interface information
227 */
228void batadv_gw_init(struct batadv_priv *bat_priv)
229{
230 batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
231 NULL, BATADV_TVLV_GW, 1,
232 BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
233}
234
235/**
236 * batadv_gw_free - free the gateway handling internals
237 * @bat_priv: the bat priv with all the soft interface information
238 */
239void batadv_gw_free(struct batadv_priv *bat_priv)
240{
241 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
242 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1);
243}
diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h
index 509b2bf8c2f4..56384a4cd18c 100644
--- a/net/batman-adv/gateway_common.h
+++ b/net/batman-adv/gateway_common.h
@@ -26,12 +26,24 @@ enum batadv_gw_modes {
26 BATADV_GW_MODE_SERVER, 26 BATADV_GW_MODE_SERVER,
27}; 27};
28 28
29/**
30 * enum batadv_bandwidth_units - bandwidth unit types
31 * @BATADV_BW_UNIT_KBIT: unit type kbit
32 * @BATADV_BW_UNIT_MBIT: unit type mbit
33 */
34enum batadv_bandwidth_units {
35 BATADV_BW_UNIT_KBIT,
36 BATADV_BW_UNIT_MBIT,
37};
38
29#define BATADV_GW_MODE_OFF_NAME "off" 39#define BATADV_GW_MODE_OFF_NAME "off"
30#define BATADV_GW_MODE_CLIENT_NAME "client" 40#define BATADV_GW_MODE_CLIENT_NAME "client"
31#define BATADV_GW_MODE_SERVER_NAME "server" 41#define BATADV_GW_MODE_SERVER_NAME "server"
32 42
33void batadv_gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up);
34ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, 43ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
35 size_t count); 44 size_t count);
45void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv);
46void batadv_gw_init(struct batadv_priv *bat_priv);
47void batadv_gw_free(struct batadv_priv *bat_priv);
36 48
37#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ 49#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index c478e6bcf89b..eeb667112d64 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -194,22 +194,13 @@ out:
194static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, 194static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
195 struct batadv_hard_iface *oldif) 195 struct batadv_hard_iface *oldif)
196{ 196{
197 struct batadv_vis_packet *vis_packet;
198 struct batadv_hard_iface *primary_if; 197 struct batadv_hard_iface *primary_if;
199 struct sk_buff *skb;
200 198
201 primary_if = batadv_primary_if_get_selected(bat_priv); 199 primary_if = batadv_primary_if_get_selected(bat_priv);
202 if (!primary_if) 200 if (!primary_if)
203 goto out; 201 goto out;
204 202
205 batadv_dat_init_own_addr(bat_priv, primary_if); 203 batadv_dat_init_own_addr(bat_priv, primary_if);
206
207 skb = bat_priv->vis.my_info->skb_packet;
208 vis_packet = (struct batadv_vis_packet *)skb->data;
209 memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
210 memcpy(vis_packet->sender_orig,
211 primary_if->net_dev->dev_addr, ETH_ALEN);
212
213 batadv_bla_update_orig_address(bat_priv, primary_if, oldif); 204 batadv_bla_update_orig_address(bat_priv, primary_if, oldif);
214out: 205out:
215 if (primary_if) 206 if (primary_if)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 1356af660b5b..8b195e63e70e 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -36,7 +36,8 @@
36#include "gateway_client.h" 36#include "gateway_client.h"
37#include "bridge_loop_avoidance.h" 37#include "bridge_loop_avoidance.h"
38#include "distributed-arp-table.h" 38#include "distributed-arp-table.h"
39#include "vis.h" 39#include "unicast.h"
40#include "gateway_common.h"
40#include "hash.h" 41#include "hash.h"
41#include "bat_algo.h" 42#include "bat_algo.h"
42#include "network-coding.h" 43#include "network-coding.h"
@@ -110,8 +111,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
110 spin_lock_init(&bat_priv->tt.roam_list_lock); 111 spin_lock_init(&bat_priv->tt.roam_list_lock);
111 spin_lock_init(&bat_priv->tt.last_changeset_lock); 112 spin_lock_init(&bat_priv->tt.last_changeset_lock);
112 spin_lock_init(&bat_priv->gw.list_lock); 113 spin_lock_init(&bat_priv->gw.list_lock);
113 spin_lock_init(&bat_priv->vis.hash_lock); 114 spin_lock_init(&bat_priv->tvlv.container_list_lock);
114 spin_lock_init(&bat_priv->vis.list_lock); 115 spin_lock_init(&bat_priv->tvlv.handler_list_lock);
115 116
116 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 117 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
117 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); 118 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
@@ -119,6 +120,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
119 INIT_LIST_HEAD(&bat_priv->tt.changes_list); 120 INIT_LIST_HEAD(&bat_priv->tt.changes_list);
120 INIT_LIST_HEAD(&bat_priv->tt.req_list); 121 INIT_LIST_HEAD(&bat_priv->tt.req_list);
121 INIT_LIST_HEAD(&bat_priv->tt.roam_list); 122 INIT_LIST_HEAD(&bat_priv->tt.roam_list);
123 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
124 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
122 125
123 ret = batadv_originator_init(bat_priv); 126 ret = batadv_originator_init(bat_priv);
124 if (ret < 0) 127 if (ret < 0)
@@ -131,10 +134,6 @@ int batadv_mesh_init(struct net_device *soft_iface)
131 batadv_tt_local_add(soft_iface, soft_iface->dev_addr, 134 batadv_tt_local_add(soft_iface, soft_iface->dev_addr,
132 BATADV_NULL_IFINDEX); 135 BATADV_NULL_IFINDEX);
133 136
134 ret = batadv_vis_init(bat_priv);
135 if (ret < 0)
136 goto err;
137
138 ret = batadv_bla_init(bat_priv); 137 ret = batadv_bla_init(bat_priv);
139 if (ret < 0) 138 if (ret < 0)
140 goto err; 139 goto err;
@@ -147,6 +146,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
147 if (ret < 0) 146 if (ret < 0)
148 goto err; 147 goto err;
149 148
149 batadv_gw_init(bat_priv);
150
150 atomic_set(&bat_priv->gw.reselect, 0); 151 atomic_set(&bat_priv->gw.reselect, 0);
151 atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); 152 atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
152 153
@@ -165,8 +166,6 @@ void batadv_mesh_free(struct net_device *soft_iface)
165 166
166 batadv_purge_outstanding_packets(bat_priv, NULL); 167 batadv_purge_outstanding_packets(bat_priv, NULL);
167 168
168 batadv_vis_quit(bat_priv);
169
170 batadv_gw_node_purge(bat_priv); 169 batadv_gw_node_purge(bat_priv);
171 batadv_nc_mesh_free(bat_priv); 170 batadv_nc_mesh_free(bat_priv);
172 batadv_dat_free(bat_priv); 171 batadv_dat_free(bat_priv);
@@ -185,6 +184,8 @@ void batadv_mesh_free(struct net_device *soft_iface)
185 */ 184 */
186 batadv_originator_free(bat_priv); 185 batadv_originator_free(bat_priv);
187 186
187 batadv_gw_free(bat_priv);
188
188 free_percpu(bat_priv->bat_counters); 189 free_percpu(bat_priv->bat_counters);
189 bat_priv->bat_counters = NULL; 190 bat_priv->bat_counters = NULL;
190 191
@@ -392,22 +393,31 @@ static void batadv_recv_handler_init(void)
392 for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++) 393 for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++)
393 batadv_rx_handler[i] = batadv_recv_unhandled_packet; 394 batadv_rx_handler[i] = batadv_recv_unhandled_packet;
394 395
395 /* batman icmp packet */ 396 for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++)
396 batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; 397 batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet;
398
399 /* compile time checks for struct member offsets */
400 BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
401 BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
402 BUILD_BUG_ON(offsetof(struct batadv_unicast_frag_packet, dest) != 4);
403 BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
404 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
405 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
406
407 /* broadcast packet */
408 batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
409
410 /* unicast packets ... */
397 /* unicast with 4 addresses packet */ 411 /* unicast with 4 addresses packet */
398 batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; 412 batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
399 /* unicast packet */ 413 /* unicast packet */
400 batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; 414 batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
401 /* fragmented unicast packet */ 415 /* fragmented unicast packet */
402 batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet; 416 batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
403 /* broadcast packet */ 417 /* unicast tvlv packet */
404 batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; 418 batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
405 /* vis packet */ 419 /* batman icmp packet */
406 batadv_rx_handler[BATADV_VIS] = batadv_recv_vis_packet; 420 batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
407 /* Translation table query (request or response) */
408 batadv_rx_handler[BATADV_TT_QUERY] = batadv_recv_tt_query;
409 /* Roaming advertisement */
410 batadv_rx_handler[BATADV_ROAM_ADV] = batadv_recv_roam_adv;
411} 421}
412 422
413int 423int
@@ -415,7 +425,12 @@ batadv_recv_handler_register(uint8_t packet_type,
415 int (*recv_handler)(struct sk_buff *, 425 int (*recv_handler)(struct sk_buff *,
416 struct batadv_hard_iface *)) 426 struct batadv_hard_iface *))
417{ 427{
418 if (batadv_rx_handler[packet_type] != &batadv_recv_unhandled_packet) 428 int (*curr)(struct sk_buff *,
429 struct batadv_hard_iface *);
430 curr = batadv_rx_handler[packet_type];
431
432 if ((curr != batadv_recv_unhandled_packet) &&
433 (curr != batadv_recv_unhandled_unicast_packet))
419 return -EBUSY; 434 return -EBUSY;
420 435
421 batadv_rx_handler[packet_type] = recv_handler; 436 batadv_rx_handler[packet_type] = recv_handler;
@@ -536,6 +551,574 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
536 return htonl(crc); 551 return htonl(crc);
537} 552}
538 553
554/**
555 * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and
556 * possibly free it
557 * @tvlv_handler: the tvlv handler to free
558 */
559static void
560batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler)
561{
562 if (atomic_dec_and_test(&tvlv_handler->refcount))
563 kfree_rcu(tvlv_handler, rcu);
564}
565
566/**
567 * batadv_tvlv_handler_get - retrieve tvlv handler from the tvlv handler list
568 * based on the provided type and version (both need to match)
569 * @bat_priv: the bat priv with all the soft interface information
570 * @type: tvlv handler type to look for
571 * @version: tvlv handler version to look for
572 *
573 * Returns tvlv handler if found or NULL otherwise.
574 */
575static struct batadv_tvlv_handler
576*batadv_tvlv_handler_get(struct batadv_priv *bat_priv,
577 uint8_t type, uint8_t version)
578{
579 struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL;
580
581 rcu_read_lock();
582 hlist_for_each_entry_rcu(tvlv_handler_tmp,
583 &bat_priv->tvlv.handler_list, list) {
584 if (tvlv_handler_tmp->type != type)
585 continue;
586
587 if (tvlv_handler_tmp->version != version)
588 continue;
589
590 if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount))
591 continue;
592
593 tvlv_handler = tvlv_handler_tmp;
594 break;
595 }
596 rcu_read_unlock();
597
598 return tvlv_handler;
599}
600
601/**
602 * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and
603 * possibly free it
604 * @tvlv_handler: the tvlv container to free
605 */
606static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv)
607{
608 if (atomic_dec_and_test(&tvlv->refcount))
609 kfree(tvlv);
610}
611
612/**
613 * batadv_tvlv_container_get - retrieve tvlv container from the tvlv container
614 * list based on the provided type and version (both need to match)
615 * @bat_priv: the bat priv with all the soft interface information
616 * @type: tvlv container type to look for
617 * @version: tvlv container version to look for
618 *
619 * Has to be called with the appropriate locks being acquired
620 * (tvlv.container_list_lock).
621 *
622 * Returns tvlv container if found or NULL otherwise.
623 */
624static struct batadv_tvlv_container
625*batadv_tvlv_container_get(struct batadv_priv *bat_priv,
626 uint8_t type, uint8_t version)
627{
628 struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
629
630 hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
631 if (tvlv_tmp->tvlv_hdr.type != type)
632 continue;
633
634 if (tvlv_tmp->tvlv_hdr.version != version)
635 continue;
636
637 if (!atomic_inc_not_zero(&tvlv_tmp->refcount))
638 continue;
639
640 tvlv = tvlv_tmp;
641 break;
642 }
643
644 return tvlv;
645}
646
647/**
648 * batadv_tvlv_container_list_size - calculate the size of the tvlv container
649 * list entries
650 * @bat_priv: the bat priv with all the soft interface information
651 *
652 * Has to be called with the appropriate locks being acquired
653 * (tvlv.container_list_lock).
654 *
655 * Returns size of all currently registered tvlv containers in bytes.
656 */
657static uint16_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
658{
659 struct batadv_tvlv_container *tvlv;
660 uint16_t tvlv_len = 0;
661
662 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
663 tvlv_len += sizeof(struct batadv_tvlv_hdr);
664 tvlv_len += ntohs(tvlv->tvlv_hdr.len);
665 }
666
667 return tvlv_len;
668}
669
670/**
671 * batadv_tvlv_container_remove - remove tvlv container from the tvlv container
672 * list
673 * @tvlv: the to be removed tvlv container
674 *
675 * Has to be called with the appropriate locks being acquired
676 * (tvlv.container_list_lock).
677 */
678static void batadv_tvlv_container_remove(struct batadv_tvlv_container *tvlv)
679{
680 if (!tvlv)
681 return;
682
683 hlist_del(&tvlv->list);
684
685 /* first call to decrement the counter, second call to free */
686 batadv_tvlv_container_free_ref(tvlv);
687 batadv_tvlv_container_free_ref(tvlv);
688}
689
690/**
691 * batadv_tvlv_container_unregister - unregister tvlv container based on the
692 * provided type and version (both need to match)
693 * @bat_priv: the bat priv with all the soft interface information
694 * @type: tvlv container type to unregister
695 * @version: tvlv container type to unregister
696 */
697void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
698 uint8_t type, uint8_t version)
699{
700 struct batadv_tvlv_container *tvlv;
701
702 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
703 tvlv = batadv_tvlv_container_get(bat_priv, type, version);
704 batadv_tvlv_container_remove(tvlv);
705 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
706}
707
708/**
709 * batadv_tvlv_container_register - register tvlv type, version and content
710 * to be propagated with each (primary interface) OGM
711 * @bat_priv: the bat priv with all the soft interface information
712 * @type: tvlv container type
713 * @version: tvlv container version
714 * @tvlv_value: tvlv container content
715 * @tvlv_value_len: tvlv container content length
716 *
717 * If a container of the same type and version was already registered the new
718 * content is going to replace the old one.
719 */
720void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
721 uint8_t type, uint8_t version,
722 void *tvlv_value, uint16_t tvlv_value_len)
723{
724 struct batadv_tvlv_container *tvlv_old, *tvlv_new;
725
726 if (!tvlv_value)
727 tvlv_value_len = 0;
728
729 tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC);
730 if (!tvlv_new)
731 return;
732
733 tvlv_new->tvlv_hdr.version = version;
734 tvlv_new->tvlv_hdr.type = type;
735 tvlv_new->tvlv_hdr.len = htons(tvlv_value_len);
736
737 memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
738 INIT_HLIST_NODE(&tvlv_new->list);
739 atomic_set(&tvlv_new->refcount, 1);
740
741 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
742 tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
743 batadv_tvlv_container_remove(tvlv_old);
744 hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
745 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
746}
747
748/**
749 * batadv_tvlv_realloc_packet_buff - reallocate packet buffer to accomodate
750 * requested packet size
751 * @packet_buff: packet buffer
752 * @packet_buff_len: packet buffer size
753 * @packet_min_len: requested packet minimum size
754 * @additional_packet_len: requested additional packet size on top of minimum
755 * size
756 *
757 * Returns true of the packet buffer could be changed to the requested size,
758 * false otherwise.
759 */
760static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
761 int *packet_buff_len,
762 int min_packet_len,
763 int additional_packet_len)
764{
765 unsigned char *new_buff;
766
767 new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC);
768
769 /* keep old buffer if kmalloc should fail */
770 if (new_buff) {
771 memcpy(new_buff, *packet_buff, min_packet_len);
772 kfree(*packet_buff);
773 *packet_buff = new_buff;
774 *packet_buff_len = min_packet_len + additional_packet_len;
775 return true;
776 }
777
778 return false;
779}
780
781/**
782 * batadv_tvlv_container_ogm_append - append tvlv container content to given
783 * OGM packet buffer
784 * @bat_priv: the bat priv with all the soft interface information
785 * @packet_buff: ogm packet buffer
786 * @packet_buff_len: ogm packet buffer size including ogm header and tvlv
787 * content
788 * @packet_min_len: ogm header size to be preserved for the OGM itself
789 *
790 * The ogm packet might be enlarged or shrunk depending on the current size
791 * and the size of the to-be-appended tvlv containers.
792 *
793 * Returns size of all appended tvlv containers in bytes.
794 */
795uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
796 unsigned char **packet_buff,
797 int *packet_buff_len,
798 int packet_min_len)
799{
800 struct batadv_tvlv_container *tvlv;
801 struct batadv_tvlv_hdr *tvlv_hdr;
802 uint16_t tvlv_value_len;
803 void *tvlv_value;
804 bool ret;
805
806 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
807 tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
808
809 ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
810 packet_min_len, tvlv_value_len);
811
812 if (!ret)
813 goto end;
814
815 if (!tvlv_value_len)
816 goto end;
817
818 tvlv_value = (*packet_buff) + packet_min_len;
819
820 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
821 tvlv_hdr = tvlv_value;
822 tvlv_hdr->type = tvlv->tvlv_hdr.type;
823 tvlv_hdr->version = tvlv->tvlv_hdr.version;
824 tvlv_hdr->len = tvlv->tvlv_hdr.len;
825 tvlv_value = tvlv_hdr + 1;
826 memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len));
827 tvlv_value = (uint8_t *)tvlv_value + ntohs(tvlv->tvlv_hdr.len);
828 }
829
830end:
831 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
832 return tvlv_value_len;
833}
834
835/**
836 * batadv_tvlv_call_handler - parse the given tvlv buffer to call the
837 * appropriate handlers
838 * @bat_priv: the bat priv with all the soft interface information
839 * @tvlv_handler: tvlv callback function handling the tvlv content
840 * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet
841 * @orig_node: orig node emitting the ogm packet
842 * @src: source mac address of the unicast packet
843 * @dst: destination mac address of the unicast packet
844 * @tvlv_value: tvlv content
845 * @tvlv_value_len: tvlv content length
846 *
847 * Returns success if handler was not found or the return value of the handler
848 * callback.
849 */
850static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
851 struct batadv_tvlv_handler *tvlv_handler,
852 bool ogm_source,
853 struct batadv_orig_node *orig_node,
854 uint8_t *src, uint8_t *dst,
855 void *tvlv_value, uint16_t tvlv_value_len)
856{
857 if (!tvlv_handler)
858 return NET_RX_SUCCESS;
859
860 if (ogm_source) {
861 if (!tvlv_handler->ogm_handler)
862 return NET_RX_SUCCESS;
863
864 if (!orig_node)
865 return NET_RX_SUCCESS;
866
867 tvlv_handler->ogm_handler(bat_priv, orig_node,
868 BATADV_NO_FLAGS,
869 tvlv_value, tvlv_value_len);
870 tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED;
871 } else {
872 if (!src)
873 return NET_RX_SUCCESS;
874
875 if (!dst)
876 return NET_RX_SUCCESS;
877
878 if (!tvlv_handler->unicast_handler)
879 return NET_RX_SUCCESS;
880
881 return tvlv_handler->unicast_handler(bat_priv, src,
882 dst, tvlv_value,
883 tvlv_value_len);
884 }
885
886 return NET_RX_SUCCESS;
887}
888
889/**
890 * batadv_tvlv_containers_process - parse the given tvlv buffer to call the
891 * appropriate handlers
892 * @bat_priv: the bat priv with all the soft interface information
893 * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet
894 * @orig_node: orig node emitting the ogm packet
895 * @src: source mac address of the unicast packet
896 * @dst: destination mac address of the unicast packet
897 * @tvlv_value: tvlv content
898 * @tvlv_value_len: tvlv content length
899 *
900 * Returns success when processing an OGM or the return value of all called
901 * handler callbacks.
902 */
903int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
904 bool ogm_source,
905 struct batadv_orig_node *orig_node,
906 uint8_t *src, uint8_t *dst,
907 void *tvlv_value, uint16_t tvlv_value_len)
908{
909 struct batadv_tvlv_handler *tvlv_handler;
910 struct batadv_tvlv_hdr *tvlv_hdr;
911 uint16_t tvlv_value_cont_len;
912 uint8_t cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
913 int ret = NET_RX_SUCCESS;
914
915 while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
916 tvlv_hdr = tvlv_value;
917 tvlv_value_cont_len = ntohs(tvlv_hdr->len);
918 tvlv_value = tvlv_hdr + 1;
919 tvlv_value_len -= sizeof(*tvlv_hdr);
920
921 if (tvlv_value_cont_len > tvlv_value_len)
922 break;
923
924 tvlv_handler = batadv_tvlv_handler_get(bat_priv,
925 tvlv_hdr->type,
926 tvlv_hdr->version);
927
928 ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
929 ogm_source, orig_node,
930 src, dst, tvlv_value,
931 tvlv_value_cont_len);
932 if (tvlv_handler)
933 batadv_tvlv_handler_free_ref(tvlv_handler);
934 tvlv_value = (uint8_t *)tvlv_value + tvlv_value_cont_len;
935 tvlv_value_len -= tvlv_value_cont_len;
936 }
937
938 if (!ogm_source)
939 return ret;
940
941 rcu_read_lock();
942 hlist_for_each_entry_rcu(tvlv_handler,
943 &bat_priv->tvlv.handler_list, list) {
944 if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
945 !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED))
946 tvlv_handler->ogm_handler(bat_priv, orig_node,
947 cifnotfound, NULL, 0);
948
949 tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED;
950 }
951 rcu_read_unlock();
952
953 return NET_RX_SUCCESS;
954}
955
956/**
957 * batadv_tvlv_ogm_receive - process an incoming ogm and call the appropriate
958 * handlers
959 * @bat_priv: the bat priv with all the soft interface information
960 * @batadv_ogm_packet: ogm packet containing the tvlv containers
961 * @orig_node: orig node emitting the ogm packet
962 */
963void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
964 struct batadv_ogm_packet *batadv_ogm_packet,
965 struct batadv_orig_node *orig_node)
966{
967 void *tvlv_value;
968 uint16_t tvlv_value_len;
969
970 if (!batadv_ogm_packet)
971 return;
972
973 tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len);
974 if (!tvlv_value_len)
975 return;
976
977 tvlv_value = batadv_ogm_packet + 1;
978
979 batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL,
980 tvlv_value, tvlv_value_len);
981}
982
983/**
984 * batadv_tvlv_handler_register - register tvlv handler based on the provided
985 * type and version (both need to match) for ogm tvlv payload and/or unicast
986 * payload
987 * @bat_priv: the bat priv with all the soft interface information
988 * @optr: ogm tvlv handler callback function. This function receives the orig
989 * node, flags and the tvlv content as argument to process.
990 * @uptr: unicast tvlv handler callback function. This function receives the
991 * source & destination of the unicast packet as well as the tvlv content
992 * to process.
993 * @type: tvlv handler type to be registered
994 * @version: tvlv handler version to be registered
995 * @flags: flags to enable or disable TVLV API behavior
996 */
997void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
998 void (*optr)(struct batadv_priv *bat_priv,
999 struct batadv_orig_node *orig,
1000 uint8_t flags,
1001 void *tvlv_value,
1002 uint16_t tvlv_value_len),
1003 int (*uptr)(struct batadv_priv *bat_priv,
1004 uint8_t *src, uint8_t *dst,
1005 void *tvlv_value,
1006 uint16_t tvlv_value_len),
1007 uint8_t type, uint8_t version, uint8_t flags)
1008{
1009 struct batadv_tvlv_handler *tvlv_handler;
1010
1011 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
1012 if (tvlv_handler) {
1013 batadv_tvlv_handler_free_ref(tvlv_handler);
1014 return;
1015 }
1016
1017 tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
1018 if (!tvlv_handler)
1019 return;
1020
1021 tvlv_handler->ogm_handler = optr;
1022 tvlv_handler->unicast_handler = uptr;
1023 tvlv_handler->type = type;
1024 tvlv_handler->version = version;
1025 tvlv_handler->flags = flags;
1026 atomic_set(&tvlv_handler->refcount, 1);
1027 INIT_HLIST_NODE(&tvlv_handler->list);
1028
1029 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
1030 hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
1031 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
1032}
1033
1034/**
1035 * batadv_tvlv_handler_unregister - unregister tvlv handler based on the
1036 * provided type and version (both need to match)
1037 * @bat_priv: the bat priv with all the soft interface information
1038 * @type: tvlv handler type to be unregistered
1039 * @version: tvlv handler version to be unregistered
1040 */
1041void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
1042 uint8_t type, uint8_t version)
1043{
1044 struct batadv_tvlv_handler *tvlv_handler;
1045
1046 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
1047 if (!tvlv_handler)
1048 return;
1049
1050 batadv_tvlv_handler_free_ref(tvlv_handler);
1051 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
1052 hlist_del_rcu(&tvlv_handler->list);
1053 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
1054 batadv_tvlv_handler_free_ref(tvlv_handler);
1055}
1056
1057/**
1058 * batadv_tvlv_unicast_send - send a unicast packet with tvlv payload to the
1059 * specified host
1060 * @bat_priv: the bat priv with all the soft interface information
1061 * @src: source mac address of the unicast packet
1062 * @dst: destination mac address of the unicast packet
1063 * @type: tvlv type
1064 * @version: tvlv version
1065 * @tvlv_value: tvlv content
1066 * @tvlv_value_len: tvlv content length
1067 */
1068void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
1069 uint8_t *dst, uint8_t type, uint8_t version,
1070 void *tvlv_value, uint16_t tvlv_value_len)
1071{
1072 struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
1073 struct batadv_tvlv_hdr *tvlv_hdr;
1074 struct batadv_orig_node *orig_node;
1075 struct sk_buff *skb = NULL;
1076 unsigned char *tvlv_buff;
1077 unsigned int tvlv_len;
1078 ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
1079 bool ret = false;
1080
1081 orig_node = batadv_orig_hash_find(bat_priv, dst);
1082 if (!orig_node)
1083 goto out;
1084
1085 tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len;
1086
1087 skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len);
1088 if (!skb)
1089 goto out;
1090
1091 skb->priority = TC_PRIO_CONTROL;
1092 skb_reserve(skb, ETH_HLEN);
1093 tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
1094 unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
1095 unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
1096 unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
1097 unicast_tvlv_packet->header.ttl = BATADV_TTL;
1098 unicast_tvlv_packet->reserved = 0;
1099 unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
1100 unicast_tvlv_packet->align = 0;
1101 memcpy(unicast_tvlv_packet->src, src, ETH_ALEN);
1102 memcpy(unicast_tvlv_packet->dst, dst, ETH_ALEN);
1103
1104 tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1);
1105 tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff;
1106 tvlv_hdr->version = version;
1107 tvlv_hdr->type = type;
1108 tvlv_hdr->len = htons(tvlv_value_len);
1109 tvlv_buff += sizeof(*tvlv_hdr);
1110 memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
1111
1112 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
1113 ret = true;
1114
1115out:
1116 if (skb && !ret)
1117 kfree_skb(skb);
1118 if (orig_node)
1119 batadv_orig_node_free_ref(orig_node);
1120}
1121
539static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) 1122static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
540{ 1123{
541 struct batadv_algo_ops *bat_algo_ops; 1124 struct batadv_algo_ops *bat_algo_ops;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 24675523930f..e11c2ec7a739 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -86,8 +86,6 @@
86/* numbers of originator to contact for any PUT/GET DHT operation */ 86/* numbers of originator to contact for any PUT/GET DHT operation */
87#define BATADV_DAT_CANDIDATES_NUM 3 87#define BATADV_DAT_CANDIDATES_NUM 3
88 88
89#define BATADV_VIS_INTERVAL 5000 /* 5 seconds */
90
91/* how much worse secondary interfaces may be to be considered as bonding 89/* how much worse secondary interfaces may be to be considered as bonding
92 * candidates 90 * candidates
93 */ 91 */
@@ -326,4 +324,39 @@ static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv,
326 */ 324 */
327#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0])) 325#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0]))
328 326
327void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
328 uint8_t type, uint8_t version,
329 void *tvlv_value, uint16_t tvlv_value_len);
330uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
331 unsigned char **packet_buff,
332 int *packet_buff_len,
333 int packet_min_len);
334void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
335 struct batadv_ogm_packet *batadv_ogm_packet,
336 struct batadv_orig_node *orig_node);
337void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
338 uint8_t type, uint8_t version);
339
340void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
341 void (*optr)(struct batadv_priv *bat_priv,
342 struct batadv_orig_node *orig,
343 uint8_t flags,
344 void *tvlv_value,
345 uint16_t tvlv_value_len),
346 int (*uptr)(struct batadv_priv *bat_priv,
347 uint8_t *src, uint8_t *dst,
348 void *tvlv_value,
349 uint16_t tvlv_value_len),
350 uint8_t type, uint8_t version, uint8_t flags);
351void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
352 uint8_t type, uint8_t version);
353int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
354 bool ogm_source,
355 struct batadv_orig_node *orig_node,
356 uint8_t *src, uint8_t *dst,
357 void *tvlv_buff, uint16_t tvlv_buff_len);
358void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
359 uint8_t *dst, uint8_t type, uint8_t version,
360 void *tvlv_value, uint16_t tvlv_value_len);
361
329#endif /* _NET_BATMAN_ADV_MAIN_H_ */ 362#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index 4ecc0b6bf8ab..23f611bedb0f 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -59,6 +59,59 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
59} 59}
60 60
61/** 61/**
62 * batadv_nc_tvlv_container_update - update the network coding tvlv container
63 * after network coding setting change
64 * @bat_priv: the bat priv with all the soft interface information
65 */
66static void batadv_nc_tvlv_container_update(struct batadv_priv *bat_priv)
67{
68 char nc_mode;
69
70 nc_mode = atomic_read(&bat_priv->network_coding);
71
72 switch (nc_mode) {
73 case 0:
74 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1);
75 break;
76 case 1:
77 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_NC, 1,
78 NULL, 0);
79 break;
80 }
81}
82
83/**
84 * batadv_nc_status_update - update the network coding tvlv container after
85 * network coding setting change
86 * @net_dev: the soft interface net device
87 */
88void batadv_nc_status_update(struct net_device *net_dev)
89{
90 struct batadv_priv *bat_priv = netdev_priv(net_dev);
91 batadv_nc_tvlv_container_update(bat_priv);
92}
93
94/**
95 * batadv_nc_tvlv_ogm_handler_v1 - process incoming nc tvlv container
96 * @bat_priv: the bat priv with all the soft interface information
97 * @orig: the orig_node of the ogm
98 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
99 * @tvlv_value: tvlv buffer containing the gateway data
100 * @tvlv_value_len: tvlv buffer length
101 */
102static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
103 struct batadv_orig_node *orig,
104 uint8_t flags,
105 void *tvlv_value,
106 uint16_t tvlv_value_len)
107{
108 if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
109 orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_NC;
110 else
111 orig->capabilities |= BATADV_ORIG_CAPA_HAS_NC;
112}
113
114/**
62 * batadv_nc_mesh_init - initialise coding hash table and start house keeping 115 * batadv_nc_mesh_init - initialise coding hash table and start house keeping
63 * @bat_priv: the bat priv with all the soft interface information 116 * @bat_priv: the bat priv with all the soft interface information
64 */ 117 */
@@ -87,6 +140,10 @@ int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
87 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); 140 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
88 batadv_nc_start_timer(bat_priv); 141 batadv_nc_start_timer(bat_priv);
89 142
143 batadv_tvlv_handler_register(bat_priv, batadv_nc_tvlv_ogm_handler_v1,
144 NULL, BATADV_TVLV_NC, 1,
145 BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
146 batadv_nc_tvlv_container_update(bat_priv);
90 return 0; 147 return 0;
91 148
92err: 149err:
@@ -802,6 +859,10 @@ void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
802 if (!atomic_read(&bat_priv->network_coding)) 859 if (!atomic_read(&bat_priv->network_coding))
803 goto out; 860 goto out;
804 861
862 /* check if orig node is network coding enabled */
863 if (!(orig_node->capabilities & BATADV_ORIG_CAPA_HAS_NC))
864 goto out;
865
805 /* accept ogms from 'good' neighbors and single hop neighbors */ 866 /* accept ogms from 'good' neighbors and single hop neighbors */
806 if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) && 867 if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
807 !is_single_hop_neigh) 868 !is_single_hop_neigh)
@@ -1735,6 +1796,8 @@ free_nc_packet:
1735 */ 1796 */
1736void batadv_nc_mesh_free(struct batadv_priv *bat_priv) 1797void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
1737{ 1798{
1799 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1);
1800 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_NC, 1);
1738 cancel_delayed_work_sync(&bat_priv->nc.work); 1801 cancel_delayed_work_sync(&bat_priv->nc.work);
1739 1802
1740 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); 1803 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h
index ddfa618e80bf..d4fd315b5261 100644
--- a/net/batman-adv/network-coding.h
+++ b/net/batman-adv/network-coding.h
@@ -22,6 +22,7 @@
22 22
23#ifdef CONFIG_BATMAN_ADV_NC 23#ifdef CONFIG_BATMAN_ADV_NC
24 24
25void batadv_nc_status_update(struct net_device *net_dev);
25int batadv_nc_init(void); 26int batadv_nc_init(void);
26int batadv_nc_mesh_init(struct batadv_priv *bat_priv); 27int batadv_nc_mesh_init(struct batadv_priv *bat_priv);
27void batadv_nc_mesh_free(struct batadv_priv *bat_priv); 28void batadv_nc_mesh_free(struct batadv_priv *bat_priv);
@@ -47,6 +48,10 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
47 48
48#else /* ifdef CONFIG_BATMAN_ADV_NC */ 49#else /* ifdef CONFIG_BATMAN_ADV_NC */
49 50
51static inline void batadv_nc_status_update(struct net_device *net_dev)
52{
53}
54
50static inline int batadv_nc_init(void) 55static inline int batadv_nc_init(void)
51{ 56{
52 return 0; 57 return 0;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index f50553a7de62..5d53d2f38377 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -388,9 +388,7 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
388 hlist_for_each_entry_safe(orig_node, node_tmp, 388 hlist_for_each_entry_safe(orig_node, node_tmp,
389 head, hash_entry) { 389 head, hash_entry) {
390 if (batadv_purge_orig_node(bat_priv, orig_node)) { 390 if (batadv_purge_orig_node(bat_priv, orig_node)) {
391 if (orig_node->gw_flags) 391 batadv_gw_node_delete(bat_priv, orig_node);
392 batadv_gw_node_delete(bat_priv,
393 orig_node);
394 hlist_del_rcu(&orig_node->hash_entry); 392 hlist_del_rcu(&orig_node->hash_entry);
395 batadv_orig_node_free_ref(orig_node); 393 batadv_orig_node_free_ref(orig_node);
396 continue; 394 continue;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index a51ccfc39da4..4361bae6186a 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -20,17 +20,34 @@
20#ifndef _NET_BATMAN_ADV_PACKET_H_ 20#ifndef _NET_BATMAN_ADV_PACKET_H_
21#define _NET_BATMAN_ADV_PACKET_H_ 21#define _NET_BATMAN_ADV_PACKET_H_
22 22
23/**
24 * enum batadv_packettype - types for batman-adv encapsulated packets
25 * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV
26 * @BATADV_BCAST: broadcast packets carrying broadcast payload
27 * @BATADV_CODED: network coded packets
28 *
29 * @BATADV_UNICAST: unicast packets carrying unicast payload traffic
30 * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
31 * payload packet
32 * @BATADV_UNICAST_4ADDR: unicast packet including the originator address of
33 * the sender
34 * @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute
35 * @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers
36 */
23enum batadv_packettype { 37enum batadv_packettype {
24 BATADV_IV_OGM = 0x01, 38 /* 0x00 - 0x3f: local packets or special rules for handling */
25 BATADV_ICMP = 0x02, 39 BATADV_IV_OGM = 0x00,
26 BATADV_UNICAST = 0x03, 40 BATADV_BCAST = 0x01,
27 BATADV_BCAST = 0x04, 41 BATADV_CODED = 0x02,
28 BATADV_VIS = 0x05, 42 /* 0x40 - 0x7f: unicast */
29 BATADV_UNICAST_FRAG = 0x06, 43#define BATADV_UNICAST_MIN 0x40
30 BATADV_TT_QUERY = 0x07, 44 BATADV_UNICAST = 0x40,
31 BATADV_ROAM_ADV = 0x08, 45 BATADV_UNICAST_FRAG = 0x41,
32 BATADV_UNICAST_4ADDR = 0x09, 46 BATADV_UNICAST_4ADDR = 0x42,
33 BATADV_CODED = 0x0a, 47 BATADV_ICMP = 0x43,
48 BATADV_UNICAST_TVLV = 0x44,
49#define BATADV_UNICAST_MAX 0x7f
50 /* 0x80 - 0xff: reserved */
34}; 51};
35 52
36/** 53/**
@@ -48,13 +65,21 @@ enum batadv_subtype {
48}; 65};
49 66
50/* this file is included by batctl which needs these defines */ 67/* this file is included by batctl which needs these defines */
51#define BATADV_COMPAT_VERSION 14 68#define BATADV_COMPAT_VERSION 15
52 69
70/**
71 * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets
72 * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was
73 * previously received from someone else than the best neighbor.
74 * @BATADV_PRIMARIES_FIRST_HOP: flag is set when the primary interface address
75 * is used, and the packet travels its first hop.
76 * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a
77 * one hop neighbor on the interface where it was originally received.
78 */
53enum batadv_iv_flags { 79enum batadv_iv_flags {
54 BATADV_NOT_BEST_NEXT_HOP = BIT(3), 80 BATADV_NOT_BEST_NEXT_HOP = BIT(0),
55 BATADV_PRIMARIES_FIRST_HOP = BIT(4), 81 BATADV_PRIMARIES_FIRST_HOP = BIT(1),
56 BATADV_VIS_SERVER = BIT(5), 82 BATADV_DIRECTLINK = BIT(2),
57 BATADV_DIRECTLINK = BIT(6),
58}; 83};
59 84
60/* ICMP message types */ 85/* ICMP message types */
@@ -66,29 +91,27 @@ enum batadv_icmp_packettype {
66 BATADV_PARAMETER_PROBLEM = 12, 91 BATADV_PARAMETER_PROBLEM = 12,
67}; 92};
68 93
69/* vis defines */
70enum batadv_vis_packettype {
71 BATADV_VIS_TYPE_SERVER_SYNC = 0,
72 BATADV_VIS_TYPE_CLIENT_UPDATE = 1,
73};
74
75/* fragmentation defines */ 94/* fragmentation defines */
76enum batadv_unicast_frag_flags { 95enum batadv_unicast_frag_flags {
77 BATADV_UNI_FRAG_HEAD = BIT(0), 96 BATADV_UNI_FRAG_HEAD = BIT(0),
78 BATADV_UNI_FRAG_LARGETAIL = BIT(1), 97 BATADV_UNI_FRAG_LARGETAIL = BIT(1),
79}; 98};
80 99
81/* TT_QUERY subtypes */ 100/* tt data subtypes */
82#define BATADV_TT_QUERY_TYPE_MASK 0x3 101#define BATADV_TT_DATA_TYPE_MASK 0x0F
83 102
84enum batadv_tt_query_packettype { 103/**
85 BATADV_TT_REQUEST = 0, 104 * enum batadv_tt_data_flags - flags for tt data tvlv
86 BATADV_TT_RESPONSE = 1, 105 * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM
87}; 106 * @BATADV_TT_REQUEST: TT request message
88 107 * @BATADV_TT_RESPONSE: TT response message
89/* TT_QUERY flags */ 108 * @BATADV_TT_FULL_TABLE: contains full table to replace existing table
90enum batadv_tt_query_flags { 109 */
91 BATADV_TT_FULL_TABLE = BIT(2), 110enum batadv_tt_data_flags {
111 BATADV_TT_OGM_DIFF = BIT(0),
112 BATADV_TT_REQUEST = BIT(1),
113 BATADV_TT_RESPONSE = BIT(2),
114 BATADV_TT_FULL_TABLE = BIT(4),
92}; 115};
93 116
94/* BATADV_TT_CLIENT flags. 117/* BATADV_TT_CLIENT flags.
@@ -99,10 +122,10 @@ enum batadv_tt_client_flags {
99 BATADV_TT_CLIENT_DEL = BIT(0), 122 BATADV_TT_CLIENT_DEL = BIT(0),
100 BATADV_TT_CLIENT_ROAM = BIT(1), 123 BATADV_TT_CLIENT_ROAM = BIT(1),
101 BATADV_TT_CLIENT_WIFI = BIT(2), 124 BATADV_TT_CLIENT_WIFI = BIT(2),
102 BATADV_TT_CLIENT_TEMP = BIT(3),
103 BATADV_TT_CLIENT_NOPURGE = BIT(8), 125 BATADV_TT_CLIENT_NOPURGE = BIT(8),
104 BATADV_TT_CLIENT_NEW = BIT(9), 126 BATADV_TT_CLIENT_NEW = BIT(9),
105 BATADV_TT_CLIENT_PENDING = BIT(10), 127 BATADV_TT_CLIENT_PENDING = BIT(10),
128 BATADV_TT_CLIENT_TEMP = BIT(11),
106}; 129};
107 130
108/* claim frame types for the bridge loop avoidance */ 131/* claim frame types for the bridge loop avoidance */
@@ -113,6 +136,22 @@ enum batadv_bla_claimframe {
113 BATADV_CLAIM_TYPE_REQUEST = 0x03, 136 BATADV_CLAIM_TYPE_REQUEST = 0x03,
114}; 137};
115 138
139/**
140 * enum batadv_tvlv_type - tvlv type definitions
141 * @BATADV_TVLV_GW: gateway tvlv
142 * @BATADV_TVLV_DAT: distributed arp table tvlv
143 * @BATADV_TVLV_NC: network coding tvlv
144 * @BATADV_TVLV_TT: translation table tvlv
145 * @BATADV_TVLV_ROAM: roaming advertisement tvlv
146 */
147enum batadv_tvlv_type {
148 BATADV_TVLV_GW = 0x01,
149 BATADV_TVLV_DAT = 0x02,
150 BATADV_TVLV_NC = 0x03,
151 BATADV_TVLV_TT = 0x04,
152 BATADV_TVLV_ROAM = 0x05,
153};
154
116/* the destination hardware field in the ARP frame is used to 155/* the destination hardware field in the ARP frame is used to
117 * transport the claim type and the group id 156 * transport the claim type and the group id
118 */ 157 */
@@ -131,18 +170,25 @@ struct batadv_header {
131 */ 170 */
132}; 171};
133 172
173/**
174 * struct batadv_ogm_packet - ogm (routing protocol) packet
175 * @header: common batman packet header
176 * @flags: contains routing relevant flags - see enum batadv_iv_flags
177 * @tvlv_len: length of tvlv data following the ogm header
178 */
134struct batadv_ogm_packet { 179struct batadv_ogm_packet {
135 struct batadv_header header; 180 struct batadv_header header;
136 uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ 181 uint8_t flags;
137 __be32 seqno; 182 __be32 seqno;
138 uint8_t orig[ETH_ALEN]; 183 uint8_t orig[ETH_ALEN];
139 uint8_t prev_sender[ETH_ALEN]; 184 uint8_t prev_sender[ETH_ALEN];
140 uint8_t gw_flags; /* flags related to gateway class */ 185 uint8_t reserved;
141 uint8_t tq; 186 uint8_t tq;
142 uint8_t tt_num_changes; 187 __be16 tvlv_len;
143 uint8_t ttvn; /* translation table version number */ 188 /* __packed is not needed as the struct size is divisible by 4,
144 __be16 tt_crc; 189 * and the largest data type in this struct has a size of 4.
145} __packed; 190 */
191};
146 192
147#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) 193#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
148 194
@@ -231,54 +277,6 @@ struct batadv_bcast_packet {
231 277
232#pragma pack() 278#pragma pack()
233 279
234struct batadv_vis_packet {
235 struct batadv_header header;
236 uint8_t vis_type; /* which type of vis-participant sent this? */
237 __be32 seqno; /* sequence number */
238 uint8_t entries; /* number of entries behind this struct */
239 uint8_t reserved;
240 uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */
241 uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */
242 uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
243};
244
245struct batadv_tt_query_packet {
246 struct batadv_header header;
247 /* the flag field is a combination of:
248 * - TT_REQUEST or TT_RESPONSE
249 * - TT_FULL_TABLE
250 */
251 uint8_t flags;
252 uint8_t dst[ETH_ALEN];
253 uint8_t src[ETH_ALEN];
254 /* the ttvn field is:
255 * if TT_REQUEST: ttvn that triggered the
256 * request
257 * if TT_RESPONSE: new ttvn for the src
258 * orig_node
259 */
260 uint8_t ttvn;
261 /* tt_data field is:
262 * if TT_REQUEST: crc associated with the
263 * ttvn
264 * if TT_RESPONSE: table_size
265 */
266 __be16 tt_data;
267} __packed;
268
269struct batadv_roam_adv_packet {
270 struct batadv_header header;
271 uint8_t reserved;
272 uint8_t dst[ETH_ALEN];
273 uint8_t src[ETH_ALEN];
274 uint8_t client[ETH_ALEN];
275} __packed;
276
277struct batadv_tt_change {
278 uint8_t flags;
279 uint8_t addr[ETH_ALEN];
280} __packed;
281
282/** 280/**
283 * struct batadv_coded_packet - network coded packet 281 * struct batadv_coded_packet - network coded packet
284 * @header: common batman packet header and ttl of first included packet 282 * @header: common batman packet header and ttl of first included packet
@@ -311,4 +309,82 @@ struct batadv_coded_packet {
311 __be16 coded_len; 309 __be16 coded_len;
312}; 310};
313 311
312/**
313 * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
314 * @header: common batman packet header
315 * @reserved: reserved field (for packet alignment)
316 * @src: address of the source
317 * @dst: address of the destination
318 * @tvlv_len: length of tvlv data following the unicast tvlv header
319 * @align: 2 bytes to align the header to a 4 byte boundry
320 */
321struct batadv_unicast_tvlv_packet {
322 struct batadv_header header;
323 uint8_t reserved;
324 uint8_t dst[ETH_ALEN];
325 uint8_t src[ETH_ALEN];
326 __be16 tvlv_len;
327 uint16_t align;
328};
329
330/**
331 * struct batadv_tvlv_hdr - base tvlv header struct
332 * @type: tvlv container type (see batadv_tvlv_type)
333 * @version: tvlv container version
334 * @len: tvlv container length
335 */
336struct batadv_tvlv_hdr {
337 uint8_t type;
338 uint8_t version;
339 __be16 len;
340};
341
342/**
343 * struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv
344 * container
345 * @bandwidth_down: advertised uplink download bandwidth
346 * @bandwidth_up: advertised uplink upload bandwidth
347 */
348struct batadv_tvlv_gateway_data {
349 __be32 bandwidth_down;
350 __be32 bandwidth_up;
351};
352
353/**
354 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
355 * @flags: translation table flags (see batadv_tt_data_flags)
356 * @ttvn: translation table version number
357 * @reserved: field reserved for future use
358 * @crc: crc32 checksum of the local translation table
359 */
360struct batadv_tvlv_tt_data {
361 uint8_t flags;
362 uint8_t ttvn;
363 uint16_t reserved;
364 __be32 crc;
365};
366
367/**
368 * struct batadv_tvlv_tt_change - translation table diff data
369 * @flags: status indicators concerning the non-mesh client (see
370 * batadv_tt_client_flags)
371 * @reserved: reserved field
372 * @addr: mac address of non-mesh client that triggered this tt change
373 */
374struct batadv_tvlv_tt_change {
375 uint8_t flags;
376 uint8_t reserved;
377 uint8_t addr[ETH_ALEN];
378};
379
380/**
381 * struct batadv_tvlv_roam_adv - roaming advertisement
382 * @client: mac address of roaming client
383 * @reserved: field reserved for future use
384 */
385struct batadv_tvlv_roam_adv {
386 uint8_t client[ETH_ALEN];
387 uint16_t reserved;
388};
389
314#endif /* _NET_BATMAN_ADV_PACKET_H_ */ 390#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 0439395d7ba5..457dfef9c5fc 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -25,7 +25,6 @@
25#include "icmp_socket.h" 25#include "icmp_socket.h"
26#include "translation-table.h" 26#include "translation-table.h"
27#include "originator.h" 27#include "originator.h"
28#include "vis.h"
29#include "unicast.h" 28#include "unicast.h"
30#include "bridge_loop_avoidance.h" 29#include "bridge_loop_avoidance.h"
31#include "distributed-arp-table.h" 30#include "distributed-arp-table.h"
@@ -557,126 +556,6 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
557 return 0; 556 return 0;
558} 557}
559 558
560int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
561{
562 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
563 struct batadv_tt_query_packet *tt_query;
564 uint16_t tt_size;
565 int hdr_size = sizeof(*tt_query);
566 char tt_flag;
567 size_t packet_size;
568
569 if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
570 return NET_RX_DROP;
571
572 /* I could need to modify it */
573 if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0)
574 goto out;
575
576 tt_query = (struct batadv_tt_query_packet *)skb->data;
577
578 switch (tt_query->flags & BATADV_TT_QUERY_TYPE_MASK) {
579 case BATADV_TT_REQUEST:
580 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
581
582 /* If we cannot provide an answer the tt_request is
583 * forwarded
584 */
585 if (!batadv_send_tt_response(bat_priv, tt_query)) {
586 if (tt_query->flags & BATADV_TT_FULL_TABLE)
587 tt_flag = 'F';
588 else
589 tt_flag = '.';
590
591 batadv_dbg(BATADV_DBG_TT, bat_priv,
592 "Routing TT_REQUEST to %pM [%c]\n",
593 tt_query->dst,
594 tt_flag);
595 return batadv_route_unicast_packet(skb, recv_if);
596 }
597 break;
598 case BATADV_TT_RESPONSE:
599 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
600
601 if (batadv_is_my_mac(bat_priv, tt_query->dst)) {
602 /* packet needs to be linearized to access the TT
603 * changes
604 */
605 if (skb_linearize(skb) < 0)
606 goto out;
607 /* skb_linearize() possibly changed skb->data */
608 tt_query = (struct batadv_tt_query_packet *)skb->data;
609
610 tt_size = batadv_tt_len(ntohs(tt_query->tt_data));
611
612 /* Ensure we have all the claimed data */
613 packet_size = sizeof(struct batadv_tt_query_packet);
614 packet_size += tt_size;
615 if (unlikely(skb_headlen(skb) < packet_size))
616 goto out;
617
618 batadv_handle_tt_response(bat_priv, tt_query);
619 } else {
620 if (tt_query->flags & BATADV_TT_FULL_TABLE)
621 tt_flag = 'F';
622 else
623 tt_flag = '.';
624 batadv_dbg(BATADV_DBG_TT, bat_priv,
625 "Routing TT_RESPONSE to %pM [%c]\n",
626 tt_query->dst,
627 tt_flag);
628 return batadv_route_unicast_packet(skb, recv_if);
629 }
630 break;
631 }
632
633out:
634 /* returning NET_RX_DROP will make the caller function kfree the skb */
635 return NET_RX_DROP;
636}
637
638int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
639{
640 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
641 struct batadv_roam_adv_packet *roam_adv_packet;
642 struct batadv_orig_node *orig_node;
643
644 if (batadv_check_unicast_packet(bat_priv, skb,
645 sizeof(*roam_adv_packet)) < 0)
646 goto out;
647
648 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
649
650 roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data;
651
652 if (!batadv_is_my_mac(bat_priv, roam_adv_packet->dst))
653 return batadv_route_unicast_packet(skb, recv_if);
654
655 /* check if it is a backbone gateway. we don't accept
656 * roaming advertisement from it, as it has the same
657 * entries as we have.
658 */
659 if (batadv_bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src))
660 goto out;
661
662 orig_node = batadv_orig_hash_find(bat_priv, roam_adv_packet->src);
663 if (!orig_node)
664 goto out;
665
666 batadv_dbg(BATADV_DBG_TT, bat_priv,
667 "Received ROAMING_ADV from %pM (client %pM)\n",
668 roam_adv_packet->src, roam_adv_packet->client);
669
670 batadv_tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
671 BATADV_TT_CLIENT_ROAM,
672 atomic_read(&orig_node->last_ttvn) + 1);
673
674 batadv_orig_node_free_ref(orig_node);
675out:
676 /* returning NET_RX_DROP will make the caller function kfree the skb */
677 return NET_RX_DROP;
678}
679
680/* find a suitable router for this originator, and use 559/* find a suitable router for this originator, and use
681 * bonding if possible. increases the found neighbors 560 * bonding if possible. increases the found neighbors
682 * refcount. 561 * refcount.
@@ -1032,6 +911,34 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
1032 return 1; 911 return 1;
1033} 912}
1034 913
914/**
915 * batadv_recv_unhandled_unicast_packet - receive and process packets which
916 * are in the unicast number space but not yet known to the implementation
917 * @skb: unicast tvlv packet to process
918 * @recv_if: pointer to interface this packet was received on
919 *
920 * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
921 * otherwise.
922 */
923int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
924 struct batadv_hard_iface *recv_if)
925{
926 struct batadv_unicast_packet *unicast_packet;
927 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
928 int check, hdr_size = sizeof(*unicast_packet);
929
930 check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
931 if (check < 0)
932 return NET_RX_DROP;
933
934 /* we don't know about this type, drop it. */
935 unicast_packet = (struct batadv_unicast_packet *)skb->data;
936 if (batadv_is_my_mac(bat_priv, unicast_packet->dest))
937 return NET_RX_DROP;
938
939 return batadv_route_unicast_packet(skb, recv_if);
940}
941
1035int batadv_recv_unicast_packet(struct sk_buff *skb, 942int batadv_recv_unicast_packet(struct sk_buff *skb,
1036 struct batadv_hard_iface *recv_if) 943 struct batadv_hard_iface *recv_if)
1037{ 944{
@@ -1139,6 +1046,54 @@ rx_success:
1139 return batadv_route_unicast_packet(skb, recv_if); 1046 return batadv_route_unicast_packet(skb, recv_if);
1140} 1047}
1141 1048
1049/**
1050 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
1051 * @skb: unicast tvlv packet to process
1052 * @recv_if: pointer to interface this packet was received on
1053 * @dst_addr: the payload destination
1054 *
1055 * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
1056 * otherwise.
1057 */
1058int batadv_recv_unicast_tvlv(struct sk_buff *skb,
1059 struct batadv_hard_iface *recv_if)
1060{
1061 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1062 struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
1063 unsigned char *tvlv_buff;
1064 uint16_t tvlv_buff_len;
1065 int hdr_size = sizeof(*unicast_tvlv_packet);
1066 int ret = NET_RX_DROP;
1067
1068 if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
1069 return NET_RX_DROP;
1070
1071 /* the header is likely to be modified while forwarding */
1072 if (skb_cow(skb, hdr_size) < 0)
1073 return NET_RX_DROP;
1074
1075 /* packet needs to be linearized to access the tvlv content */
1076 if (skb_linearize(skb) < 0)
1077 return NET_RX_DROP;
1078
1079 unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data;
1080
1081 tvlv_buff = (unsigned char *)(skb->data + hdr_size);
1082 tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len);
1083
1084 if (tvlv_buff_len > skb->len - hdr_size)
1085 return NET_RX_DROP;
1086
1087 ret = batadv_tvlv_containers_process(bat_priv, false, NULL,
1088 unicast_tvlv_packet->src,
1089 unicast_tvlv_packet->dst,
1090 tvlv_buff, tvlv_buff_len);
1091
1092 if (ret != NET_RX_SUCCESS)
1093 ret = batadv_route_unicast_packet(skb, recv_if);
1094
1095 return ret;
1096}
1142 1097
1143int batadv_recv_bcast_packet(struct sk_buff *skb, 1098int batadv_recv_bcast_packet(struct sk_buff *skb,
1144 struct batadv_hard_iface *recv_if) 1099 struct batadv_hard_iface *recv_if)
@@ -1240,53 +1195,3 @@ out:
1240 batadv_orig_node_free_ref(orig_node); 1195 batadv_orig_node_free_ref(orig_node);
1241 return ret; 1196 return ret;
1242} 1197}
1243
1244int batadv_recv_vis_packet(struct sk_buff *skb,
1245 struct batadv_hard_iface *recv_if)
1246{
1247 struct batadv_vis_packet *vis_packet;
1248 struct ethhdr *ethhdr;
1249 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1250 int hdr_size = sizeof(*vis_packet);
1251
1252 /* keep skb linear */
1253 if (skb_linearize(skb) < 0)
1254 return NET_RX_DROP;
1255
1256 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1257 return NET_RX_DROP;
1258
1259 vis_packet = (struct batadv_vis_packet *)skb->data;
1260 ethhdr = eth_hdr(skb);
1261
1262 /* not for me */
1263 if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
1264 return NET_RX_DROP;
1265
1266 /* ignore own packets */
1267 if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig))
1268 return NET_RX_DROP;
1269
1270 if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig))
1271 return NET_RX_DROP;
1272
1273 switch (vis_packet->vis_type) {
1274 case BATADV_VIS_TYPE_SERVER_SYNC:
1275 batadv_receive_server_sync_packet(bat_priv, vis_packet,
1276 skb_headlen(skb));
1277 break;
1278
1279 case BATADV_VIS_TYPE_CLIENT_UPDATE:
1280 batadv_receive_client_update_packet(bat_priv, vis_packet,
1281 skb_headlen(skb));
1282 break;
1283
1284 default: /* ignore unknown packet */
1285 break;
1286 }
1287
1288 /* We take a copy of the data in the packet, so we should
1289 * always free the skbuf.
1290 */
1291 return NET_RX_DROP;
1292}
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 72a29bde2010..ea15fa6302ad 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -34,12 +34,14 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 34 struct batadv_hard_iface *recv_if);
35int batadv_recv_bcast_packet(struct sk_buff *skb, 35int batadv_recv_bcast_packet(struct sk_buff *skb,
36 struct batadv_hard_iface *recv_if); 36 struct batadv_hard_iface *recv_if);
37int batadv_recv_vis_packet(struct sk_buff *skb,
38 struct batadv_hard_iface *recv_if);
39int batadv_recv_tt_query(struct sk_buff *skb, 37int batadv_recv_tt_query(struct sk_buff *skb,
40 struct batadv_hard_iface *recv_if); 38 struct batadv_hard_iface *recv_if);
41int batadv_recv_roam_adv(struct sk_buff *skb, 39int batadv_recv_roam_adv(struct sk_buff *skb,
42 struct batadv_hard_iface *recv_if); 40 struct batadv_hard_iface *recv_if);
41int batadv_recv_unicast_tvlv(struct sk_buff *skb,
42 struct batadv_hard_iface *recv_if);
43int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
44 struct batadv_hard_iface *recv_if);
43struct batadv_neigh_node * 45struct batadv_neigh_node *
44batadv_find_router(struct batadv_priv *bat_priv, 46batadv_find_router(struct batadv_priv *bat_priv,
45 struct batadv_orig_node *orig_node, 47 struct batadv_orig_node *orig_node,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 0266edd0fa7f..81d69fb97c17 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -24,7 +24,6 @@
24#include "translation-table.h" 24#include "translation-table.h"
25#include "soft-interface.h" 25#include "soft-interface.h"
26#include "hard-interface.h" 26#include "hard-interface.h"
27#include "vis.h"
28#include "gateway_common.h" 27#include "gateway_common.h"
29#include "originator.h" 28#include "originator.h"
30#include "network-coding.h" 29#include "network-coding.h"
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 813db4e64602..25e6004e8e01 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -469,10 +469,10 @@ static int batadv_softif_init_late(struct net_device *dev)
469 atomic_set(&bat_priv->distributed_arp_table, 1); 469 atomic_set(&bat_priv->distributed_arp_table, 1);
470#endif 470#endif
471 atomic_set(&bat_priv->ap_isolation, 0); 471 atomic_set(&bat_priv->ap_isolation, 0);
472 atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
473 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 472 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
474 atomic_set(&bat_priv->gw_sel_class, 20); 473 atomic_set(&bat_priv->gw_sel_class, 20);
475 atomic_set(&bat_priv->gw_bandwidth, 41); 474 atomic_set(&bat_priv->gw.bandwidth_down, 100);
475 atomic_set(&bat_priv->gw.bandwidth_up, 20);
476 atomic_set(&bat_priv->orig_interval, 1000); 476 atomic_set(&bat_priv->orig_interval, 1000);
477 atomic_set(&bat_priv->hop_penalty, 30); 477 atomic_set(&bat_priv->hop_penalty, 30);
478#ifdef CONFIG_BATMAN_ADV_DEBUG 478#ifdef CONFIG_BATMAN_ADV_DEBUG
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 4114b961bc2c..869eb46329cb 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -21,11 +21,11 @@
21#include "sysfs.h" 21#include "sysfs.h"
22#include "translation-table.h" 22#include "translation-table.h"
23#include "distributed-arp-table.h" 23#include "distributed-arp-table.h"
24#include "network-coding.h"
24#include "originator.h" 25#include "originator.h"
25#include "hard-interface.h" 26#include "hard-interface.h"
26#include "gateway_common.h" 27#include "gateway_common.h"
27#include "gateway_client.h" 28#include "gateway_client.h"
28#include "vis.h"
29 29
30static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) 30static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
31{ 31{
@@ -230,74 +230,6 @@ __batadv_store_uint_attr(const char *buff, size_t count,
230 return ret; 230 return ret;
231} 231}
232 232
233static ssize_t batadv_show_vis_mode(struct kobject *kobj,
234 struct attribute *attr, char *buff)
235{
236 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
237 int vis_mode = atomic_read(&bat_priv->vis_mode);
238 const char *mode;
239
240 if (vis_mode == BATADV_VIS_TYPE_CLIENT_UPDATE)
241 mode = "client";
242 else
243 mode = "server";
244
245 return sprintf(buff, "%s\n", mode);
246}
247
248static ssize_t batadv_store_vis_mode(struct kobject *kobj,
249 struct attribute *attr, char *buff,
250 size_t count)
251{
252 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
253 struct batadv_priv *bat_priv = netdev_priv(net_dev);
254 unsigned long val;
255 int ret, vis_mode_tmp = -1;
256 const char *old_mode, *new_mode;
257
258 ret = kstrtoul(buff, 10, &val);
259
260 if (((count == 2) && (!ret) &&
261 (val == BATADV_VIS_TYPE_CLIENT_UPDATE)) ||
262 (strncmp(buff, "client", 6) == 0) ||
263 (strncmp(buff, "off", 3) == 0))
264 vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE;
265
266 if (((count == 2) && (!ret) &&
267 (val == BATADV_VIS_TYPE_SERVER_SYNC)) ||
268 (strncmp(buff, "server", 6) == 0))
269 vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC;
270
271 if (vis_mode_tmp < 0) {
272 if (buff[count - 1] == '\n')
273 buff[count - 1] = '\0';
274
275 batadv_info(net_dev,
276 "Invalid parameter for 'vis mode' setting received: %s\n",
277 buff);
278 return -EINVAL;
279 }
280
281 if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
282 return count;
283
284 if (atomic_read(&bat_priv->vis_mode) == BATADV_VIS_TYPE_CLIENT_UPDATE)
285 old_mode = "client";
286 else
287 old_mode = "server";
288
289 if (vis_mode_tmp == BATADV_VIS_TYPE_CLIENT_UPDATE)
290 new_mode = "client";
291 else
292 new_mode = "server";
293
294 batadv_info(net_dev, "Changing vis mode from: %s to: %s\n", old_mode,
295 new_mode);
296
297 atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp);
298 return count;
299}
300
301static ssize_t batadv_show_bat_algo(struct kobject *kobj, 233static ssize_t batadv_show_bat_algo(struct kobject *kobj,
302 struct attribute *attr, char *buff) 234 struct attribute *attr, char *buff)
303{ 235{
@@ -390,6 +322,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
390 */ 322 */
391 batadv_gw_check_client_stop(bat_priv); 323 batadv_gw_check_client_stop(bat_priv);
392 atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); 324 atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
325 batadv_gw_tvlv_container_update(bat_priv);
393 return count; 326 return count;
394} 327}
395 328
@@ -397,15 +330,13 @@ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
397 struct attribute *attr, char *buff) 330 struct attribute *attr, char *buff)
398{ 331{
399 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 332 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
400 int down, up; 333 uint32_t down, up;
401 int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); 334
402 335 down = atomic_read(&bat_priv->gw.bandwidth_down);
403 batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); 336 up = atomic_read(&bat_priv->gw.bandwidth_up);
404 return sprintf(buff, "%i%s/%i%s\n", 337
405 (down > 2048 ? down / 1024 : down), 338 return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
406 (down > 2048 ? "MBit" : "KBit"), 339 down % 10, up / 10, up % 10);
407 (up > 2048 ? up / 1024 : up),
408 (up > 2048 ? "MBit" : "KBit"));
409} 340}
410 341
411static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, 342static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
@@ -426,12 +357,11 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
426BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); 357BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
427#endif 358#endif
428#ifdef CONFIG_BATMAN_ADV_DAT 359#ifdef CONFIG_BATMAN_ADV_DAT
429BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); 360BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
361 batadv_dat_status_update);
430#endif 362#endif
431BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); 363BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
432BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); 364BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
433static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
434 batadv_store_vis_mode);
435static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); 365static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
436static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, 366static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
437 batadv_store_gw_mode); 367 batadv_store_gw_mode);
@@ -447,7 +377,8 @@ static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
447BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); 377BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
448#endif 378#endif
449#ifdef CONFIG_BATMAN_ADV_NC 379#ifdef CONFIG_BATMAN_ADV_NC
450BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL); 380BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
381 batadv_nc_status_update);
451#endif 382#endif
452 383
453static struct batadv_attribute *batadv_mesh_attrs[] = { 384static struct batadv_attribute *batadv_mesh_attrs[] = {
@@ -461,7 +392,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
461#endif 392#endif
462 &batadv_attr_fragmentation, 393 &batadv_attr_fragmentation,
463 &batadv_attr_ap_isolation, 394 &batadv_attr_ap_isolation,
464 &batadv_attr_vis_mode,
465 &batadv_attr_routing_algo, 395 &batadv_attr_routing_algo,
466 &batadv_attr_gw_mode, 396 &batadv_attr_gw_mode,
467 &batadv_attr_orig_interval, 397 &batadv_attr_orig_interval,
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 34510f38708f..c7416947a4e0 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -27,7 +27,7 @@
27#include "routing.h" 27#include "routing.h"
28#include "bridge_loop_avoidance.h" 28#include "bridge_loop_avoidance.h"
29 29
30#include <linux/crc16.h> 30#include <linux/crc32c.h>
31 31
32/* hash class keys */ 32/* hash class keys */
33static struct lock_class_key batadv_tt_local_hash_lock_class_key; 33static struct lock_class_key batadv_tt_local_hash_lock_class_key;
@@ -180,11 +180,11 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
180 bool del_op_requested, del_op_entry; 180 bool del_op_requested, del_op_entry;
181 181
182 tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC); 182 tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
183
184 if (!tt_change_node) 183 if (!tt_change_node)
185 return; 184 return;
186 185
187 tt_change_node->change.flags = flags; 186 tt_change_node->change.flags = flags;
187 tt_change_node->change.reserved = 0;
188 memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); 188 memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
189 189
190 del_op_requested = flags & BATADV_TT_CLIENT_DEL; 190 del_op_requested = flags & BATADV_TT_CLIENT_DEL;
@@ -229,9 +229,15 @@ unlock:
229 atomic_inc(&bat_priv->tt.local_changes); 229 atomic_inc(&bat_priv->tt.local_changes);
230} 230}
231 231
232int batadv_tt_len(int changes_num) 232/**
233 * batadv_tt_len - compute length in bytes of given number of tt changes
234 * @changes_num: number of tt changes
235 *
236 * Returns computed length in bytes.
237 */
238static int batadv_tt_len(int changes_num)
233{ 239{
234 return changes_num * sizeof(struct batadv_tt_change); 240 return changes_num * sizeof(struct batadv_tvlv_tt_change);
235} 241}
236 242
237static int batadv_tt_local_init(struct batadv_priv *bat_priv) 243static int batadv_tt_local_init(struct batadv_priv *bat_priv)
@@ -376,71 +382,52 @@ out:
376 batadv_tt_global_entry_free_ref(tt_global); 382 batadv_tt_global_entry_free_ref(tt_global);
377} 383}
378 384
379static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, 385/**
380 int *packet_buff_len, 386 * batadv_tt_tvlv_container_update - update the translation table tvlv container
381 int min_packet_len, 387 * after local tt changes have been committed
382 int new_packet_len) 388 * @bat_priv: the bat priv with all the soft interface information
383{ 389 */
384 unsigned char *new_buff; 390static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
385
386 new_buff = kmalloc(new_packet_len, GFP_ATOMIC);
387
388 /* keep old buffer if kmalloc should fail */
389 if (new_buff) {
390 memcpy(new_buff, *packet_buff, min_packet_len);
391 kfree(*packet_buff);
392 *packet_buff = new_buff;
393 *packet_buff_len = new_packet_len;
394 }
395}
396
397static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
398 unsigned char **packet_buff,
399 int *packet_buff_len,
400 int min_packet_len)
401{ 391{
402 int req_len; 392 struct batadv_tt_change_node *entry, *safe;
393 struct batadv_tvlv_tt_data *tt_data;
394 struct batadv_tvlv_tt_change *tt_change;
395 int tt_diff_len = 0, tt_change_len = 0;
396 int tt_diff_entries_num = 0, tt_diff_entries_count = 0;
403 397
404 req_len = min_packet_len; 398 tt_diff_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
405 req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
406 399
407 /* if we have too many changes for one packet don't send any 400 /* if we have too many changes for one packet don't send any
408 * and wait for the tt table request which will be fragmented 401 * and wait for the tt table request which will be fragmented
409 */ 402 */
410 if (req_len > bat_priv->soft_iface->mtu) 403 if (tt_diff_len > bat_priv->soft_iface->mtu)
411 req_len = min_packet_len; 404 tt_diff_len = 0;
412 405
413 batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, 406 tt_data = kzalloc(sizeof(*tt_data) + tt_diff_len, GFP_ATOMIC);
414 min_packet_len, req_len); 407 if (!tt_data)
415} 408 return;
416
417static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
418 unsigned char **packet_buff,
419 int *packet_buff_len,
420 int min_packet_len)
421{
422 struct batadv_tt_change_node *entry, *safe;
423 int count = 0, tot_changes = 0, new_len;
424 unsigned char *tt_buff;
425 409
426 batadv_tt_prepare_packet_buff(bat_priv, packet_buff, 410 tt_data->flags = BATADV_TT_OGM_DIFF;
427 packet_buff_len, min_packet_len); 411 tt_data->ttvn = atomic_read(&bat_priv->tt.vn);
412 tt_data->crc = htonl(bat_priv->tt.local_crc);
428 413
429 new_len = *packet_buff_len - min_packet_len; 414 if (tt_diff_len == 0)
430 tt_buff = *packet_buff + min_packet_len; 415 goto container_register;
431 416
432 if (new_len > 0) 417 tt_diff_entries_num = tt_diff_len / batadv_tt_len(1);
433 tot_changes = new_len / batadv_tt_len(1);
434 418
435 spin_lock_bh(&bat_priv->tt.changes_list_lock); 419 spin_lock_bh(&bat_priv->tt.changes_list_lock);
436 atomic_set(&bat_priv->tt.local_changes, 0); 420 atomic_set(&bat_priv->tt.local_changes, 0);
437 421
422 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
423
438 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, 424 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
439 list) { 425 list) {
440 if (count < tot_changes) { 426 if (tt_diff_entries_count < tt_diff_entries_num) {
441 memcpy(tt_buff + batadv_tt_len(count), 427 memcpy(tt_change + tt_diff_entries_count,
442 &entry->change, sizeof(struct batadv_tt_change)); 428 &entry->change,
443 count++; 429 sizeof(struct batadv_tvlv_tt_change));
430 tt_diff_entries_count++;
444 } 431 }
445 list_del(&entry->list); 432 list_del(&entry->list);
446 kfree(entry); 433 kfree(entry);
@@ -452,20 +439,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
452 kfree(bat_priv->tt.last_changeset); 439 kfree(bat_priv->tt.last_changeset);
453 bat_priv->tt.last_changeset_len = 0; 440 bat_priv->tt.last_changeset_len = 0;
454 bat_priv->tt.last_changeset = NULL; 441 bat_priv->tt.last_changeset = NULL;
442 tt_change_len = batadv_tt_len(tt_diff_entries_count);
455 /* check whether this new OGM has no changes due to size problems */ 443 /* check whether this new OGM has no changes due to size problems */
456 if (new_len > 0) { 444 if (tt_diff_entries_count > 0) {
457 /* if kmalloc() fails we will reply with the full table 445 /* if kmalloc() fails we will reply with the full table
458 * instead of providing the diff 446 * instead of providing the diff
459 */ 447 */
460 bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); 448 bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
461 if (bat_priv->tt.last_changeset) { 449 if (bat_priv->tt.last_changeset) {
462 memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); 450 memcpy(bat_priv->tt.last_changeset,
463 bat_priv->tt.last_changeset_len = new_len; 451 tt_change, tt_change_len);
452 bat_priv->tt.last_changeset_len = tt_diff_len;
464 } 453 }
465 } 454 }
466 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 455 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
467 456
468 return count; 457container_register:
458 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
459 sizeof(*tt_data) + tt_change_len);
460 kfree(tt_data);
469} 461}
470 462
471int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) 463int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
@@ -489,7 +481,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
489 goto out; 481 goto out;
490 482
491 seq_printf(seq, 483 seq_printf(seq,
492 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x):\n", 484 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.8x):\n",
493 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn), 485 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn),
494 bat_priv->tt.local_crc); 486 bat_priv->tt.local_crc);
495 seq_printf(seq, " %-13s %-7s %-10s\n", "Client", "Flags", 487 seq_printf(seq, " %-13s %-7s %-10s\n", "Client", "Flags",
@@ -1001,7 +993,7 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
1001 if (best_entry) { 993 if (best_entry) {
1002 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn); 994 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
1003 seq_printf(seq, 995 seq_printf(seq,
1004 " %c %pM (%3u) via %pM (%3u) (%#.4x) [%c%c%c]\n", 996 " %c %pM (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
1005 '*', tt_global_entry->common.addr, 997 '*', tt_global_entry->common.addr,
1006 best_entry->ttvn, best_entry->orig_node->orig, 998 best_entry->ttvn, best_entry->orig_node->orig,
1007 last_ttvn, best_entry->orig_node->tt_crc, 999 last_ttvn, best_entry->orig_node->tt_crc,
@@ -1045,7 +1037,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
1045 seq_printf(seq, 1037 seq_printf(seq,
1046 "Globally announced TT entries received via the mesh %s\n", 1038 "Globally announced TT entries received via the mesh %s\n",
1047 net_dev->name); 1039 net_dev->name);
1048 seq_printf(seq, " %-13s %s %-15s %s (%-6s) %s\n", 1040 seq_printf(seq, " %-13s %s %-15s %s (%-10s) %s\n",
1049 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC", 1041 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC",
1050 "Flags"); 1042 "Flags");
1051 1043
@@ -1402,17 +1394,19 @@ out:
1402 return orig_node; 1394 return orig_node;
1403} 1395}
1404 1396
1405/* Calculates the checksum of the local table of a given orig_node */ 1397/**
1406static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, 1398 * batadv_tt_global_crc - calculates the checksum of the local table belonging
1399 * to the given orig_node
1400 * @bat_priv: the bat priv with all the soft interface information
1401 */
1402static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1407 struct batadv_orig_node *orig_node) 1403 struct batadv_orig_node *orig_node)
1408{ 1404{
1409 uint16_t total = 0, total_one;
1410 struct batadv_hashtable *hash = bat_priv->tt.global_hash; 1405 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1411 struct batadv_tt_common_entry *tt_common; 1406 struct batadv_tt_common_entry *tt_common;
1412 struct batadv_tt_global_entry *tt_global; 1407 struct batadv_tt_global_entry *tt_global;
1413 struct hlist_head *head; 1408 struct hlist_head *head;
1414 uint32_t i; 1409 uint32_t i, crc = 0;
1415 int j;
1416 1410
1417 for (i = 0; i < hash->size; i++) { 1411 for (i = 0; i < hash->size; i++) {
1418 head = &hash->table[i]; 1412 head = &hash->table[i];
@@ -1443,27 +1437,24 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1443 orig_node)) 1437 orig_node))
1444 continue; 1438 continue;
1445 1439
1446 total_one = 0; 1440 crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
1447 for (j = 0; j < ETH_ALEN; j++)
1448 total_one = crc16_byte(total_one,
1449 tt_common->addr[j]);
1450 total ^= total_one;
1451 } 1441 }
1452 rcu_read_unlock(); 1442 rcu_read_unlock();
1453 } 1443 }
1454 1444
1455 return total; 1445 return crc;
1456} 1446}
1457 1447
1458/* Calculates the checksum of the local table */ 1448/**
1459static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) 1449 * batadv_tt_local_crc - calculates the checksum of the local table
1450 * @bat_priv: the bat priv with all the soft interface information
1451 */
1452static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1460{ 1453{
1461 uint16_t total = 0, total_one;
1462 struct batadv_hashtable *hash = bat_priv->tt.local_hash; 1454 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1463 struct batadv_tt_common_entry *tt_common; 1455 struct batadv_tt_common_entry *tt_common;
1464 struct hlist_head *head; 1456 struct hlist_head *head;
1465 uint32_t i; 1457 uint32_t i, crc = 0;
1466 int j;
1467 1458
1468 for (i = 0; i < hash->size; i++) { 1459 for (i = 0; i < hash->size; i++) {
1469 head = &hash->table[i]; 1460 head = &hash->table[i];
@@ -1475,16 +1466,13 @@ static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1475 */ 1466 */
1476 if (tt_common->flags & BATADV_TT_CLIENT_NEW) 1467 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
1477 continue; 1468 continue;
1478 total_one = 0; 1469
1479 for (j = 0; j < ETH_ALEN; j++) 1470 crc ^= crc32c(0, tt_common->addr, ETH_ALEN);
1480 total_one = crc16_byte(total_one,
1481 tt_common->addr[j]);
1482 total ^= total_one;
1483 } 1471 }
1484 rcu_read_unlock(); 1472 rcu_read_unlock();
1485 } 1473 }
1486 1474
1487 return total; 1475 return crc;
1488} 1476}
1489 1477
1490static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) 1478static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
@@ -1504,7 +1492,7 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
1504static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, 1492static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
1505 struct batadv_orig_node *orig_node, 1493 struct batadv_orig_node *orig_node,
1506 const unsigned char *tt_buff, 1494 const unsigned char *tt_buff,
1507 uint8_t tt_num_changes) 1495 uint16_t tt_num_changes)
1508{ 1496{
1509 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes); 1497 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1510 1498
@@ -1569,9 +1557,14 @@ unlock:
1569 return tt_req_node; 1557 return tt_req_node;
1570} 1558}
1571 1559
1572/* data_ptr is useless here, but has to be kept to respect the prototype */ 1560/**
1573static int batadv_tt_local_valid_entry(const void *entry_ptr, 1561 * batadv_tt_local_valid - verify that given tt entry is a valid one
1574 const void *data_ptr) 1562 * @entry_ptr: to be checked local tt entry
1563 * @data_ptr: not used but definition required to satisfy the callback prototype
1564 *
1565 * Returns 1 if the entry is a valid, 0 otherwise.
1566 */
1567static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
1575{ 1568{
1576 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; 1569 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1577 1570
@@ -1598,41 +1591,45 @@ static int batadv_tt_global_valid(const void *entry_ptr,
1598 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); 1591 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
1599} 1592}
1600 1593
1601static struct sk_buff * 1594/**
1602batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, 1595 * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the
1603 struct batadv_hashtable *hash, 1596 * tt entries from the specified tt hash
1604 struct batadv_priv *bat_priv, 1597 * @bat_priv: the bat priv with all the soft interface information
1605 int (*valid_cb)(const void *, const void *), 1598 * @hash: hash table containing the tt entries
1606 void *cb_data) 1599 * @tt_len: expected tvlv tt data buffer length in number of bytes
1600 * @valid_cb: function to filter tt change entries
1601 * @cb_data: data passed to the filter function as argument
1602 *
1603 * Returns pointer to allocated tvlv tt data buffer if operation was
1604 * successful or NULL otherwise.
1605 */
1606static struct batadv_tvlv_tt_data *
1607batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1608 struct batadv_hashtable *hash, uint16_t tt_len,
1609 int (*valid_cb)(const void *, const void *),
1610 void *cb_data)
1607{ 1611{
1608 struct batadv_tt_common_entry *tt_common_entry; 1612 struct batadv_tt_common_entry *tt_common_entry;
1609 struct batadv_tt_query_packet *tt_response; 1613 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1610 struct batadv_tt_change *tt_change; 1614 struct batadv_tvlv_tt_change *tt_change;
1611 struct hlist_head *head; 1615 struct hlist_head *head;
1612 struct sk_buff *skb = NULL; 1616 uint16_t tt_tot, tt_num_entries = 0;
1613 uint16_t tt_tot, tt_count; 1617 ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data);
1614 ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
1615 uint32_t i; 1618 uint32_t i;
1616 size_t len;
1617 1619
1618 if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) { 1620 if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) {
1619 tt_len = bat_priv->soft_iface->mtu - tt_query_size; 1621 tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size;
1620 tt_len -= tt_len % sizeof(struct batadv_tt_change); 1622 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
1621 } 1623 }
1622 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1623 1624
1624 len = tt_query_size + tt_len; 1625 tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change);
1625 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
1626 if (!skb)
1627 goto out;
1628 1626
1629 skb->priority = TC_PRIO_CONTROL; 1627 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1630 skb_reserve(skb, ETH_HLEN); 1628 GFP_ATOMIC);
1631 tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); 1629 if (!tvlv_tt_data)
1632 tt_response->ttvn = ttvn; 1630 goto out;
1633 1631
1634 tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size); 1632 tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1);
1635 tt_count = 0;
1636 1633
1637 rcu_read_lock(); 1634 rcu_read_lock();
1638 for (i = 0; i < hash->size; i++) { 1635 for (i = 0; i < hash->size; i++) {
@@ -1640,7 +1637,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1640 1637
1641 hlist_for_each_entry_rcu(tt_common_entry, 1638 hlist_for_each_entry_rcu(tt_common_entry,
1642 head, hash_entry) { 1639 head, hash_entry) {
1643 if (tt_count == tt_tot) 1640 if (tt_tot == tt_num_entries)
1644 break; 1641 break;
1645 1642
1646 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) 1643 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
@@ -1649,33 +1646,36 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1649 memcpy(tt_change->addr, tt_common_entry->addr, 1646 memcpy(tt_change->addr, tt_common_entry->addr,
1650 ETH_ALEN); 1647 ETH_ALEN);
1651 tt_change->flags = tt_common_entry->flags; 1648 tt_change->flags = tt_common_entry->flags;
1649 tt_change->reserved = 0;
1652 1650
1653 tt_count++; 1651 tt_num_entries++;
1654 tt_change++; 1652 tt_change++;
1655 } 1653 }
1656 } 1654 }
1657 rcu_read_unlock(); 1655 rcu_read_unlock();
1658 1656
1659 /* store in the message the number of entries we have successfully
1660 * copied
1661 */
1662 tt_response->tt_data = htons(tt_count);
1663
1664out: 1657out:
1665 return skb; 1658 return tvlv_tt_data;
1666} 1659}
1667 1660
1661/**
1662 * batadv_send_tt_request - send a TT Request message to a given node
1663 * @bat_priv: the bat priv with all the soft interface information
1664 * @dst_orig_node: the destination of the message
1665 * @ttvn: the version number that the source of the message is looking for
1666 * @tt_crc: the CRC associated with the version number
1667 * @full_table: ask for the entire translation table if true, while only for the
1668 * last TT diff otherwise
1669 */
1668static int batadv_send_tt_request(struct batadv_priv *bat_priv, 1670static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1669 struct batadv_orig_node *dst_orig_node, 1671 struct batadv_orig_node *dst_orig_node,
1670 uint8_t ttvn, uint16_t tt_crc, 1672 uint8_t ttvn, uint32_t tt_crc,
1671 bool full_table) 1673 bool full_table)
1672{ 1674{
1673 struct sk_buff *skb = NULL; 1675 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1674 struct batadv_tt_query_packet *tt_request;
1675 struct batadv_hard_iface *primary_if; 1676 struct batadv_hard_iface *primary_if;
1676 struct batadv_tt_req_node *tt_req_node = NULL; 1677 struct batadv_tt_req_node *tt_req_node = NULL;
1677 int ret = 1; 1678 bool ret = false;
1678 size_t tt_req_len;
1679 1679
1680 primary_if = batadv_primary_if_get_selected(bat_priv); 1680 primary_if = batadv_primary_if_get_selected(bat_priv);
1681 if (!primary_if) 1681 if (!primary_if)
@@ -1688,157 +1688,136 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1688 if (!tt_req_node) 1688 if (!tt_req_node)
1689 goto out; 1689 goto out;
1690 1690
1691 skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN); 1691 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC);
1692 if (!skb) 1692 if (!tvlv_tt_data)
1693 goto out; 1693 goto out;
1694 1694
1695 skb->priority = TC_PRIO_CONTROL; 1695 tvlv_tt_data->flags = BATADV_TT_REQUEST;
1696 skb_reserve(skb, ETH_HLEN); 1696 tvlv_tt_data->ttvn = ttvn;
1697 1697 tvlv_tt_data->crc = htonl(tt_crc);
1698 tt_req_len = sizeof(*tt_request);
1699 tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
1700
1701 tt_request->header.packet_type = BATADV_TT_QUERY;
1702 tt_request->header.version = BATADV_COMPAT_VERSION;
1703 memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1704 memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1705 tt_request->header.ttl = BATADV_TTL;
1706 tt_request->ttvn = ttvn;
1707 tt_request->tt_data = htons(tt_crc);
1708 tt_request->flags = BATADV_TT_REQUEST;
1709 1698
1710 if (full_table) 1699 if (full_table)
1711 tt_request->flags |= BATADV_TT_FULL_TABLE; 1700 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1712 1701
1713 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n", 1702 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
1714 dst_orig_node->orig, (full_table ? 'F' : '.')); 1703 dst_orig_node->orig, full_table ? 'F' : '.');
1715 1704
1716 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); 1705 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1717 1706 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1718 if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP) 1707 dst_orig_node->orig, BATADV_TVLV_TT, 1,
1719 ret = 0; 1708 tvlv_tt_data, sizeof(*tvlv_tt_data));
1709 ret = true;
1720 1710
1721out: 1711out:
1722 if (primary_if) 1712 if (primary_if)
1723 batadv_hardif_free_ref(primary_if); 1713 batadv_hardif_free_ref(primary_if);
1724 if (ret)
1725 kfree_skb(skb);
1726 if (ret && tt_req_node) { 1714 if (ret && tt_req_node) {
1727 spin_lock_bh(&bat_priv->tt.req_list_lock); 1715 spin_lock_bh(&bat_priv->tt.req_list_lock);
1728 list_del(&tt_req_node->list); 1716 list_del(&tt_req_node->list);
1729 spin_unlock_bh(&bat_priv->tt.req_list_lock); 1717 spin_unlock_bh(&bat_priv->tt.req_list_lock);
1730 kfree(tt_req_node); 1718 kfree(tt_req_node);
1731 } 1719 }
1720 kfree(tvlv_tt_data);
1732 return ret; 1721 return ret;
1733} 1722}
1734 1723
1735static bool 1724/**
1736batadv_send_other_tt_response(struct batadv_priv *bat_priv, 1725 * batadv_send_other_tt_response - send reply to tt request concerning another
1737 struct batadv_tt_query_packet *tt_request) 1726 * node's translation table
1727 * @bat_priv: the bat priv with all the soft interface information
1728 * @tt_data: tt data containing the tt request information
1729 * @req_src: mac address of tt request sender
1730 * @req_dst: mac address of tt request recipient
1731 *
1732 * Returns true if tt request reply was sent, false otherwise.
1733 */
1734static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1735 struct batadv_tvlv_tt_data *tt_data,
1736 uint8_t *req_src, uint8_t *req_dst)
1738{ 1737{
1739 struct batadv_orig_node *req_dst_orig_node; 1738 struct batadv_orig_node *req_dst_orig_node;
1740 struct batadv_orig_node *res_dst_orig_node = NULL; 1739 struct batadv_orig_node *res_dst_orig_node = NULL;
1741 uint8_t orig_ttvn, req_ttvn, ttvn; 1740 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1742 int res, ret = false; 1741 uint8_t orig_ttvn, req_ttvn;
1743 unsigned char *tt_buff; 1742 uint16_t tt_len;
1744 bool full_table; 1743 bool ret = false, full_table;
1745 uint16_t tt_len, tt_tot;
1746 struct sk_buff *skb = NULL;
1747 struct batadv_tt_query_packet *tt_response;
1748 uint8_t *packet_pos;
1749 size_t len;
1750 1744
1751 batadv_dbg(BATADV_DBG_TT, bat_priv, 1745 batadv_dbg(BATADV_DBG_TT, bat_priv,
1752 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n", 1746 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
1753 tt_request->src, tt_request->ttvn, tt_request->dst, 1747 req_src, tt_data->ttvn, req_dst,
1754 (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1748 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1755 1749
1756 /* Let's get the orig node of the REAL destination */ 1750 /* Let's get the orig node of the REAL destination */
1757 req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst); 1751 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
1758 if (!req_dst_orig_node) 1752 if (!req_dst_orig_node)
1759 goto out; 1753 goto out;
1760 1754
1761 res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); 1755 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
1762 if (!res_dst_orig_node) 1756 if (!res_dst_orig_node)
1763 goto out; 1757 goto out;
1764 1758
1765 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1759 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1766 req_ttvn = tt_request->ttvn; 1760 req_ttvn = tt_data->ttvn;
1767 1761
1768 /* I don't have the requested data */ 1762 /* this node doesn't have the requested data */
1769 if (orig_ttvn != req_ttvn || 1763 if (orig_ttvn != req_ttvn ||
1770 tt_request->tt_data != htons(req_dst_orig_node->tt_crc)) 1764 tt_data->crc != htonl(req_dst_orig_node->tt_crc))
1771 goto out; 1765 goto out;
1772 1766
1773 /* If the full table has been explicitly requested */ 1767 /* If the full table has been explicitly requested */
1774 if (tt_request->flags & BATADV_TT_FULL_TABLE || 1768 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
1775 !req_dst_orig_node->tt_buff) 1769 !req_dst_orig_node->tt_buff)
1776 full_table = true; 1770 full_table = true;
1777 else 1771 else
1778 full_table = false; 1772 full_table = false;
1779 1773
1780 /* In this version, fragmentation is not implemented, then 1774 /* TT fragmentation hasn't been implemented yet, so send as many
1781 * I'll send only one packet with as much TT entries as I can 1775 * TT entries fit a single packet as possible only
1782 */ 1776 */
1783 if (!full_table) { 1777 if (!full_table) {
1784 spin_lock_bh(&req_dst_orig_node->tt_buff_lock); 1778 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1785 tt_len = req_dst_orig_node->tt_buff_len; 1779 tt_len = req_dst_orig_node->tt_buff_len;
1786 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1787 1780
1788 len = sizeof(*tt_response) + tt_len; 1781 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1789 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1782 GFP_ATOMIC);
1790 if (!skb) 1783 if (!tvlv_tt_data)
1791 goto unlock; 1784 goto unlock;
1792 1785
1793 skb->priority = TC_PRIO_CONTROL;
1794 skb_reserve(skb, ETH_HLEN);
1795 packet_pos = skb_put(skb, len);
1796 tt_response = (struct batadv_tt_query_packet *)packet_pos;
1797 tt_response->ttvn = req_ttvn;
1798 tt_response->tt_data = htons(tt_tot);
1799
1800 tt_buff = skb->data + sizeof(*tt_response);
1801 /* Copy the last orig_node's OGM buffer */ 1786 /* Copy the last orig_node's OGM buffer */
1802 memcpy(tt_buff, req_dst_orig_node->tt_buff, 1787 memcpy(tvlv_tt_data + 1, req_dst_orig_node->tt_buff,
1803 req_dst_orig_node->tt_buff_len); 1788 req_dst_orig_node->tt_buff_len);
1804
1805 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); 1789 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1806 } else { 1790 } else {
1807 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); 1791 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
1808 tt_len *= sizeof(struct batadv_tt_change); 1792 tt_len = batadv_tt_len(tt_len);
1809 ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1793
1810 1794 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
1811 skb = batadv_tt_response_fill_table(tt_len, ttvn, 1795 bat_priv->tt.global_hash,
1812 bat_priv->tt.global_hash, 1796 tt_len,
1813 bat_priv, 1797 batadv_tt_global_valid,
1814 batadv_tt_global_valid, 1798 req_dst_orig_node);
1815 req_dst_orig_node); 1799 if (!tvlv_tt_data)
1816 if (!skb)
1817 goto out; 1800 goto out;
1818
1819 tt_response = (struct batadv_tt_query_packet *)skb->data;
1820 } 1801 }
1821 1802
1822 tt_response->header.packet_type = BATADV_TT_QUERY; 1803 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
1823 tt_response->header.version = BATADV_COMPAT_VERSION; 1804 tvlv_tt_data->ttvn = req_ttvn;
1824 tt_response->header.ttl = BATADV_TTL;
1825 memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
1826 memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1827 tt_response->flags = BATADV_TT_RESPONSE;
1828 1805
1829 if (full_table) 1806 if (full_table)
1830 tt_response->flags |= BATADV_TT_FULL_TABLE; 1807 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1831 1808
1832 batadv_dbg(BATADV_DBG_TT, bat_priv, 1809 batadv_dbg(BATADV_DBG_TT, bat_priv,
1833 "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n", 1810 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
1834 res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn); 1811 res_dst_orig_node->orig, req_dst_orig_node->orig,
1812 full_table ? 'F' : '.', req_ttvn);
1835 1813
1836 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 1814 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1837 1815
1838 res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL); 1816 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
1839 if (res != NET_XMIT_DROP) 1817 req_src, BATADV_TVLV_TT, 1,
1840 ret = true; 1818 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
1841 1819
1820 ret = true;
1842 goto out; 1821 goto out;
1843 1822
1844unlock: 1823unlock:
@@ -1849,37 +1828,40 @@ out:
1849 batadv_orig_node_free_ref(res_dst_orig_node); 1828 batadv_orig_node_free_ref(res_dst_orig_node);
1850 if (req_dst_orig_node) 1829 if (req_dst_orig_node)
1851 batadv_orig_node_free_ref(req_dst_orig_node); 1830 batadv_orig_node_free_ref(req_dst_orig_node);
1852 if (!ret) 1831 kfree(tvlv_tt_data);
1853 kfree_skb(skb);
1854 return ret; 1832 return ret;
1855} 1833}
1856 1834
1857static bool 1835/**
1858batadv_send_my_tt_response(struct batadv_priv *bat_priv, 1836 * batadv_send_my_tt_response - send reply to tt request concerning this node's
1859 struct batadv_tt_query_packet *tt_request) 1837 * translation table
1838 * @bat_priv: the bat priv with all the soft interface information
1839 * @tt_data: tt data containing the tt request information
1840 * @req_src: mac address of tt request sender
1841 *
1842 * Returns true if tt request reply was sent, false otherwise.
1843 */
1844static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1845 struct batadv_tvlv_tt_data *tt_data,
1846 uint8_t *req_src)
1860{ 1847{
1848 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1861 struct batadv_orig_node *orig_node; 1849 struct batadv_orig_node *orig_node;
1862 struct batadv_hard_iface *primary_if = NULL; 1850 struct batadv_hard_iface *primary_if = NULL;
1863 uint8_t my_ttvn, req_ttvn, ttvn; 1851 uint8_t my_ttvn, req_ttvn;
1864 int ret = false;
1865 unsigned char *tt_buff;
1866 bool full_table; 1852 bool full_table;
1867 uint16_t tt_len, tt_tot; 1853 uint16_t tt_len;
1868 struct sk_buff *skb = NULL;
1869 struct batadv_tt_query_packet *tt_response;
1870 uint8_t *packet_pos;
1871 size_t len;
1872 1854
1873 batadv_dbg(BATADV_DBG_TT, bat_priv, 1855 batadv_dbg(BATADV_DBG_TT, bat_priv,
1874 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n", 1856 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
1875 tt_request->src, tt_request->ttvn, 1857 req_src, tt_data->ttvn,
1876 (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1858 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1877 1859
1878 1860
1879 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1861 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1880 req_ttvn = tt_request->ttvn; 1862 req_ttvn = tt_data->ttvn;
1881 1863
1882 orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); 1864 orig_node = batadv_orig_hash_find(bat_priv, req_src);
1883 if (!orig_node) 1865 if (!orig_node)
1884 goto out; 1866 goto out;
1885 1867
@@ -1890,71 +1872,58 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1890 /* If the full table has been explicitly requested or the gap 1872 /* If the full table has been explicitly requested or the gap
1891 * is too big send the whole local translation table 1873 * is too big send the whole local translation table
1892 */ 1874 */
1893 if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || 1875 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
1894 !bat_priv->tt.last_changeset) 1876 !bat_priv->tt.last_changeset)
1895 full_table = true; 1877 full_table = true;
1896 else 1878 else
1897 full_table = false; 1879 full_table = false;
1898 1880
1899 /* In this version, fragmentation is not implemented, then 1881 /* TT fragmentation hasn't been implemented yet, so send as many
1900 * I'll send only one packet with as much TT entries as I can 1882 * TT entries fit a single packet as possible only
1901 */ 1883 */
1902 if (!full_table) { 1884 if (!full_table) {
1903 spin_lock_bh(&bat_priv->tt.last_changeset_lock); 1885 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1904 tt_len = bat_priv->tt.last_changeset_len; 1886 tt_len = bat_priv->tt.last_changeset_len;
1905 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1906 1887
1907 len = sizeof(*tt_response) + tt_len; 1888 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1908 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1889 GFP_ATOMIC);
1909 if (!skb) 1890 if (!tvlv_tt_data)
1910 goto unlock; 1891 goto unlock;
1911 1892
1912 skb->priority = TC_PRIO_CONTROL; 1893 /* Copy the last orig_node's OGM buffer */
1913 skb_reserve(skb, ETH_HLEN); 1894 memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset,
1914 packet_pos = skb_put(skb, len);
1915 tt_response = (struct batadv_tt_query_packet *)packet_pos;
1916 tt_response->ttvn = req_ttvn;
1917 tt_response->tt_data = htons(tt_tot);
1918
1919 tt_buff = skb->data + sizeof(*tt_response);
1920 memcpy(tt_buff, bat_priv->tt.last_changeset,
1921 bat_priv->tt.last_changeset_len); 1895 bat_priv->tt.last_changeset_len);
1922 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 1896 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1923 } else { 1897 } else {
1924 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); 1898 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
1925 tt_len *= sizeof(struct batadv_tt_change); 1899 tt_len = batadv_tt_len(tt_len);
1926 ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1900 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1927 1901
1928 skb = batadv_tt_response_fill_table(tt_len, ttvn, 1902 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
1929 bat_priv->tt.local_hash, 1903 bat_priv->tt.local_hash,
1930 bat_priv, 1904 tt_len,
1931 batadv_tt_local_valid_entry, 1905 batadv_tt_local_valid,
1932 NULL); 1906 NULL);
1933 if (!skb) 1907 if (!tvlv_tt_data)
1934 goto out; 1908 goto out;
1935
1936 tt_response = (struct batadv_tt_query_packet *)skb->data;
1937 } 1909 }
1938 1910
1939 tt_response->header.packet_type = BATADV_TT_QUERY; 1911 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
1940 tt_response->header.version = BATADV_COMPAT_VERSION; 1912 tvlv_tt_data->ttvn = req_ttvn;
1941 tt_response->header.ttl = BATADV_TTL;
1942 memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1943 memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1944 tt_response->flags = BATADV_TT_RESPONSE;
1945 1913
1946 if (full_table) 1914 if (full_table)
1947 tt_response->flags |= BATADV_TT_FULL_TABLE; 1915 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1948 1916
1949 batadv_dbg(BATADV_DBG_TT, bat_priv, 1917 batadv_dbg(BATADV_DBG_TT, bat_priv,
1950 "Sending TT_RESPONSE to %pM [%c]\n", 1918 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
1951 orig_node->orig, 1919 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
1952 (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1953 1920
1954 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 1921 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1955 1922
1956 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 1923 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1957 ret = true; 1924 req_src, BATADV_TVLV_TT, 1,
1925 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
1926
1958 goto out; 1927 goto out;
1959 1928
1960unlock: 1929unlock:
@@ -1964,29 +1933,39 @@ out:
1964 batadv_orig_node_free_ref(orig_node); 1933 batadv_orig_node_free_ref(orig_node);
1965 if (primary_if) 1934 if (primary_if)
1966 batadv_hardif_free_ref(primary_if); 1935 batadv_hardif_free_ref(primary_if);
1967 if (!ret) 1936 kfree(tvlv_tt_data);
1968 kfree_skb(skb); 1937 /* The packet was for this host, so it doesn't need to be re-routed */
1969 /* This packet was for me, so it doesn't need to be re-routed */
1970 return true; 1938 return true;
1971} 1939}
1972 1940
1973bool batadv_send_tt_response(struct batadv_priv *bat_priv, 1941/**
1974 struct batadv_tt_query_packet *tt_request) 1942 * batadv_send_tt_response - send reply to tt request
1943 * @bat_priv: the bat priv with all the soft interface information
1944 * @tt_data: tt data containing the tt request information
1945 * @req_src: mac address of tt request sender
1946 * @req_dst: mac address of tt request recipient
1947 *
1948 * Returns true if tt request reply was sent, false otherwise.
1949 */
1950static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
1951 struct batadv_tvlv_tt_data *tt_data,
1952 uint8_t *req_src, uint8_t *req_dst)
1975{ 1953{
1976 if (batadv_is_my_mac(bat_priv, tt_request->dst)) { 1954 if (batadv_is_my_mac(bat_priv, req_dst)) {
1977 /* don't answer backbone gws! */ 1955 /* don't answer backbone gws! */
1978 if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src)) 1956 if (batadv_bla_is_backbone_gw_orig(bat_priv, req_src))
1979 return true; 1957 return true;
1980 1958
1981 return batadv_send_my_tt_response(bat_priv, tt_request); 1959 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
1982 } else { 1960 } else {
1983 return batadv_send_other_tt_response(bat_priv, tt_request); 1961 return batadv_send_other_tt_response(bat_priv, tt_data,
1962 req_src, req_dst);
1984 } 1963 }
1985} 1964}
1986 1965
1987static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, 1966static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
1988 struct batadv_orig_node *orig_node, 1967 struct batadv_orig_node *orig_node,
1989 struct batadv_tt_change *tt_change, 1968 struct batadv_tvlv_tt_change *tt_change,
1990 uint16_t tt_num_changes, uint8_t ttvn) 1969 uint16_t tt_num_changes, uint8_t ttvn)
1991{ 1970{
1992 int i; 1971 int i;
@@ -2016,11 +1995,12 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
2016} 1995}
2017 1996
2018static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 1997static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2019 struct batadv_tt_query_packet *tt_response) 1998 struct batadv_tvlv_tt_data *tt_data,
1999 uint8_t *resp_src, uint16_t num_entries)
2020{ 2000{
2021 struct batadv_orig_node *orig_node; 2001 struct batadv_orig_node *orig_node;
2022 2002
2023 orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 2003 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
2024 if (!orig_node) 2004 if (!orig_node)
2025 goto out; 2005 goto out;
2026 2006
@@ -2028,9 +2008,8 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2028 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); 2008 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
2029 2009
2030 _batadv_tt_update_changes(bat_priv, orig_node, 2010 _batadv_tt_update_changes(bat_priv, orig_node,
2031 (struct batadv_tt_change *)(tt_response + 1), 2011 (struct batadv_tvlv_tt_change *)(tt_data + 1),
2032 ntohs(tt_response->tt_data), 2012 num_entries, tt_data->ttvn);
2033 tt_response->ttvn);
2034 2013
2035 spin_lock_bh(&orig_node->tt_buff_lock); 2014 spin_lock_bh(&orig_node->tt_buff_lock);
2036 kfree(orig_node->tt_buff); 2015 kfree(orig_node->tt_buff);
@@ -2038,7 +2017,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2038 orig_node->tt_buff = NULL; 2017 orig_node->tt_buff = NULL;
2039 spin_unlock_bh(&orig_node->tt_buff_lock); 2018 spin_unlock_bh(&orig_node->tt_buff_lock);
2040 2019
2041 atomic_set(&orig_node->last_ttvn, tt_response->ttvn); 2020 atomic_set(&orig_node->last_ttvn, tt_data->ttvn);
2042 2021
2043out: 2022out:
2044 if (orig_node) 2023 if (orig_node)
@@ -2048,7 +2027,7 @@ out:
2048static void batadv_tt_update_changes(struct batadv_priv *bat_priv, 2027static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
2049 struct batadv_orig_node *orig_node, 2028 struct batadv_orig_node *orig_node,
2050 uint16_t tt_num_changes, uint8_t ttvn, 2029 uint16_t tt_num_changes, uint8_t ttvn,
2051 struct batadv_tt_change *tt_change) 2030 struct batadv_tvlv_tt_change *tt_change)
2052{ 2031{
2053 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, 2032 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
2054 tt_num_changes, ttvn); 2033 tt_num_changes, ttvn);
@@ -2079,40 +2058,46 @@ out:
2079 return ret; 2058 return ret;
2080} 2059}
2081 2060
2082void batadv_handle_tt_response(struct batadv_priv *bat_priv, 2061/**
2083 struct batadv_tt_query_packet *tt_response) 2062 * batadv_handle_tt_response - process incoming tt reply
2063 * @bat_priv: the bat priv with all the soft interface information
2064 * @tt_data: tt data containing the tt request information
2065 * @resp_src: mac address of tt reply sender
2066 * @num_entries: number of tt change entries appended to the tt data
2067 */
2068static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2069 struct batadv_tvlv_tt_data *tt_data,
2070 uint8_t *resp_src, uint16_t num_entries)
2084{ 2071{
2085 struct batadv_tt_req_node *node, *safe; 2072 struct batadv_tt_req_node *node, *safe;
2086 struct batadv_orig_node *orig_node = NULL; 2073 struct batadv_orig_node *orig_node = NULL;
2087 struct batadv_tt_change *tt_change; 2074 struct batadv_tvlv_tt_change *tt_change;
2088 2075
2089 batadv_dbg(BATADV_DBG_TT, bat_priv, 2076 batadv_dbg(BATADV_DBG_TT, bat_priv,
2090 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", 2077 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
2091 tt_response->src, tt_response->ttvn, 2078 resp_src, tt_data->ttvn, num_entries,
2092 ntohs(tt_response->tt_data), 2079 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2093 (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2094 2080
2095 /* we should have never asked a backbone gw */ 2081 /* we should have never asked a backbone gw */
2096 if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src)) 2082 if (batadv_bla_is_backbone_gw_orig(bat_priv, resp_src))
2097 goto out; 2083 goto out;
2098 2084
2099 orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 2085 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
2100 if (!orig_node) 2086 if (!orig_node)
2101 goto out; 2087 goto out;
2102 2088
2103 if (tt_response->flags & BATADV_TT_FULL_TABLE) { 2089 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
2104 batadv_tt_fill_gtable(bat_priv, tt_response); 2090 batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries);
2105 } else { 2091 } else {
2106 tt_change = (struct batadv_tt_change *)(tt_response + 1); 2092 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
2107 batadv_tt_update_changes(bat_priv, orig_node, 2093 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
2108 ntohs(tt_response->tt_data), 2094 tt_data->ttvn, tt_change);
2109 tt_response->ttvn, tt_change);
2110 } 2095 }
2111 2096
2112 /* Delete the tt_req_node from pending tt_requests list */ 2097 /* Delete the tt_req_node from pending tt_requests list */
2113 spin_lock_bh(&bat_priv->tt.req_list_lock); 2098 spin_lock_bh(&bat_priv->tt.req_list_lock);
2114 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { 2099 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2115 if (!batadv_compare_eth(node->addr, tt_response->src)) 2100 if (!batadv_compare_eth(node->addr, resp_src))
2116 continue; 2101 continue;
2117 list_del(&node->list); 2102 list_del(&node->list);
2118 kfree(node); 2103 kfree(node);
@@ -2126,25 +2111,6 @@ out:
2126 batadv_orig_node_free_ref(orig_node); 2111 batadv_orig_node_free_ref(orig_node);
2127} 2112}
2128 2113
2129int batadv_tt_init(struct batadv_priv *bat_priv)
2130{
2131 int ret;
2132
2133 ret = batadv_tt_local_init(bat_priv);
2134 if (ret < 0)
2135 return ret;
2136
2137 ret = batadv_tt_global_init(bat_priv);
2138 if (ret < 0)
2139 return ret;
2140
2141 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
2142 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
2143 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
2144
2145 return 1;
2146}
2147
2148static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) 2114static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
2149{ 2115{
2150 struct batadv_tt_roam_node *node, *safe; 2116 struct batadv_tt_roam_node *node, *safe;
@@ -2228,11 +2194,12 @@ unlock:
2228static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, 2194static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
2229 struct batadv_orig_node *orig_node) 2195 struct batadv_orig_node *orig_node)
2230{ 2196{
2231 struct sk_buff *skb = NULL;
2232 struct batadv_roam_adv_packet *roam_adv_packet;
2233 int ret = 1;
2234 struct batadv_hard_iface *primary_if; 2197 struct batadv_hard_iface *primary_if;
2235 size_t len = sizeof(*roam_adv_packet); 2198 struct batadv_tvlv_roam_adv tvlv_roam;
2199
2200 primary_if = batadv_primary_if_get_selected(bat_priv);
2201 if (!primary_if)
2202 goto out;
2236 2203
2237 /* before going on we have to check whether the client has 2204 /* before going on we have to check whether the client has
2238 * already roamed to us too many times 2205 * already roamed to us too many times
@@ -2240,40 +2207,22 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
2240 if (!batadv_tt_check_roam_count(bat_priv, client)) 2207 if (!batadv_tt_check_roam_count(bat_priv, client))
2241 goto out; 2208 goto out;
2242 2209
2243 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
2244 if (!skb)
2245 goto out;
2246
2247 skb->priority = TC_PRIO_CONTROL;
2248 skb_reserve(skb, ETH_HLEN);
2249
2250 roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
2251
2252 roam_adv_packet->header.packet_type = BATADV_ROAM_ADV;
2253 roam_adv_packet->header.version = BATADV_COMPAT_VERSION;
2254 roam_adv_packet->header.ttl = BATADV_TTL;
2255 roam_adv_packet->reserved = 0;
2256 primary_if = batadv_primary_if_get_selected(bat_priv);
2257 if (!primary_if)
2258 goto out;
2259 memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
2260 batadv_hardif_free_ref(primary_if);
2261 memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
2262 memcpy(roam_adv_packet->client, client, ETH_ALEN);
2263
2264 batadv_dbg(BATADV_DBG_TT, bat_priv, 2210 batadv_dbg(BATADV_DBG_TT, bat_priv,
2265 "Sending ROAMING_ADV to %pM (client %pM)\n", 2211 "Sending ROAMING_ADV to %pM (client %pM)\n",
2266 orig_node->orig, client); 2212 orig_node->orig, client);
2267 2213
2268 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); 2214 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
2269 2215
2270 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 2216 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
2271 ret = 0; 2217 tvlv_roam.reserved = 0;
2218
2219 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
2220 orig_node->orig, BATADV_TVLV_ROAM, 1,
2221 &tvlv_roam, sizeof(tvlv_roam));
2272 2222
2273out: 2223out:
2274 if (ret && skb) 2224 if (primary_if)
2275 kfree_skb(skb); 2225 batadv_hardif_free_ref(primary_if);
2276 return;
2277} 2226}
2278 2227
2279static void batadv_tt_purge(struct work_struct *work) 2228static void batadv_tt_purge(struct work_struct *work)
@@ -2297,6 +2246,9 @@ static void batadv_tt_purge(struct work_struct *work)
2297 2246
2298void batadv_tt_free(struct batadv_priv *bat_priv) 2247void batadv_tt_free(struct batadv_priv *bat_priv)
2299{ 2248{
2249 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
2250 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
2251
2300 cancel_delayed_work_sync(&bat_priv->tt.work); 2252 cancel_delayed_work_sync(&bat_priv->tt.work);
2301 2253
2302 batadv_tt_local_table_free(bat_priv); 2254 batadv_tt_local_table_free(bat_priv);
@@ -2384,14 +2336,20 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2384 } 2336 }
2385} 2337}
2386 2338
2387static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, 2339/**
2388 unsigned char **packet_buff, 2340 * batadv_tt_local_commit_changes - commit all pending local tt changes which
2389 int *packet_buff_len, int packet_min_len) 2341 * have been queued in the time since the last commit
2342 * @bat_priv: the bat priv with all the soft interface information
2343 */
2344void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2390{ 2345{
2391 uint16_t changed_num = 0; 2346 uint16_t changed_num = 0;
2392 2347
2393 if (atomic_read(&bat_priv->tt.local_changes) < 1) 2348 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
2394 return -ENOENT; 2349 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
2350 batadv_tt_tvlv_container_update(bat_priv);
2351 return;
2352 }
2395 2353
2396 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, 2354 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
2397 BATADV_TT_CLIENT_NEW, false); 2355 BATADV_TT_CLIENT_NEW, false);
@@ -2409,32 +2367,7 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2409 2367
2410 /* reset the sending counter */ 2368 /* reset the sending counter */
2411 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); 2369 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
2412 2370 batadv_tt_tvlv_container_update(bat_priv);
2413 return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
2414 packet_buff_len, packet_min_len);
2415}
2416
2417/* when calling this function (hard_iface == primary_if) has to be true */
2418int batadv_tt_append_diff(struct batadv_priv *bat_priv,
2419 unsigned char **packet_buff, int *packet_buff_len,
2420 int packet_min_len)
2421{
2422 int tt_num_changes;
2423
2424 /* if at least one change happened */
2425 tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff,
2426 packet_buff_len,
2427 packet_min_len);
2428
2429 /* if the changes have been sent often enough */
2430 if ((tt_num_changes < 0) &&
2431 (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
2432 batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
2433 packet_min_len, packet_min_len);
2434 tt_num_changes = 0;
2435 }
2436
2437 return tt_num_changes;
2438} 2371}
2439 2372
2440bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 2373bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
@@ -2468,14 +2401,25 @@ out:
2468 return ret; 2401 return ret;
2469} 2402}
2470 2403
2471void batadv_tt_update_orig(struct batadv_priv *bat_priv, 2404/**
2472 struct batadv_orig_node *orig_node, 2405 * batadv_tt_update_orig - update global translation table with new tt
2473 const unsigned char *tt_buff, uint8_t tt_num_changes, 2406 * information received via ogms
2474 uint8_t ttvn, uint16_t tt_crc) 2407 * @bat_priv: the bat priv with all the soft interface information
2408 * @orig: the orig_node of the ogm
2409 * @tt_buff: buffer holding the tt information
2410 * @tt_num_changes: number of tt changes inside the tt buffer
2411 * @ttvn: translation table version number of this changeset
2412 * @tt_crc: crc32 checksum of orig node's translation table
2413 */
2414static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2415 struct batadv_orig_node *orig_node,
2416 const unsigned char *tt_buff,
2417 uint16_t tt_num_changes, uint8_t ttvn,
2418 uint32_t tt_crc)
2475{ 2419{
2476 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 2420 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
2477 bool full_table = true; 2421 bool full_table = true;
2478 struct batadv_tt_change *tt_change; 2422 struct batadv_tvlv_tt_change *tt_change;
2479 2423
2480 /* don't care about a backbone gateways updates. */ 2424 /* don't care about a backbone gateways updates. */
2481 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) 2425 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
@@ -2496,7 +2440,7 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2496 goto request_table; 2440 goto request_table;
2497 } 2441 }
2498 2442
2499 tt_change = (struct batadv_tt_change *)tt_buff; 2443 tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
2500 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, 2444 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2501 ttvn, tt_change); 2445 ttvn, tt_change);
2502 2446
@@ -2525,7 +2469,7 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2525 orig_node->tt_crc != tt_crc) { 2469 orig_node->tt_crc != tt_crc) {
2526request_table: 2470request_table:
2527 batadv_dbg(BATADV_DBG_TT, bat_priv, 2471 batadv_dbg(BATADV_DBG_TT, bat_priv,
2528 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u)\n", 2472 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.8x last_crc: %#.8x num_changes: %u)\n",
2529 orig_node->orig, ttvn, orig_ttvn, tt_crc, 2473 orig_node->orig, ttvn, orig_ttvn, tt_crc,
2530 orig_node->tt_crc, tt_num_changes); 2474 orig_node->tt_crc, tt_num_changes);
2531 batadv_send_tt_request(bat_priv, orig_node, ttvn, 2475 batadv_send_tt_request(bat_priv, orig_node, ttvn,
@@ -2605,3 +2549,198 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2605out: 2549out:
2606 return ret; 2550 return ret;
2607} 2551}
2552
2553/**
2554 * batadv_tt_tvlv_ogm_handler_v1 - process incoming tt tvlv container
2555 * @bat_priv: the bat priv with all the soft interface information
2556 * @orig: the orig_node of the ogm
2557 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
2558 * @tvlv_value: tvlv buffer containing the gateway data
2559 * @tvlv_value_len: tvlv buffer length
2560 */
2561static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2562 struct batadv_orig_node *orig,
2563 uint8_t flags,
2564 void *tvlv_value,
2565 uint16_t tvlv_value_len)
2566{
2567 struct batadv_tvlv_tt_data *tt_data;
2568 uint16_t num_entries;
2569
2570 if (tvlv_value_len < sizeof(*tt_data))
2571 return;
2572
2573 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2574 tvlv_value_len -= sizeof(*tt_data);
2575
2576 num_entries = tvlv_value_len / batadv_tt_len(1);
2577
2578 batadv_tt_update_orig(bat_priv, orig,
2579 (unsigned char *)(tt_data + 1),
2580 num_entries, tt_data->ttvn, ntohl(tt_data->crc));
2581}
2582
2583/**
2584 * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv
2585 * container
2586 * @bat_priv: the bat priv with all the soft interface information
2587 * @src: mac address of tt tvlv sender
2588 * @dst: mac address of tt tvlv recipient
2589 * @tvlv_value: tvlv buffer containing the tt data
2590 * @tvlv_value_len: tvlv buffer length
2591 *
2592 * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
2593 * otherwise.
2594 */
2595static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2596 uint8_t *src, uint8_t *dst,
2597 void *tvlv_value,
2598 uint16_t tvlv_value_len)
2599{
2600 struct batadv_tvlv_tt_data *tt_data;
2601 uint16_t num_entries;
2602 char tt_flag;
2603 bool ret;
2604
2605 if (tvlv_value_len < sizeof(*tt_data))
2606 return NET_RX_SUCCESS;
2607
2608 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2609 tvlv_value_len -= sizeof(*tt_data);
2610
2611 num_entries = tvlv_value_len / batadv_tt_len(1);
2612
2613 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
2614 case BATADV_TT_REQUEST:
2615 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
2616
2617 /* If this node cannot provide a TT response the tt_request is
2618 * forwarded
2619 */
2620 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
2621 if (!ret) {
2622 if (tt_data->flags & BATADV_TT_FULL_TABLE)
2623 tt_flag = 'F';
2624 else
2625 tt_flag = '.';
2626
2627 batadv_dbg(BATADV_DBG_TT, bat_priv,
2628 "Routing TT_REQUEST to %pM [%c]\n",
2629 dst, tt_flag);
2630 /* tvlv API will re-route the packet */
2631 return NET_RX_DROP;
2632 }
2633 break;
2634 case BATADV_TT_RESPONSE:
2635 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
2636
2637 if (batadv_is_my_mac(bat_priv, dst)) {
2638 batadv_handle_tt_response(bat_priv, tt_data,
2639 src, num_entries);
2640 return NET_RX_SUCCESS;
2641 }
2642
2643 if (tt_data->flags & BATADV_TT_FULL_TABLE)
2644 tt_flag = 'F';
2645 else
2646 tt_flag = '.';
2647
2648 batadv_dbg(BATADV_DBG_TT, bat_priv,
2649 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
2650
2651 /* tvlv API will re-route the packet */
2652 return NET_RX_DROP;
2653 }
2654
2655 return NET_RX_SUCCESS;
2656}
2657
2658/**
2659 * batadv_roam_tvlv_unicast_handler_v1 - process incoming tt roam tvlv container
2660 * @bat_priv: the bat priv with all the soft interface information
2661 * @src: mac address of tt tvlv sender
2662 * @dst: mac address of tt tvlv recipient
2663 * @tvlv_value: tvlv buffer containing the tt data
2664 * @tvlv_value_len: tvlv buffer length
2665 *
2666 * Returns NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
2667 * otherwise.
2668 */
2669static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2670 uint8_t *src, uint8_t *dst,
2671 void *tvlv_value,
2672 uint16_t tvlv_value_len)
2673{
2674 struct batadv_tvlv_roam_adv *roaming_adv;
2675 struct batadv_orig_node *orig_node = NULL;
2676
2677 /* If this node is not the intended recipient of the
2678 * roaming advertisement the packet is forwarded
2679 * (the tvlv API will re-route the packet).
2680 */
2681 if (!batadv_is_my_mac(bat_priv, dst))
2682 return NET_RX_DROP;
2683
2684 /* check if it is a backbone gateway. we don't accept
2685 * roaming advertisement from it, as it has the same
2686 * entries as we have.
2687 */
2688 if (batadv_bla_is_backbone_gw_orig(bat_priv, src))
2689 goto out;
2690
2691 if (tvlv_value_len < sizeof(*roaming_adv))
2692 goto out;
2693
2694 orig_node = batadv_orig_hash_find(bat_priv, src);
2695 if (!orig_node)
2696 goto out;
2697
2698 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
2699 roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value;
2700
2701 batadv_dbg(BATADV_DBG_TT, bat_priv,
2702 "Received ROAMING_ADV from %pM (client %pM)\n",
2703 src, roaming_adv->client);
2704
2705 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
2706 BATADV_TT_CLIENT_ROAM,
2707 atomic_read(&orig_node->last_ttvn) + 1);
2708
2709out:
2710 if (orig_node)
2711 batadv_orig_node_free_ref(orig_node);
2712 return NET_RX_SUCCESS;
2713}
2714
2715/**
2716 * batadv_tt_init - initialise the translation table internals
2717 * @bat_priv: the bat priv with all the soft interface information
2718 *
2719 * Return 0 on success or negative error number in case of failure.
2720 */
2721int batadv_tt_init(struct batadv_priv *bat_priv)
2722{
2723 int ret;
2724
2725 ret = batadv_tt_local_init(bat_priv);
2726 if (ret < 0)
2727 return ret;
2728
2729 ret = batadv_tt_global_init(bat_priv);
2730 if (ret < 0)
2731 return ret;
2732
2733 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
2734 batadv_tt_tvlv_unicast_handler_v1,
2735 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
2736
2737 batadv_tvlv_handler_register(bat_priv, NULL,
2738 batadv_roam_tvlv_unicast_handler_v1,
2739 BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
2740
2741 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
2742 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
2743 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
2744
2745 return 1;
2746}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 659a3bb759ce..b4b6dea4e2be 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -20,7 +20,6 @@
20#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ 20#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
21#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ 21#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
22 22
23int batadv_tt_len(int changes_num);
24int batadv_tt_init(struct batadv_priv *bat_priv); 23int batadv_tt_init(struct batadv_priv *bat_priv);
25void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 24void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
26 int ifindex); 25 int ifindex);
@@ -43,20 +42,10 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
43 const uint8_t *src, 42 const uint8_t *src,
44 const uint8_t *addr); 43 const uint8_t *addr);
45void batadv_tt_free(struct batadv_priv *bat_priv); 44void batadv_tt_free(struct batadv_priv *bat_priv);
46bool batadv_send_tt_response(struct batadv_priv *bat_priv,
47 struct batadv_tt_query_packet *tt_request);
48bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); 45bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr);
49void batadv_handle_tt_response(struct batadv_priv *bat_priv,
50 struct batadv_tt_query_packet *tt_response);
51bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 46bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
52 uint8_t *dst); 47 uint8_t *dst);
53void batadv_tt_update_orig(struct batadv_priv *bat_priv, 48void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv);
54 struct batadv_orig_node *orig_node,
55 const unsigned char *tt_buff, uint8_t tt_num_changes,
56 uint8_t ttvn, uint16_t tt_crc);
57int batadv_tt_append_diff(struct batadv_priv *bat_priv,
58 unsigned char **packet_buff, int *packet_buff_len,
59 int packet_min_len);
60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 49bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
61 uint8_t *addr); 50 uint8_t *addr);
62bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, 51bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index b2c94e139319..8fbd89d167cd 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -99,8 +99,7 @@ struct batadv_hard_iface {
99 * @last_seen: time when last packet from this node was received 99 * @last_seen: time when last packet from this node was received
100 * @bcast_seqno_reset: time when the broadcast seqno window was reset 100 * @bcast_seqno_reset: time when the broadcast seqno window was reset
101 * @batman_seqno_reset: time when the batman seqno window was reset 101 * @batman_seqno_reset: time when the batman seqno window was reset
102 * @gw_flags: flags related to gateway class 102 * @capabilities: announced capabilities of this originator
103 * @flags: for now only VIS_SERVER flag
104 * @last_ttvn: last seen translation table version number 103 * @last_ttvn: last seen translation table version number
105 * @tt_crc: CRC of the translation table 104 * @tt_crc: CRC of the translation table
106 * @tt_buff: last tt changeset this node received from the orig node 105 * @tt_buff: last tt changeset this node received from the orig node
@@ -147,10 +146,9 @@ struct batadv_orig_node {
147 unsigned long last_seen; 146 unsigned long last_seen;
148 unsigned long bcast_seqno_reset; 147 unsigned long bcast_seqno_reset;
149 unsigned long batman_seqno_reset; 148 unsigned long batman_seqno_reset;
150 uint8_t gw_flags; 149 uint8_t capabilities;
151 uint8_t flags;
152 atomic_t last_ttvn; 150 atomic_t last_ttvn;
153 uint16_t tt_crc; 151 uint32_t tt_crc;
154 unsigned char *tt_buff; 152 unsigned char *tt_buff;
155 int16_t tt_buff_len; 153 int16_t tt_buff_len;
156 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ 154 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */
@@ -186,9 +184,21 @@ struct batadv_orig_node {
186}; 184};
187 185
188/** 186/**
187 * enum batadv_orig_capabilities - orig node capabilities
188 * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled
189 * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled
190 */
191enum batadv_orig_capabilities {
192 BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
193 BATADV_ORIG_CAPA_HAS_NC = BIT(1),
194};
195
196/**
189 * struct batadv_gw_node - structure for orig nodes announcing gw capabilities 197 * struct batadv_gw_node - structure for orig nodes announcing gw capabilities
190 * @list: list node for batadv_priv_gw::list 198 * @list: list node for batadv_priv_gw::list
191 * @orig_node: pointer to corresponding orig node 199 * @orig_node: pointer to corresponding orig node
200 * @bandwidth_down: advertised uplink download bandwidth
201 * @bandwidth_up: advertised uplink upload bandwidth
192 * @deleted: this struct is scheduled for deletion 202 * @deleted: this struct is scheduled for deletion
193 * @refcount: number of contexts the object is used 203 * @refcount: number of contexts the object is used
194 * @rcu: struct used for freeing in an RCU-safe manner 204 * @rcu: struct used for freeing in an RCU-safe manner
@@ -196,6 +206,8 @@ struct batadv_orig_node {
196struct batadv_gw_node { 206struct batadv_gw_node {
197 struct hlist_node list; 207 struct hlist_node list;
198 struct batadv_orig_node *orig_node; 208 struct batadv_orig_node *orig_node;
209 uint32_t bandwidth_down;
210 uint32_t bandwidth_up;
199 unsigned long deleted; 211 unsigned long deleted;
200 atomic_t refcount; 212 atomic_t refcount;
201 struct rcu_head rcu; 213 struct rcu_head rcu;
@@ -363,7 +375,7 @@ struct batadv_priv_tt {
363 spinlock_t req_list_lock; /* protects req_list */ 375 spinlock_t req_list_lock; /* protects req_list */
364 spinlock_t roam_list_lock; /* protects roam_list */ 376 spinlock_t roam_list_lock; /* protects roam_list */
365 atomic_t local_entry_num; 377 atomic_t local_entry_num;
366 uint16_t local_crc; 378 uint32_t local_crc;
367 unsigned char *last_changeset; 379 unsigned char *last_changeset;
368 int16_t last_changeset_len; 380 int16_t last_changeset_len;
369 /* protects last_changeset & last_changeset_len */ 381 /* protects last_changeset & last_changeset_len */
@@ -420,31 +432,31 @@ struct batadv_priv_debug_log {
420 * @list: list of available gateway nodes 432 * @list: list of available gateway nodes
421 * @list_lock: lock protecting gw_list & curr_gw 433 * @list_lock: lock protecting gw_list & curr_gw
422 * @curr_gw: pointer to currently selected gateway node 434 * @curr_gw: pointer to currently selected gateway node
435 * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server)
436 * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server)
423 * @reselect: bool indicating a gateway re-selection is in progress 437 * @reselect: bool indicating a gateway re-selection is in progress
424 */ 438 */
425struct batadv_priv_gw { 439struct batadv_priv_gw {
426 struct hlist_head list; 440 struct hlist_head list;
427 spinlock_t list_lock; /* protects gw_list & curr_gw */ 441 spinlock_t list_lock; /* protects gw_list & curr_gw */
428 struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ 442 struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */
443 atomic_t bandwidth_down;
444 atomic_t bandwidth_up;
429 atomic_t reselect; 445 atomic_t reselect;
430}; 446};
431 447
432/** 448/**
433 * struct batadv_priv_vis - per mesh interface vis data 449 * struct batadv_priv_tvlv - per mesh interface tvlv data
434 * @send_list: list of batadv_vis_info packets to sent 450 * @container_list: list of registered tvlv containers to be sent with each OGM
435 * @hash: hash table containing vis data from other nodes in the network 451 * @handler_list: list of the various tvlv content handlers
436 * @hash_lock: lock protecting the hash table 452 * @container_list_lock: protects tvlv container list access
437 * @list_lock: lock protecting my_info::recv_list 453 * @handler_list_lock: protects handler list access
438 * @work: work queue callback item for vis packet sending
439 * @my_info: holds this node's vis data sent on a regular basis
440 */ 454 */
441struct batadv_priv_vis { 455struct batadv_priv_tvlv {
442 struct list_head send_list; 456 struct hlist_head container_list;
443 struct batadv_hashtable *hash; 457 struct hlist_head handler_list;
444 spinlock_t hash_lock; /* protects hash */ 458 spinlock_t container_list_lock; /* protects container_list */
445 spinlock_t list_lock; /* protects my_info::recv_list */ 459 spinlock_t handler_list_lock; /* protects handler_list */
446 struct delayed_work work;
447 struct batadv_vis_info *my_info;
448}; 460};
449 461
450/** 462/**
@@ -504,10 +516,8 @@ struct batadv_priv_nc {
504 * enabled 516 * enabled
505 * @distributed_arp_table: bool indicating whether distributed ARP table is 517 * @distributed_arp_table: bool indicating whether distributed ARP table is
506 * enabled 518 * enabled
507 * @vis_mode: vis operation: client or server (see batadv_vis_packettype)
508 * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) 519 * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes)
509 * @gw_sel_class: gateway selection class (applies if gw_mode client) 520 * @gw_sel_class: gateway selection class (applies if gw_mode client)
510 * @gw_bandwidth: gateway announced bandwidth (applies if gw_mode server)
511 * @orig_interval: OGM broadcast interval in milliseconds 521 * @orig_interval: OGM broadcast interval in milliseconds
512 * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop 522 * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop
513 * @log_level: configured log level (see batadv_dbg_level) 523 * @log_level: configured log level (see batadv_dbg_level)
@@ -531,7 +541,7 @@ struct batadv_priv_nc {
531 * @debug_log: holding debug logging relevant data 541 * @debug_log: holding debug logging relevant data
532 * @gw: gateway data 542 * @gw: gateway data
533 * @tt: translation table data 543 * @tt: translation table data
534 * @vis: vis data 544 * @tvlv: type-version-length-value data
535 * @dat: distributed arp table data 545 * @dat: distributed arp table data
536 * @network_coding: bool indicating whether network coding is enabled 546 * @network_coding: bool indicating whether network coding is enabled
537 * @batadv_priv_nc: network coding data 547 * @batadv_priv_nc: network coding data
@@ -551,10 +561,8 @@ struct batadv_priv {
551#ifdef CONFIG_BATMAN_ADV_DAT 561#ifdef CONFIG_BATMAN_ADV_DAT
552 atomic_t distributed_arp_table; 562 atomic_t distributed_arp_table;
553#endif 563#endif
554 atomic_t vis_mode;
555 atomic_t gw_mode; 564 atomic_t gw_mode;
556 atomic_t gw_sel_class; 565 atomic_t gw_sel_class;
557 atomic_t gw_bandwidth;
558 atomic_t orig_interval; 566 atomic_t orig_interval;
559 atomic_t hop_penalty; 567 atomic_t hop_penalty;
560#ifdef CONFIG_BATMAN_ADV_DEBUG 568#ifdef CONFIG_BATMAN_ADV_DEBUG
@@ -583,7 +591,7 @@ struct batadv_priv {
583#endif 591#endif
584 struct batadv_priv_gw gw; 592 struct batadv_priv_gw gw;
585 struct batadv_priv_tt tt; 593 struct batadv_priv_tt tt;
586 struct batadv_priv_vis vis; 594 struct batadv_priv_tvlv tvlv;
587#ifdef CONFIG_BATMAN_ADV_DAT 595#ifdef CONFIG_BATMAN_ADV_DAT
588 struct batadv_priv_dat dat; 596 struct batadv_priv_dat dat;
589#endif 597#endif
@@ -740,7 +748,7 @@ struct batadv_tt_orig_list_entry {
740 */ 748 */
741struct batadv_tt_change_node { 749struct batadv_tt_change_node {
742 struct list_head list; 750 struct list_head list;
743 struct batadv_tt_change change; 751 struct batadv_tvlv_tt_change change;
744}; 752};
745 753
746/** 754/**
@@ -878,66 +886,6 @@ struct batadv_frag_packet_list_entry {
878}; 886};
879 887
880/** 888/**
881 * struct batadv_vis_info - local data for vis information
882 * @first_seen: timestamp used for purging stale vis info entries
883 * @recv_list: List of server-neighbors we have received this packet from. This
884 * packet should not be re-forward to them again. List elements are struct
885 * batadv_vis_recvlist_node
886 * @send_list: list of packets to be forwarded
887 * @refcount: number of contexts the object is used
888 * @hash_entry: hlist node for batadv_priv_vis::hash
889 * @bat_priv: pointer to soft_iface this orig node belongs to
890 * @skb_packet: contains the vis packet
891 */
892struct batadv_vis_info {
893 unsigned long first_seen;
894 struct list_head recv_list;
895 struct list_head send_list;
896 struct kref refcount;
897 struct hlist_node hash_entry;
898 struct batadv_priv *bat_priv;
899 struct sk_buff *skb_packet;
900} __packed;
901
902/**
903 * struct batadv_vis_info_entry - contains link information for vis
904 * @src: source MAC of the link, all zero for local TT entry
905 * @dst: destination MAC of the link, client mac address for local TT entry
906 * @quality: transmission quality of the link, or 0 for local TT entry
907 */
908struct batadv_vis_info_entry {
909 uint8_t src[ETH_ALEN];
910 uint8_t dest[ETH_ALEN];
911 uint8_t quality;
912} __packed;
913
914/**
915 * struct batadv_vis_recvlist_node - list entry for batadv_vis_info::recv_list
916 * @list: list node for batadv_vis_info::recv_list
917 * @mac: MAC address of the originator from where the vis_info was received
918 */
919struct batadv_vis_recvlist_node {
920 struct list_head list;
921 uint8_t mac[ETH_ALEN];
922};
923
924/**
925 * struct batadv_vis_if_list_entry - auxiliary data for vis data generation
926 * @addr: MAC address of the interface
927 * @primary: true if this interface is the primary interface
928 * @list: list node the interface list
929 *
930 * While scanning for vis-entries of a particular vis-originator
931 * this list collects its interfaces to create a subgraph/cluster
932 * out of them later
933 */
934struct batadv_vis_if_list_entry {
935 uint8_t addr[ETH_ALEN];
936 bool primary;
937 struct hlist_node list;
938};
939
940/**
941 * struct batadv_algo_ops - mesh algorithm callbacks 889 * struct batadv_algo_ops - mesh algorithm callbacks
942 * @list: list node for the batadv_algo_list 890 * @list: list node for the batadv_algo_list
943 * @name: name of the algorithm 891 * @name: name of the algorithm
@@ -992,4 +940,60 @@ struct batadv_dat_candidate {
992 struct batadv_orig_node *orig_node; 940 struct batadv_orig_node *orig_node;
993}; 941};
994 942
943/**
944 * struct batadv_tvlv_container - container for tvlv appended to OGMs
945 * @list: hlist node for batadv_priv_tvlv::container_list
946 * @tvlv_hdr: tvlv header information needed to construct the tvlv
947 * @value_len: length of the buffer following this struct which contains
948 * the actual tvlv payload
949 * @refcount: number of contexts the object is used
950 */
951struct batadv_tvlv_container {
952 struct hlist_node list;
953 struct batadv_tvlv_hdr tvlv_hdr;
954 atomic_t refcount;
955};
956
957/**
958 * struct batadv_tvlv_handler - handler for specific tvlv type and version
959 * @list: hlist node for batadv_priv_tvlv::handler_list
960 * @ogm_handler: handler callback which is given the tvlv payload to process on
961 * incoming OGM packets
962 * @unicast_handler: handler callback which is given the tvlv payload to process
963 * on incoming unicast tvlv packets
964 * @type: tvlv type this handler feels responsible for
965 * @version: tvlv version this handler feels responsible for
966 * @flags: tvlv handler flags
967 * @refcount: number of contexts the object is used
968 * @rcu: struct used for freeing in an RCU-safe manner
969 */
970struct batadv_tvlv_handler {
971 struct hlist_node list;
972 void (*ogm_handler)(struct batadv_priv *bat_priv,
973 struct batadv_orig_node *orig,
974 uint8_t flags,
975 void *tvlv_value, uint16_t tvlv_value_len);
976 int (*unicast_handler)(struct batadv_priv *bat_priv,
977 uint8_t *src, uint8_t *dst,
978 void *tvlv_value, uint16_t tvlv_value_len);
979 uint8_t type;
980 uint8_t version;
981 uint8_t flags;
982 atomic_t refcount;
983 struct rcu_head rcu;
984};
985
986/**
987 * enum batadv_tvlv_handler_flags - tvlv handler flags definitions
988 * @BATADV_TVLV_HANDLER_OGM_CIFNOTFND: tvlv ogm processing function will call
989 * this handler even if its type was not found (with no data)
990 * @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the API marks
991 * a handler as being called, so it won't be called if the
992 * BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set
993 */
994enum batadv_tvlv_handler_flags {
995 BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1),
996 BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2),
997};
998
995#endif /* _NET_BATMAN_ADV_TYPES_H_ */ 999#endif /* _NET_BATMAN_ADV_TYPES_H_ */
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
deleted file mode 100644
index d8ea31a58457..000000000000
--- a/net/batman-adv/vis.c
+++ /dev/null
@@ -1,938 +0,0 @@
1/* Copyright (C) 2008-2013 B.A.T.M.A.N. contributors:
2 *
3 * Simon Wunderlich
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#include "main.h"
21#include "send.h"
22#include "translation-table.h"
23#include "vis.h"
24#include "soft-interface.h"
25#include "hard-interface.h"
26#include "hash.h"
27#include "originator.h"
28
29#define BATADV_MAX_VIS_PACKET_SIZE 1000
30
31/* hash class keys */
32static struct lock_class_key batadv_vis_hash_lock_class_key;
33
34/* free the info */
35static void batadv_free_info(struct kref *ref)
36{
37 struct batadv_vis_info *info;
38 struct batadv_priv *bat_priv;
39 struct batadv_vis_recvlist_node *entry, *tmp;
40
41 info = container_of(ref, struct batadv_vis_info, refcount);
42 bat_priv = info->bat_priv;
43
44 list_del_init(&info->send_list);
45 spin_lock_bh(&bat_priv->vis.list_lock);
46 list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
47 list_del(&entry->list);
48 kfree(entry);
49 }
50
51 spin_unlock_bh(&bat_priv->vis.list_lock);
52 kfree_skb(info->skb_packet);
53 kfree(info);
54}
55
56/* Compare two vis packets, used by the hashing algorithm */
57static int batadv_vis_info_cmp(const struct hlist_node *node, const void *data2)
58{
59 const struct batadv_vis_info *d1, *d2;
60 const struct batadv_vis_packet *p1, *p2;
61
62 d1 = container_of(node, struct batadv_vis_info, hash_entry);
63 d2 = data2;
64 p1 = (struct batadv_vis_packet *)d1->skb_packet->data;
65 p2 = (struct batadv_vis_packet *)d2->skb_packet->data;
66 return batadv_compare_eth(p1->vis_orig, p2->vis_orig);
67}
68
69/* hash function to choose an entry in a hash table of given size
70 * hash algorithm from http://en.wikipedia.org/wiki/Hash_table
71 */
72static uint32_t batadv_vis_info_choose(const void *data, uint32_t size)
73{
74 const struct batadv_vis_info *vis_info = data;
75 const struct batadv_vis_packet *packet;
76 const unsigned char *key;
77 uint32_t hash = 0;
78 size_t i;
79
80 packet = (struct batadv_vis_packet *)vis_info->skb_packet->data;
81 key = packet->vis_orig;
82 for (i = 0; i < ETH_ALEN; i++) {
83 hash += key[i];
84 hash += (hash << 10);
85 hash ^= (hash >> 6);
86 }
87
88 hash += (hash << 3);
89 hash ^= (hash >> 11);
90 hash += (hash << 15);
91
92 return hash % size;
93}
94
95static struct batadv_vis_info *
96batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
97{
98 struct batadv_hashtable *hash = bat_priv->vis.hash;
99 struct hlist_head *head;
100 struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
101 uint32_t index;
102
103 if (!hash)
104 return NULL;
105
106 index = batadv_vis_info_choose(data, hash->size);
107 head = &hash->table[index];
108
109 rcu_read_lock();
110 hlist_for_each_entry_rcu(vis_info, head, hash_entry) {
111 if (!batadv_vis_info_cmp(&vis_info->hash_entry, data))
112 continue;
113
114 vis_info_tmp = vis_info;
115 break;
116 }
117 rcu_read_unlock();
118
119 return vis_info_tmp;
120}
121
122/* insert interface to the list of interfaces of one originator, if it
123 * does not already exist in the list
124 */
125static void batadv_vis_data_insert_interface(const uint8_t *interface,
126 struct hlist_head *if_list,
127 bool primary)
128{
129 struct batadv_vis_if_list_entry *entry;
130
131 hlist_for_each_entry(entry, if_list, list) {
132 if (batadv_compare_eth(entry->addr, interface))
133 return;
134 }
135
136 /* it's a new address, add it to the list */
137 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
138 if (!entry)
139 return;
140 memcpy(entry->addr, interface, ETH_ALEN);
141 entry->primary = primary;
142 hlist_add_head(&entry->list, if_list);
143}
144
145static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
146 const struct hlist_head *if_list)
147{
148 struct batadv_vis_if_list_entry *entry;
149
150 hlist_for_each_entry(entry, if_list, list) {
151 if (entry->primary)
152 seq_puts(seq, "PRIMARY, ");
153 else
154 seq_printf(seq, "SEC %pM, ", entry->addr);
155 }
156}
157
158/* read an entry */
159static ssize_t
160batadv_vis_data_read_entry(struct seq_file *seq,
161 const struct batadv_vis_info_entry *entry,
162 const uint8_t *src, bool primary)
163{
164 if (primary && entry->quality == 0)
165 return seq_printf(seq, "TT %pM, ", entry->dest);
166 else if (batadv_compare_eth(entry->src, src))
167 return seq_printf(seq, "TQ %pM %d, ", entry->dest,
168 entry->quality);
169
170 return 0;
171}
172
173static void
174batadv_vis_data_insert_interfaces(struct hlist_head *list,
175 struct batadv_vis_packet *packet,
176 struct batadv_vis_info_entry *entries)
177{
178 int i;
179
180 for (i = 0; i < packet->entries; i++) {
181 if (entries[i].quality == 0)
182 continue;
183
184 if (batadv_compare_eth(entries[i].src, packet->vis_orig))
185 continue;
186
187 batadv_vis_data_insert_interface(entries[i].src, list, false);
188 }
189}
190
191static void batadv_vis_data_read_entries(struct seq_file *seq,
192 struct hlist_head *list,
193 struct batadv_vis_packet *packet,
194 struct batadv_vis_info_entry *entries)
195{
196 int i;
197 struct batadv_vis_if_list_entry *entry;
198
199 hlist_for_each_entry(entry, list, list) {
200 seq_printf(seq, "%pM,", entry->addr);
201
202 for (i = 0; i < packet->entries; i++)
203 batadv_vis_data_read_entry(seq, &entries[i],
204 entry->addr, entry->primary);
205
206 /* add primary/secondary records */
207 if (batadv_compare_eth(entry->addr, packet->vis_orig))
208 batadv_vis_data_read_prim_sec(seq, list);
209
210 seq_puts(seq, "\n");
211 }
212}
213
214static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
215 const struct hlist_head *head)
216{
217 struct batadv_vis_info *info;
218 struct batadv_vis_packet *packet;
219 uint8_t *entries_pos;
220 struct batadv_vis_info_entry *entries;
221 struct batadv_vis_if_list_entry *entry;
222 struct hlist_node *n;
223
224 HLIST_HEAD(vis_if_list);
225
226 hlist_for_each_entry_rcu(info, head, hash_entry) {
227 packet = (struct batadv_vis_packet *)info->skb_packet->data;
228 entries_pos = (uint8_t *)packet + sizeof(*packet);
229 entries = (struct batadv_vis_info_entry *)entries_pos;
230
231 batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list,
232 true);
233 batadv_vis_data_insert_interfaces(&vis_if_list, packet,
234 entries);
235 batadv_vis_data_read_entries(seq, &vis_if_list, packet,
236 entries);
237
238 hlist_for_each_entry_safe(entry, n, &vis_if_list, list) {
239 hlist_del(&entry->list);
240 kfree(entry);
241 }
242 }
243}
244
245int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
246{
247 struct batadv_hard_iface *primary_if;
248 struct hlist_head *head;
249 struct net_device *net_dev = (struct net_device *)seq->private;
250 struct batadv_priv *bat_priv = netdev_priv(net_dev);
251 struct batadv_hashtable *hash = bat_priv->vis.hash;
252 uint32_t i;
253 int ret = 0;
254 int vis_server = atomic_read(&bat_priv->vis_mode);
255
256 primary_if = batadv_primary_if_get_selected(bat_priv);
257 if (!primary_if)
258 goto out;
259
260 if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
261 goto out;
262
263 spin_lock_bh(&bat_priv->vis.hash_lock);
264 for (i = 0; i < hash->size; i++) {
265 head = &hash->table[i];
266 batadv_vis_seq_print_text_bucket(seq, head);
267 }
268 spin_unlock_bh(&bat_priv->vis.hash_lock);
269
270out:
271 if (primary_if)
272 batadv_hardif_free_ref(primary_if);
273 return ret;
274}
275
276/* add the info packet to the send list, if it was not
277 * already linked in.
278 */
279static void batadv_send_list_add(struct batadv_priv *bat_priv,
280 struct batadv_vis_info *info)
281{
282 if (list_empty(&info->send_list)) {
283 kref_get(&info->refcount);
284 list_add_tail(&info->send_list, &bat_priv->vis.send_list);
285 }
286}
287
288/* delete the info packet from the send list, if it was
289 * linked in.
290 */
291static void batadv_send_list_del(struct batadv_vis_info *info)
292{
293 if (!list_empty(&info->send_list)) {
294 list_del_init(&info->send_list);
295 kref_put(&info->refcount, batadv_free_info);
296 }
297}
298
299/* tries to add one entry to the receive list. */
300static void batadv_recv_list_add(struct batadv_priv *bat_priv,
301 struct list_head *recv_list, const char *mac)
302{
303 struct batadv_vis_recvlist_node *entry;
304
305 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
306 if (!entry)
307 return;
308
309 memcpy(entry->mac, mac, ETH_ALEN);
310 spin_lock_bh(&bat_priv->vis.list_lock);
311 list_add_tail(&entry->list, recv_list);
312 spin_unlock_bh(&bat_priv->vis.list_lock);
313}
314
315/* returns 1 if this mac is in the recv_list */
316static int batadv_recv_list_is_in(struct batadv_priv *bat_priv,
317 const struct list_head *recv_list,
318 const char *mac)
319{
320 const struct batadv_vis_recvlist_node *entry;
321
322 spin_lock_bh(&bat_priv->vis.list_lock);
323 list_for_each_entry(entry, recv_list, list) {
324 if (batadv_compare_eth(entry->mac, mac)) {
325 spin_unlock_bh(&bat_priv->vis.list_lock);
326 return 1;
327 }
328 }
329 spin_unlock_bh(&bat_priv->vis.list_lock);
330 return 0;
331}
332
333/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
334 * broken.. ). vis hash must be locked outside. is_new is set when the packet
335 * is newer than old entries in the hash.
336 */
337static struct batadv_vis_info *
338batadv_add_packet(struct batadv_priv *bat_priv,
339 struct batadv_vis_packet *vis_packet, int vis_info_len,
340 int *is_new, int make_broadcast)
341{
342 struct batadv_vis_info *info, *old_info;
343 struct batadv_vis_packet *search_packet, *old_packet;
344 struct batadv_vis_info search_elem;
345 struct batadv_vis_packet *packet;
346 struct sk_buff *tmp_skb;
347 int hash_added;
348 size_t len;
349 size_t max_entries;
350
351 *is_new = 0;
352 /* sanity check */
353 if (!bat_priv->vis.hash)
354 return NULL;
355
356 /* see if the packet is already in vis_hash */
357 search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet));
358 if (!search_elem.skb_packet)
359 return NULL;
360 len = sizeof(*search_packet);
361 tmp_skb = search_elem.skb_packet;
362 search_packet = (struct batadv_vis_packet *)skb_put(tmp_skb, len);
363
364 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
365 old_info = batadv_vis_hash_find(bat_priv, &search_elem);
366 kfree_skb(search_elem.skb_packet);
367
368 if (old_info) {
369 tmp_skb = old_info->skb_packet;
370 old_packet = (struct batadv_vis_packet *)tmp_skb->data;
371 if (!batadv_seq_after(ntohl(vis_packet->seqno),
372 ntohl(old_packet->seqno))) {
373 if (old_packet->seqno == vis_packet->seqno) {
374 batadv_recv_list_add(bat_priv,
375 &old_info->recv_list,
376 vis_packet->sender_orig);
377 return old_info;
378 } else {
379 /* newer packet is already in hash. */
380 return NULL;
381 }
382 }
383 /* remove old entry */
384 batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp,
385 batadv_vis_info_choose, old_info);
386 batadv_send_list_del(old_info);
387 kref_put(&old_info->refcount, batadv_free_info);
388 }
389
390 info = kmalloc(sizeof(*info), GFP_ATOMIC);
391 if (!info)
392 return NULL;
393
394 len = sizeof(*packet) + vis_info_len;
395 info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
396 if (!info->skb_packet) {
397 kfree(info);
398 return NULL;
399 }
400 info->skb_packet->priority = TC_PRIO_CONTROL;
401 skb_reserve(info->skb_packet, ETH_HLEN);
402 packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
403
404 kref_init(&info->refcount);
405 INIT_LIST_HEAD(&info->send_list);
406 INIT_LIST_HEAD(&info->recv_list);
407 info->first_seen = jiffies;
408 info->bat_priv = bat_priv;
409 memcpy(packet, vis_packet, len);
410
411 /* initialize and add new packet. */
412 *is_new = 1;
413
414 /* Make it a broadcast packet, if required */
415 if (make_broadcast)
416 memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
417
418 /* repair if entries is longer than packet. */
419 max_entries = vis_info_len / sizeof(struct batadv_vis_info_entry);
420 if (packet->entries > max_entries)
421 packet->entries = max_entries;
422
423 batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
424
425 /* try to add it */
426 hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
427 batadv_vis_info_choose, info,
428 &info->hash_entry);
429 if (hash_added != 0) {
430 /* did not work (for some reason) */
431 kref_put(&info->refcount, batadv_free_info);
432 info = NULL;
433 }
434
435 return info;
436}
437
438/* handle the server sync packet, forward if needed. */
439void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
440 struct batadv_vis_packet *vis_packet,
441 int vis_info_len)
442{
443 struct batadv_vis_info *info;
444 int is_new, make_broadcast;
445 int vis_server = atomic_read(&bat_priv->vis_mode);
446
447 make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
448
449 spin_lock_bh(&bat_priv->vis.hash_lock);
450 info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
451 &is_new, make_broadcast);
452 if (!info)
453 goto end;
454
455 /* only if we are server ourselves and packet is newer than the one in
456 * hash.
457 */
458 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
459 batadv_send_list_add(bat_priv, info);
460end:
461 spin_unlock_bh(&bat_priv->vis.hash_lock);
462}
463
464/* handle an incoming client update packet and schedule forward if needed. */
465void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
466 struct batadv_vis_packet *vis_packet,
467 int vis_info_len)
468{
469 struct batadv_vis_info *info;
470 struct batadv_vis_packet *packet;
471 int is_new;
472 int vis_server = atomic_read(&bat_priv->vis_mode);
473 int are_target = 0;
474
475 /* clients shall not broadcast. */
476 if (is_broadcast_ether_addr(vis_packet->target_orig))
477 return;
478
479 /* Are we the target for this VIS packet? */
480 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC &&
481 batadv_is_my_mac(bat_priv, vis_packet->target_orig))
482 are_target = 1;
483
484 spin_lock_bh(&bat_priv->vis.hash_lock);
485 info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
486 &is_new, are_target);
487
488 if (!info)
489 goto end;
490 /* note that outdated packets will be dropped at this point. */
491
492 packet = (struct batadv_vis_packet *)info->skb_packet->data;
493
494 /* send only if we're the target server or ... */
495 if (are_target && is_new) {
496 packet->vis_type = BATADV_VIS_TYPE_SERVER_SYNC; /* upgrade! */
497 batadv_send_list_add(bat_priv, info);
498
499 /* ... we're not the recipient (and thus need to forward). */
500 } else if (!batadv_is_my_mac(bat_priv, packet->target_orig)) {
501 batadv_send_list_add(bat_priv, info);
502 }
503
504end:
505 spin_unlock_bh(&bat_priv->vis.hash_lock);
506}
507
508/* Walk the originators and find the VIS server with the best tq. Set the packet
509 * address to its address and return the best_tq.
510 *
511 * Must be called with the originator hash locked
512 */
513static int batadv_find_best_vis_server(struct batadv_priv *bat_priv,
514 struct batadv_vis_info *info)
515{
516 struct batadv_hashtable *hash = bat_priv->orig_hash;
517 struct batadv_neigh_node *router;
518 struct hlist_head *head;
519 struct batadv_orig_node *orig_node;
520 struct batadv_vis_packet *packet;
521 int best_tq = -1;
522 uint32_t i;
523
524 packet = (struct batadv_vis_packet *)info->skb_packet->data;
525
526 for (i = 0; i < hash->size; i++) {
527 head = &hash->table[i];
528
529 rcu_read_lock();
530 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
531 router = batadv_orig_node_get_router(orig_node);
532 if (!router)
533 continue;
534
535 if ((orig_node->flags & BATADV_VIS_SERVER) &&
536 (router->tq_avg > best_tq)) {
537 best_tq = router->tq_avg;
538 memcpy(packet->target_orig, orig_node->orig,
539 ETH_ALEN);
540 }
541 batadv_neigh_node_free_ref(router);
542 }
543 rcu_read_unlock();
544 }
545
546 return best_tq;
547}
548
549/* Return true if the vis packet is full. */
550static bool batadv_vis_packet_full(const struct batadv_vis_info *info)
551{
552 const struct batadv_vis_packet *packet;
553 size_t num;
554
555 packet = (struct batadv_vis_packet *)info->skb_packet->data;
556 num = BATADV_MAX_VIS_PACKET_SIZE / sizeof(struct batadv_vis_info_entry);
557
558 if (num < packet->entries + 1)
559 return true;
560 return false;
561}
562
563/* generates a packet of own vis data,
564 * returns 0 on success, -1 if no packet could be generated
565 */
566static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
567{
568 struct batadv_hashtable *hash = bat_priv->orig_hash;
569 struct hlist_head *head;
570 struct batadv_orig_node *orig_node;
571 struct batadv_neigh_node *router;
572 struct batadv_vis_info *info = bat_priv->vis.my_info;
573 struct batadv_vis_packet *packet;
574 struct batadv_vis_info_entry *entry;
575 struct batadv_tt_common_entry *tt_common_entry;
576 uint8_t *packet_pos;
577 int best_tq = -1;
578 uint32_t i;
579
580 info->first_seen = jiffies;
581 packet = (struct batadv_vis_packet *)info->skb_packet->data;
582 packet->vis_type = atomic_read(&bat_priv->vis_mode);
583
584 memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
585 packet->header.ttl = BATADV_TTL;
586 packet->seqno = htonl(ntohl(packet->seqno) + 1);
587 packet->entries = 0;
588 packet->reserved = 0;
589 skb_trim(info->skb_packet, sizeof(*packet));
590
591 if (packet->vis_type == BATADV_VIS_TYPE_CLIENT_UPDATE) {
592 best_tq = batadv_find_best_vis_server(bat_priv, info);
593
594 if (best_tq < 0)
595 return best_tq;
596 }
597
598 for (i = 0; i < hash->size; i++) {
599 head = &hash->table[i];
600
601 rcu_read_lock();
602 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
603 router = batadv_orig_node_get_router(orig_node);
604 if (!router)
605 continue;
606
607 if (!batadv_compare_eth(router->addr, orig_node->orig))
608 goto next;
609
610 if (router->if_incoming->if_status != BATADV_IF_ACTIVE)
611 goto next;
612
613 if (router->tq_avg < 1)
614 goto next;
615
616 /* fill one entry into buffer. */
617 packet_pos = skb_put(info->skb_packet, sizeof(*entry));
618 entry = (struct batadv_vis_info_entry *)packet_pos;
619 memcpy(entry->src,
620 router->if_incoming->net_dev->dev_addr,
621 ETH_ALEN);
622 memcpy(entry->dest, orig_node->orig, ETH_ALEN);
623 entry->quality = router->tq_avg;
624 packet->entries++;
625
626next:
627 batadv_neigh_node_free_ref(router);
628
629 if (batadv_vis_packet_full(info))
630 goto unlock;
631 }
632 rcu_read_unlock();
633 }
634
635 hash = bat_priv->tt.local_hash;
636
637 for (i = 0; i < hash->size; i++) {
638 head = &hash->table[i];
639
640 rcu_read_lock();
641 hlist_for_each_entry_rcu(tt_common_entry, head,
642 hash_entry) {
643 packet_pos = skb_put(info->skb_packet, sizeof(*entry));
644 entry = (struct batadv_vis_info_entry *)packet_pos;
645 memset(entry->src, 0, ETH_ALEN);
646 memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
647 entry->quality = 0; /* 0 means TT */
648 packet->entries++;
649
650 if (batadv_vis_packet_full(info))
651 goto unlock;
652 }
653 rcu_read_unlock();
654 }
655
656 return 0;
657
658unlock:
659 rcu_read_unlock();
660 return 0;
661}
662
663/* free old vis packets. Must be called with this vis_hash_lock
664 * held
665 */
666static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
667{
668 uint32_t i;
669 struct batadv_hashtable *hash = bat_priv->vis.hash;
670 struct hlist_node *node_tmp;
671 struct hlist_head *head;
672 struct batadv_vis_info *info;
673
674 for (i = 0; i < hash->size; i++) {
675 head = &hash->table[i];
676
677 hlist_for_each_entry_safe(info, node_tmp,
678 head, hash_entry) {
679 /* never purge own data. */
680 if (info == bat_priv->vis.my_info)
681 continue;
682
683 if (batadv_has_timed_out(info->first_seen,
684 BATADV_VIS_TIMEOUT)) {
685 hlist_del(&info->hash_entry);
686 batadv_send_list_del(info);
687 kref_put(&info->refcount, batadv_free_info);
688 }
689 }
690 }
691}
692
693static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
694 struct batadv_vis_info *info)
695{
696 struct batadv_hashtable *hash = bat_priv->orig_hash;
697 struct hlist_head *head;
698 struct batadv_orig_node *orig_node;
699 struct batadv_vis_packet *packet;
700 struct sk_buff *skb;
701 uint32_t i, res;
702
703
704 packet = (struct batadv_vis_packet *)info->skb_packet->data;
705
706 /* send to all routers in range. */
707 for (i = 0; i < hash->size; i++) {
708 head = &hash->table[i];
709
710 rcu_read_lock();
711 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
712 /* if it's a vis server and reachable, send it. */
713 if (!(orig_node->flags & BATADV_VIS_SERVER))
714 continue;
715
716 /* don't send it if we already received the packet from
717 * this node.
718 */
719 if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
720 orig_node->orig))
721 continue;
722
723 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
724 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
725 if (!skb)
726 continue;
727
728 res = batadv_send_skb_to_orig(skb, orig_node, NULL);
729 if (res == NET_XMIT_DROP)
730 kfree_skb(skb);
731 }
732 rcu_read_unlock();
733 }
734}
735
736static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
737 struct batadv_vis_info *info)
738{
739 struct batadv_orig_node *orig_node;
740 struct sk_buff *skb;
741 struct batadv_vis_packet *packet;
742
743 packet = (struct batadv_vis_packet *)info->skb_packet->data;
744
745 orig_node = batadv_orig_hash_find(bat_priv, packet->target_orig);
746 if (!orig_node)
747 goto out;
748
749 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
750 if (!skb)
751 goto out;
752
753 if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
754 kfree_skb(skb);
755
756out:
757 if (orig_node)
758 batadv_orig_node_free_ref(orig_node);
759}
760
761/* only send one vis packet. called from batadv_send_vis_packets() */
762static void batadv_send_vis_packet(struct batadv_priv *bat_priv,
763 struct batadv_vis_info *info)
764{
765 struct batadv_hard_iface *primary_if;
766 struct batadv_vis_packet *packet;
767
768 primary_if = batadv_primary_if_get_selected(bat_priv);
769 if (!primary_if)
770 goto out;
771
772 packet = (struct batadv_vis_packet *)info->skb_packet->data;
773 if (packet->header.ttl < 2) {
774 pr_debug("Error - can't send vis packet: ttl exceeded\n");
775 goto out;
776 }
777
778 memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
779 packet->header.ttl--;
780
781 if (is_broadcast_ether_addr(packet->target_orig))
782 batadv_broadcast_vis_packet(bat_priv, info);
783 else
784 batadv_unicast_vis_packet(bat_priv, info);
785 packet->header.ttl++; /* restore TTL */
786
787out:
788 if (primary_if)
789 batadv_hardif_free_ref(primary_if);
790}
791
792/* called from timer; send (and maybe generate) vis packet. */
793static void batadv_send_vis_packets(struct work_struct *work)
794{
795 struct delayed_work *delayed_work;
796 struct batadv_priv *bat_priv;
797 struct batadv_priv_vis *priv_vis;
798 struct batadv_vis_info *info;
799
800 delayed_work = container_of(work, struct delayed_work, work);
801 priv_vis = container_of(delayed_work, struct batadv_priv_vis, work);
802 bat_priv = container_of(priv_vis, struct batadv_priv, vis);
803 spin_lock_bh(&bat_priv->vis.hash_lock);
804 batadv_purge_vis_packets(bat_priv);
805
806 if (batadv_generate_vis_packet(bat_priv) == 0) {
807 /* schedule if generation was successful */
808 batadv_send_list_add(bat_priv, bat_priv->vis.my_info);
809 }
810
811 while (!list_empty(&bat_priv->vis.send_list)) {
812 info = list_first_entry(&bat_priv->vis.send_list,
813 typeof(*info), send_list);
814
815 kref_get(&info->refcount);
816 spin_unlock_bh(&bat_priv->vis.hash_lock);
817
818 batadv_send_vis_packet(bat_priv, info);
819
820 spin_lock_bh(&bat_priv->vis.hash_lock);
821 batadv_send_list_del(info);
822 kref_put(&info->refcount, batadv_free_info);
823 }
824 spin_unlock_bh(&bat_priv->vis.hash_lock);
825
826 queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
827 msecs_to_jiffies(BATADV_VIS_INTERVAL));
828}
829
830/* init the vis server. this may only be called when if_list is already
831 * initialized (e.g. bat0 is initialized, interfaces have been added)
832 */
833int batadv_vis_init(struct batadv_priv *bat_priv)
834{
835 struct batadv_vis_packet *packet;
836 int hash_added;
837 unsigned int len;
838 unsigned long first_seen;
839 struct sk_buff *tmp_skb;
840
841 if (bat_priv->vis.hash)
842 return 0;
843
844 spin_lock_bh(&bat_priv->vis.hash_lock);
845
846 bat_priv->vis.hash = batadv_hash_new(256);
847 if (!bat_priv->vis.hash) {
848 pr_err("Can't initialize vis_hash\n");
849 goto err;
850 }
851
852 batadv_hash_set_lock_class(bat_priv->vis.hash,
853 &batadv_vis_hash_lock_class_key);
854
855 bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
856 if (!bat_priv->vis.my_info)
857 goto err;
858
859 len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
860 bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL,
861 len);
862 if (!bat_priv->vis.my_info->skb_packet)
863 goto free_info;
864
865 bat_priv->vis.my_info->skb_packet->priority = TC_PRIO_CONTROL;
866 skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
867 tmp_skb = bat_priv->vis.my_info->skb_packet;
868 packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
869
870 /* prefill the vis info */
871 first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
872 bat_priv->vis.my_info->first_seen = first_seen;
873 INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list);
874 INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list);
875 kref_init(&bat_priv->vis.my_info->refcount);
876 bat_priv->vis.my_info->bat_priv = bat_priv;
877 packet->header.version = BATADV_COMPAT_VERSION;
878 packet->header.packet_type = BATADV_VIS;
879 packet->header.ttl = BATADV_TTL;
880 packet->seqno = 0;
881 packet->reserved = 0;
882 packet->entries = 0;
883
884 INIT_LIST_HEAD(&bat_priv->vis.send_list);
885
886 hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
887 batadv_vis_info_choose,
888 bat_priv->vis.my_info,
889 &bat_priv->vis.my_info->hash_entry);
890 if (hash_added != 0) {
891 pr_err("Can't add own vis packet into hash\n");
892 /* not in hash, need to remove it manually. */
893 kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info);
894 goto err;
895 }
896
897 spin_unlock_bh(&bat_priv->vis.hash_lock);
898
899 INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets);
900 queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
901 msecs_to_jiffies(BATADV_VIS_INTERVAL));
902
903 return 0;
904
905free_info:
906 kfree(bat_priv->vis.my_info);
907 bat_priv->vis.my_info = NULL;
908err:
909 spin_unlock_bh(&bat_priv->vis.hash_lock);
910 batadv_vis_quit(bat_priv);
911 return -ENOMEM;
912}
913
914/* Decrease the reference count on a hash item info */
915static void batadv_free_info_ref(struct hlist_node *node, void *arg)
916{
917 struct batadv_vis_info *info;
918
919 info = container_of(node, struct batadv_vis_info, hash_entry);
920 batadv_send_list_del(info);
921 kref_put(&info->refcount, batadv_free_info);
922}
923
924/* shutdown vis-server */
925void batadv_vis_quit(struct batadv_priv *bat_priv)
926{
927 if (!bat_priv->vis.hash)
928 return;
929
930 cancel_delayed_work_sync(&bat_priv->vis.work);
931
932 spin_lock_bh(&bat_priv->vis.hash_lock);
933 /* properly remove, kill timers ... */
934 batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL);
935 bat_priv->vis.hash = NULL;
936 bat_priv->vis.my_info = NULL;
937 spin_unlock_bh(&bat_priv->vis.hash_lock);
938}
diff --git a/net/batman-adv/vis.h b/net/batman-adv/vis.h
deleted file mode 100644
index ad92b0e3c230..000000000000
--- a/net/batman-adv/vis.h
+++ /dev/null
@@ -1,36 +0,0 @@
1/* Copyright (C) 2008-2013 B.A.T.M.A.N. contributors:
2 *
3 * Simon Wunderlich, Marek Lindner
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#ifndef _NET_BATMAN_ADV_VIS_H_
21#define _NET_BATMAN_ADV_VIS_H_
22
23/* timeout of vis packets in milliseconds */
24#define BATADV_VIS_TIMEOUT 200000
25
26int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
27void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
28 struct batadv_vis_packet *vis_packet,
29 int vis_info_len);
30void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
31 struct batadv_vis_packet *vis_packet,
32 int vis_info_len);
33int batadv_vis_init(struct batadv_priv *bat_priv);
34void batadv_vis_quit(struct batadv_priv *bat_priv);
35
36#endif /* _NET_BATMAN_ADV_VIS_H_ */