aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2013-04-23 09:40:01 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-09 15:22:29 -0400
commite1bf0c14096f9dc09c7695f42051d178b23d0670 (patch)
treee20f3c396c9506c9e042276ca93a3175959dffd6 /net/batman-adv
parent3f4841ffb336075f74b05fe4a205e877bb22848d (diff)
batman-adv: tvlv - convert tt data sent within OGMs
The translation table meta data (version number, crc checksum, etc) as well as the translation table diff propgated within OGMs now uses the newly introduced tvlv infrastructure. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/bat_iv_ogm.c44
-rw-r--r--net/batman-adv/packet.h51
-rw-r--r--net/batman-adv/translation-table.c240
-rw-r--r--net/batman-adv/translation-table.h8
-rw-r--r--net/batman-adv/types.h2
5 files changed, 187 insertions, 158 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index f0f02d1a10d7..871ba672bdc2 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -137,8 +137,6 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
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->reserved = 0;
139 batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; 139 batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
140 batadv_ogm_packet->tt_num_changes = 0;
141 batadv_ogm_packet->ttvn = 0;
142 140
143 res = 0; 141 res = 0;
144 142
@@ -257,14 +255,14 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
257 fwd_str = "Sending own"; 255 fwd_str = "Sending own";
258 256
259 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 257 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
260 "%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",
261 fwd_str, (packet_num > 0 ? "aggregated " : ""), 259 fwd_str, (packet_num > 0 ? "aggregated " : ""),
262 batadv_ogm_packet->orig, 260 batadv_ogm_packet->orig,
263 ntohl(batadv_ogm_packet->seqno), 261 ntohl(batadv_ogm_packet->seqno),
264 batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl, 262 batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
265 (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 263 (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
266 "on" : "off"), 264 "on" : "off"),
267 batadv_ogm_packet->ttvn, hard_iface->net_dev->name, 265 hard_iface->net_dev->name,
268 hard_iface->net_dev->dev_addr); 266 hard_iface->net_dev->dev_addr);
269 267
270 buff_pos += BATADV_OGM_HLEN; 268 buff_pos += BATADV_OGM_HLEN;
@@ -689,17 +687,22 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
689 struct batadv_ogm_packet *batadv_ogm_packet; 687 struct batadv_ogm_packet *batadv_ogm_packet;
690 struct batadv_hard_iface *primary_if; 688 struct batadv_hard_iface *primary_if;
691 int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; 689 int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
692 int vis_server, tt_num_changes = 0; 690 int vis_server;
693 uint32_t seqno; 691 uint32_t seqno;
694 uint16_t tvlv_len = 0; 692 uint16_t tvlv_len = 0;
695 693
696 vis_server = atomic_read(&bat_priv->vis_mode); 694 vis_server = atomic_read(&bat_priv->vis_mode);
697 primary_if = batadv_primary_if_get_selected(bat_priv); 695 primary_if = batadv_primary_if_get_selected(bat_priv);
698 696
699 if (hard_iface == primary_if) 697 if (hard_iface == primary_if) {
698 /* tt changes have to be committed before the tvlv data is
699 * appended as it may alter the tt tvlv container
700 */
701 batadv_tt_local_commit_changes(bat_priv);
700 tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff, 702 tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
701 ogm_buff_len, 703 ogm_buff_len,
702 BATADV_OGM_HLEN); 704 BATADV_OGM_HLEN);
705 }
703 706
704 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); 707 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
705 batadv_ogm_packet->tvlv_len = htons(tvlv_len); 708 batadv_ogm_packet->tvlv_len = htons(tvlv_len);
@@ -709,11 +712,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
709 batadv_ogm_packet->seqno = htonl(seqno); 712 batadv_ogm_packet->seqno = htonl(seqno);
710 atomic_inc(&hard_iface->bat_iv.ogm_seqno); 713 atomic_inc(&hard_iface->bat_iv.ogm_seqno);
711 714
712 batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
713 batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
714 if (tt_num_changes >= 0)
715 batadv_ogm_packet->tt_num_changes = tt_num_changes;
716
717 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC) 715 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC)
718 batadv_ogm_packet->flags |= BATADV_VIS_SERVER; 716 batadv_ogm_packet->flags |= BATADV_VIS_SERVER;
719 else 717 else
@@ -814,11 +812,11 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
814 */ 812 */
815 router = batadv_orig_node_get_router(orig_node); 813 router = batadv_orig_node_get_router(orig_node);
816 if (router == neigh_node) 814 if (router == neigh_node)
817 goto update_tt; 815 goto out;
818 816
819 /* if this neighbor does not offer a better TQ we won't consider it */ 817 /* if this neighbor does not offer a better TQ we won't consider it */
820 if (router && (router->tq_avg > neigh_node->tq_avg)) 818 if (router && (router->tq_avg > neigh_node->tq_avg))
821 goto update_tt; 819 goto out;
822 820
823 /* if the TQ is the same and the link not more symmetric we 821 /* if the TQ is the same and the link not more symmetric we
824 * won't consider it either 822 * won't consider it either
@@ -837,22 +835,10 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
837 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); 835 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
838 836
839 if (sum_orig >= sum_neigh) 837 if (sum_orig >= sum_neigh)
840 goto update_tt; 838 goto out;
841 } 839 }
842 840
843 batadv_update_route(bat_priv, orig_node, neigh_node); 841 batadv_update_route(bat_priv, orig_node, neigh_node);
844
845update_tt:
846 /* I have to check for transtable changes only if the OGM has been
847 * sent through a primary interface
848 */
849 if (((batadv_ogm_packet->orig != ethhdr->h_source) &&
850 (batadv_ogm_packet->header.ttl > 2)) ||
851 (batadv_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP))
852 batadv_tt_update_orig(bat_priv, orig_node, tt_buff,
853 batadv_ogm_packet->tt_num_changes,
854 batadv_ogm_packet->ttvn,
855 ntohs(batadv_ogm_packet->tt_crc));
856 goto out; 842 goto out;
857 843
858unlock: 844unlock:
@@ -1103,13 +1089,11 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1103 is_single_hop_neigh = true; 1089 is_single_hop_neigh = true;
1104 1090
1105 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1091 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1106 "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", 1092 "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",
1107 ethhdr->h_source, if_incoming->net_dev->name, 1093 ethhdr->h_source, if_incoming->net_dev->name,
1108 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig, 1094 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
1109 batadv_ogm_packet->prev_sender, 1095 batadv_ogm_packet->prev_sender,
1110 ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->ttvn, 1096 ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
1111 ntohs(batadv_ogm_packet->tt_crc),
1112 batadv_ogm_packet->tt_num_changes, batadv_ogm_packet->tq,
1113 batadv_ogm_packet->header.ttl, 1097 batadv_ogm_packet->header.ttl,
1114 batadv_ogm_packet->header.version, has_directlink_flag); 1098 batadv_ogm_packet->header.version, has_directlink_flag);
1115 1099
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 55deb4dea842..cd59fcc9b79a 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -86,14 +86,21 @@ enum batadv_unicast_frag_flags {
86/* TT_QUERY subtypes */ 86/* TT_QUERY subtypes */
87#define BATADV_TT_QUERY_TYPE_MASK 0x3 87#define BATADV_TT_QUERY_TYPE_MASK 0x3
88 88
89enum batadv_tt_query_packettype { 89/* tt data subtypes */
90 BATADV_TT_REQUEST = 0, 90#define BATADV_TT_DATA_TYPE_MASK 0x0F
91 BATADV_TT_RESPONSE = 1,
92};
93 91
94/* TT_QUERY flags */ 92/**
95enum batadv_tt_query_flags { 93 * enum batadv_tt_data_flags - flags for tt data tvlv
96 BATADV_TT_FULL_TABLE = BIT(2), 94 * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM
95 * @BATADV_TT_REQUEST: TT request message
96 * @BATADV_TT_RESPONSE: TT response message
97 * @BATADV_TT_FULL_TABLE: contains full table to replace existing table
98 */
99enum batadv_tt_data_flags {
100 BATADV_TT_OGM_DIFF = BIT(0),
101 BATADV_TT_REQUEST = BIT(1),
102 BATADV_TT_RESPONSE = BIT(2),
103 BATADV_TT_FULL_TABLE = BIT(4),
97}; 104};
98 105
99/* BATADV_TT_CLIENT flags. 106/* BATADV_TT_CLIENT flags.
@@ -123,11 +130,13 @@ enum batadv_bla_claimframe {
123 * @BATADV_TVLV_GW: gateway tvlv 130 * @BATADV_TVLV_GW: gateway tvlv
124 * @BATADV_TVLV_DAT: distributed arp table tvlv 131 * @BATADV_TVLV_DAT: distributed arp table tvlv
125 * @BATADV_TVLV_NC: network coding tvlv 132 * @BATADV_TVLV_NC: network coding tvlv
133 * @BATADV_TVLV_TT: translation table tvlv
126 */ 134 */
127enum batadv_tvlv_type { 135enum batadv_tvlv_type {
128 BATADV_TVLV_GW = 0x01, 136 BATADV_TVLV_GW = 0x01,
129 BATADV_TVLV_DAT = 0x02, 137 BATADV_TVLV_DAT = 0x02,
130 BATADV_TVLV_NC = 0x03, 138 BATADV_TVLV_NC = 0x03,
139 BATADV_TVLV_TT = 0x04,
131}; 140};
132 141
133/* the destination hardware field in the ARP frame is used to 142/* the destination hardware field in the ARP frame is used to
@@ -161,9 +170,6 @@ struct batadv_ogm_packet {
161 uint8_t prev_sender[ETH_ALEN]; 170 uint8_t prev_sender[ETH_ALEN];
162 uint8_t reserved; 171 uint8_t reserved;
163 uint8_t tq; 172 uint8_t tq;
164 uint8_t tt_num_changes;
165 uint8_t ttvn; /* translation table version number */
166 __be16 tt_crc;
167 __be16 tvlv_len; 173 __be16 tvlv_len;
168} __packed; 174} __packed;
169 175
@@ -375,4 +381,29 @@ struct batadv_tvlv_gateway_data {
375 __be32 bandwidth_up; 381 __be32 bandwidth_up;
376}; 382};
377 383
384/**
385 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
386 * @flags: translation table flags (see batadv_tt_data_flags)
387 * @ttvn: translation table version number
388 * @crc: crc16 checksum of the local translation table
389 */
390struct batadv_tvlv_tt_data {
391 uint8_t flags;
392 uint8_t ttvn;
393 __be16 crc;
394};
395
396/**
397 * struct batadv_tvlv_tt_change - translation table diff data
398 * @flags: status indicators concerning the non-mesh client (see
399 * batadv_tt_client_flags)
400 * @reserved: reserved field
401 * @addr: mac address of non-mesh client that triggered this tt change
402 */
403struct batadv_tvlv_tt_change {
404 uint8_t flags;
405 uint8_t reserved;
406 uint8_t addr[ETH_ALEN];
407};
408
378#endif /* _NET_BATMAN_ADV_PACKET_H_ */ 409#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 34510f38708f..3fac67ffd524 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -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;
@@ -376,71 +376,52 @@ out:
376 batadv_tt_global_entry_free_ref(tt_global); 376 batadv_tt_global_entry_free_ref(tt_global);
377} 377}
378 378
379static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, 379/**
380 int *packet_buff_len, 380 * batadv_tt_tvlv_container_update - update the translation table tvlv container
381 int min_packet_len, 381 * after local tt changes have been committed
382 int new_packet_len) 382 * @bat_priv: the bat priv with all the soft interface information
383{ 383 */
384 unsigned char *new_buff; 384static 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{ 385{
402 int req_len; 386 struct batadv_tt_change_node *entry, *safe;
387 struct batadv_tvlv_tt_data *tt_data;
388 struct batadv_tvlv_tt_change *tt_change;
389 int tt_diff_len = 0, tt_change_len = 0;
390 int tt_diff_entries_num = 0, tt_diff_entries_count = 0;
403 391
404 req_len = min_packet_len; 392 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 393
407 /* if we have too many changes for one packet don't send any 394 /* 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 395 * and wait for the tt table request which will be fragmented
409 */ 396 */
410 if (req_len > bat_priv->soft_iface->mtu) 397 if (tt_diff_len > bat_priv->soft_iface->mtu)
411 req_len = min_packet_len; 398 tt_diff_len = 0;
412 399
413 batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, 400 tt_data = kzalloc(sizeof(*tt_data) + tt_diff_len, GFP_ATOMIC);
414 min_packet_len, req_len); 401 if (!tt_data)
415} 402 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 403
426 batadv_tt_prepare_packet_buff(bat_priv, packet_buff, 404 tt_data->flags = BATADV_TT_OGM_DIFF;
427 packet_buff_len, min_packet_len); 405 tt_data->ttvn = atomic_read(&bat_priv->tt.vn);
406 tt_data->crc = htons(bat_priv->tt.local_crc);
428 407
429 new_len = *packet_buff_len - min_packet_len; 408 if (tt_diff_len == 0)
430 tt_buff = *packet_buff + min_packet_len; 409 goto container_register;
431 410
432 if (new_len > 0) 411 tt_diff_entries_num = tt_diff_len / batadv_tt_len(1);
433 tot_changes = new_len / batadv_tt_len(1);
434 412
435 spin_lock_bh(&bat_priv->tt.changes_list_lock); 413 spin_lock_bh(&bat_priv->tt.changes_list_lock);
436 atomic_set(&bat_priv->tt.local_changes, 0); 414 atomic_set(&bat_priv->tt.local_changes, 0);
437 415
416 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
417
438 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, 418 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
439 list) { 419 list) {
440 if (count < tot_changes) { 420 if (tt_diff_entries_count < tt_diff_entries_num) {
441 memcpy(tt_buff + batadv_tt_len(count), 421 memcpy(tt_change + tt_diff_entries_count,
442 &entry->change, sizeof(struct batadv_tt_change)); 422 &entry->change,
443 count++; 423 sizeof(struct batadv_tvlv_tt_change));
424 tt_diff_entries_count++;
444 } 425 }
445 list_del(&entry->list); 426 list_del(&entry->list);
446 kfree(entry); 427 kfree(entry);
@@ -452,20 +433,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
452 kfree(bat_priv->tt.last_changeset); 433 kfree(bat_priv->tt.last_changeset);
453 bat_priv->tt.last_changeset_len = 0; 434 bat_priv->tt.last_changeset_len = 0;
454 bat_priv->tt.last_changeset = NULL; 435 bat_priv->tt.last_changeset = NULL;
436 tt_change_len = batadv_tt_len(tt_diff_entries_count);
455 /* check whether this new OGM has no changes due to size problems */ 437 /* check whether this new OGM has no changes due to size problems */
456 if (new_len > 0) { 438 if (tt_diff_entries_count > 0) {
457 /* if kmalloc() fails we will reply with the full table 439 /* if kmalloc() fails we will reply with the full table
458 * instead of providing the diff 440 * instead of providing the diff
459 */ 441 */
460 bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); 442 bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
461 if (bat_priv->tt.last_changeset) { 443 if (bat_priv->tt.last_changeset) {
462 memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); 444 memcpy(bat_priv->tt.last_changeset,
463 bat_priv->tt.last_changeset_len = new_len; 445 tt_change, tt_change_len);
446 bat_priv->tt.last_changeset_len = tt_diff_len;
464 } 447 }
465 } 448 }
466 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 449 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
467 450
468 return count; 451container_register:
452 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
453 sizeof(*tt_data) + tt_change_len);
454 kfree(tt_data);
469} 455}
470 456
471int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) 457int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
@@ -1504,7 +1490,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, 1490static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
1505 struct batadv_orig_node *orig_node, 1491 struct batadv_orig_node *orig_node,
1506 const unsigned char *tt_buff, 1492 const unsigned char *tt_buff,
1507 uint8_t tt_num_changes) 1493 uint16_t tt_num_changes)
1508{ 1494{
1509 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes); 1495 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1510 1496
@@ -2126,25 +2112,6 @@ out:
2126 batadv_orig_node_free_ref(orig_node); 2112 batadv_orig_node_free_ref(orig_node);
2127} 2113}
2128 2114
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) 2115static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
2149{ 2116{
2150 struct batadv_tt_roam_node *node, *safe; 2117 struct batadv_tt_roam_node *node, *safe;
@@ -2297,6 +2264,9 @@ static void batadv_tt_purge(struct work_struct *work)
2297 2264
2298void batadv_tt_free(struct batadv_priv *bat_priv) 2265void batadv_tt_free(struct batadv_priv *bat_priv)
2299{ 2266{
2267 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
2268 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
2269
2300 cancel_delayed_work_sync(&bat_priv->tt.work); 2270 cancel_delayed_work_sync(&bat_priv->tt.work);
2301 2271
2302 batadv_tt_local_table_free(bat_priv); 2272 batadv_tt_local_table_free(bat_priv);
@@ -2384,14 +2354,20 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2384 } 2354 }
2385} 2355}
2386 2356
2387static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, 2357/**
2388 unsigned char **packet_buff, 2358 * batadv_tt_local_commit_changes - commit all pending local tt changes which
2389 int *packet_buff_len, int packet_min_len) 2359 * have been queued in the time since the last commit
2360 * @bat_priv: the bat priv with all the soft interface information
2361 */
2362void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2390{ 2363{
2391 uint16_t changed_num = 0; 2364 uint16_t changed_num = 0;
2392 2365
2393 if (atomic_read(&bat_priv->tt.local_changes) < 1) 2366 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
2394 return -ENOENT; 2367 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
2368 batadv_tt_tvlv_container_update(bat_priv);
2369 return;
2370 }
2395 2371
2396 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, 2372 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
2397 BATADV_TT_CLIENT_NEW, false); 2373 BATADV_TT_CLIENT_NEW, false);
@@ -2409,32 +2385,7 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2409 2385
2410 /* reset the sending counter */ 2386 /* reset the sending counter */
2411 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); 2387 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
2412 2388 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} 2389}
2439 2390
2440bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 2391bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
@@ -2468,10 +2419,21 @@ out:
2468 return ret; 2419 return ret;
2469} 2420}
2470 2421
2471void batadv_tt_update_orig(struct batadv_priv *bat_priv, 2422/**
2472 struct batadv_orig_node *orig_node, 2423 * batadv_tt_update_orig - update global translation table with new tt
2473 const unsigned char *tt_buff, uint8_t tt_num_changes, 2424 * information received via ogms
2474 uint8_t ttvn, uint16_t tt_crc) 2425 * @bat_priv: the bat priv with all the soft interface information
2426 * @orig: the orig_node of the ogm
2427 * @tt_buff: buffer holding the tt information
2428 * @tt_num_changes: number of tt changes inside the tt buffer
2429 * @ttvn: translation table version number of this changeset
2430 * @tt_crc: crc16 checksum of orig node's translation table
2431 */
2432static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2433 struct batadv_orig_node *orig_node,
2434 const unsigned char *tt_buff,
2435 uint16_t tt_num_changes, uint8_t ttvn,
2436 uint16_t tt_crc)
2475{ 2437{
2476 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 2438 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
2477 bool full_table = true; 2439 bool full_table = true;
@@ -2605,3 +2567,61 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2605out: 2567out:
2606 return ret; 2568 return ret;
2607} 2569}
2570
2571/**
2572 * batadv_tt_tvlv_ogm_handler_v1 - process incoming tt tvlv container
2573 * @bat_priv: the bat priv with all the soft interface information
2574 * @orig: the orig_node of the ogm
2575 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
2576 * @tvlv_value: tvlv buffer containing the gateway data
2577 * @tvlv_value_len: tvlv buffer length
2578 */
2579static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2580 struct batadv_orig_node *orig,
2581 uint8_t flags,
2582 void *tvlv_value,
2583 uint16_t tvlv_value_len)
2584{
2585 struct batadv_tvlv_tt_data *tt_data;
2586 uint16_t num_entries;
2587
2588 if (tvlv_value_len < sizeof(*tt_data))
2589 return;
2590
2591 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2592 tvlv_value_len -= sizeof(*tt_data);
2593
2594 num_entries = tvlv_value_len / batadv_tt_len(1);
2595
2596 batadv_tt_update_orig(bat_priv, orig,
2597 (unsigned char *)(tt_data + 1),
2598 num_entries, tt_data->ttvn, ntohs(tt_data->crc));
2599}
2600
2601/**
2602 * batadv_tt_init - initialise the translation table internals
2603 * @bat_priv: the bat priv with all the soft interface information
2604 *
2605 * Return 0 on success or negative error number in case of failure.
2606 */
2607int batadv_tt_init(struct batadv_priv *bat_priv)
2608{
2609 int ret;
2610
2611 ret = batadv_tt_local_init(bat_priv);
2612 if (ret < 0)
2613 return ret;
2614
2615 ret = batadv_tt_global_init(bat_priv);
2616 if (ret < 0)
2617 return ret;
2618
2619 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
2620 NULL, BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
2621
2622 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
2623 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
2624 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
2625
2626 return 1;
2627}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 659a3bb759ce..a709249cf9d0 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -50,13 +50,7 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
50 struct batadv_tt_query_packet *tt_response); 50 struct batadv_tt_query_packet *tt_response);
51bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 51bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
52 uint8_t *dst); 52 uint8_t *dst);
53void batadv_tt_update_orig(struct batadv_priv *bat_priv, 53void 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, 54bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
61 uint8_t *addr); 55 uint8_t *addr);
62bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, 56bool 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 fa5cb0d99ed5..bdabbc21eb41 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -772,7 +772,7 @@ struct batadv_tt_orig_list_entry {
772 */ 772 */
773struct batadv_tt_change_node { 773struct batadv_tt_change_node {
774 struct list_head list; 774 struct list_head list;
775 struct batadv_tt_change change; 775 struct batadv_tvlv_tt_change change;
776}; 776};
777 777
778/** 778/**