diff options
author | David S. Miller <davem@davemloft.net> | 2013-10-11 16:28:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-11 16:28:55 -0400 |
commit | 29b67c39dc6e7ec4fdf78c620675de761971cd28 (patch) | |
tree | ecc7076fc3dce7d2c5f917bca2b0c8c60cf7d520 /net | |
parent | 58308451e91974267e1f4a618346055342019e02 (diff) | |
parent | 18c68d5960c8dfeb2db113f4b871bab259cfd565 (diff) |
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes:
- update emails for A. Quartulli and M. Lindner in MAINTAINERS
- switch to the next on-the-wire protocol version
- introduce the T(ype) V(ersion) L(ength) V(alue) framework
- adjust the existing components to make them use the new TVLV code
- make the TT component use CRC32 instead of CRC16
- totally remove the VIS functionality (has been moved to userspace)
- reorder packet types and flags
- add static checks on packet format
- remove __packed from batadv_ogm_packet
Diffstat (limited to 'net')
26 files changed, 1964 insertions, 2072 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 489bb36f1b94..8ddbfe66d637 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile | |||
@@ -38,4 +38,3 @@ batman-adv-y += soft-interface.o | |||
38 | batman-adv-y += sysfs.o | 38 | batman-adv-y += sysfs.o |
39 | batman-adv-y += translation-table.o | 39 | batman-adv-y += translation-table.o |
40 | batman-adv-y += unicast.o | 40 | batman-adv-y += unicast.o |
41 | batman-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? */ |
209 | static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, | 208 | static 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 | |||
851 | update_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 | ||
877 | unlock: | 836 | unlock: |
@@ -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 | ||
303 | static 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 | |||
309 | struct batadv_debuginfo { | 302 | struct 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 |
357 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, | 350 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, |
358 | batadv_transtable_local_open); | 351 | batadv_transtable_local_open); |
359 | static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open); | ||
360 | #ifdef CONFIG_BATMAN_ADV_NC | 352 | #ifdef CONFIG_BATMAN_ADV_NC |
361 | static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); | 353 | static 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 | */ | ||
637 | static 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 | */ | ||
659 | void 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 | */ | ||
673 | static 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 | */ |
667 | void batadv_dat_free(struct batadv_priv *bat_priv) | 728 | void 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 | ||
32 | void batadv_dat_status_update(struct net_device *net_dev); | ||
32 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | 33 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, |
33 | struct sk_buff *skb); | 34 | struct sk_buff *skb); |
34 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | 35 | bool 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 | ||
102 | static inline void batadv_dat_status_update(struct net_device *net_dev) | ||
103 | { | ||
104 | } | ||
105 | |||
101 | static inline bool | 106 | static inline bool |
102 | batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | 107 | batadv_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 | */ | ||
340 | static void batadv_gw_node_add(struct batadv_priv *bat_priv, | 350 | static 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 | ||
369 | void 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 | */ | ||
387 | static struct batadv_gw_node * | ||
388 | batadv_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 | */ | ||
419 | void 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 | ||
413 | deselect: | 457 | /* Note: We don't need a NULL check here, since curr_gw never |
414 | batadv_gw_deselect(bat_priv); | 458 | * gets dereferenced. |
415 | unlock: | 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 | ||
465 | out: | ||
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 | ||
422 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, | 472 | void 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 | ||
428 | void batadv_gw_node_purge(struct batadv_priv *bat_priv) | 483 | void 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); |
30 | void batadv_gw_node_update(struct batadv_priv *bat_priv, | 30 | void 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); |
33 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, | 33 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, |
34 | struct batadv_orig_node *orig_node); | 34 | struct batadv_orig_node *orig_node); |
35 | void batadv_gw_node_purge(struct batadv_priv *bat_priv); | 35 | void 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 | /** |
25 | static 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 */ | ||
60 | void 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 | |||
76 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | 34 | static 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 | */ | ||
117 | void 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 | |||
137 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, | 141 | ssize_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 | ||
177 | end: | 177 | end: |
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 | */ | ||
189 | static 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 | */ | ||
228 | void 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 | */ | ||
239 | void 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 | */ | ||
34 | enum 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 | ||
33 | void batadv_gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up); | ||
34 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, | 43 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, |
35 | size_t count); | 44 | size_t count); |
45 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv); | ||
46 | void batadv_gw_init(struct batadv_priv *bat_priv); | ||
47 | void 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: | |||
194 | static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, | 194 | static 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); |
214 | out: | 205 | out: |
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 | ||
413 | int | 423 | int |
@@ -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 | */ | ||
559 | static void | ||
560 | batadv_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 | */ | ||
575 | static 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 | */ | ||
606 | static 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 | */ | ||
624 | static 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 | */ | ||
657 | static 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 | */ | ||
678 | static 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 | */ | ||
697 | void 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 | */ | ||
720 | void 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 | */ | ||
760 | static 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 | */ | ||
795 | uint16_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 | |||
830 | end: | ||
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 | */ | ||
850 | static 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 | */ | ||
903 | int 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 | */ | ||
963 | void 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 | */ | ||
997 | void 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 | */ | ||
1041 | void 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 | */ | ||
1068 | void 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 | |||
1115 | out: | ||
1116 | if (skb && !ret) | ||
1117 | kfree_skb(skb); | ||
1118 | if (orig_node) | ||
1119 | batadv_orig_node_free_ref(orig_node); | ||
1120 | } | ||
1121 | |||
539 | static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) | 1122 | static 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 | ||
327 | void 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); | ||
330 | uint16_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); | ||
334 | void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, | ||
335 | struct batadv_ogm_packet *batadv_ogm_packet, | ||
336 | struct batadv_orig_node *orig_node); | ||
337 | void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, | ||
338 | uint8_t type, uint8_t version); | ||
339 | |||
340 | void 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); | ||
351 | void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, | ||
352 | uint8_t type, uint8_t version); | ||
353 | int 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); | ||
358 | void 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 | */ | ||
66 | static 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 | */ | ||
88 | void 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 | */ | ||
102 | static 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 | ||
92 | err: | 149 | err: |
@@ -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 | */ |
1736 | void batadv_nc_mesh_free(struct batadv_priv *bat_priv) | 1797 | void 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 | ||
25 | void batadv_nc_status_update(struct net_device *net_dev); | ||
25 | int batadv_nc_init(void); | 26 | int batadv_nc_init(void); |
26 | int batadv_nc_mesh_init(struct batadv_priv *bat_priv); | 27 | int batadv_nc_mesh_init(struct batadv_priv *bat_priv); |
27 | void batadv_nc_mesh_free(struct batadv_priv *bat_priv); | 28 | void 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 | ||
51 | static inline void batadv_nc_status_update(struct net_device *net_dev) | ||
52 | { | ||
53 | } | ||
54 | |||
50 | static inline int batadv_nc_init(void) | 55 | static 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 | */ | ||
23 | enum batadv_packettype { | 37 | enum 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 | */ | ||
53 | enum batadv_iv_flags { | 79 | enum 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 */ | ||
70 | enum 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 */ |
76 | enum batadv_unicast_frag_flags { | 95 | enum 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 | ||
84 | enum 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 |
90 | enum batadv_tt_query_flags { | 109 | */ |
91 | BATADV_TT_FULL_TABLE = BIT(2), | 110 | enum 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 | */ | ||
147 | enum 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 | */ | ||
134 | struct batadv_ogm_packet { | 179 | struct 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 | ||
234 | struct 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 | |||
245 | struct 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 | |||
269 | struct 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 | |||
277 | struct 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 | */ | ||
321 | struct 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 | */ | ||
336 | struct 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 | */ | ||
348 | struct 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 | */ | ||
360 | struct 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 | */ | ||
374 | struct 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 | */ | ||
385 | struct 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 | ||
560 | int 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 | |||
633 | out: | ||
634 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | ||
635 | return NET_RX_DROP; | ||
636 | } | ||
637 | |||
638 | int 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); | ||
675 | out: | ||
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 | */ | ||
923 | int 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 | |||
1035 | int batadv_recv_unicast_packet(struct sk_buff *skb, | 942 | int 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 | */ | ||
1058 | int 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 | ||
1143 | int batadv_recv_bcast_packet(struct sk_buff *skb, | 1098 | int 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 | |||
1244 | int 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); |
35 | int batadv_recv_bcast_packet(struct sk_buff *skb, | 35 | int batadv_recv_bcast_packet(struct sk_buff *skb, |
36 | struct batadv_hard_iface *recv_if); | 36 | struct batadv_hard_iface *recv_if); |
37 | int batadv_recv_vis_packet(struct sk_buff *skb, | ||
38 | struct batadv_hard_iface *recv_if); | ||
39 | int batadv_recv_tt_query(struct sk_buff *skb, | 37 | int batadv_recv_tt_query(struct sk_buff *skb, |
40 | struct batadv_hard_iface *recv_if); | 38 | struct batadv_hard_iface *recv_if); |
41 | int batadv_recv_roam_adv(struct sk_buff *skb, | 39 | int batadv_recv_roam_adv(struct sk_buff *skb, |
42 | struct batadv_hard_iface *recv_if); | 40 | struct batadv_hard_iface *recv_if); |
41 | int batadv_recv_unicast_tvlv(struct sk_buff *skb, | ||
42 | struct batadv_hard_iface *recv_if); | ||
43 | int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, | ||
44 | struct batadv_hard_iface *recv_if); | ||
43 | struct batadv_neigh_node * | 45 | struct batadv_neigh_node * |
44 | batadv_find_router(struct batadv_priv *bat_priv, | 46 | batadv_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 | ||
30 | static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) | 30 | static 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 | ||
233 | static 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 | |||
248 | static 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 | |||
301 | static ssize_t batadv_show_bat_algo(struct kobject *kobj, | 233 | static 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 | ||
411 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, | 342 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, |
@@ -426,12 +357,11 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | |||
426 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); | 357 | BATADV_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 |
429 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); | 360 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, |
361 | batadv_dat_status_update); | ||
430 | #endif | 362 | #endif |
431 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); | 363 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); |
432 | BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | 364 | BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); |
433 | static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode, | ||
434 | batadv_store_vis_mode); | ||
435 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); | 365 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); |
436 | static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, | 366 | static 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, | |||
447 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); | 377 | BATADV_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 |
450 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL); | 380 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, |
381 | batadv_nc_status_update); | ||
451 | #endif | 382 | #endif |
452 | 383 | ||
453 | static struct batadv_attribute *batadv_mesh_attrs[] = { | 384 | static 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 */ |
33 | static struct lock_class_key batadv_tt_local_hash_lock_class_key; | 33 | static 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 | ||
232 | int 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 | */ | ||
238 | static 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 | ||
237 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) | 243 | static 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 | ||
379 | static 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; | 390 | static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv) |
385 | |||
386 | new_buff = kmalloc(new_packet_len, GFP_ATOMIC); | ||
387 | |||
388 | /* keep old buffer if kmalloc should fail */ | ||
389 | if (new_buff) { | ||
390 | memcpy(new_buff, *packet_buff, min_packet_len); | ||
391 | kfree(*packet_buff); | ||
392 | *packet_buff = new_buff; | ||
393 | *packet_buff_len = new_packet_len; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv, | ||
398 | unsigned char **packet_buff, | ||
399 | int *packet_buff_len, | ||
400 | int min_packet_len) | ||
401 | { | 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 | |||
417 | static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, | ||
418 | unsigned char **packet_buff, | ||
419 | int *packet_buff_len, | ||
420 | int min_packet_len) | ||
421 | { | ||
422 | struct batadv_tt_change_node *entry, *safe; | ||
423 | int count = 0, tot_changes = 0, new_len; | ||
424 | unsigned char *tt_buff; | ||
425 | 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; | 457 | container_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 | ||
471 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | 463 | int 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 | /** |
1406 | static 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 | */ | ||
1402 | static 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 | /** |
1459 | static 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 | */ | ||
1452 | static 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 | ||
1490 | static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | 1478 | static 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) | |||
1504 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, | 1492 | static 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 | /** |
1573 | static 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 | */ | ||
1567 | static 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 | ||
1601 | static struct sk_buff * | 1594 | /** |
1602 | batadv_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 | */ | ||
1606 | static struct batadv_tvlv_tt_data * | ||
1607 | batadv_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 | |||
1664 | out: | 1657 | out: |
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 | */ | ||
1668 | static int batadv_send_tt_request(struct batadv_priv *bat_priv, | 1670 | static 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 | ||
1721 | out: | 1711 | out: |
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 | ||
1735 | static bool | 1724 | /** |
1736 | batadv_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 | */ | ||
1734 | static 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 | ||
1844 | unlock: | 1823 | unlock: |
@@ -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 | ||
1857 | static bool | 1835 | /** |
1858 | batadv_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 | */ | ||
1844 | static 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 | ||
1960 | unlock: | 1929 | unlock: |
@@ -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 | ||
1973 | bool 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 | */ | ||
1950 | static 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 | ||
1987 | static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, | 1966 | static 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 | ||
2018 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, | 1997 | static 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 | ||
2043 | out: | 2022 | out: |
2044 | if (orig_node) | 2023 | if (orig_node) |
@@ -2048,7 +2027,7 @@ out: | |||
2048 | static void batadv_tt_update_changes(struct batadv_priv *bat_priv, | 2027 | static 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 | ||
2082 | void 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 | */ | ||
2068 | static 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 | ||
2129 | int batadv_tt_init(struct batadv_priv *bat_priv) | ||
2130 | { | ||
2131 | int ret; | ||
2132 | |||
2133 | ret = batadv_tt_local_init(bat_priv); | ||
2134 | if (ret < 0) | ||
2135 | return ret; | ||
2136 | |||
2137 | ret = batadv_tt_global_init(bat_priv); | ||
2138 | if (ret < 0) | ||
2139 | return ret; | ||
2140 | |||
2141 | INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); | ||
2142 | queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, | ||
2143 | msecs_to_jiffies(BATADV_TT_WORK_PERIOD)); | ||
2144 | |||
2145 | return 1; | ||
2146 | } | ||
2147 | |||
2148 | static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) | 2114 | static 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: | |||
2228 | static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, | 2194 | static 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 | ||
2273 | out: | 2223 | out: |
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 | ||
2279 | static void batadv_tt_purge(struct work_struct *work) | 2228 | static void batadv_tt_purge(struct work_struct *work) |
@@ -2297,6 +2246,9 @@ static void batadv_tt_purge(struct work_struct *work) | |||
2297 | 2246 | ||
2298 | void batadv_tt_free(struct batadv_priv *bat_priv) | 2247 | void 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 | ||
2387 | static 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 | */ | ||
2344 | void 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 */ | ||
2418 | int batadv_tt_append_diff(struct batadv_priv *bat_priv, | ||
2419 | unsigned char **packet_buff, int *packet_buff_len, | ||
2420 | int packet_min_len) | ||
2421 | { | ||
2422 | int tt_num_changes; | ||
2423 | |||
2424 | /* if at least one change happened */ | ||
2425 | tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff, | ||
2426 | packet_buff_len, | ||
2427 | packet_min_len); | ||
2428 | |||
2429 | /* if the changes have been sent often enough */ | ||
2430 | if ((tt_num_changes < 0) && | ||
2431 | (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { | ||
2432 | batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, | ||
2433 | packet_min_len, packet_min_len); | ||
2434 | tt_num_changes = 0; | ||
2435 | } | ||
2436 | |||
2437 | return tt_num_changes; | ||
2438 | } | 2371 | } |
2439 | 2372 | ||
2440 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, | 2373 | bool 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 | ||
2471 | void 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 | */ | ||
2414 | static 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) { |
2526 | request_table: | 2470 | request_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, | |||
2605 | out: | 2549 | out: |
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 | */ | ||
2561 | static 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 | */ | ||
2595 | static 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 | */ | ||
2669 | static 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 | |||
2709 | out: | ||
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 | */ | ||
2721 | int 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 | ||
23 | int batadv_tt_len(int changes_num); | ||
24 | int batadv_tt_init(struct batadv_priv *bat_priv); | 23 | int batadv_tt_init(struct batadv_priv *bat_priv); |
25 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | 24 | void 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); |
45 | void batadv_tt_free(struct batadv_priv *bat_priv); | 44 | void batadv_tt_free(struct batadv_priv *bat_priv); |
46 | bool batadv_send_tt_response(struct batadv_priv *bat_priv, | ||
47 | struct batadv_tt_query_packet *tt_request); | ||
48 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); | 45 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); |
49 | void batadv_handle_tt_response(struct batadv_priv *bat_priv, | ||
50 | struct batadv_tt_query_packet *tt_response); | ||
51 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, | 46 | bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, |
52 | uint8_t *dst); | 47 | uint8_t *dst); |
53 | void batadv_tt_update_orig(struct batadv_priv *bat_priv, | 48 | void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv); |
54 | struct batadv_orig_node *orig_node, | ||
55 | const unsigned char *tt_buff, uint8_t tt_num_changes, | ||
56 | uint8_t ttvn, uint16_t tt_crc); | ||
57 | int batadv_tt_append_diff(struct batadv_priv *bat_priv, | ||
58 | unsigned char **packet_buff, int *packet_buff_len, | ||
59 | int packet_min_len); | ||
60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | 49 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | uint8_t *addr); | 50 | uint8_t *addr); |
62 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | 51 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 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 | */ | ||
191 | enum 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 { | |||
196 | struct batadv_gw_node { | 206 | struct 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 | */ |
425 | struct batadv_priv_gw { | 439 | struct 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 | */ |
441 | struct batadv_priv_vis { | 455 | struct 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 | */ |
741 | struct batadv_tt_change_node { | 749 | struct 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 | */ | ||
892 | struct 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 | */ | ||
908 | struct 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 | */ | ||
919 | struct 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 | */ | ||
934 | struct 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 | */ | ||
951 | struct 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 | */ | ||
970 | struct 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 | */ | ||
994 | enum 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 */ | ||
32 | static struct lock_class_key batadv_vis_hash_lock_class_key; | ||
33 | |||
34 | /* free the info */ | ||
35 | static 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 */ | ||
57 | static 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 | */ | ||
72 | static 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 | |||
95 | static struct batadv_vis_info * | ||
96 | batadv_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 | */ | ||
125 | static 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 | |||
145 | static 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 */ | ||
159 | static ssize_t | ||
160 | batadv_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 | |||
173 | static void | ||
174 | batadv_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 | |||
191 | static 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 | |||
214 | static 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 | |||
245 | int 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 | |||
270 | out: | ||
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 | */ | ||
279 | static 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 | */ | ||
291 | static 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. */ | ||
300 | static 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 */ | ||
316 | static 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 | */ | ||
337 | static struct batadv_vis_info * | ||
338 | batadv_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. */ | ||
439 | void 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); | ||
460 | end: | ||
461 | spin_unlock_bh(&bat_priv->vis.hash_lock); | ||
462 | } | ||
463 | |||
464 | /* handle an incoming client update packet and schedule forward if needed. */ | ||
465 | void 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 | |||
504 | end: | ||
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 | */ | ||
513 | static 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. */ | ||
550 | static 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 | */ | ||
566 | static 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 | |||
626 | next: | ||
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 | |||
658 | unlock: | ||
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 | */ | ||
666 | static 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 | |||
693 | static 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 | |||
736 | static 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 | |||
756 | out: | ||
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() */ | ||
762 | static 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 | |||
787 | out: | ||
788 | if (primary_if) | ||
789 | batadv_hardif_free_ref(primary_if); | ||
790 | } | ||
791 | |||
792 | /* called from timer; send (and maybe generate) vis packet. */ | ||
793 | static 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 | */ | ||
833 | int 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 | |||
905 | free_info: | ||
906 | kfree(bat_priv->vis.my_info); | ||
907 | bat_priv->vis.my_info = NULL; | ||
908 | err: | ||
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 */ | ||
915 | static 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 */ | ||
925 | void 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 | |||
26 | int batadv_vis_seq_print_text(struct seq_file *seq, void *offset); | ||
27 | void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv, | ||
28 | struct batadv_vis_packet *vis_packet, | ||
29 | int vis_info_len); | ||
30 | void batadv_receive_client_update_packet(struct batadv_priv *bat_priv, | ||
31 | struct batadv_vis_packet *vis_packet, | ||
32 | int vis_info_len); | ||
33 | int batadv_vis_init(struct batadv_priv *bat_priv); | ||
34 | void batadv_vis_quit(struct batadv_priv *bat_priv); | ||
35 | |||
36 | #endif /* _NET_BATMAN_ADV_VIS_H_ */ | ||