aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-mesh11
-rw-r--r--Documentation/networking/batman-adv.txt50
-rw-r--r--MAINTAINERS4
-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
29 files changed, 1968 insertions, 2133 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index bdcd8b4e38f2..f00a69b68a25 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -88,14 +88,3 @@ Contact: Marek Lindner <lindner_marek@yahoo.de>
88Description: 88Description:
89 Defines the routing procotol this mesh instance 89 Defines the routing procotol this mesh instance
90 uses to find the optimal paths through the mesh. 90 uses to find the optimal paths through the mesh.
91
92What: /sys/class/net/<mesh_iface>/mesh/vis_mode
93Date: May 2010
94Contact: Marek Lindner <lindner_marek@yahoo.de>
95Description:
96 Each batman node only maintains information about its
97 own local neighborhood, therefore generating graphs
98 showing the topology of the entire mesh is not easily
99 feasible without having a central instance to collect
100 the local topologies from all nodes. This file allows
101 to activate the collecting (server) mode.
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index c1d82047a4b1..897d1f4e1df1 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -69,8 +69,7 @@ folder:
69# aggregated_ogms gw_bandwidth log_level 69# aggregated_ogms gw_bandwidth log_level
70# ap_isolation gw_mode orig_interval 70# ap_isolation gw_mode orig_interval
71# bonding gw_sel_class routing_algo 71# bonding gw_sel_class routing_algo
72# bridge_loop_avoidance hop_penalty vis_mode 72# bridge_loop_avoidance hop_penalty fragmentation
73# fragmentation
74 73
75 74
76There is a special folder for debugging information: 75There is a special folder for debugging information:
@@ -78,7 +77,7 @@ There is a special folder for debugging information:
78# ls /sys/kernel/debug/batman_adv/bat0/ 77# ls /sys/kernel/debug/batman_adv/bat0/
79# bla_backbone_table log transtable_global 78# bla_backbone_table log transtable_global
80# bla_claim_table originators transtable_local 79# bla_claim_table originators transtable_local
81# gateways socket vis_data 80# gateways socket
82 81
83Some of the files contain all sort of status information regard- 82Some of the files contain all sort of status information regard-
84ing the mesh network. For example, you can view the table of 83ing the mesh network. For example, you can view the table of
@@ -127,51 +126,6 @@ ously assigned to interfaces now used by batman advanced, e.g.
127# ifconfig eth0 0.0.0.0 126# ifconfig eth0 0.0.0.0
128 127
129 128
130VISUALIZATION
131-------------
132
133If you want topology visualization, at least one mesh node must
134be configured as VIS-server:
135
136# echo "server" > /sys/class/net/bat0/mesh/vis_mode
137
138Each node is either configured as "server" or as "client" (de-
139fault: "client"). Clients send their topology data to the server
140next to them, and server synchronize with other servers. If there
141is no server configured (default) within the mesh, no topology
142information will be transmitted. With these "synchronizing
143servers", there can be 1 or more vis servers sharing the same (or
144at least very similar) data.
145
146When configured as server, you can get a topology snapshot of
147your mesh:
148
149# cat /sys/kernel/debug/batman_adv/bat0/vis_data
150
151This raw output is intended to be easily parsable and convertable
152with other tools. Have a look at the batctl README if you want a
153vis output in dot or json format for instance and how those out-
154puts could then be visualised in an image.
155
156The raw format consists of comma separated values per entry where
157each entry is giving information about a certain source inter-
158face. Each entry can/has to have the following values:
159-> "mac" - mac address of an originator's source interface
160 (each line begins with it)
161-> "TQ mac value" - src mac's link quality towards mac address
162 of a neighbor originator's interface which
163 is being used for routing
164-> "TT mac" - TT announced by source mac
165-> "PRIMARY" - this is a primary interface
166-> "SEC mac" - secondary mac address of source
167 (requires preceding PRIMARY)
168
169The TQ value has a range from 4 to 255 with 255 being the best.
170The TT entries are showing which hosts are connected to the mesh
171via bat0 or being bridged into the mesh network. The PRIMARY/SEC
172values are only applied on primary interfaces
173
174
175LOGGING/DEBUGGING 129LOGGING/DEBUGGING
176----------------- 130-----------------
177 131
diff --git a/MAINTAINERS b/MAINTAINERS
index 43dfc821c584..7a86b44a4c56 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1652,9 +1652,9 @@ F: drivers/video/backlight/
1652F: include/linux/backlight.h 1652F: include/linux/backlight.h
1653 1653
1654BATMAN ADVANCED 1654BATMAN ADVANCED
1655M: Marek Lindner <lindner_marek@yahoo.de> 1655M: Marek Lindner <mareklindner@neomailbox.ch>
1656M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 1656M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
1657M: Antonio Quartulli <ordex@autistici.org> 1657M: Antonio Quartulli <antonio@meshcoding.com>
1658L: b.a.t.m.a.n@lists.open-mesh.org 1658L: b.a.t.m.a.n@lists.open-mesh.org
1659W: http://www.open-mesh.org/ 1659W: http://www.open-mesh.org/
1660S: Maintained 1660S: Maintained
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_ */