diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2013-04-23 09:40:01 -0400 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2013-10-09 15:22:29 -0400 |
commit | e1bf0c14096f9dc09c7695f42051d178b23d0670 (patch) | |
tree | e20f3c396c9506c9e042276ca93a3175959dffd6 /net/batman-adv | |
parent | 3f4841ffb336075f74b05fe4a205e877bb22848d (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.c | 44 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 51 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 240 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 8 | ||||
-rw-r--r-- | net/batman-adv/types.h | 2 |
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 | |||
845 | update_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 | ||
858 | unlock: | 844 | unlock: |
@@ -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 | ||
89 | enum 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 | /** |
95 | enum 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 | */ | ||
99 | enum 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 | */ |
127 | enum batadv_tvlv_type { | 135 | enum 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 | */ | ||
390 | struct 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 | */ | ||
403 | struct 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 | ||
379 | static 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; | 384 | static 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 | |||
397 | static 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 | |||
417 | static 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; | 451 | container_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 | ||
471 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | 457 | int 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) | |||
1504 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, | 1490 | static 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 | ||
2129 | int 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 | |||
2148 | static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) | 2115 | static 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 | ||
2298 | void batadv_tt_free(struct batadv_priv *bat_priv) | 2265 | void 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 | ||
2387 | static 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 | */ | ||
2362 | void 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 */ | ||
2418 | int 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 | ||
2440 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, | 2391 | bool 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 | ||
2471 | void 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 | */ | ||
2432 | static 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, | |||
2605 | out: | 2567 | out: |
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 | */ | ||
2579 | static 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 | */ | ||
2607 | int 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); |
51 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, | 51 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, |
52 | uint8_t *dst); | 52 | uint8_t *dst); |
53 | void batadv_tt_update_orig(struct batadv_priv *bat_priv, | 53 | void 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); | ||
57 | int batadv_tt_append_diff(struct batadv_priv *bat_priv, | ||
58 | unsigned char **packet_buff, int *packet_buff_len, | ||
59 | int packet_min_len); | ||
60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | 54 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | uint8_t *addr); | 55 | uint8_t *addr); |
62 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | 56 | bool 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 | */ |
773 | struct batadv_tt_change_node { | 773 | struct 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 | /** |