Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+1969 -2134
-11
Documentation/ABI/testing/sysfs-class-net-mesh
··· 88 88 Description: 89 89 Defines the routing procotol this mesh instance 90 90 uses to find the optimal paths through the mesh. 91 - 92 - What: /sys/class/net/<mesh_iface>/mesh/vis_mode 93 - Date: May 2010 94 - Contact: Marek Lindner <lindner_marek@yahoo.de> 95 - Description: 96 - Each batman node only maintains information about its 97 - own local neighborhood, therefore generating graphs 98 - showing the topology of the entire mesh is not easily 99 - feasible without having a central instance to collect 100 - the local topologies from all nodes. This file allows 101 - to activate the collecting (server) mode.
+2 -48
Documentation/networking/batman-adv.txt
··· 69 69 # aggregated_ogms gw_bandwidth log_level 70 70 # ap_isolation gw_mode orig_interval 71 71 # bonding gw_sel_class routing_algo 72 - # bridge_loop_avoidance hop_penalty vis_mode 73 - # fragmentation 72 + # bridge_loop_avoidance hop_penalty fragmentation 74 73 75 74 76 75 There is a special folder for debugging information: ··· 77 78 # ls /sys/kernel/debug/batman_adv/bat0/ 78 79 # bla_backbone_table log transtable_global 79 80 # bla_claim_table originators transtable_local 80 - # gateways socket vis_data 81 + # gateways socket 81 82 82 83 Some of the files contain all sort of status information regard- 83 84 ing the mesh network. For example, you can view the table of ··· 124 125 ously assigned to interfaces now used by batman advanced, e.g. 125 126 126 127 # ifconfig eth0 0.0.0.0 127 - 128 - 129 - VISUALIZATION 130 - ------------- 131 - 132 - If you want topology visualization, at least one mesh node must 133 - be configured as VIS-server: 134 - 135 - # echo "server" > /sys/class/net/bat0/mesh/vis_mode 136 - 137 - Each node is either configured as "server" or as "client" (de- 138 - fault: "client"). Clients send their topology data to the server 139 - next to them, and server synchronize with other servers. If there 140 - is no server configured (default) within the mesh, no topology 141 - information will be transmitted. With these "synchronizing 142 - servers", there can be 1 or more vis servers sharing the same (or 143 - at least very similar) data. 144 - 145 - When configured as server, you can get a topology snapshot of 146 - your mesh: 147 - 148 - # cat /sys/kernel/debug/batman_adv/bat0/vis_data 149 - 150 - This raw output is intended to be easily parsable and convertable 151 - with other tools. Have a look at the batctl README if you want a 152 - vis output in dot or json format for instance and how those out- 153 - puts could then be visualised in an image. 154 - 155 - The raw format consists of comma separated values per entry where 156 - each entry is giving information about a certain source inter- 157 - face. Each entry can/has to have the following values: 158 - -> "mac" - mac address of an originator's source interface 159 - (each line begins with it) 160 - -> "TQ mac value" - src mac's link quality towards mac address 161 - of a neighbor originator's interface which 162 - is being used for routing 163 - -> "TT mac" - TT announced by source mac 164 - -> "PRIMARY" - this is a primary interface 165 - -> "SEC mac" - secondary mac address of source 166 - (requires preceding PRIMARY) 167 - 168 - The TQ value has a range from 4 to 255 with 255 being the best. 169 - The TT entries are showing which hosts are connected to the mesh 170 - via bat0 or being bridged into the mesh network. The PRIMARY/SEC 171 - values are only applied on primary interfaces 172 128 173 129 174 130 LOGGING/DEBUGGING
+2 -2
MAINTAINERS
··· 1652 1652 F: include/linux/backlight.h 1653 1653 1654 1654 BATMAN ADVANCED 1655 - M: Marek Lindner <lindner_marek@yahoo.de> 1655 + M: Marek Lindner <mareklindner@neomailbox.ch> 1656 1656 M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 1657 - M: Antonio Quartulli <ordex@autistici.org> 1657 + M: Antonio Quartulli <antonio@meshcoding.com> 1658 1658 L: b.a.t.m.a.n@lists.open-mesh.org 1659 1659 W: http://www.open-mesh.org/ 1660 1660 S: Maintained
-1
net/batman-adv/Makefile
··· 38 38 batman-adv-y += sysfs.o 39 39 batman-adv-y += translation-table.o 40 40 batman-adv-y += unicast.o 41 - batman-adv-y += vis.o
+35 -76
net/batman-adv/bat_iv_ogm.c
··· 135 135 batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; 136 136 batadv_ogm_packet->header.ttl = 2; 137 137 batadv_ogm_packet->flags = BATADV_NO_FLAGS; 138 + batadv_ogm_packet->reserved = 0; 138 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 141 res = 0; 143 142 ··· 206 207 207 208 /* is there another aggregated packet here? */ 208 209 static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, 209 - int tt_num_changes) 210 + __be16 tvlv_len) 210 211 { 211 212 int next_buff_pos = 0; 212 213 213 214 next_buff_pos += buff_pos + BATADV_OGM_HLEN; 214 - next_buff_pos += batadv_tt_len(tt_num_changes); 215 + next_buff_pos += ntohs(tvlv_len); 215 216 216 217 return (next_buff_pos <= packet_len) && 217 218 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); ··· 239 240 240 241 /* adjust all flags and log packets */ 241 242 while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, 242 - batadv_ogm_packet->tt_num_changes)) { 243 + batadv_ogm_packet->tvlv_len)) { 243 244 /* we might have aggregated direct link packets with an 244 245 * ordinary base packet 245 246 */ ··· 255 256 fwd_str = "Sending own"; 256 257 257 258 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 258 - "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", 259 + "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s) on interface %s [%pM]\n", 259 260 fwd_str, (packet_num > 0 ? "aggregated " : ""), 260 261 batadv_ogm_packet->orig, 261 262 ntohl(batadv_ogm_packet->seqno), 262 263 batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl, 263 264 (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 264 265 "on" : "off"), 265 - batadv_ogm_packet->ttvn, hard_iface->net_dev->name, 266 + hard_iface->net_dev->name, 266 267 hard_iface->net_dev->dev_addr); 267 268 268 269 buff_pos += BATADV_OGM_HLEN; 269 - buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 270 + buff_pos += ntohs(batadv_ogm_packet->tvlv_len); 270 271 packet_num++; 271 272 packet_pos = forw_packet->skb->data + buff_pos; 272 273 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; ··· 600 601 struct batadv_hard_iface *if_incoming) 601 602 { 602 603 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 603 - uint8_t tt_num_changes; 604 + uint16_t tvlv_len; 604 605 605 606 if (batadv_ogm_packet->header.ttl <= 1) { 606 607 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n"); ··· 620 621 return; 621 622 } 622 623 623 - tt_num_changes = batadv_ogm_packet->tt_num_changes; 624 + tvlv_len = ntohs(batadv_ogm_packet->tvlv_len); 624 625 625 626 batadv_ogm_packet->header.ttl--; 626 627 memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); ··· 641 642 batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; 642 643 643 644 batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, 644 - BATADV_OGM_HLEN + batadv_tt_len(tt_num_changes), 645 + BATADV_OGM_HLEN + tvlv_len, 645 646 if_incoming, 0, batadv_iv_ogm_fwd_send_time()); 646 647 } 647 648 ··· 687 688 struct batadv_ogm_packet *batadv_ogm_packet; 688 689 struct batadv_hard_iface *primary_if; 689 690 int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; 690 - int vis_server, tt_num_changes = 0; 691 691 uint32_t seqno; 692 - uint8_t bandwidth; 692 + uint16_t tvlv_len = 0; 693 693 694 - vis_server = atomic_read(&bat_priv->vis_mode); 695 694 primary_if = batadv_primary_if_get_selected(bat_priv); 696 695 697 - if (hard_iface == primary_if) 698 - tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff, 699 - ogm_buff_len, 700 - BATADV_OGM_HLEN); 696 + if (hard_iface == primary_if) { 697 + /* tt changes have to be committed before the tvlv data is 698 + * appended as it may alter the tt tvlv container 699 + */ 700 + batadv_tt_local_commit_changes(bat_priv); 701 + tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff, 702 + ogm_buff_len, 703 + BATADV_OGM_HLEN); 704 + } 701 705 702 706 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); 707 + batadv_ogm_packet->tvlv_len = htons(tvlv_len); 703 708 704 709 /* change sequence number to network order */ 705 710 seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno); 706 711 batadv_ogm_packet->seqno = htonl(seqno); 707 712 atomic_inc(&hard_iface->bat_iv.ogm_seqno); 708 - 709 - batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn); 710 - batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); 711 - if (tt_num_changes >= 0) 712 - batadv_ogm_packet->tt_num_changes = tt_num_changes; 713 - 714 - if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC) 715 - batadv_ogm_packet->flags |= BATADV_VIS_SERVER; 716 - else 717 - batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER; 718 - 719 - if (hard_iface == primary_if && 720 - atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) { 721 - bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); 722 - batadv_ogm_packet->gw_flags = bandwidth; 723 - } else { 724 - batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; 725 - } 726 713 727 714 batadv_iv_ogm_slide_own_bcast_window(hard_iface); 728 715 batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, ··· 783 798 784 799 rcu_read_unlock(); 785 800 786 - orig_node->flags = batadv_ogm_packet->flags; 787 801 neigh_node->last_seen = jiffies; 788 802 789 803 spin_lock_bh(&neigh_node->lq_update_lock); ··· 804 820 */ 805 821 router = batadv_orig_node_get_router(orig_node); 806 822 if (router == neigh_node) 807 - goto update_tt; 823 + goto out; 808 824 809 825 /* if this neighbor does not offer a better TQ we won't consider it */ 810 826 if (router && (router->tq_avg > neigh_node->tq_avg)) 811 - goto update_tt; 827 + goto out; 812 828 813 829 /* if the TQ is the same and the link not more symmetric we 814 830 * won't consider it either ··· 827 843 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); 828 844 829 845 if (sum_orig >= sum_neigh) 830 - goto update_tt; 846 + goto out; 831 847 } 832 848 833 849 batadv_update_route(bat_priv, orig_node, neigh_node); 834 - 835 - update_tt: 836 - /* I have to check for transtable changes only if the OGM has been 837 - * sent through a primary interface 838 - */ 839 - if (((batadv_ogm_packet->orig != ethhdr->h_source) && 840 - (batadv_ogm_packet->header.ttl > 2)) || 841 - (batadv_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP)) 842 - batadv_tt_update_orig(bat_priv, orig_node, tt_buff, 843 - batadv_ogm_packet->tt_num_changes, 844 - batadv_ogm_packet->ttvn, 845 - ntohs(batadv_ogm_packet->tt_crc)); 846 - 847 - if (orig_node->gw_flags != batadv_ogm_packet->gw_flags) 848 - batadv_gw_node_update(bat_priv, orig_node, 849 - batadv_ogm_packet->gw_flags); 850 - 851 - orig_node->gw_flags = batadv_ogm_packet->gw_flags; 852 - 853 - /* restart gateway selection if fast or late switching was enabled */ 854 - if ((orig_node->gw_flags) && 855 - (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && 856 - (atomic_read(&bat_priv->gw_sel_class) > 2)) 857 - batadv_gw_check_election(bat_priv, orig_node); 858 - 859 850 goto out; 860 851 861 852 unlock: ··· 1081 1122 is_single_hop_neigh = true; 1082 1123 1083 1124 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1084 - "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", 1125 + "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", 1085 1126 ethhdr->h_source, if_incoming->net_dev->name, 1086 1127 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig, 1087 1128 batadv_ogm_packet->prev_sender, 1088 - ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->ttvn, 1089 - ntohs(batadv_ogm_packet->tt_crc), 1090 - batadv_ogm_packet->tt_num_changes, batadv_ogm_packet->tq, 1129 + ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq, 1091 1130 batadv_ogm_packet->header.ttl, 1092 1131 batadv_ogm_packet->header.version, has_directlink_flag); 1093 1132 ··· 1211 1254 goto out; 1212 1255 } 1213 1256 1257 + batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node); 1258 + 1214 1259 /* if sender is a direct neighbor the sender mac equals 1215 1260 * originator mac 1216 1261 */ ··· 1309 1350 struct batadv_ogm_packet *batadv_ogm_packet; 1310 1351 struct ethhdr *ethhdr; 1311 1352 int buff_pos = 0, packet_len; 1312 - unsigned char *tt_buff, *packet_buff; 1313 - bool ret; 1353 + unsigned char *tvlv_buff, *packet_buff; 1314 1354 uint8_t *packet_pos; 1355 + bool ret; 1315 1356 1316 1357 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); 1317 1358 if (!ret) ··· 1334 1375 1335 1376 /* unpack the aggregated packets and process them one by one */ 1336 1377 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, 1337 - batadv_ogm_packet->tt_num_changes)) { 1338 - tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; 1378 + batadv_ogm_packet->tvlv_len)) { 1379 + tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; 1339 1380 1340 - batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, 1341 - if_incoming); 1381 + batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, 1382 + tvlv_buff, if_incoming); 1342 1383 1343 1384 buff_pos += BATADV_OGM_HLEN; 1344 - buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 1385 + buff_pos += ntohs(batadv_ogm_packet->tvlv_len); 1345 1386 1346 1387 packet_pos = packet_buff + buff_pos; 1347 1388 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
-9
net/batman-adv/debugfs.c
··· 28 28 #include "gateway_common.h" 29 29 #include "gateway_client.h" 30 30 #include "soft-interface.h" 31 - #include "vis.h" 32 31 #include "icmp_socket.h" 33 32 #include "bridge_loop_avoidance.h" 34 33 #include "distributed-arp-table.h" ··· 299 300 return single_open(file, batadv_tt_local_seq_print_text, net_dev); 300 301 } 301 302 302 - static int batadv_vis_data_open(struct inode *inode, struct file *file) 303 - { 304 - struct net_device *net_dev = (struct net_device *)inode->i_private; 305 - return single_open(file, batadv_vis_seq_print_text, net_dev); 306 - } 307 - 308 303 struct batadv_debuginfo { 309 304 struct attribute attr; 310 305 const struct file_operations fops; ··· 349 356 #endif 350 357 static BATADV_DEBUGINFO(transtable_local, S_IRUGO, 351 358 batadv_transtable_local_open); 352 - static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open); 353 359 #ifdef CONFIG_BATMAN_ADV_NC 354 360 static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); 355 361 #endif ··· 365 373 &batadv_debuginfo_dat_cache, 366 374 #endif 367 375 &batadv_debuginfo_transtable_local, 368 - &batadv_debuginfo_vis_data, 369 376 #ifdef CONFIG_BATMAN_ADV_NC 370 377 &batadv_debuginfo_nc_nodes, 371 378 #endif
+64
net/batman-adv/distributed-arp-table.c
··· 419 419 bool ret = false; 420 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 426 /* Check if this node has already been selected... */ 423 427 for (j = 0; j < select; j++) 424 428 if (res[j].orig_node == candidate) ··· 630 626 } 631 627 632 628 /** 629 + * batadv_dat_tvlv_container_update - update the dat tvlv container after dat 630 + * setting change 631 + * @bat_priv: the bat priv with all the soft interface information 632 + */ 633 + static void batadv_dat_tvlv_container_update(struct batadv_priv *bat_priv) 634 + { 635 + char dat_mode; 636 + 637 + dat_mode = atomic_read(&bat_priv->distributed_arp_table); 638 + 639 + switch (dat_mode) { 640 + case 0: 641 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1); 642 + break; 643 + case 1: 644 + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_DAT, 1, 645 + NULL, 0); 646 + break; 647 + } 648 + } 649 + 650 + /** 651 + * batadv_dat_status_update - update the dat tvlv container after dat 652 + * setting change 653 + * @net_dev: the soft interface net device 654 + */ 655 + void batadv_dat_status_update(struct net_device *net_dev) 656 + { 657 + struct batadv_priv *bat_priv = netdev_priv(net_dev); 658 + batadv_dat_tvlv_container_update(bat_priv); 659 + } 660 + 661 + /** 662 + * batadv_gw_tvlv_ogm_handler_v1 - process incoming dat tvlv container 663 + * @bat_priv: the bat priv with all the soft interface information 664 + * @orig: the orig_node of the ogm 665 + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 666 + * @tvlv_value: tvlv buffer containing the gateway data 667 + * @tvlv_value_len: tvlv buffer length 668 + */ 669 + static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 670 + struct batadv_orig_node *orig, 671 + uint8_t flags, 672 + void *tvlv_value, 673 + uint16_t tvlv_value_len) 674 + { 675 + if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) 676 + orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT; 677 + else 678 + orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT; 679 + } 680 + 681 + /** 633 682 * batadv_dat_hash_free - free the local DAT hash table 634 683 * @bat_priv: the bat priv with all the soft interface information 635 684 */ ··· 714 657 715 658 batadv_dat_start_timer(bat_priv); 716 659 660 + batadv_tvlv_handler_register(bat_priv, batadv_dat_tvlv_ogm_handler_v1, 661 + NULL, BATADV_TVLV_DAT, 1, 662 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 663 + batadv_dat_tvlv_container_update(bat_priv); 717 664 return 0; 718 665 } 719 666 ··· 727 666 */ 728 667 void batadv_dat_free(struct batadv_priv *bat_priv) 729 668 { 669 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1); 670 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_DAT, 1); 671 + 730 672 cancel_delayed_work_sync(&bat_priv->dat.work); 731 673 732 674 batadv_dat_hash_free(bat_priv);
+5
net/batman-adv/distributed-arp-table.h
··· 29 29 30 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 33 bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, 33 34 struct sk_buff *skb); 34 35 bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, ··· 98 97 } 99 98 100 99 #else 100 + 101 + static inline void batadv_dat_status_update(struct net_device *net_dev) 102 + { 103 + } 101 104 102 105 static inline bool 103 106 batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+125 -70
net/batman-adv/gateway_client.c
··· 118 118 uint32_t max_gw_factor = 0, tmp_gw_factor = 0; 119 119 uint32_t gw_divisor; 120 120 uint8_t max_tq = 0; 121 - int down, up; 122 121 uint8_t tq_avg; 123 122 struct batadv_orig_node *orig_node; 124 123 ··· 141 142 142 143 switch (atomic_read(&bat_priv->gw_sel_class)) { 143 144 case 1: /* fast connection */ 144 - batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, 145 - &down, &up); 146 - 147 - tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100; 145 + tmp_gw_factor = tq_avg * tq_avg; 146 + tmp_gw_factor *= gw_node->bandwidth_down; 147 + tmp_gw_factor *= 100 * 100; 148 148 tmp_gw_factor /= gw_divisor; 149 149 150 150 if ((tmp_gw_factor > max_gw_factor) || ··· 256 258 NULL); 257 259 } else if ((!curr_gw) && (next_gw)) { 258 260 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 259 - "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n", 261 + "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", 260 262 next_gw->orig_node->orig, 261 - next_gw->orig_node->gw_flags, router->tq_avg); 263 + next_gw->bandwidth_down / 10, 264 + next_gw->bandwidth_down % 10, 265 + next_gw->bandwidth_up / 10, 266 + next_gw->bandwidth_up % 10, router->tq_avg); 262 267 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, 263 268 gw_addr); 264 269 } else { 265 270 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 266 - "Changing route to gateway %pM (gw_flags: %i, tq: %i)\n", 271 + "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", 267 272 next_gw->orig_node->orig, 268 - next_gw->orig_node->gw_flags, router->tq_avg); 273 + next_gw->bandwidth_down / 10, 274 + next_gw->bandwidth_down % 10, 275 + next_gw->bandwidth_up / 10, 276 + next_gw->bandwidth_up % 10, router->tq_avg); 269 277 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, 270 278 gw_addr); 271 279 } ··· 341 337 return; 342 338 } 343 339 340 + /** 341 + * batadv_gw_node_add - add gateway node to list of available gateways 342 + * @bat_priv: the bat priv with all the soft interface information 343 + * @orig_node: originator announcing gateway capabilities 344 + * @gateway: announced bandwidth information 345 + */ 344 346 static void batadv_gw_node_add(struct batadv_priv *bat_priv, 345 347 struct batadv_orig_node *orig_node, 346 - uint8_t new_gwflags) 348 + struct batadv_tvlv_gateway_data *gateway) 347 349 { 348 350 struct batadv_gw_node *gw_node; 349 - int down, up; 351 + 352 + if (gateway->bandwidth_down == 0) 353 + return; 350 354 351 355 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); 352 356 if (!gw_node) ··· 368 356 hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); 369 357 spin_unlock_bh(&bat_priv->gw.list_lock); 370 358 371 - batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); 372 359 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 373 - "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", 374 - orig_node->orig, new_gwflags, 375 - (down > 2048 ? down / 1024 : down), 376 - (down > 2048 ? "MBit" : "KBit"), 377 - (up > 2048 ? up / 1024 : up), 378 - (up > 2048 ? "MBit" : "KBit")); 360 + "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", 361 + orig_node->orig, 362 + ntohl(gateway->bandwidth_down) / 10, 363 + ntohl(gateway->bandwidth_down) % 10, 364 + ntohl(gateway->bandwidth_up) / 10, 365 + ntohl(gateway->bandwidth_up) % 10); 379 366 } 380 367 381 - void batadv_gw_node_update(struct batadv_priv *bat_priv, 382 - struct batadv_orig_node *orig_node, 383 - uint8_t new_gwflags) 368 + /** 369 + * batadv_gw_node_get - retrieve gateway node from list of available gateways 370 + * @bat_priv: the bat priv with all the soft interface information 371 + * @orig_node: originator announcing gateway capabilities 372 + * 373 + * Returns gateway node if found or NULL otherwise. 374 + */ 375 + static struct batadv_gw_node * 376 + batadv_gw_node_get(struct batadv_priv *bat_priv, 377 + struct batadv_orig_node *orig_node) 384 378 { 385 - struct batadv_gw_node *gw_node, *curr_gw; 386 - 387 - /* Note: We don't need a NULL check here, since curr_gw never gets 388 - * dereferenced. If curr_gw is NULL we also should not exit as we may 389 - * have this gateway in our list (duplication check!) even though we 390 - * have no currently selected gateway. 391 - */ 392 - curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 379 + struct batadv_gw_node *gw_node_tmp, *gw_node = NULL; 393 380 394 381 rcu_read_lock(); 395 - hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { 396 - if (gw_node->orig_node != orig_node) 382 + hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) { 383 + if (gw_node_tmp->orig_node != orig_node) 397 384 continue; 398 385 399 - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 400 - "Gateway class of originator %pM changed from %i to %i\n", 401 - orig_node->orig, gw_node->orig_node->gw_flags, 402 - new_gwflags); 386 + if (gw_node_tmp->deleted) 387 + continue; 403 388 404 - gw_node->deleted = 0; 389 + if (!atomic_inc_not_zero(&gw_node_tmp->refcount)) 390 + continue; 405 391 406 - if (new_gwflags == BATADV_NO_FLAGS) { 407 - gw_node->deleted = jiffies; 408 - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 409 - "Gateway %pM removed from gateway list\n", 410 - orig_node->orig); 411 - 412 - if (gw_node == curr_gw) 413 - goto deselect; 414 - } 415 - 416 - goto unlock; 392 + gw_node = gw_node_tmp; 393 + break; 417 394 } 418 - 419 - if (new_gwflags == BATADV_NO_FLAGS) 420 - goto unlock; 421 - 422 - batadv_gw_node_add(bat_priv, orig_node, new_gwflags); 423 - goto unlock; 424 - 425 - deselect: 426 - batadv_gw_deselect(bat_priv); 427 - unlock: 428 395 rcu_read_unlock(); 429 396 397 + return gw_node; 398 + } 399 + 400 + /** 401 + * batadv_gw_node_update - update list of available gateways with changed 402 + * bandwidth information 403 + * @bat_priv: the bat priv with all the soft interface information 404 + * @orig_node: originator announcing gateway capabilities 405 + * @gateway: announced bandwidth information 406 + */ 407 + void batadv_gw_node_update(struct batadv_priv *bat_priv, 408 + struct batadv_orig_node *orig_node, 409 + struct batadv_tvlv_gateway_data *gateway) 410 + { 411 + struct batadv_gw_node *gw_node, *curr_gw = NULL; 412 + 413 + gw_node = batadv_gw_node_get(bat_priv, orig_node); 414 + if (!gw_node) { 415 + batadv_gw_node_add(bat_priv, orig_node, gateway); 416 + goto out; 417 + } 418 + 419 + if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && 420 + (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) 421 + goto out; 422 + 423 + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 424 + "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n", 425 + orig_node->orig, 426 + gw_node->bandwidth_down / 10, 427 + gw_node->bandwidth_down % 10, 428 + gw_node->bandwidth_up / 10, 429 + gw_node->bandwidth_up % 10, 430 + ntohl(gateway->bandwidth_down) / 10, 431 + ntohl(gateway->bandwidth_down) % 10, 432 + ntohl(gateway->bandwidth_up) / 10, 433 + ntohl(gateway->bandwidth_up) % 10); 434 + 435 + gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); 436 + gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); 437 + 438 + gw_node->deleted = 0; 439 + if (ntohl(gateway->bandwidth_down) == 0) { 440 + gw_node->deleted = jiffies; 441 + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 442 + "Gateway %pM removed from gateway list\n", 443 + orig_node->orig); 444 + 445 + /* Note: We don't need a NULL check here, since curr_gw never 446 + * gets dereferenced. 447 + */ 448 + curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 449 + if (gw_node == curr_gw) 450 + batadv_gw_deselect(bat_priv); 451 + } 452 + 453 + out: 430 454 if (curr_gw) 431 455 batadv_gw_node_free_ref(curr_gw); 456 + if (gw_node) 457 + batadv_gw_node_free_ref(gw_node); 432 458 } 433 459 434 460 void batadv_gw_node_delete(struct batadv_priv *bat_priv, 435 461 struct batadv_orig_node *orig_node) 436 462 { 437 - batadv_gw_node_update(bat_priv, orig_node, 0); 463 + struct batadv_tvlv_gateway_data gateway; 464 + 465 + gateway.bandwidth_down = 0; 466 + gateway.bandwidth_up = 0; 467 + 468 + batadv_gw_node_update(bat_priv, orig_node, &gateway); 438 469 } 439 470 440 471 void batadv_gw_node_purge(struct batadv_priv *bat_priv) ··· 522 467 { 523 468 struct batadv_gw_node *curr_gw; 524 469 struct batadv_neigh_node *router; 525 - int down, up, ret = -1; 526 - 527 - batadv_gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); 470 + int ret = -1; 528 471 529 472 router = batadv_orig_node_get_router(gw_node->orig_node); 530 473 if (!router) ··· 530 477 531 478 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 532 479 533 - ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", 480 + ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", 534 481 (curr_gw == gw_node ? "=>" : " "), 535 482 gw_node->orig_node->orig, 536 483 router->tq_avg, router->addr, 537 484 router->if_incoming->net_dev->name, 538 - gw_node->orig_node->gw_flags, 539 - (down > 2048 ? down / 1024 : down), 540 - (down > 2048 ? "MBit" : "KBit"), 541 - (up > 2048 ? up / 1024 : up), 542 - (up > 2048 ? "MBit" : "KBit")); 485 + gw_node->bandwidth_down / 10, 486 + gw_node->bandwidth_down % 10, 487 + gw_node->bandwidth_up / 10, 488 + gw_node->bandwidth_up % 10); 543 489 544 490 batadv_neigh_node_free_ref(router); 545 491 if (curr_gw) ··· 560 508 goto out; 561 509 562 510 seq_printf(seq, 563 - " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", 511 + " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", 564 512 "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", 565 513 BATADV_SOURCE_VERSION, primary_if->net_dev->name, 566 514 primary_if->net_dev->dev_addr, net_dev->name); ··· 727 675 { 728 676 struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; 729 677 struct batadv_orig_node *orig_dst_node = NULL; 730 - struct batadv_gw_node *curr_gw = NULL; 678 + struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; 731 679 struct ethhdr *ethhdr; 732 680 bool ret, out_of_range = false; 733 681 unsigned int header_len = 0; ··· 743 691 if (!orig_dst_node) 744 692 goto out; 745 693 746 - if (!orig_dst_node->gw_flags) 694 + gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); 695 + if (!gw_node->bandwidth_down == 0) 747 696 goto out; 748 697 749 698 ret = batadv_is_type_dhcprequest(skb, header_len); ··· 795 742 batadv_orig_node_free_ref(orig_dst_node); 796 743 if (curr_gw) 797 744 batadv_gw_node_free_ref(curr_gw); 745 + if (gw_node) 746 + batadv_gw_node_free_ref(gw_node); 798 747 if (neigh_old) 799 748 batadv_neigh_node_free_ref(neigh_old); 800 749 if (neigh_curr)
+1 -1
net/batman-adv/gateway_client.h
··· 29 29 struct batadv_orig_node *orig_node); 30 30 void batadv_gw_node_update(struct batadv_priv *bat_priv, 31 31 struct batadv_orig_node *orig_node, 32 - uint8_t new_gwflags); 32 + struct batadv_tvlv_gateway_data *gateway); 33 33 void batadv_gw_node_delete(struct batadv_priv *bat_priv, 34 34 struct batadv_orig_node *orig_node); 35 35 void batadv_gw_node_purge(struct batadv_priv *bat_priv);
+147 -83
net/batman-adv/gateway_common.c
··· 21 21 #include "gateway_common.h" 22 22 #include "gateway_client.h" 23 23 24 - /* calculates the gateway class from kbit */ 25 - static void batadv_kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class) 26 - { 27 - int mdown = 0, tdown, tup, difference; 28 - uint8_t sbit, part; 29 - 30 - *gw_srv_class = 0; 31 - difference = 0x0FFFFFFF; 32 - 33 - /* test all downspeeds */ 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 - 24 + /** 25 + * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download 26 + * and upload bandwidth information 27 + * @net_dev: the soft interface net device 28 + * @buff: string buffer to parse 29 + * @down: pointer holding the returned download bandwidth information 30 + * @up: pointer holding the returned upload bandwidth information 31 + * 32 + * Returns false on parse error and true otherwise. 33 + */ 76 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 38 char *slash_ptr, *tmp_ptr; 81 39 long ldown, lup; 40 + int ret; 82 41 83 42 slash_ptr = strchr(buff, '/'); 84 43 if (slash_ptr) ··· 47 88 tmp_ptr = buff + strlen(buff) - 4; 48 89 49 90 if (strnicmp(tmp_ptr, "mbit", 4) == 0) 50 - multi = 1024; 91 + bw_unit_type = BATADV_BW_UNIT_MBIT; 51 92 52 93 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || 53 - (multi > 1)) 94 + (bw_unit_type == BATADV_BW_UNIT_MBIT)) 54 95 *tmp_ptr = '\0'; 55 96 } 56 97 ··· 62 103 return false; 63 104 } 64 105 65 - *down = ldown * multi; 106 + switch (bw_unit_type) { 107 + case BATADV_BW_UNIT_MBIT: 108 + *down = ldown * 10; 109 + break; 110 + case BATADV_BW_UNIT_KBIT: 111 + default: 112 + *down = ldown / 100; 113 + break; 114 + } 66 115 67 116 /* we also got some upload info */ 68 117 if (slash_ptr) { 69 - multi = 1; 118 + bw_unit_type = BATADV_BW_UNIT_KBIT; 70 119 71 120 if (strlen(slash_ptr + 1) > 4) { 72 121 tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); 73 122 74 123 if (strnicmp(tmp_ptr, "mbit", 4) == 0) 75 - multi = 1024; 124 + bw_unit_type = BATADV_BW_UNIT_MBIT; 76 125 77 126 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || 78 - (multi > 1)) 127 + (bw_unit_type == BATADV_BW_UNIT_MBIT)) 79 128 *tmp_ptr = '\0'; 80 129 } 81 130 ··· 95 128 return false; 96 129 } 97 130 98 - *up = lup * multi; 131 + switch (bw_unit_type) { 132 + case BATADV_BW_UNIT_MBIT: 133 + *up = lup * 10; 134 + break; 135 + case BATADV_BW_UNIT_KBIT: 136 + default: 137 + *up = lup / 100; 138 + break; 139 + } 99 140 } 100 141 101 142 return true; 143 + } 144 + 145 + /** 146 + * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway 147 + * setting change 148 + * @bat_priv: the bat priv with all the soft interface information 149 + */ 150 + void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) 151 + { 152 + struct batadv_tvlv_gateway_data gw; 153 + uint32_t down, up; 154 + char gw_mode; 155 + 156 + gw_mode = atomic_read(&bat_priv->gw_mode); 157 + 158 + switch (gw_mode) { 159 + case BATADV_GW_MODE_OFF: 160 + case BATADV_GW_MODE_CLIENT: 161 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 162 + break; 163 + case BATADV_GW_MODE_SERVER: 164 + down = atomic_read(&bat_priv->gw.bandwidth_down); 165 + up = atomic_read(&bat_priv->gw.bandwidth_up); 166 + gw.bandwidth_down = htonl(down); 167 + gw.bandwidth_up = htonl(up); 168 + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, 169 + &gw, sizeof(gw)); 170 + break; 171 + } 102 172 } 103 173 104 174 ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, 105 175 size_t count) 106 176 { 107 177 struct batadv_priv *bat_priv = netdev_priv(net_dev); 108 - long gw_bandwidth_tmp = 0; 109 - int up = 0, down = 0; 178 + uint32_t down_curr, up_curr, down_new = 0, up_new = 0; 110 179 bool ret; 111 180 112 - ret = batadv_parse_gw_bandwidth(net_dev, buff, &up, &down); 181 + down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down); 182 + up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up); 183 + 184 + ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new); 113 185 if (!ret) 114 186 goto end; 115 187 116 - if ((!down) || (down < 256)) 117 - down = 2000; 188 + if (!down_new) 189 + down_new = 1; 118 190 119 - if (!up) 120 - up = down / 5; 191 + if (!up_new) 192 + up_new = down_new / 5; 121 193 122 - batadv_kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp); 194 + if (!up_new) 195 + up_new = 1; 123 196 124 - /* the gw bandwidth we guessed above might not match the given 125 - * speeds, hence we need to calculate it back to show the number 126 - * that is going to be propagated 127 - */ 128 - batadv_gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up); 129 - 130 - if (atomic_read(&bat_priv->gw_bandwidth) == gw_bandwidth_tmp) 197 + if ((down_curr == down_new) && (up_curr == up_new)) 131 198 return count; 132 199 133 200 batadv_gw_deselect(bat_priv); 134 201 batadv_info(net_dev, 135 - "Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n", 136 - atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp, 137 - (down > 2048 ? down / 1024 : down), 138 - (down > 2048 ? "MBit" : "KBit"), 139 - (up > 2048 ? up / 1024 : up), 140 - (up > 2048 ? "MBit" : "KBit")); 202 + "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n", 203 + down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10, 204 + down_new / 10, down_new % 10, up_new / 10, up_new % 10); 141 205 142 - atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp); 206 + atomic_set(&bat_priv->gw.bandwidth_down, down_new); 207 + atomic_set(&bat_priv->gw.bandwidth_up, up_new); 208 + batadv_gw_tvlv_container_update(bat_priv); 143 209 144 210 end: 145 211 return count; 212 + } 213 + 214 + /** 215 + * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container 216 + * @bat_priv: the bat priv with all the soft interface information 217 + * @orig: the orig_node of the ogm 218 + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 219 + * @tvlv_value: tvlv buffer containing the gateway data 220 + * @tvlv_value_len: tvlv buffer length 221 + */ 222 + static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 223 + struct batadv_orig_node *orig, 224 + uint8_t flags, 225 + void *tvlv_value, 226 + uint16_t tvlv_value_len) 227 + { 228 + struct batadv_tvlv_gateway_data gateway, *gateway_ptr; 229 + 230 + /* only fetch the tvlv value if the handler wasn't called via the 231 + * CIFNOTFND flag and if there is data to fetch 232 + */ 233 + if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) || 234 + (tvlv_value_len < sizeof(gateway))) { 235 + gateway.bandwidth_down = 0; 236 + gateway.bandwidth_up = 0; 237 + } else { 238 + gateway_ptr = tvlv_value; 239 + gateway.bandwidth_down = gateway_ptr->bandwidth_down; 240 + gateway.bandwidth_up = gateway_ptr->bandwidth_up; 241 + if ((gateway.bandwidth_down == 0) || 242 + (gateway.bandwidth_up == 0)) { 243 + gateway.bandwidth_down = 0; 244 + gateway.bandwidth_up = 0; 245 + } 246 + } 247 + 248 + batadv_gw_node_update(bat_priv, orig, &gateway); 249 + 250 + /* restart gateway selection if fast or late switching was enabled */ 251 + if ((gateway.bandwidth_down != 0) && 252 + (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && 253 + (atomic_read(&bat_priv->gw_sel_class) > 2)) 254 + batadv_gw_check_election(bat_priv, orig); 255 + } 256 + 257 + /** 258 + * batadv_gw_init - initialise the gateway handling internals 259 + * @bat_priv: the bat priv with all the soft interface information 260 + */ 261 + void batadv_gw_init(struct batadv_priv *bat_priv) 262 + { 263 + batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, 264 + NULL, BATADV_TVLV_GW, 1, 265 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 266 + } 267 + 268 + /** 269 + * batadv_gw_free - free the gateway handling internals 270 + * @bat_priv: the bat priv with all the soft interface information 271 + */ 272 + void batadv_gw_free(struct batadv_priv *bat_priv) 273 + { 274 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); 275 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); 146 276 }
+13 -1
net/batman-adv/gateway_common.h
··· 26 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 39 #define BATADV_GW_MODE_OFF_NAME "off" 30 40 #define BATADV_GW_MODE_CLIENT_NAME "client" 31 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 43 ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, 35 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 49 #endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
-9
net/batman-adv/hard-interface.c
··· 194 194 static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, 195 195 struct batadv_hard_iface *oldif) 196 196 { 197 - struct batadv_vis_packet *vis_packet; 198 197 struct batadv_hard_iface *primary_if; 199 - struct sk_buff *skb; 200 198 201 199 primary_if = batadv_primary_if_get_selected(bat_priv); 202 200 if (!primary_if) 203 201 goto out; 204 202 205 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 204 batadv_bla_update_orig_address(bat_priv, primary_if, oldif); 214 205 out: 215 206 if (primary_if)
+603 -20
net/batman-adv/main.c
··· 36 36 #include "gateway_client.h" 37 37 #include "bridge_loop_avoidance.h" 38 38 #include "distributed-arp-table.h" 39 - #include "vis.h" 39 + #include "unicast.h" 40 + #include "gateway_common.h" 40 41 #include "hash.h" 41 42 #include "bat_algo.h" 42 43 #include "network-coding.h" ··· 111 110 spin_lock_init(&bat_priv->tt.roam_list_lock); 112 111 spin_lock_init(&bat_priv->tt.last_changeset_lock); 113 112 spin_lock_init(&bat_priv->gw.list_lock); 114 - spin_lock_init(&bat_priv->vis.hash_lock); 115 - spin_lock_init(&bat_priv->vis.list_lock); 113 + spin_lock_init(&bat_priv->tvlv.container_list_lock); 114 + spin_lock_init(&bat_priv->tvlv.handler_list_lock); 116 115 117 116 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 118 117 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); ··· 120 119 INIT_LIST_HEAD(&bat_priv->tt.changes_list); 121 120 INIT_LIST_HEAD(&bat_priv->tt.req_list); 122 121 INIT_LIST_HEAD(&bat_priv->tt.roam_list); 122 + INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); 123 + INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); 123 124 124 125 ret = batadv_originator_init(bat_priv); 125 126 if (ret < 0) ··· 134 131 batadv_tt_local_add(soft_iface, soft_iface->dev_addr, 135 132 BATADV_NULL_IFINDEX); 136 133 137 - ret = batadv_vis_init(bat_priv); 138 - if (ret < 0) 139 - goto err; 140 - 141 134 ret = batadv_bla_init(bat_priv); 142 135 if (ret < 0) 143 136 goto err; ··· 145 146 ret = batadv_nc_mesh_init(bat_priv); 146 147 if (ret < 0) 147 148 goto err; 149 + 150 + batadv_gw_init(bat_priv); 148 151 149 152 atomic_set(&bat_priv->gw.reselect, 0); 150 153 atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); ··· 166 165 167 166 batadv_purge_outstanding_packets(bat_priv, NULL); 168 167 169 - batadv_vis_quit(bat_priv); 170 - 171 168 batadv_gw_node_purge(bat_priv); 172 169 batadv_nc_mesh_free(bat_priv); 173 170 batadv_dat_free(bat_priv); ··· 183 184 * accessing the TT data are scheduled for later execution. 184 185 */ 185 186 batadv_originator_free(bat_priv); 187 + 188 + batadv_gw_free(bat_priv); 186 189 187 190 free_percpu(bat_priv->bat_counters); 188 191 bat_priv->bat_counters = NULL; ··· 393 392 for (i = 0; i < ARRAY_SIZE(batadv_rx_handler); i++) 394 393 batadv_rx_handler[i] = batadv_recv_unhandled_packet; 395 394 396 - /* batman icmp packet */ 397 - batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; 395 + for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++) 396 + batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet; 397 + 398 + /* compile time checks for struct member offsets */ 399 + BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10); 400 + BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4); 401 + BUILD_BUG_ON(offsetof(struct batadv_unicast_frag_packet, dest) != 4); 402 + BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4); 403 + BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4); 404 + BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4); 405 + 406 + /* broadcast packet */ 407 + batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; 408 + 409 + /* unicast packets ... */ 398 410 /* unicast with 4 addresses packet */ 399 411 batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; 400 412 /* unicast packet */ 401 413 batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; 402 414 /* fragmented unicast packet */ 403 415 batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet; 404 - /* broadcast packet */ 405 - batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; 406 - /* vis packet */ 407 - batadv_rx_handler[BATADV_VIS] = batadv_recv_vis_packet; 408 - /* Translation table query (request or response) */ 409 - batadv_rx_handler[BATADV_TT_QUERY] = batadv_recv_tt_query; 410 - /* Roaming advertisement */ 411 - batadv_rx_handler[BATADV_ROAM_ADV] = batadv_recv_roam_adv; 416 + /* unicast tvlv packet */ 417 + batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv; 418 + /* batman icmp packet */ 419 + batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; 412 420 } 413 421 414 422 int ··· 425 415 int (*recv_handler)(struct sk_buff *, 426 416 struct batadv_hard_iface *)) 427 417 { 428 - if (batadv_rx_handler[packet_type] != &batadv_recv_unhandled_packet) 418 + int (*curr)(struct sk_buff *, 419 + struct batadv_hard_iface *); 420 + curr = batadv_rx_handler[packet_type]; 421 + 422 + if ((curr != batadv_recv_unhandled_packet) && 423 + (curr != batadv_recv_unhandled_unicast_packet)) 429 424 return -EBUSY; 430 425 431 426 batadv_rx_handler[packet_type] = recv_handler; ··· 549 534 } 550 535 551 536 return htonl(crc); 537 + } 538 + 539 + /** 540 + * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and 541 + * possibly free it 542 + * @tvlv_handler: the tvlv handler to free 543 + */ 544 + static void 545 + batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler) 546 + { 547 + if (atomic_dec_and_test(&tvlv_handler->refcount)) 548 + kfree_rcu(tvlv_handler, rcu); 549 + } 550 + 551 + /** 552 + * batadv_tvlv_handler_get - retrieve tvlv handler from the tvlv handler list 553 + * based on the provided type and version (both need to match) 554 + * @bat_priv: the bat priv with all the soft interface information 555 + * @type: tvlv handler type to look for 556 + * @version: tvlv handler version to look for 557 + * 558 + * Returns tvlv handler if found or NULL otherwise. 559 + */ 560 + static struct batadv_tvlv_handler 561 + *batadv_tvlv_handler_get(struct batadv_priv *bat_priv, 562 + uint8_t type, uint8_t version) 563 + { 564 + struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL; 565 + 566 + rcu_read_lock(); 567 + hlist_for_each_entry_rcu(tvlv_handler_tmp, 568 + &bat_priv->tvlv.handler_list, list) { 569 + if (tvlv_handler_tmp->type != type) 570 + continue; 571 + 572 + if (tvlv_handler_tmp->version != version) 573 + continue; 574 + 575 + if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount)) 576 + continue; 577 + 578 + tvlv_handler = tvlv_handler_tmp; 579 + break; 580 + } 581 + rcu_read_unlock(); 582 + 583 + return tvlv_handler; 584 + } 585 + 586 + /** 587 + * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and 588 + * possibly free it 589 + * @tvlv_handler: the tvlv container to free 590 + */ 591 + static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv) 592 + { 593 + if (atomic_dec_and_test(&tvlv->refcount)) 594 + kfree(tvlv); 595 + } 596 + 597 + /** 598 + * batadv_tvlv_container_get - retrieve tvlv container from the tvlv container 599 + * list based on the provided type and version (both need to match) 600 + * @bat_priv: the bat priv with all the soft interface information 601 + * @type: tvlv container type to look for 602 + * @version: tvlv container version to look for 603 + * 604 + * Has to be called with the appropriate locks being acquired 605 + * (tvlv.container_list_lock). 606 + * 607 + * Returns tvlv container if found or NULL otherwise. 608 + */ 609 + static struct batadv_tvlv_container 610 + *batadv_tvlv_container_get(struct batadv_priv *bat_priv, 611 + uint8_t type, uint8_t version) 612 + { 613 + struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL; 614 + 615 + hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) { 616 + if (tvlv_tmp->tvlv_hdr.type != type) 617 + continue; 618 + 619 + if (tvlv_tmp->tvlv_hdr.version != version) 620 + continue; 621 + 622 + if (!atomic_inc_not_zero(&tvlv_tmp->refcount)) 623 + continue; 624 + 625 + tvlv = tvlv_tmp; 626 + break; 627 + } 628 + 629 + return tvlv; 630 + } 631 + 632 + /** 633 + * batadv_tvlv_container_list_size - calculate the size of the tvlv container 634 + * list entries 635 + * @bat_priv: the bat priv with all the soft interface information 636 + * 637 + * Has to be called with the appropriate locks being acquired 638 + * (tvlv.container_list_lock). 639 + * 640 + * Returns size of all currently registered tvlv containers in bytes. 641 + */ 642 + static uint16_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) 643 + { 644 + struct batadv_tvlv_container *tvlv; 645 + uint16_t tvlv_len = 0; 646 + 647 + hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { 648 + tvlv_len += sizeof(struct batadv_tvlv_hdr); 649 + tvlv_len += ntohs(tvlv->tvlv_hdr.len); 650 + } 651 + 652 + return tvlv_len; 653 + } 654 + 655 + /** 656 + * batadv_tvlv_container_remove - remove tvlv container from the tvlv container 657 + * list 658 + * @tvlv: the to be removed tvlv container 659 + * 660 + * Has to be called with the appropriate locks being acquired 661 + * (tvlv.container_list_lock). 662 + */ 663 + static void batadv_tvlv_container_remove(struct batadv_tvlv_container *tvlv) 664 + { 665 + if (!tvlv) 666 + return; 667 + 668 + hlist_del(&tvlv->list); 669 + 670 + /* first call to decrement the counter, second call to free */ 671 + batadv_tvlv_container_free_ref(tvlv); 672 + batadv_tvlv_container_free_ref(tvlv); 673 + } 674 + 675 + /** 676 + * batadv_tvlv_container_unregister - unregister tvlv container based on the 677 + * provided type and version (both need to match) 678 + * @bat_priv: the bat priv with all the soft interface information 679 + * @type: tvlv container type to unregister 680 + * @version: tvlv container type to unregister 681 + */ 682 + void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, 683 + uint8_t type, uint8_t version) 684 + { 685 + struct batadv_tvlv_container *tvlv; 686 + 687 + spin_lock_bh(&bat_priv->tvlv.container_list_lock); 688 + tvlv = batadv_tvlv_container_get(bat_priv, type, version); 689 + batadv_tvlv_container_remove(tvlv); 690 + spin_unlock_bh(&bat_priv->tvlv.container_list_lock); 691 + } 692 + 693 + /** 694 + * batadv_tvlv_container_register - register tvlv type, version and content 695 + * to be propagated with each (primary interface) OGM 696 + * @bat_priv: the bat priv with all the soft interface information 697 + * @type: tvlv container type 698 + * @version: tvlv container version 699 + * @tvlv_value: tvlv container content 700 + * @tvlv_value_len: tvlv container content length 701 + * 702 + * If a container of the same type and version was already registered the new 703 + * content is going to replace the old one. 704 + */ 705 + void batadv_tvlv_container_register(struct batadv_priv *bat_priv, 706 + uint8_t type, uint8_t version, 707 + void *tvlv_value, uint16_t tvlv_value_len) 708 + { 709 + struct batadv_tvlv_container *tvlv_old, *tvlv_new; 710 + 711 + if (!tvlv_value) 712 + tvlv_value_len = 0; 713 + 714 + tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC); 715 + if (!tvlv_new) 716 + return; 717 + 718 + tvlv_new->tvlv_hdr.version = version; 719 + tvlv_new->tvlv_hdr.type = type; 720 + tvlv_new->tvlv_hdr.len = htons(tvlv_value_len); 721 + 722 + memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len)); 723 + INIT_HLIST_NODE(&tvlv_new->list); 724 + atomic_set(&tvlv_new->refcount, 1); 725 + 726 + spin_lock_bh(&bat_priv->tvlv.container_list_lock); 727 + tvlv_old = batadv_tvlv_container_get(bat_priv, type, version); 728 + batadv_tvlv_container_remove(tvlv_old); 729 + hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list); 730 + spin_unlock_bh(&bat_priv->tvlv.container_list_lock); 731 + } 732 + 733 + /** 734 + * batadv_tvlv_realloc_packet_buff - reallocate packet buffer to accomodate 735 + * requested packet size 736 + * @packet_buff: packet buffer 737 + * @packet_buff_len: packet buffer size 738 + * @packet_min_len: requested packet minimum size 739 + * @additional_packet_len: requested additional packet size on top of minimum 740 + * size 741 + * 742 + * Returns true of the packet buffer could be changed to the requested size, 743 + * false otherwise. 744 + */ 745 + static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff, 746 + int *packet_buff_len, 747 + int min_packet_len, 748 + int additional_packet_len) 749 + { 750 + unsigned char *new_buff; 751 + 752 + new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC); 753 + 754 + /* keep old buffer if kmalloc should fail */ 755 + if (new_buff) { 756 + memcpy(new_buff, *packet_buff, min_packet_len); 757 + kfree(*packet_buff); 758 + *packet_buff = new_buff; 759 + *packet_buff_len = min_packet_len + additional_packet_len; 760 + return true; 761 + } 762 + 763 + return false; 764 + } 765 + 766 + /** 767 + * batadv_tvlv_container_ogm_append - append tvlv container content to given 768 + * OGM packet buffer 769 + * @bat_priv: the bat priv with all the soft interface information 770 + * @packet_buff: ogm packet buffer 771 + * @packet_buff_len: ogm packet buffer size including ogm header and tvlv 772 + * content 773 + * @packet_min_len: ogm header size to be preserved for the OGM itself 774 + * 775 + * The ogm packet might be enlarged or shrunk depending on the current size 776 + * and the size of the to-be-appended tvlv containers. 777 + * 778 + * Returns size of all appended tvlv containers in bytes. 779 + */ 780 + uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, 781 + unsigned char **packet_buff, 782 + int *packet_buff_len, 783 + int packet_min_len) 784 + { 785 + struct batadv_tvlv_container *tvlv; 786 + struct batadv_tvlv_hdr *tvlv_hdr; 787 + uint16_t tvlv_value_len; 788 + void *tvlv_value; 789 + bool ret; 790 + 791 + spin_lock_bh(&bat_priv->tvlv.container_list_lock); 792 + tvlv_value_len = batadv_tvlv_container_list_size(bat_priv); 793 + 794 + ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len, 795 + packet_min_len, tvlv_value_len); 796 + 797 + if (!ret) 798 + goto end; 799 + 800 + if (!tvlv_value_len) 801 + goto end; 802 + 803 + tvlv_value = (*packet_buff) + packet_min_len; 804 + 805 + hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) { 806 + tvlv_hdr = tvlv_value; 807 + tvlv_hdr->type = tvlv->tvlv_hdr.type; 808 + tvlv_hdr->version = tvlv->tvlv_hdr.version; 809 + tvlv_hdr->len = tvlv->tvlv_hdr.len; 810 + tvlv_value = tvlv_hdr + 1; 811 + memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len)); 812 + tvlv_value = (uint8_t *)tvlv_value + ntohs(tvlv->tvlv_hdr.len); 813 + } 814 + 815 + end: 816 + spin_unlock_bh(&bat_priv->tvlv.container_list_lock); 817 + return tvlv_value_len; 818 + } 819 + 820 + /** 821 + * batadv_tvlv_call_handler - parse the given tvlv buffer to call the 822 + * appropriate handlers 823 + * @bat_priv: the bat priv with all the soft interface information 824 + * @tvlv_handler: tvlv callback function handling the tvlv content 825 + * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet 826 + * @orig_node: orig node emitting the ogm packet 827 + * @src: source mac address of the unicast packet 828 + * @dst: destination mac address of the unicast packet 829 + * @tvlv_value: tvlv content 830 + * @tvlv_value_len: tvlv content length 831 + * 832 + * Returns success if handler was not found or the return value of the handler 833 + * callback. 834 + */ 835 + static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, 836 + struct batadv_tvlv_handler *tvlv_handler, 837 + bool ogm_source, 838 + struct batadv_orig_node *orig_node, 839 + uint8_t *src, uint8_t *dst, 840 + void *tvlv_value, uint16_t tvlv_value_len) 841 + { 842 + if (!tvlv_handler) 843 + return NET_RX_SUCCESS; 844 + 845 + if (ogm_source) { 846 + if (!tvlv_handler->ogm_handler) 847 + return NET_RX_SUCCESS; 848 + 849 + if (!orig_node) 850 + return NET_RX_SUCCESS; 851 + 852 + tvlv_handler->ogm_handler(bat_priv, orig_node, 853 + BATADV_NO_FLAGS, 854 + tvlv_value, tvlv_value_len); 855 + tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED; 856 + } else { 857 + if (!src) 858 + return NET_RX_SUCCESS; 859 + 860 + if (!dst) 861 + return NET_RX_SUCCESS; 862 + 863 + if (!tvlv_handler->unicast_handler) 864 + return NET_RX_SUCCESS; 865 + 866 + return tvlv_handler->unicast_handler(bat_priv, src, 867 + dst, tvlv_value, 868 + tvlv_value_len); 869 + } 870 + 871 + return NET_RX_SUCCESS; 872 + } 873 + 874 + /** 875 + * batadv_tvlv_containers_process - parse the given tvlv buffer to call the 876 + * appropriate handlers 877 + * @bat_priv: the bat priv with all the soft interface information 878 + * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet 879 + * @orig_node: orig node emitting the ogm packet 880 + * @src: source mac address of the unicast packet 881 + * @dst: destination mac address of the unicast packet 882 + * @tvlv_value: tvlv content 883 + * @tvlv_value_len: tvlv content length 884 + * 885 + * Returns success when processing an OGM or the return value of all called 886 + * handler callbacks. 887 + */ 888 + int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, 889 + bool ogm_source, 890 + struct batadv_orig_node *orig_node, 891 + uint8_t *src, uint8_t *dst, 892 + void *tvlv_value, uint16_t tvlv_value_len) 893 + { 894 + struct batadv_tvlv_handler *tvlv_handler; 895 + struct batadv_tvlv_hdr *tvlv_hdr; 896 + uint16_t tvlv_value_cont_len; 897 + uint8_t cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND; 898 + int ret = NET_RX_SUCCESS; 899 + 900 + while (tvlv_value_len >= sizeof(*tvlv_hdr)) { 901 + tvlv_hdr = tvlv_value; 902 + tvlv_value_cont_len = ntohs(tvlv_hdr->len); 903 + tvlv_value = tvlv_hdr + 1; 904 + tvlv_value_len -= sizeof(*tvlv_hdr); 905 + 906 + if (tvlv_value_cont_len > tvlv_value_len) 907 + break; 908 + 909 + tvlv_handler = batadv_tvlv_handler_get(bat_priv, 910 + tvlv_hdr->type, 911 + tvlv_hdr->version); 912 + 913 + ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler, 914 + ogm_source, orig_node, 915 + src, dst, tvlv_value, 916 + tvlv_value_cont_len); 917 + if (tvlv_handler) 918 + batadv_tvlv_handler_free_ref(tvlv_handler); 919 + tvlv_value = (uint8_t *)tvlv_value + tvlv_value_cont_len; 920 + tvlv_value_len -= tvlv_value_cont_len; 921 + } 922 + 923 + if (!ogm_source) 924 + return ret; 925 + 926 + rcu_read_lock(); 927 + hlist_for_each_entry_rcu(tvlv_handler, 928 + &bat_priv->tvlv.handler_list, list) { 929 + if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) && 930 + !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED)) 931 + tvlv_handler->ogm_handler(bat_priv, orig_node, 932 + cifnotfound, NULL, 0); 933 + 934 + tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED; 935 + } 936 + rcu_read_unlock(); 937 + 938 + return NET_RX_SUCCESS; 939 + } 940 + 941 + /** 942 + * batadv_tvlv_ogm_receive - process an incoming ogm and call the appropriate 943 + * handlers 944 + * @bat_priv: the bat priv with all the soft interface information 945 + * @batadv_ogm_packet: ogm packet containing the tvlv containers 946 + * @orig_node: orig node emitting the ogm packet 947 + */ 948 + void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, 949 + struct batadv_ogm_packet *batadv_ogm_packet, 950 + struct batadv_orig_node *orig_node) 951 + { 952 + void *tvlv_value; 953 + uint16_t tvlv_value_len; 954 + 955 + if (!batadv_ogm_packet) 956 + return; 957 + 958 + tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len); 959 + if (!tvlv_value_len) 960 + return; 961 + 962 + tvlv_value = batadv_ogm_packet + 1; 963 + 964 + batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL, 965 + tvlv_value, tvlv_value_len); 966 + } 967 + 968 + /** 969 + * batadv_tvlv_handler_register - register tvlv handler based on the provided 970 + * type and version (both need to match) for ogm tvlv payload and/or unicast 971 + * payload 972 + * @bat_priv: the bat priv with all the soft interface information 973 + * @optr: ogm tvlv handler callback function. This function receives the orig 974 + * node, flags and the tvlv content as argument to process. 975 + * @uptr: unicast tvlv handler callback function. This function receives the 976 + * source & destination of the unicast packet as well as the tvlv content 977 + * to process. 978 + * @type: tvlv handler type to be registered 979 + * @version: tvlv handler version to be registered 980 + * @flags: flags to enable or disable TVLV API behavior 981 + */ 982 + void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, 983 + void (*optr)(struct batadv_priv *bat_priv, 984 + struct batadv_orig_node *orig, 985 + uint8_t flags, 986 + void *tvlv_value, 987 + uint16_t tvlv_value_len), 988 + int (*uptr)(struct batadv_priv *bat_priv, 989 + uint8_t *src, uint8_t *dst, 990 + void *tvlv_value, 991 + uint16_t tvlv_value_len), 992 + uint8_t type, uint8_t version, uint8_t flags) 993 + { 994 + struct batadv_tvlv_handler *tvlv_handler; 995 + 996 + tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); 997 + if (tvlv_handler) { 998 + batadv_tvlv_handler_free_ref(tvlv_handler); 999 + return; 1000 + } 1001 + 1002 + tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC); 1003 + if (!tvlv_handler) 1004 + return; 1005 + 1006 + tvlv_handler->ogm_handler = optr; 1007 + tvlv_handler->unicast_handler = uptr; 1008 + tvlv_handler->type = type; 1009 + tvlv_handler->version = version; 1010 + tvlv_handler->flags = flags; 1011 + atomic_set(&tvlv_handler->refcount, 1); 1012 + INIT_HLIST_NODE(&tvlv_handler->list); 1013 + 1014 + spin_lock_bh(&bat_priv->tvlv.handler_list_lock); 1015 + hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list); 1016 + spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); 1017 + } 1018 + 1019 + /** 1020 + * batadv_tvlv_handler_unregister - unregister tvlv handler based on the 1021 + * provided type and version (both need to match) 1022 + * @bat_priv: the bat priv with all the soft interface information 1023 + * @type: tvlv handler type to be unregistered 1024 + * @version: tvlv handler version to be unregistered 1025 + */ 1026 + void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, 1027 + uint8_t type, uint8_t version) 1028 + { 1029 + struct batadv_tvlv_handler *tvlv_handler; 1030 + 1031 + tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); 1032 + if (!tvlv_handler) 1033 + return; 1034 + 1035 + batadv_tvlv_handler_free_ref(tvlv_handler); 1036 + spin_lock_bh(&bat_priv->tvlv.handler_list_lock); 1037 + hlist_del_rcu(&tvlv_handler->list); 1038 + spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); 1039 + batadv_tvlv_handler_free_ref(tvlv_handler); 1040 + } 1041 + 1042 + /** 1043 + * batadv_tvlv_unicast_send - send a unicast packet with tvlv payload to the 1044 + * specified host 1045 + * @bat_priv: the bat priv with all the soft interface information 1046 + * @src: source mac address of the unicast packet 1047 + * @dst: destination mac address of the unicast packet 1048 + * @type: tvlv type 1049 + * @version: tvlv version 1050 + * @tvlv_value: tvlv content 1051 + * @tvlv_value_len: tvlv content length 1052 + */ 1053 + void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src, 1054 + uint8_t *dst, uint8_t type, uint8_t version, 1055 + void *tvlv_value, uint16_t tvlv_value_len) 1056 + { 1057 + struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; 1058 + struct batadv_tvlv_hdr *tvlv_hdr; 1059 + struct batadv_orig_node *orig_node; 1060 + struct sk_buff *skb = NULL; 1061 + unsigned char *tvlv_buff; 1062 + unsigned int tvlv_len; 1063 + ssize_t hdr_len = sizeof(*unicast_tvlv_packet); 1064 + bool ret = false; 1065 + 1066 + orig_node = batadv_orig_hash_find(bat_priv, dst); 1067 + if (!orig_node) 1068 + goto out; 1069 + 1070 + tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len; 1071 + 1072 + skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len); 1073 + if (!skb) 1074 + goto out; 1075 + 1076 + skb->priority = TC_PRIO_CONTROL; 1077 + skb_reserve(skb, ETH_HLEN); 1078 + tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len); 1079 + unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff; 1080 + unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV; 1081 + unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION; 1082 + unicast_tvlv_packet->header.ttl = BATADV_TTL; 1083 + unicast_tvlv_packet->reserved = 0; 1084 + unicast_tvlv_packet->tvlv_len = htons(tvlv_len); 1085 + unicast_tvlv_packet->align = 0; 1086 + memcpy(unicast_tvlv_packet->src, src, ETH_ALEN); 1087 + memcpy(unicast_tvlv_packet->dst, dst, ETH_ALEN); 1088 + 1089 + tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); 1090 + tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; 1091 + tvlv_hdr->version = version; 1092 + tvlv_hdr->type = type; 1093 + tvlv_hdr->len = htons(tvlv_value_len); 1094 + tvlv_buff += sizeof(*tvlv_hdr); 1095 + memcpy(tvlv_buff, tvlv_value, tvlv_value_len); 1096 + 1097 + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 1098 + ret = true; 1099 + 1100 + out: 1101 + if (skb && !ret) 1102 + kfree_skb(skb); 1103 + if (orig_node) 1104 + batadv_orig_node_free_ref(orig_node); 552 1105 } 553 1106 554 1107 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
+35 -2
net/batman-adv/main.h
··· 86 86 /* numbers of originator to contact for any PUT/GET DHT operation */ 87 87 #define BATADV_DAT_CANDIDATES_NUM 3 88 88 89 - #define BATADV_VIS_INTERVAL 5000 /* 5 seconds */ 90 - 91 89 /* how much worse secondary interfaces may be to be considered as bonding 92 90 * candidates 93 91 */ ··· 323 325 * The macro is inspired by the similar macro TCP_SKB_CB() in tcp.h. 324 326 */ 325 327 #define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0])) 328 + 329 + void batadv_tvlv_container_register(struct batadv_priv *bat_priv, 330 + uint8_t type, uint8_t version, 331 + void *tvlv_value, uint16_t tvlv_value_len); 332 + uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, 333 + unsigned char **packet_buff, 334 + int *packet_buff_len, 335 + int packet_min_len); 336 + void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv, 337 + struct batadv_ogm_packet *batadv_ogm_packet, 338 + struct batadv_orig_node *orig_node); 339 + void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv, 340 + uint8_t type, uint8_t version); 341 + 342 + void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, 343 + void (*optr)(struct batadv_priv *bat_priv, 344 + struct batadv_orig_node *orig, 345 + uint8_t flags, 346 + void *tvlv_value, 347 + uint16_t tvlv_value_len), 348 + int (*uptr)(struct batadv_priv *bat_priv, 349 + uint8_t *src, uint8_t *dst, 350 + void *tvlv_value, 351 + uint16_t tvlv_value_len), 352 + uint8_t type, uint8_t version, uint8_t flags); 353 + void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv, 354 + uint8_t type, uint8_t version); 355 + int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, 356 + bool ogm_source, 357 + struct batadv_orig_node *orig_node, 358 + uint8_t *src, uint8_t *dst, 359 + void *tvlv_buff, uint16_t tvlv_buff_len); 360 + void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src, 361 + uint8_t *dst, uint8_t type, uint8_t version, 362 + void *tvlv_value, uint16_t tvlv_value_len); 326 363 327 364 #endif /* _NET_BATMAN_ADV_MAIN_H_ */
+63
net/batman-adv/network-coding.c
··· 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 115 * batadv_nc_mesh_init - initialise coding hash table and start house keeping 63 116 * @bat_priv: the bat priv with all the soft interface information 64 117 */ ··· 140 87 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); 141 88 batadv_nc_start_timer(bat_priv); 142 89 90 + batadv_tvlv_handler_register(bat_priv, batadv_nc_tvlv_ogm_handler_v1, 91 + NULL, BATADV_TVLV_NC, 1, 92 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 93 + batadv_nc_tvlv_container_update(bat_priv); 143 94 return 0; 144 95 145 96 err: ··· 857 800 858 801 /* Check if network coding is enabled */ 859 802 if (!atomic_read(&bat_priv->network_coding)) 803 + goto out; 804 + 805 + /* check if orig node is network coding enabled */ 806 + if (!(orig_node->capabilities & BATADV_ORIG_CAPA_HAS_NC)) 860 807 goto out; 861 808 862 809 /* accept ogms from 'good' neighbors and single hop neighbors */ ··· 1796 1735 */ 1797 1736 void batadv_nc_mesh_free(struct batadv_priv *bat_priv) 1798 1737 { 1738 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1); 1739 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_NC, 1); 1799 1740 cancel_delayed_work_sync(&bat_priv->nc.work); 1800 1741 1801 1742 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
+5
net/batman-adv/network-coding.h
··· 22 22 23 23 #ifdef CONFIG_BATMAN_ADV_NC 24 24 25 + void batadv_nc_status_update(struct net_device *net_dev); 25 26 int batadv_nc_init(void); 26 27 int batadv_nc_mesh_init(struct batadv_priv *bat_priv); 27 28 void batadv_nc_mesh_free(struct batadv_priv *bat_priv); ··· 47 46 int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); 48 47 49 48 #else /* ifdef CONFIG_BATMAN_ADV_NC */ 49 + 50 + static inline void batadv_nc_status_update(struct net_device *net_dev) 51 + { 52 + } 50 53 51 54 static inline int batadv_nc_init(void) 52 55 {
+1 -3
net/batman-adv/originator.c
··· 388 388 hlist_for_each_entry_safe(orig_node, node_tmp, 389 389 head, hash_entry) { 390 390 if (batadv_purge_orig_node(bat_priv, orig_node)) { 391 - if (orig_node->gw_flags) 392 - batadv_gw_node_delete(bat_priv, 393 - orig_node); 391 + batadv_gw_node_delete(bat_priv, orig_node); 394 392 hlist_del_rcu(&orig_node->hash_entry); 395 393 batadv_orig_node_free_ref(orig_node); 396 394 continue;
+162 -86
net/batman-adv/packet.h
··· 20 20 #ifndef _NET_BATMAN_ADV_PACKET_H_ 21 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 37 enum batadv_packettype { 24 - BATADV_IV_OGM = 0x01, 25 - BATADV_ICMP = 0x02, 26 - BATADV_UNICAST = 0x03, 27 - BATADV_BCAST = 0x04, 28 - BATADV_VIS = 0x05, 29 - BATADV_UNICAST_FRAG = 0x06, 30 - BATADV_TT_QUERY = 0x07, 31 - BATADV_ROAM_ADV = 0x08, 32 - BATADV_UNICAST_4ADDR = 0x09, 33 - BATADV_CODED = 0x0a, 38 + /* 0x00 - 0x3f: local packets or special rules for handling */ 39 + BATADV_IV_OGM = 0x00, 40 + BATADV_BCAST = 0x01, 41 + BATADV_CODED = 0x02, 42 + /* 0x40 - 0x7f: unicast */ 43 + #define BATADV_UNICAST_MIN 0x40 44 + BATADV_UNICAST = 0x40, 45 + BATADV_UNICAST_FRAG = 0x41, 46 + BATADV_UNICAST_4ADDR = 0x42, 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 /** ··· 65 48 }; 66 49 67 50 /* this file is included by batctl which needs these defines */ 68 - #define BATADV_COMPAT_VERSION 14 51 + #define BATADV_COMPAT_VERSION 15 69 52 53 + /** 54 + * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets 55 + * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was 56 + * previously received from someone else than the best neighbor. 57 + * @BATADV_PRIMARIES_FIRST_HOP: flag is set when the primary interface address 58 + * is used, and the packet travels its first hop. 59 + * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a 60 + * one hop neighbor on the interface where it was originally received. 61 + */ 70 62 enum batadv_iv_flags { 71 - BATADV_NOT_BEST_NEXT_HOP = BIT(3), 72 - BATADV_PRIMARIES_FIRST_HOP = BIT(4), 73 - BATADV_VIS_SERVER = BIT(5), 74 - BATADV_DIRECTLINK = BIT(6), 63 + BATADV_NOT_BEST_NEXT_HOP = BIT(0), 64 + BATADV_PRIMARIES_FIRST_HOP = BIT(1), 65 + BATADV_DIRECTLINK = BIT(2), 75 66 }; 76 67 77 68 /* ICMP message types */ ··· 91 66 BATADV_PARAMETER_PROBLEM = 12, 92 67 }; 93 68 94 - /* vis defines */ 95 - enum batadv_vis_packettype { 96 - BATADV_VIS_TYPE_SERVER_SYNC = 0, 97 - BATADV_VIS_TYPE_CLIENT_UPDATE = 1, 98 - }; 99 - 100 69 /* fragmentation defines */ 101 70 enum batadv_unicast_frag_flags { 102 71 BATADV_UNI_FRAG_HEAD = BIT(0), 103 72 BATADV_UNI_FRAG_LARGETAIL = BIT(1), 104 73 }; 105 74 106 - /* TT_QUERY subtypes */ 107 - #define BATADV_TT_QUERY_TYPE_MASK 0x3 75 + /* tt data subtypes */ 76 + #define BATADV_TT_DATA_TYPE_MASK 0x0F 108 77 109 - enum batadv_tt_query_packettype { 110 - BATADV_TT_REQUEST = 0, 111 - BATADV_TT_RESPONSE = 1, 112 - }; 113 - 114 - /* TT_QUERY flags */ 115 - enum batadv_tt_query_flags { 116 - BATADV_TT_FULL_TABLE = BIT(2), 78 + /** 79 + * enum batadv_tt_data_flags - flags for tt data tvlv 80 + * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM 81 + * @BATADV_TT_REQUEST: TT request message 82 + * @BATADV_TT_RESPONSE: TT response message 83 + * @BATADV_TT_FULL_TABLE: contains full table to replace existing table 84 + */ 85 + enum batadv_tt_data_flags { 86 + BATADV_TT_OGM_DIFF = BIT(0), 87 + BATADV_TT_REQUEST = BIT(1), 88 + BATADV_TT_RESPONSE = BIT(2), 89 + BATADV_TT_FULL_TABLE = BIT(4), 117 90 }; 118 91 119 92 /* BATADV_TT_CLIENT flags. ··· 122 99 BATADV_TT_CLIENT_DEL = BIT(0), 123 100 BATADV_TT_CLIENT_ROAM = BIT(1), 124 101 BATADV_TT_CLIENT_WIFI = BIT(2), 125 - BATADV_TT_CLIENT_TEMP = BIT(3), 126 102 BATADV_TT_CLIENT_NOPURGE = BIT(8), 127 103 BATADV_TT_CLIENT_NEW = BIT(9), 128 104 BATADV_TT_CLIENT_PENDING = BIT(10), 105 + BATADV_TT_CLIENT_TEMP = BIT(11), 129 106 }; 130 107 131 108 /* claim frame types for the bridge loop avoidance */ ··· 134 111 BATADV_CLAIM_TYPE_UNCLAIM = 0x01, 135 112 BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, 136 113 BATADV_CLAIM_TYPE_REQUEST = 0x03, 114 + }; 115 + 116 + /** 117 + * enum batadv_tvlv_type - tvlv type definitions 118 + * @BATADV_TVLV_GW: gateway tvlv 119 + * @BATADV_TVLV_DAT: distributed arp table tvlv 120 + * @BATADV_TVLV_NC: network coding tvlv 121 + * @BATADV_TVLV_TT: translation table tvlv 122 + * @BATADV_TVLV_ROAM: roaming advertisement tvlv 123 + */ 124 + enum batadv_tvlv_type { 125 + BATADV_TVLV_GW = 0x01, 126 + BATADV_TVLV_DAT = 0x02, 127 + BATADV_TVLV_NC = 0x03, 128 + BATADV_TVLV_TT = 0x04, 129 + BATADV_TVLV_ROAM = 0x05, 137 130 }; 138 131 139 132 /* the destination hardware field in the ARP frame is used to ··· 170 131 */ 171 132 }; 172 133 134 + /** 135 + * struct batadv_ogm_packet - ogm (routing protocol) packet 136 + * @header: common batman packet header 137 + * @flags: contains routing relevant flags - see enum batadv_iv_flags 138 + * @tvlv_len: length of tvlv data following the ogm header 139 + */ 173 140 struct batadv_ogm_packet { 174 141 struct batadv_header header; 175 - uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ 142 + uint8_t flags; 176 143 __be32 seqno; 177 144 uint8_t orig[ETH_ALEN]; 178 145 uint8_t prev_sender[ETH_ALEN]; 179 - uint8_t gw_flags; /* flags related to gateway class */ 146 + uint8_t reserved; 180 147 uint8_t tq; 181 - uint8_t tt_num_changes; 182 - uint8_t ttvn; /* translation table version number */ 183 - __be16 tt_crc; 184 - } __packed; 148 + __be16 tvlv_len; 149 + /* __packed is not needed as the struct size is divisible by 4, 150 + * and the largest data type in this struct has a size of 4. 151 + */ 152 + }; 185 153 186 154 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) 187 155 ··· 277 231 278 232 #pragma pack() 279 233 280 - struct batadv_vis_packet { 281 - struct batadv_header header; 282 - uint8_t vis_type; /* which type of vis-participant sent this? */ 283 - __be32 seqno; /* sequence number */ 284 - uint8_t entries; /* number of entries behind this struct */ 285 - uint8_t reserved; 286 - uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */ 287 - uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */ 288 - uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */ 289 - }; 290 - 291 - struct batadv_tt_query_packet { 292 - struct batadv_header header; 293 - /* the flag field is a combination of: 294 - * - TT_REQUEST or TT_RESPONSE 295 - * - TT_FULL_TABLE 296 - */ 297 - uint8_t flags; 298 - uint8_t dst[ETH_ALEN]; 299 - uint8_t src[ETH_ALEN]; 300 - /* the ttvn field is: 301 - * if TT_REQUEST: ttvn that triggered the 302 - * request 303 - * if TT_RESPONSE: new ttvn for the src 304 - * orig_node 305 - */ 306 - uint8_t ttvn; 307 - /* tt_data field is: 308 - * if TT_REQUEST: crc associated with the 309 - * ttvn 310 - * if TT_RESPONSE: table_size 311 - */ 312 - __be16 tt_data; 313 - } __packed; 314 - 315 - struct batadv_roam_adv_packet { 316 - struct batadv_header header; 317 - uint8_t reserved; 318 - uint8_t dst[ETH_ALEN]; 319 - uint8_t src[ETH_ALEN]; 320 - uint8_t client[ETH_ALEN]; 321 - } __packed; 322 - 323 - struct batadv_tt_change { 324 - uint8_t flags; 325 - uint8_t addr[ETH_ALEN]; 326 - } __packed; 327 - 328 234 /** 329 235 * struct batadv_coded_packet - network coded packet 330 236 * @header: common batman packet header and ttl of first included packet ··· 307 309 uint8_t second_orig_dest[ETH_ALEN]; 308 310 __be32 second_crc; 309 311 __be16 coded_len; 312 + }; 313 + 314 + /** 315 + * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload 316 + * @header: common batman packet header 317 + * @reserved: reserved field (for packet alignment) 318 + * @src: address of the source 319 + * @dst: address of the destination 320 + * @tvlv_len: length of tvlv data following the unicast tvlv header 321 + * @align: 2 bytes to align the header to a 4 byte boundry 322 + */ 323 + struct batadv_unicast_tvlv_packet { 324 + struct batadv_header header; 325 + uint8_t reserved; 326 + uint8_t dst[ETH_ALEN]; 327 + uint8_t src[ETH_ALEN]; 328 + __be16 tvlv_len; 329 + uint16_t align; 330 + }; 331 + 332 + /** 333 + * struct batadv_tvlv_hdr - base tvlv header struct 334 + * @type: tvlv container type (see batadv_tvlv_type) 335 + * @version: tvlv container version 336 + * @len: tvlv container length 337 + */ 338 + struct batadv_tvlv_hdr { 339 + uint8_t type; 340 + uint8_t version; 341 + __be16 len; 342 + }; 343 + 344 + /** 345 + * struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv 346 + * container 347 + * @bandwidth_down: advertised uplink download bandwidth 348 + * @bandwidth_up: advertised uplink upload bandwidth 349 + */ 350 + struct batadv_tvlv_gateway_data { 351 + __be32 bandwidth_down; 352 + __be32 bandwidth_up; 353 + }; 354 + 355 + /** 356 + * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container 357 + * @flags: translation table flags (see batadv_tt_data_flags) 358 + * @ttvn: translation table version number 359 + * @reserved: field reserved for future use 360 + * @crc: crc32 checksum of the local translation table 361 + */ 362 + struct batadv_tvlv_tt_data { 363 + uint8_t flags; 364 + uint8_t ttvn; 365 + uint16_t reserved; 366 + __be32 crc; 367 + }; 368 + 369 + /** 370 + * struct batadv_tvlv_tt_change - translation table diff data 371 + * @flags: status indicators concerning the non-mesh client (see 372 + * batadv_tt_client_flags) 373 + * @reserved: reserved field 374 + * @addr: mac address of non-mesh client that triggered this tt change 375 + */ 376 + struct batadv_tvlv_tt_change { 377 + uint8_t flags; 378 + uint8_t reserved; 379 + uint8_t addr[ETH_ALEN]; 380 + }; 381 + 382 + /** 383 + * struct batadv_tvlv_roam_adv - roaming advertisement 384 + * @client: mac address of roaming client 385 + * @reserved: field reserved for future use 386 + */ 387 + struct batadv_tvlv_roam_adv { 388 + uint8_t client[ETH_ALEN]; 389 + uint16_t reserved; 310 390 }; 311 391 312 392 #endif /* _NET_BATMAN_ADV_PACKET_H_ */
+76 -171
net/batman-adv/routing.c
··· 25 25 #include "icmp_socket.h" 26 26 #include "translation-table.h" 27 27 #include "originator.h" 28 - #include "vis.h" 29 28 #include "unicast.h" 30 29 #include "bridge_loop_avoidance.h" 31 30 #include "distributed-arp-table.h" ··· 556 557 return 0; 557 558 } 558 559 559 - int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) 560 - { 561 - struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 562 - struct batadv_tt_query_packet *tt_query; 563 - uint16_t tt_size; 564 - int hdr_size = sizeof(*tt_query); 565 - char tt_flag; 566 - size_t packet_size; 567 - 568 - if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0) 569 - return NET_RX_DROP; 570 - 571 - /* I could need to modify it */ 572 - if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) 573 - goto out; 574 - 575 - tt_query = (struct batadv_tt_query_packet *)skb->data; 576 - 577 - switch (tt_query->flags & BATADV_TT_QUERY_TYPE_MASK) { 578 - case BATADV_TT_REQUEST: 579 - batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX); 580 - 581 - /* If we cannot provide an answer the tt_request is 582 - * forwarded 583 - */ 584 - if (!batadv_send_tt_response(bat_priv, tt_query)) { 585 - if (tt_query->flags & BATADV_TT_FULL_TABLE) 586 - tt_flag = 'F'; 587 - else 588 - tt_flag = '.'; 589 - 590 - batadv_dbg(BATADV_DBG_TT, bat_priv, 591 - "Routing TT_REQUEST to %pM [%c]\n", 592 - tt_query->dst, 593 - tt_flag); 594 - return batadv_route_unicast_packet(skb, recv_if); 595 - } 596 - break; 597 - case BATADV_TT_RESPONSE: 598 - batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX); 599 - 600 - if (batadv_is_my_mac(bat_priv, tt_query->dst)) { 601 - /* packet needs to be linearized to access the TT 602 - * changes 603 - */ 604 - if (skb_linearize(skb) < 0) 605 - goto out; 606 - /* skb_linearize() possibly changed skb->data */ 607 - tt_query = (struct batadv_tt_query_packet *)skb->data; 608 - 609 - tt_size = batadv_tt_len(ntohs(tt_query->tt_data)); 610 - 611 - /* Ensure we have all the claimed data */ 612 - packet_size = sizeof(struct batadv_tt_query_packet); 613 - packet_size += tt_size; 614 - if (unlikely(skb_headlen(skb) < packet_size)) 615 - goto out; 616 - 617 - batadv_handle_tt_response(bat_priv, tt_query); 618 - } else { 619 - if (tt_query->flags & BATADV_TT_FULL_TABLE) 620 - tt_flag = 'F'; 621 - else 622 - tt_flag = '.'; 623 - batadv_dbg(BATADV_DBG_TT, bat_priv, 624 - "Routing TT_RESPONSE to %pM [%c]\n", 625 - tt_query->dst, 626 - tt_flag); 627 - return batadv_route_unicast_packet(skb, recv_if); 628 - } 629 - break; 630 - } 631 - 632 - out: 633 - /* returning NET_RX_DROP will make the caller function kfree the skb */ 634 - return NET_RX_DROP; 635 - } 636 - 637 - int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) 638 - { 639 - struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 640 - struct batadv_roam_adv_packet *roam_adv_packet; 641 - struct batadv_orig_node *orig_node; 642 - 643 - if (batadv_check_unicast_packet(bat_priv, skb, 644 - sizeof(*roam_adv_packet)) < 0) 645 - goto out; 646 - 647 - batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); 648 - 649 - roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data; 650 - 651 - if (!batadv_is_my_mac(bat_priv, roam_adv_packet->dst)) 652 - return batadv_route_unicast_packet(skb, recv_if); 653 - 654 - /* check if it is a backbone gateway. we don't accept 655 - * roaming advertisement from it, as it has the same 656 - * entries as we have. 657 - */ 658 - if (batadv_bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src)) 659 - goto out; 660 - 661 - orig_node = batadv_orig_hash_find(bat_priv, roam_adv_packet->src); 662 - if (!orig_node) 663 - goto out; 664 - 665 - batadv_dbg(BATADV_DBG_TT, bat_priv, 666 - "Received ROAMING_ADV from %pM (client %pM)\n", 667 - roam_adv_packet->src, roam_adv_packet->client); 668 - 669 - batadv_tt_global_add(bat_priv, orig_node, roam_adv_packet->client, 670 - BATADV_TT_CLIENT_ROAM, 671 - atomic_read(&orig_node->last_ttvn) + 1); 672 - 673 - batadv_orig_node_free_ref(orig_node); 674 - out: 675 - /* returning NET_RX_DROP will make the caller function kfree the skb */ 676 - return NET_RX_DROP; 677 - } 678 - 679 560 /* find a suitable router for this originator, and use 680 561 * bonding if possible. increases the found neighbors 681 562 * refcount. ··· 911 1032 return 1; 912 1033 } 913 1034 1035 + /** 1036 + * batadv_recv_unhandled_unicast_packet - receive and process packets which 1037 + * are in the unicast number space but not yet known to the implementation 1038 + * @skb: unicast tvlv packet to process 1039 + * @recv_if: pointer to interface this packet was received on 1040 + * 1041 + * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP 1042 + * otherwise. 1043 + */ 1044 + int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, 1045 + struct batadv_hard_iface *recv_if) 1046 + { 1047 + struct batadv_unicast_packet *unicast_packet; 1048 + struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1049 + int check, hdr_size = sizeof(*unicast_packet); 1050 + 1051 + check = batadv_check_unicast_packet(bat_priv, skb, hdr_size); 1052 + if (check < 0) 1053 + return NET_RX_DROP; 1054 + 1055 + /* we don't know about this type, drop it. */ 1056 + unicast_packet = (struct batadv_unicast_packet *)skb->data; 1057 + if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) 1058 + return NET_RX_DROP; 1059 + 1060 + return batadv_route_unicast_packet(skb, recv_if); 1061 + } 1062 + 914 1063 int batadv_recv_unicast_packet(struct sk_buff *skb, 915 1064 struct batadv_hard_iface *recv_if) 916 1065 { ··· 1046 1139 return batadv_route_unicast_packet(skb, recv_if); 1047 1140 } 1048 1141 1142 + /** 1143 + * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets 1144 + * @skb: unicast tvlv packet to process 1145 + * @recv_if: pointer to interface this packet was received on 1146 + * @dst_addr: the payload destination 1147 + * 1148 + * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP 1149 + * otherwise. 1150 + */ 1151 + int batadv_recv_unicast_tvlv(struct sk_buff *skb, 1152 + struct batadv_hard_iface *recv_if) 1153 + { 1154 + struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1155 + struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; 1156 + unsigned char *tvlv_buff; 1157 + uint16_t tvlv_buff_len; 1158 + int hdr_size = sizeof(*unicast_tvlv_packet); 1159 + int ret = NET_RX_DROP; 1160 + 1161 + if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0) 1162 + return NET_RX_DROP; 1163 + 1164 + /* the header is likely to be modified while forwarding */ 1165 + if (skb_cow(skb, hdr_size) < 0) 1166 + return NET_RX_DROP; 1167 + 1168 + /* packet needs to be linearized to access the tvlv content */ 1169 + if (skb_linearize(skb) < 0) 1170 + return NET_RX_DROP; 1171 + 1172 + unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data; 1173 + 1174 + tvlv_buff = (unsigned char *)(skb->data + hdr_size); 1175 + tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len); 1176 + 1177 + if (tvlv_buff_len > skb->len - hdr_size) 1178 + return NET_RX_DROP; 1179 + 1180 + ret = batadv_tvlv_containers_process(bat_priv, false, NULL, 1181 + unicast_tvlv_packet->src, 1182 + unicast_tvlv_packet->dst, 1183 + tvlv_buff, tvlv_buff_len); 1184 + 1185 + if (ret != NET_RX_SUCCESS) 1186 + ret = batadv_route_unicast_packet(skb, recv_if); 1187 + 1188 + return ret; 1189 + } 1049 1190 1050 1191 int batadv_recv_bcast_packet(struct sk_buff *skb, 1051 1192 struct batadv_hard_iface *recv_if) ··· 1194 1239 if (orig_node) 1195 1240 batadv_orig_node_free_ref(orig_node); 1196 1241 return ret; 1197 - } 1198 - 1199 - int batadv_recv_vis_packet(struct sk_buff *skb, 1200 - struct batadv_hard_iface *recv_if) 1201 - { 1202 - struct batadv_vis_packet *vis_packet; 1203 - struct ethhdr *ethhdr; 1204 - struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1205 - int hdr_size = sizeof(*vis_packet); 1206 - 1207 - /* keep skb linear */ 1208 - if (skb_linearize(skb) < 0) 1209 - return NET_RX_DROP; 1210 - 1211 - if (unlikely(!pskb_may_pull(skb, hdr_size))) 1212 - return NET_RX_DROP; 1213 - 1214 - vis_packet = (struct batadv_vis_packet *)skb->data; 1215 - ethhdr = eth_hdr(skb); 1216 - 1217 - /* not for me */ 1218 - if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) 1219 - return NET_RX_DROP; 1220 - 1221 - /* ignore own packets */ 1222 - if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig)) 1223 - return NET_RX_DROP; 1224 - 1225 - if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig)) 1226 - return NET_RX_DROP; 1227 - 1228 - switch (vis_packet->vis_type) { 1229 - case BATADV_VIS_TYPE_SERVER_SYNC: 1230 - batadv_receive_server_sync_packet(bat_priv, vis_packet, 1231 - skb_headlen(skb)); 1232 - break; 1233 - 1234 - case BATADV_VIS_TYPE_CLIENT_UPDATE: 1235 - batadv_receive_client_update_packet(bat_priv, vis_packet, 1236 - skb_headlen(skb)); 1237 - break; 1238 - 1239 - default: /* ignore unknown packet */ 1240 - break; 1241 - } 1242 - 1243 - /* We take a copy of the data in the packet, so we should 1244 - * always free the skbuf. 1245 - */ 1246 - return NET_RX_DROP; 1247 1242 }
+4 -2
net/batman-adv/routing.h
··· 34 34 struct batadv_hard_iface *recv_if); 35 35 int batadv_recv_bcast_packet(struct sk_buff *skb, 36 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 37 int batadv_recv_tt_query(struct sk_buff *skb, 40 38 struct batadv_hard_iface *recv_if); 41 39 int batadv_recv_roam_adv(struct sk_buff *skb, 42 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 45 struct batadv_neigh_node * 44 46 batadv_find_router(struct batadv_priv *bat_priv, 45 47 struct batadv_orig_node *orig_node,
-1
net/batman-adv/send.c
··· 24 24 #include "translation-table.h" 25 25 #include "soft-interface.h" 26 26 #include "hard-interface.h" 27 - #include "vis.h" 28 27 #include "gateway_common.h" 29 28 #include "originator.h" 30 29 #include "network-coding.h"
+2 -2
net/batman-adv/soft-interface.c
··· 469 469 atomic_set(&bat_priv->distributed_arp_table, 1); 470 470 #endif 471 471 atomic_set(&bat_priv->ap_isolation, 0); 472 - atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); 473 472 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 474 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 476 atomic_set(&bat_priv->orig_interval, 1000); 477 477 atomic_set(&bat_priv->hop_penalty, 30); 478 478 #ifdef CONFIG_BATMAN_ADV_DEBUG
+12 -82
net/batman-adv/sysfs.c
··· 21 21 #include "sysfs.h" 22 22 #include "translation-table.h" 23 23 #include "distributed-arp-table.h" 24 + #include "network-coding.h" 24 25 #include "originator.h" 25 26 #include "hard-interface.h" 26 27 #include "gateway_common.h" 27 28 #include "gateway_client.h" 28 - #include "vis.h" 29 29 30 30 static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) 31 31 { ··· 230 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 233 static ssize_t batadv_show_bat_algo(struct kobject *kobj, 302 234 struct attribute *attr, char *buff) 303 235 { ··· 322 390 */ 323 391 batadv_gw_check_client_stop(bat_priv); 324 392 atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); 393 + batadv_gw_tvlv_container_update(bat_priv); 325 394 return count; 326 395 } 327 396 ··· 330 397 struct attribute *attr, char *buff) 331 398 { 332 399 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 333 - int down, up; 334 - int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); 400 + uint32_t down, up; 335 401 336 - batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); 337 - return sprintf(buff, "%i%s/%i%s\n", 338 - (down > 2048 ? down / 1024 : down), 339 - (down > 2048 ? "MBit" : "KBit"), 340 - (up > 2048 ? up / 1024 : up), 341 - (up > 2048 ? "MBit" : "KBit")); 402 + down = atomic_read(&bat_priv->gw.bandwidth_down); 403 + up = atomic_read(&bat_priv->gw.bandwidth_up); 404 + 405 + return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, 406 + down % 10, up / 10, up % 10); 342 407 } 343 408 344 409 static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, ··· 357 426 BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); 358 427 #endif 359 428 #ifdef CONFIG_BATMAN_ADV_DAT 360 - BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); 429 + BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, 430 + batadv_dat_status_update); 361 431 #endif 362 432 BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); 363 433 BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); 364 - static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode, 365 - batadv_store_vis_mode); 366 434 static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); 367 435 static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, 368 436 batadv_store_gw_mode); ··· 377 447 BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); 378 448 #endif 379 449 #ifdef CONFIG_BATMAN_ADV_NC 380 - BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL); 450 + BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, 451 + batadv_nc_status_update); 381 452 #endif 382 453 383 454 static struct batadv_attribute *batadv_mesh_attrs[] = { ··· 392 461 #endif 393 462 &batadv_attr_fragmentation, 394 463 &batadv_attr_ap_isolation, 395 - &batadv_attr_vis_mode, 396 464 &batadv_attr_routing_algo, 397 465 &batadv_attr_gw_mode, 398 466 &batadv_attr_orig_interval,
+520 -381
net/batman-adv/translation-table.c
··· 27 27 #include "routing.h" 28 28 #include "bridge_loop_avoidance.h" 29 29 30 - #include <linux/crc16.h> 30 + #include <linux/crc32c.h> 31 31 32 32 /* hash class keys */ 33 33 static struct lock_class_key batadv_tt_local_hash_lock_class_key; ··· 180 180 bool del_op_requested, del_op_entry; 181 181 182 182 tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC); 183 - 184 183 if (!tt_change_node) 185 184 return; 186 185 187 186 tt_change_node->change.flags = flags; 187 + tt_change_node->change.reserved = 0; 188 188 memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); 189 189 190 190 del_op_requested = flags & BATADV_TT_CLIENT_DEL; ··· 229 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 243 static int batadv_tt_local_init(struct batadv_priv *bat_priv) ··· 382 376 batadv_tt_global_entry_free_ref(tt_global); 383 377 } 384 378 385 - static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, 386 - int *packet_buff_len, 387 - int min_packet_len, 388 - int new_packet_len) 379 + /** 380 + * batadv_tt_tvlv_container_update - update the translation table tvlv container 381 + * after local tt changes have been committed 382 + * @bat_priv: the bat priv with all the soft interface information 383 + */ 384 + static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv) 389 385 { 390 - unsigned char *new_buff; 386 + struct batadv_tt_change_node *entry, *safe; 387 + struct batadv_tvlv_tt_data *tt_data; 388 + struct batadv_tvlv_tt_change *tt_change; 389 + int tt_diff_len = 0, tt_change_len = 0; 390 + int tt_diff_entries_num = 0, tt_diff_entries_count = 0; 391 391 392 - new_buff = kmalloc(new_packet_len, GFP_ATOMIC); 393 - 394 - /* keep old buffer if kmalloc should fail */ 395 - if (new_buff) { 396 - memcpy(new_buff, *packet_buff, min_packet_len); 397 - kfree(*packet_buff); 398 - *packet_buff = new_buff; 399 - *packet_buff_len = new_packet_len; 400 - } 401 - } 402 - 403 - static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv, 404 - unsigned char **packet_buff, 405 - int *packet_buff_len, 406 - int min_packet_len) 407 - { 408 - int req_len; 409 - 410 - req_len = min_packet_len; 411 - req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); 392 + tt_diff_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); 412 393 413 394 /* if we have too many changes for one packet don't send any 414 395 * and wait for the tt table request which will be fragmented 415 396 */ 416 - if (req_len > bat_priv->soft_iface->mtu) 417 - req_len = min_packet_len; 397 + if (tt_diff_len > bat_priv->soft_iface->mtu) 398 + tt_diff_len = 0; 418 399 419 - batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, 420 - min_packet_len, req_len); 421 - } 400 + tt_data = kzalloc(sizeof(*tt_data) + tt_diff_len, GFP_ATOMIC); 401 + if (!tt_data) 402 + return; 422 403 423 - static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, 424 - unsigned char **packet_buff, 425 - int *packet_buff_len, 426 - int min_packet_len) 427 - { 428 - struct batadv_tt_change_node *entry, *safe; 429 - int count = 0, tot_changes = 0, new_len; 430 - unsigned char *tt_buff; 404 + tt_data->flags = BATADV_TT_OGM_DIFF; 405 + tt_data->ttvn = atomic_read(&bat_priv->tt.vn); 406 + tt_data->crc = htonl(bat_priv->tt.local_crc); 431 407 432 - batadv_tt_prepare_packet_buff(bat_priv, packet_buff, 433 - packet_buff_len, min_packet_len); 408 + if (tt_diff_len == 0) 409 + goto container_register; 434 410 435 - new_len = *packet_buff_len - min_packet_len; 436 - tt_buff = *packet_buff + min_packet_len; 437 - 438 - if (new_len > 0) 439 - tot_changes = new_len / batadv_tt_len(1); 411 + tt_diff_entries_num = tt_diff_len / batadv_tt_len(1); 440 412 441 413 spin_lock_bh(&bat_priv->tt.changes_list_lock); 442 414 atomic_set(&bat_priv->tt.local_changes, 0); 443 415 416 + tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1); 417 + 444 418 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, 445 419 list) { 446 - if (count < tot_changes) { 447 - memcpy(tt_buff + batadv_tt_len(count), 448 - &entry->change, sizeof(struct batadv_tt_change)); 449 - count++; 420 + if (tt_diff_entries_count < tt_diff_entries_num) { 421 + memcpy(tt_change + tt_diff_entries_count, 422 + &entry->change, 423 + sizeof(struct batadv_tvlv_tt_change)); 424 + tt_diff_entries_count++; 450 425 } 451 426 list_del(&entry->list); 452 427 kfree(entry); ··· 439 452 kfree(bat_priv->tt.last_changeset); 440 453 bat_priv->tt.last_changeset_len = 0; 441 454 bat_priv->tt.last_changeset = NULL; 455 + tt_change_len = batadv_tt_len(tt_diff_entries_count); 442 456 /* check whether this new OGM has no changes due to size problems */ 443 - if (new_len > 0) { 457 + if (tt_diff_entries_count > 0) { 444 458 /* if kmalloc() fails we will reply with the full table 445 459 * instead of providing the diff 446 460 */ 447 - bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); 461 + bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC); 448 462 if (bat_priv->tt.last_changeset) { 449 - memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); 450 - bat_priv->tt.last_changeset_len = new_len; 463 + memcpy(bat_priv->tt.last_changeset, 464 + tt_change, tt_change_len); 465 + bat_priv->tt.last_changeset_len = tt_diff_len; 451 466 } 452 467 } 453 468 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 454 469 455 - return count; 470 + container_register: 471 + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data, 472 + sizeof(*tt_data) + tt_change_len); 473 + kfree(tt_data); 456 474 } 457 475 458 476 int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) ··· 481 489 goto out; 482 490 483 491 seq_printf(seq, 484 - "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x):\n", 492 + "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.8x):\n", 485 493 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn), 486 494 bat_priv->tt.local_crc); 487 495 seq_printf(seq, " %-13s %-7s %-10s\n", "Client", "Flags", ··· 993 1001 if (best_entry) { 994 1002 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn); 995 1003 seq_printf(seq, 996 - " %c %pM (%3u) via %pM (%3u) (%#.4x) [%c%c%c]\n", 1004 + " %c %pM (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n", 997 1005 '*', tt_global_entry->common.addr, 998 1006 best_entry->ttvn, best_entry->orig_node->orig, 999 1007 last_ttvn, best_entry->orig_node->tt_crc, ··· 1037 1045 seq_printf(seq, 1038 1046 "Globally announced TT entries received via the mesh %s\n", 1039 1047 net_dev->name); 1040 - seq_printf(seq, " %-13s %s %-15s %s (%-6s) %s\n", 1048 + seq_printf(seq, " %-13s %s %-15s %s (%-10s) %s\n", 1041 1049 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC", 1042 1050 "Flags"); 1043 1051 ··· 1394 1402 return orig_node; 1395 1403 } 1396 1404 1397 - /* Calculates the checksum of the local table of a given orig_node */ 1398 - static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, 1405 + /** 1406 + * batadv_tt_global_crc - calculates the checksum of the local table belonging 1407 + * to the given orig_node 1408 + * @bat_priv: the bat priv with all the soft interface information 1409 + */ 1410 + static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, 1399 1411 struct batadv_orig_node *orig_node) 1400 1412 { 1401 - uint16_t total = 0, total_one; 1402 1413 struct batadv_hashtable *hash = bat_priv->tt.global_hash; 1403 1414 struct batadv_tt_common_entry *tt_common; 1404 1415 struct batadv_tt_global_entry *tt_global; 1405 1416 struct hlist_head *head; 1406 - uint32_t i; 1407 - int j; 1417 + uint32_t i, crc = 0; 1408 1418 1409 1419 for (i = 0; i < hash->size; i++) { 1410 1420 head = &hash->table[i]; ··· 1437 1443 orig_node)) 1438 1444 continue; 1439 1445 1440 - total_one = 0; 1441 - for (j = 0; j < ETH_ALEN; j++) 1442 - total_one = crc16_byte(total_one, 1443 - tt_common->addr[j]); 1444 - total ^= total_one; 1446 + crc ^= crc32c(0, tt_common->addr, ETH_ALEN); 1445 1447 } 1446 1448 rcu_read_unlock(); 1447 1449 } 1448 1450 1449 - return total; 1451 + return crc; 1450 1452 } 1451 1453 1452 - /* Calculates the checksum of the local table */ 1453 - static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) 1454 + /** 1455 + * batadv_tt_local_crc - calculates the checksum of the local table 1456 + * @bat_priv: the bat priv with all the soft interface information 1457 + */ 1458 + static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv) 1454 1459 { 1455 - uint16_t total = 0, total_one; 1456 1460 struct batadv_hashtable *hash = bat_priv->tt.local_hash; 1457 1461 struct batadv_tt_common_entry *tt_common; 1458 1462 struct hlist_head *head; 1459 - uint32_t i; 1460 - int j; 1463 + uint32_t i, crc = 0; 1461 1464 1462 1465 for (i = 0; i < hash->size; i++) { 1463 1466 head = &hash->table[i]; ··· 1466 1475 */ 1467 1476 if (tt_common->flags & BATADV_TT_CLIENT_NEW) 1468 1477 continue; 1469 - total_one = 0; 1470 - for (j = 0; j < ETH_ALEN; j++) 1471 - total_one = crc16_byte(total_one, 1472 - tt_common->addr[j]); 1473 - total ^= total_one; 1478 + 1479 + crc ^= crc32c(0, tt_common->addr, ETH_ALEN); 1474 1480 } 1475 1481 rcu_read_unlock(); 1476 1482 } 1477 1483 1478 - return total; 1484 + return crc; 1479 1485 } 1480 1486 1481 1487 static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) ··· 1492 1504 static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, 1493 1505 struct batadv_orig_node *orig_node, 1494 1506 const unsigned char *tt_buff, 1495 - uint8_t tt_num_changes) 1507 + uint16_t tt_num_changes) 1496 1508 { 1497 1509 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes); 1498 1510 ··· 1557 1569 return tt_req_node; 1558 1570 } 1559 1571 1560 - /* data_ptr is useless here, but has to be kept to respect the prototype */ 1561 - static int batadv_tt_local_valid_entry(const void *entry_ptr, 1562 - const void *data_ptr) 1572 + /** 1573 + * batadv_tt_local_valid - verify that given tt entry is a valid one 1574 + * @entry_ptr: to be checked local tt entry 1575 + * @data_ptr: not used but definition required to satisfy the callback prototype 1576 + * 1577 + * Returns 1 if the entry is a valid, 0 otherwise. 1578 + */ 1579 + static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) 1563 1580 { 1564 1581 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; 1565 1582 ··· 1591 1598 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); 1592 1599 } 1593 1600 1594 - static struct sk_buff * 1595 - batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, 1596 - struct batadv_hashtable *hash, 1597 - struct batadv_priv *bat_priv, 1598 - int (*valid_cb)(const void *, const void *), 1599 - void *cb_data) 1601 + /** 1602 + * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the 1603 + * tt entries from the specified tt hash 1604 + * @bat_priv: the bat priv with all the soft interface information 1605 + * @hash: hash table containing the tt entries 1606 + * @tt_len: expected tvlv tt data buffer length in number of bytes 1607 + * @valid_cb: function to filter tt change entries 1608 + * @cb_data: data passed to the filter function as argument 1609 + * 1610 + * Returns pointer to allocated tvlv tt data buffer if operation was 1611 + * successful or NULL otherwise. 1612 + */ 1613 + static struct batadv_tvlv_tt_data * 1614 + batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, 1615 + struct batadv_hashtable *hash, uint16_t tt_len, 1616 + int (*valid_cb)(const void *, const void *), 1617 + void *cb_data) 1600 1618 { 1601 1619 struct batadv_tt_common_entry *tt_common_entry; 1602 - struct batadv_tt_query_packet *tt_response; 1603 - struct batadv_tt_change *tt_change; 1620 + struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 1621 + struct batadv_tvlv_tt_change *tt_change; 1604 1622 struct hlist_head *head; 1605 - struct sk_buff *skb = NULL; 1606 - uint16_t tt_tot, tt_count; 1607 - ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet); 1623 + uint16_t tt_tot, tt_num_entries = 0; 1624 + ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data); 1608 1625 uint32_t i; 1609 - size_t len; 1610 1626 1611 - if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) { 1612 - tt_len = bat_priv->soft_iface->mtu - tt_query_size; 1613 - tt_len -= tt_len % sizeof(struct batadv_tt_change); 1627 + if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) { 1628 + tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size; 1629 + tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change); 1614 1630 } 1615 - tt_tot = tt_len / sizeof(struct batadv_tt_change); 1616 1631 1617 - len = tt_query_size + tt_len; 1618 - skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1619 - if (!skb) 1632 + tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change); 1633 + 1634 + tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 1635 + GFP_ATOMIC); 1636 + if (!tvlv_tt_data) 1620 1637 goto out; 1621 1638 1622 - skb->priority = TC_PRIO_CONTROL; 1623 - skb_reserve(skb, ETH_HLEN); 1624 - tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); 1625 - tt_response->ttvn = ttvn; 1626 - 1627 - tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size); 1628 - tt_count = 0; 1639 + tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1); 1629 1640 1630 1641 rcu_read_lock(); 1631 1642 for (i = 0; i < hash->size; i++) { ··· 1637 1640 1638 1641 hlist_for_each_entry_rcu(tt_common_entry, 1639 1642 head, hash_entry) { 1640 - if (tt_count == tt_tot) 1643 + if (tt_tot == tt_num_entries) 1641 1644 break; 1642 1645 1643 1646 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) ··· 1646 1649 memcpy(tt_change->addr, tt_common_entry->addr, 1647 1650 ETH_ALEN); 1648 1651 tt_change->flags = tt_common_entry->flags; 1652 + tt_change->reserved = 0; 1649 1653 1650 - tt_count++; 1654 + tt_num_entries++; 1651 1655 tt_change++; 1652 1656 } 1653 1657 } 1654 1658 rcu_read_unlock(); 1655 1659 1656 - /* store in the message the number of entries we have successfully 1657 - * copied 1658 - */ 1659 - tt_response->tt_data = htons(tt_count); 1660 - 1661 1660 out: 1662 - return skb; 1661 + return tvlv_tt_data; 1663 1662 } 1664 1663 1664 + /** 1665 + * batadv_send_tt_request - send a TT Request message to a given node 1666 + * @bat_priv: the bat priv with all the soft interface information 1667 + * @dst_orig_node: the destination of the message 1668 + * @ttvn: the version number that the source of the message is looking for 1669 + * @tt_crc: the CRC associated with the version number 1670 + * @full_table: ask for the entire translation table if true, while only for the 1671 + * last TT diff otherwise 1672 + */ 1665 1673 static int batadv_send_tt_request(struct batadv_priv *bat_priv, 1666 1674 struct batadv_orig_node *dst_orig_node, 1667 - uint8_t ttvn, uint16_t tt_crc, 1675 + uint8_t ttvn, uint32_t tt_crc, 1668 1676 bool full_table) 1669 1677 { 1670 - struct sk_buff *skb = NULL; 1671 - struct batadv_tt_query_packet *tt_request; 1678 + struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 1672 1679 struct batadv_hard_iface *primary_if; 1673 1680 struct batadv_tt_req_node *tt_req_node = NULL; 1674 - int ret = 1; 1675 - size_t tt_req_len; 1681 + bool ret = false; 1676 1682 1677 1683 primary_if = batadv_primary_if_get_selected(bat_priv); 1678 1684 if (!primary_if) ··· 1688 1688 if (!tt_req_node) 1689 1689 goto out; 1690 1690 1691 - skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN); 1692 - if (!skb) 1691 + tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC); 1692 + if (!tvlv_tt_data) 1693 1693 goto out; 1694 1694 1695 - skb->priority = TC_PRIO_CONTROL; 1696 - skb_reserve(skb, ETH_HLEN); 1697 - 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; 1695 + tvlv_tt_data->flags = BATADV_TT_REQUEST; 1696 + tvlv_tt_data->ttvn = ttvn; 1697 + tvlv_tt_data->crc = htonl(tt_crc); 1709 1698 1710 1699 if (full_table) 1711 - tt_request->flags |= BATADV_TT_FULL_TABLE; 1700 + tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE; 1712 1701 1713 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 1705 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); 1717 - 1718 - if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP) 1719 - ret = 0; 1706 + batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 1707 + dst_orig_node->orig, BATADV_TVLV_TT, 1, 1708 + tvlv_tt_data, sizeof(*tvlv_tt_data)); 1709 + ret = true; 1720 1710 1721 1711 out: 1722 1712 if (primary_if) 1723 1713 batadv_hardif_free_ref(primary_if); 1724 - if (ret) 1725 - kfree_skb(skb); 1726 1714 if (ret && tt_req_node) { 1727 1715 spin_lock_bh(&bat_priv->tt.req_list_lock); 1728 1716 list_del(&tt_req_node->list); 1729 1717 spin_unlock_bh(&bat_priv->tt.req_list_lock); 1730 1718 kfree(tt_req_node); 1731 1719 } 1720 + kfree(tvlv_tt_data); 1732 1721 return ret; 1733 1722 } 1734 1723 1735 - static bool 1736 - batadv_send_other_tt_response(struct batadv_priv *bat_priv, 1737 - struct batadv_tt_query_packet *tt_request) 1724 + /** 1725 + * batadv_send_other_tt_response - send reply to tt request concerning another 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 1738 struct batadv_orig_node *req_dst_orig_node; 1740 1739 struct batadv_orig_node *res_dst_orig_node = NULL; 1741 - uint8_t orig_ttvn, req_ttvn, ttvn; 1742 - int res, ret = false; 1743 - unsigned char *tt_buff; 1744 - bool 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; 1740 + struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 1741 + uint8_t orig_ttvn, req_ttvn; 1742 + uint16_t tt_len; 1743 + bool ret = false, full_table; 1750 1744 1751 1745 batadv_dbg(BATADV_DBG_TT, bat_priv, 1752 1746 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n", 1753 - tt_request->src, tt_request->ttvn, tt_request->dst, 1754 - (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1747 + req_src, tt_data->ttvn, req_dst, 1748 + (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1755 1749 1756 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 1752 if (!req_dst_orig_node) 1759 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 1756 if (!res_dst_orig_node) 1763 1757 goto out; 1764 1758 1765 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 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 1765 goto out; 1772 1766 1773 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 1769 !req_dst_orig_node->tt_buff) 1776 1770 full_table = true; 1777 1771 else 1778 1772 full_table = false; 1779 1773 1780 - /* In this version, fragmentation is not implemented, then 1781 - * I'll send only one packet with as much TT entries as I can 1774 + /* TT fragmentation hasn't been implemented yet, so send as many 1775 + * TT entries fit a single packet as possible only 1782 1776 */ 1783 1777 if (!full_table) { 1784 1778 spin_lock_bh(&req_dst_orig_node->tt_buff_lock); 1785 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; 1789 - skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1790 - if (!skb) 1781 + tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 1782 + GFP_ATOMIC); 1783 + if (!tvlv_tt_data) 1791 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 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 1788 req_dst_orig_node->tt_buff_len); 1804 - 1805 1789 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); 1806 1790 } else { 1807 1791 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); 1808 - tt_len *= sizeof(struct batadv_tt_change); 1809 - ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1792 + tt_len = batadv_tt_len(tt_len); 1810 1793 1811 - skb = batadv_tt_response_fill_table(tt_len, ttvn, 1812 - bat_priv->tt.global_hash, 1813 - bat_priv, 1814 - batadv_tt_global_valid, 1815 - req_dst_orig_node); 1816 - if (!skb) 1794 + tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 1795 + bat_priv->tt.global_hash, 1796 + tt_len, 1797 + batadv_tt_global_valid, 1798 + req_dst_orig_node); 1799 + if (!tvlv_tt_data) 1817 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; 1823 - tt_response->header.version = BATADV_COMPAT_VERSION; 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; 1803 + tvlv_tt_data->flags = BATADV_TT_RESPONSE; 1804 + tvlv_tt_data->ttvn = req_ttvn; 1828 1805 1829 1806 if (full_table) 1830 - tt_response->flags |= BATADV_TT_FULL_TABLE; 1807 + tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE; 1831 1808 1832 1809 batadv_dbg(BATADV_DBG_TT, bat_priv, 1833 - "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n", 1834 - res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn); 1810 + "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n", 1811 + res_dst_orig_node->orig, req_dst_orig_node->orig, 1812 + full_table ? 'F' : '.', req_ttvn); 1835 1813 1836 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); 1839 - if (res != NET_XMIT_DROP) 1840 - ret = true; 1816 + batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig, 1817 + req_src, BATADV_TVLV_TT, 1, 1818 + tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 1841 1819 1820 + ret = true; 1842 1821 goto out; 1843 1822 1844 1823 unlock: ··· 1828 1849 batadv_orig_node_free_ref(res_dst_orig_node); 1829 1850 if (req_dst_orig_node) 1830 1851 batadv_orig_node_free_ref(req_dst_orig_node); 1831 - if (!ret) 1832 - kfree_skb(skb); 1852 + kfree(tvlv_tt_data); 1833 1853 return ret; 1834 1854 } 1835 1855 1836 - static bool 1837 - batadv_send_my_tt_response(struct batadv_priv *bat_priv, 1838 - struct batadv_tt_query_packet *tt_request) 1856 + /** 1857 + * batadv_send_my_tt_response - send reply to tt request concerning this node's 1858 + * translation table 1859 + * @bat_priv: the bat priv with all the soft interface information 1860 + * @tt_data: tt data containing the tt request information 1861 + * @req_src: mac address of tt request sender 1862 + * 1863 + * Returns true if tt request reply was sent, false otherwise. 1864 + */ 1865 + static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv, 1866 + struct batadv_tvlv_tt_data *tt_data, 1867 + uint8_t *req_src) 1839 1868 { 1869 + struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 1840 1870 struct batadv_orig_node *orig_node; 1841 1871 struct batadv_hard_iface *primary_if = NULL; 1842 - uint8_t my_ttvn, req_ttvn, ttvn; 1843 - int ret = false; 1844 - unsigned char *tt_buff; 1872 + uint8_t my_ttvn, req_ttvn; 1845 1873 bool full_table; 1846 - uint16_t tt_len, tt_tot; 1847 - struct sk_buff *skb = NULL; 1848 - struct batadv_tt_query_packet *tt_response; 1849 - uint8_t *packet_pos; 1850 - size_t len; 1874 + uint16_t tt_len; 1851 1875 1852 1876 batadv_dbg(BATADV_DBG_TT, bat_priv, 1853 1877 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n", 1854 - tt_request->src, tt_request->ttvn, 1855 - (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1878 + req_src, tt_data->ttvn, 1879 + (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1856 1880 1857 1881 1858 1882 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1859 - req_ttvn = tt_request->ttvn; 1883 + req_ttvn = tt_data->ttvn; 1860 1884 1861 - orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); 1885 + orig_node = batadv_orig_hash_find(bat_priv, req_src); 1862 1886 if (!orig_node) 1863 1887 goto out; 1864 1888 ··· 1872 1890 /* If the full table has been explicitly requested or the gap 1873 1891 * is too big send the whole local translation table 1874 1892 */ 1875 - if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || 1893 + if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || 1876 1894 !bat_priv->tt.last_changeset) 1877 1895 full_table = true; 1878 1896 else 1879 1897 full_table = false; 1880 1898 1881 - /* In this version, fragmentation is not implemented, then 1882 - * I'll send only one packet with as much TT entries as I can 1899 + /* TT fragmentation hasn't been implemented yet, so send as many 1900 + * TT entries fit a single packet as possible only 1883 1901 */ 1884 1902 if (!full_table) { 1885 1903 spin_lock_bh(&bat_priv->tt.last_changeset_lock); 1886 1904 tt_len = bat_priv->tt.last_changeset_len; 1887 - tt_tot = tt_len / sizeof(struct batadv_tt_change); 1888 1905 1889 - len = sizeof(*tt_response) + tt_len; 1890 - skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1891 - if (!skb) 1906 + tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 1907 + GFP_ATOMIC); 1908 + if (!tvlv_tt_data) 1892 1909 goto unlock; 1893 1910 1894 - skb->priority = TC_PRIO_CONTROL; 1895 - skb_reserve(skb, ETH_HLEN); 1896 - packet_pos = skb_put(skb, len); 1897 - tt_response = (struct batadv_tt_query_packet *)packet_pos; 1898 - tt_response->ttvn = req_ttvn; 1899 - tt_response->tt_data = htons(tt_tot); 1900 - 1901 - tt_buff = skb->data + sizeof(*tt_response); 1902 - memcpy(tt_buff, bat_priv->tt.last_changeset, 1911 + /* Copy the last orig_node's OGM buffer */ 1912 + memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset, 1903 1913 bat_priv->tt.last_changeset_len); 1904 1914 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 1905 1915 } else { 1906 1916 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); 1907 - tt_len *= sizeof(struct batadv_tt_change); 1908 - ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1917 + tt_len = batadv_tt_len(tt_len); 1918 + req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1909 1919 1910 - skb = batadv_tt_response_fill_table(tt_len, ttvn, 1911 - bat_priv->tt.local_hash, 1912 - bat_priv, 1913 - batadv_tt_local_valid_entry, 1914 - NULL); 1915 - if (!skb) 1920 + tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 1921 + bat_priv->tt.local_hash, 1922 + tt_len, 1923 + batadv_tt_local_valid, 1924 + NULL); 1925 + if (!tvlv_tt_data) 1916 1926 goto out; 1917 - 1918 - tt_response = (struct batadv_tt_query_packet *)skb->data; 1919 1927 } 1920 1928 1921 - tt_response->header.packet_type = BATADV_TT_QUERY; 1922 - tt_response->header.version = BATADV_COMPAT_VERSION; 1923 - tt_response->header.ttl = BATADV_TTL; 1924 - memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN); 1925 - memcpy(tt_response->dst, tt_request->src, ETH_ALEN); 1926 - tt_response->flags = BATADV_TT_RESPONSE; 1929 + tvlv_tt_data->flags = BATADV_TT_RESPONSE; 1930 + tvlv_tt_data->ttvn = req_ttvn; 1927 1931 1928 1932 if (full_table) 1929 - tt_response->flags |= BATADV_TT_FULL_TABLE; 1933 + tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE; 1930 1934 1931 1935 batadv_dbg(BATADV_DBG_TT, bat_priv, 1932 - "Sending TT_RESPONSE to %pM [%c]\n", 1933 - orig_node->orig, 1934 - (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1936 + "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n", 1937 + orig_node->orig, full_table ? 'F' : '.', req_ttvn); 1935 1938 1936 1939 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 1937 1940 1938 - if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 1939 - ret = true; 1941 + batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 1942 + req_src, BATADV_TVLV_TT, 1, 1943 + tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 1944 + 1940 1945 goto out; 1941 1946 1942 1947 unlock: ··· 1933 1964 batadv_orig_node_free_ref(orig_node); 1934 1965 if (primary_if) 1935 1966 batadv_hardif_free_ref(primary_if); 1936 - if (!ret) 1937 - kfree_skb(skb); 1938 - /* This packet was for me, so it doesn't need to be re-routed */ 1967 + kfree(tvlv_tt_data); 1968 + /* The packet was for this host, so it doesn't need to be re-routed */ 1939 1969 return true; 1940 1970 } 1941 1971 1942 - bool batadv_send_tt_response(struct batadv_priv *bat_priv, 1943 - struct batadv_tt_query_packet *tt_request) 1972 + /** 1973 + * batadv_send_tt_response - send reply to tt request 1974 + * @bat_priv: the bat priv with all the soft interface information 1975 + * @tt_data: tt data containing the tt request information 1976 + * @req_src: mac address of tt request sender 1977 + * @req_dst: mac address of tt request recipient 1978 + * 1979 + * Returns true if tt request reply was sent, false otherwise. 1980 + */ 1981 + static bool batadv_send_tt_response(struct batadv_priv *bat_priv, 1982 + struct batadv_tvlv_tt_data *tt_data, 1983 + uint8_t *req_src, uint8_t *req_dst) 1944 1984 { 1945 - if (batadv_is_my_mac(bat_priv, tt_request->dst)) { 1985 + if (batadv_is_my_mac(bat_priv, req_dst)) { 1946 1986 /* don't answer backbone gws! */ 1947 - if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src)) 1987 + if (batadv_bla_is_backbone_gw_orig(bat_priv, req_src)) 1948 1988 return true; 1949 1989 1950 - return batadv_send_my_tt_response(bat_priv, tt_request); 1990 + return batadv_send_my_tt_response(bat_priv, tt_data, req_src); 1951 1991 } else { 1952 - return batadv_send_other_tt_response(bat_priv, tt_request); 1992 + return batadv_send_other_tt_response(bat_priv, tt_data, 1993 + req_src, req_dst); 1953 1994 } 1954 1995 } 1955 1996 1956 1997 static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, 1957 1998 struct batadv_orig_node *orig_node, 1958 - struct batadv_tt_change *tt_change, 1999 + struct batadv_tvlv_tt_change *tt_change, 1959 2000 uint16_t tt_num_changes, uint8_t ttvn) 1960 2001 { 1961 2002 int i; ··· 1995 2016 } 1996 2017 1997 2018 static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 1998 - struct batadv_tt_query_packet *tt_response) 2019 + struct batadv_tvlv_tt_data *tt_data, 2020 + uint8_t *resp_src, uint16_t num_entries) 1999 2021 { 2000 2022 struct batadv_orig_node *orig_node; 2001 2023 2002 - orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 2024 + orig_node = batadv_orig_hash_find(bat_priv, resp_src); 2003 2025 if (!orig_node) 2004 2026 goto out; 2005 2027 ··· 2008 2028 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); 2009 2029 2010 2030 _batadv_tt_update_changes(bat_priv, orig_node, 2011 - (struct batadv_tt_change *)(tt_response + 1), 2012 - ntohs(tt_response->tt_data), 2013 - tt_response->ttvn); 2031 + (struct batadv_tvlv_tt_change *)(tt_data + 1), 2032 + num_entries, tt_data->ttvn); 2014 2033 2015 2034 spin_lock_bh(&orig_node->tt_buff_lock); 2016 2035 kfree(orig_node->tt_buff); ··· 2017 2038 orig_node->tt_buff = NULL; 2018 2039 spin_unlock_bh(&orig_node->tt_buff_lock); 2019 2040 2020 - atomic_set(&orig_node->last_ttvn, tt_response->ttvn); 2041 + atomic_set(&orig_node->last_ttvn, tt_data->ttvn); 2021 2042 2022 2043 out: 2023 2044 if (orig_node) ··· 2027 2048 static void batadv_tt_update_changes(struct batadv_priv *bat_priv, 2028 2049 struct batadv_orig_node *orig_node, 2029 2050 uint16_t tt_num_changes, uint8_t ttvn, 2030 - struct batadv_tt_change *tt_change) 2051 + struct batadv_tvlv_tt_change *tt_change) 2031 2052 { 2032 2053 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, 2033 2054 tt_num_changes, ttvn); ··· 2058 2079 return ret; 2059 2080 } 2060 2081 2061 - void batadv_handle_tt_response(struct batadv_priv *bat_priv, 2062 - struct batadv_tt_query_packet *tt_response) 2082 + /** 2083 + * batadv_handle_tt_response - process incoming tt reply 2084 + * @bat_priv: the bat priv with all the soft interface information 2085 + * @tt_data: tt data containing the tt request information 2086 + * @resp_src: mac address of tt reply sender 2087 + * @num_entries: number of tt change entries appended to the tt data 2088 + */ 2089 + static void batadv_handle_tt_response(struct batadv_priv *bat_priv, 2090 + struct batadv_tvlv_tt_data *tt_data, 2091 + uint8_t *resp_src, uint16_t num_entries) 2063 2092 { 2064 2093 struct batadv_tt_req_node *node, *safe; 2065 2094 struct batadv_orig_node *orig_node = NULL; 2066 - struct batadv_tt_change *tt_change; 2095 + struct batadv_tvlv_tt_change *tt_change; 2067 2096 2068 2097 batadv_dbg(BATADV_DBG_TT, bat_priv, 2069 2098 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", 2070 - tt_response->src, tt_response->ttvn, 2071 - ntohs(tt_response->tt_data), 2072 - (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 2099 + resp_src, tt_data->ttvn, num_entries, 2100 + (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 2073 2101 2074 2102 /* we should have never asked a backbone gw */ 2075 - if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src)) 2103 + if (batadv_bla_is_backbone_gw_orig(bat_priv, resp_src)) 2076 2104 goto out; 2077 2105 2078 - orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 2106 + orig_node = batadv_orig_hash_find(bat_priv, resp_src); 2079 2107 if (!orig_node) 2080 2108 goto out; 2081 2109 2082 - if (tt_response->flags & BATADV_TT_FULL_TABLE) { 2083 - batadv_tt_fill_gtable(bat_priv, tt_response); 2110 + if (tt_data->flags & BATADV_TT_FULL_TABLE) { 2111 + batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries); 2084 2112 } else { 2085 - tt_change = (struct batadv_tt_change *)(tt_response + 1); 2086 - batadv_tt_update_changes(bat_priv, orig_node, 2087 - ntohs(tt_response->tt_data), 2088 - tt_response->ttvn, tt_change); 2113 + tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1); 2114 + batadv_tt_update_changes(bat_priv, orig_node, num_entries, 2115 + tt_data->ttvn, tt_change); 2089 2116 } 2090 2117 2091 2118 /* Delete the tt_req_node from pending tt_requests list */ 2092 2119 spin_lock_bh(&bat_priv->tt.req_list_lock); 2093 2120 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { 2094 - if (!batadv_compare_eth(node->addr, tt_response->src)) 2121 + if (!batadv_compare_eth(node->addr, resp_src)) 2095 2122 continue; 2096 2123 list_del(&node->list); 2097 2124 kfree(node); ··· 2109 2124 out: 2110 2125 if (orig_node) 2111 2126 batadv_orig_node_free_ref(orig_node); 2112 - } 2113 - 2114 - int batadv_tt_init(struct batadv_priv *bat_priv) 2115 - { 2116 - int ret; 2117 - 2118 - ret = batadv_tt_local_init(bat_priv); 2119 - if (ret < 0) 2120 - return ret; 2121 - 2122 - ret = batadv_tt_global_init(bat_priv); 2123 - if (ret < 0) 2124 - return ret; 2125 - 2126 - INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); 2127 - queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, 2128 - msecs_to_jiffies(BATADV_TT_WORK_PERIOD)); 2129 - 2130 - return 1; 2131 2127 } 2132 2128 2133 2129 static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) ··· 2194 2228 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, 2195 2229 struct batadv_orig_node *orig_node) 2196 2230 { 2197 - struct sk_buff *skb = NULL; 2198 - struct batadv_roam_adv_packet *roam_adv_packet; 2199 - int ret = 1; 2200 2231 struct batadv_hard_iface *primary_if; 2201 - size_t len = sizeof(*roam_adv_packet); 2232 + struct batadv_tvlv_roam_adv tvlv_roam; 2233 + 2234 + primary_if = batadv_primary_if_get_selected(bat_priv); 2235 + if (!primary_if) 2236 + goto out; 2202 2237 2203 2238 /* before going on we have to check whether the client has 2204 2239 * already roamed to us too many times ··· 2207 2240 if (!batadv_tt_check_roam_count(bat_priv, client)) 2208 2241 goto out; 2209 2242 2210 - skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 2211 - if (!skb) 2212 - goto out; 2213 - 2214 - skb->priority = TC_PRIO_CONTROL; 2215 - skb_reserve(skb, ETH_HLEN); 2216 - 2217 - roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len); 2218 - 2219 - roam_adv_packet->header.packet_type = BATADV_ROAM_ADV; 2220 - roam_adv_packet->header.version = BATADV_COMPAT_VERSION; 2221 - roam_adv_packet->header.ttl = BATADV_TTL; 2222 - roam_adv_packet->reserved = 0; 2223 - primary_if = batadv_primary_if_get_selected(bat_priv); 2224 - if (!primary_if) 2225 - goto out; 2226 - memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN); 2227 - batadv_hardif_free_ref(primary_if); 2228 - memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN); 2229 - memcpy(roam_adv_packet->client, client, ETH_ALEN); 2230 - 2231 2243 batadv_dbg(BATADV_DBG_TT, bat_priv, 2232 2244 "Sending ROAMING_ADV to %pM (client %pM)\n", 2233 2245 orig_node->orig, client); 2234 2246 2235 2247 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); 2236 2248 2237 - if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 2238 - ret = 0; 2249 + memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client)); 2250 + tvlv_roam.reserved = 0; 2251 + 2252 + batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2253 + orig_node->orig, BATADV_TVLV_ROAM, 1, 2254 + &tvlv_roam, sizeof(tvlv_roam)); 2239 2255 2240 2256 out: 2241 - if (ret && skb) 2242 - kfree_skb(skb); 2243 - return; 2257 + if (primary_if) 2258 + batadv_hardif_free_ref(primary_if); 2244 2259 } 2245 2260 2246 2261 static void batadv_tt_purge(struct work_struct *work) ··· 2246 2297 2247 2298 void batadv_tt_free(struct batadv_priv *bat_priv) 2248 2299 { 2300 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1); 2301 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1); 2302 + 2249 2303 cancel_delayed_work_sync(&bat_priv->tt.work); 2250 2304 2251 2305 batadv_tt_local_table_free(bat_priv); ··· 2336 2384 } 2337 2385 } 2338 2386 2339 - static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, 2340 - unsigned char **packet_buff, 2341 - int *packet_buff_len, int packet_min_len) 2387 + /** 2388 + * batadv_tt_local_commit_changes - commit all pending local tt changes which 2389 + * have been queued in the time since the last commit 2390 + * @bat_priv: the bat priv with all the soft interface information 2391 + */ 2392 + void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv) 2342 2393 { 2343 2394 uint16_t changed_num = 0; 2344 2395 2345 - if (atomic_read(&bat_priv->tt.local_changes) < 1) 2346 - return -ENOENT; 2396 + if (atomic_read(&bat_priv->tt.local_changes) < 1) { 2397 + if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) 2398 + batadv_tt_tvlv_container_update(bat_priv); 2399 + return; 2400 + } 2347 2401 2348 2402 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, 2349 2403 BATADV_TT_CLIENT_NEW, false); ··· 2367 2409 2368 2410 /* reset the sending counter */ 2369 2411 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); 2370 - 2371 - return batadv_tt_changes_fill_buff(bat_priv, packet_buff, 2372 - packet_buff_len, packet_min_len); 2373 - } 2374 - 2375 - /* when calling this function (hard_iface == primary_if) has to be true */ 2376 - int batadv_tt_append_diff(struct batadv_priv *bat_priv, 2377 - unsigned char **packet_buff, int *packet_buff_len, 2378 - int packet_min_len) 2379 - { 2380 - int tt_num_changes; 2381 - 2382 - /* if at least one change happened */ 2383 - tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff, 2384 - packet_buff_len, 2385 - packet_min_len); 2386 - 2387 - /* if the changes have been sent often enough */ 2388 - if ((tt_num_changes < 0) && 2389 - (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { 2390 - batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, 2391 - packet_min_len, packet_min_len); 2392 - tt_num_changes = 0; 2393 - } 2394 - 2395 - return tt_num_changes; 2412 + batadv_tt_tvlv_container_update(bat_priv); 2396 2413 } 2397 2414 2398 2415 bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, ··· 2401 2468 return ret; 2402 2469 } 2403 2470 2404 - void batadv_tt_update_orig(struct batadv_priv *bat_priv, 2405 - struct batadv_orig_node *orig_node, 2406 - const unsigned char *tt_buff, uint8_t tt_num_changes, 2407 - uint8_t ttvn, uint16_t tt_crc) 2471 + /** 2472 + * batadv_tt_update_orig - update global translation table with new tt 2473 + * information received via ogms 2474 + * @bat_priv: the bat priv with all the soft interface information 2475 + * @orig: the orig_node of the ogm 2476 + * @tt_buff: buffer holding the tt information 2477 + * @tt_num_changes: number of tt changes inside the tt buffer 2478 + * @ttvn: translation table version number of this changeset 2479 + * @tt_crc: crc32 checksum of orig node's translation table 2480 + */ 2481 + static void batadv_tt_update_orig(struct batadv_priv *bat_priv, 2482 + struct batadv_orig_node *orig_node, 2483 + const unsigned char *tt_buff, 2484 + uint16_t tt_num_changes, uint8_t ttvn, 2485 + uint32_t tt_crc) 2408 2486 { 2409 2487 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 2410 2488 bool full_table = true; 2411 - struct batadv_tt_change *tt_change; 2489 + struct batadv_tvlv_tt_change *tt_change; 2412 2490 2413 2491 /* don't care about a backbone gateways updates. */ 2414 2492 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) ··· 2440 2496 goto request_table; 2441 2497 } 2442 2498 2443 - tt_change = (struct batadv_tt_change *)tt_buff; 2499 + tt_change = (struct batadv_tvlv_tt_change *)tt_buff; 2444 2500 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, 2445 2501 ttvn, tt_change); 2446 2502 ··· 2469 2525 orig_node->tt_crc != tt_crc) { 2470 2526 request_table: 2471 2527 batadv_dbg(BATADV_DBG_TT, bat_priv, 2472 - "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u)\n", 2528 + "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.8x last_crc: %#.8x num_changes: %u)\n", 2473 2529 orig_node->orig, ttvn, orig_ttvn, tt_crc, 2474 2530 orig_node->tt_crc, tt_num_changes); 2475 2531 batadv_send_tt_request(bat_priv, orig_node, ttvn, ··· 2548 2604 ret = true; 2549 2605 out: 2550 2606 return ret; 2607 + } 2608 + 2609 + /** 2610 + * batadv_tt_tvlv_ogm_handler_v1 - process incoming tt tvlv container 2611 + * @bat_priv: the bat priv with all the soft interface information 2612 + * @orig: the orig_node of the ogm 2613 + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 2614 + * @tvlv_value: tvlv buffer containing the gateway data 2615 + * @tvlv_value_len: tvlv buffer length 2616 + */ 2617 + static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 2618 + struct batadv_orig_node *orig, 2619 + uint8_t flags, 2620 + void *tvlv_value, 2621 + uint16_t tvlv_value_len) 2622 + { 2623 + struct batadv_tvlv_tt_data *tt_data; 2624 + uint16_t num_entries; 2625 + 2626 + if (tvlv_value_len < sizeof(*tt_data)) 2627 + return; 2628 + 2629 + tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 2630 + tvlv_value_len -= sizeof(*tt_data); 2631 + 2632 + num_entries = tvlv_value_len / batadv_tt_len(1); 2633 + 2634 + batadv_tt_update_orig(bat_priv, orig, 2635 + (unsigned char *)(tt_data + 1), 2636 + num_entries, tt_data->ttvn, ntohl(tt_data->crc)); 2637 + } 2638 + 2639 + /** 2640 + * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv 2641 + * container 2642 + * @bat_priv: the bat priv with all the soft interface information 2643 + * @src: mac address of tt tvlv sender 2644 + * @dst: mac address of tt tvlv recipient 2645 + * @tvlv_value: tvlv buffer containing the tt data 2646 + * @tvlv_value_len: tvlv buffer length 2647 + * 2648 + * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS 2649 + * otherwise. 2650 + */ 2651 + static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv, 2652 + uint8_t *src, uint8_t *dst, 2653 + void *tvlv_value, 2654 + uint16_t tvlv_value_len) 2655 + { 2656 + struct batadv_tvlv_tt_data *tt_data; 2657 + uint16_t num_entries; 2658 + char tt_flag; 2659 + bool ret; 2660 + 2661 + if (tvlv_value_len < sizeof(*tt_data)) 2662 + return NET_RX_SUCCESS; 2663 + 2664 + tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 2665 + tvlv_value_len -= sizeof(*tt_data); 2666 + 2667 + num_entries = tvlv_value_len / batadv_tt_len(1); 2668 + 2669 + switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) { 2670 + case BATADV_TT_REQUEST: 2671 + batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX); 2672 + 2673 + /* If this node cannot provide a TT response the tt_request is 2674 + * forwarded 2675 + */ 2676 + ret = batadv_send_tt_response(bat_priv, tt_data, src, dst); 2677 + if (!ret) { 2678 + if (tt_data->flags & BATADV_TT_FULL_TABLE) 2679 + tt_flag = 'F'; 2680 + else 2681 + tt_flag = '.'; 2682 + 2683 + batadv_dbg(BATADV_DBG_TT, bat_priv, 2684 + "Routing TT_REQUEST to %pM [%c]\n", 2685 + dst, tt_flag); 2686 + /* tvlv API will re-route the packet */ 2687 + return NET_RX_DROP; 2688 + } 2689 + break; 2690 + case BATADV_TT_RESPONSE: 2691 + batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX); 2692 + 2693 + if (batadv_is_my_mac(bat_priv, dst)) { 2694 + batadv_handle_tt_response(bat_priv, tt_data, 2695 + src, num_entries); 2696 + return NET_RX_SUCCESS; 2697 + } 2698 + 2699 + if (tt_data->flags & BATADV_TT_FULL_TABLE) 2700 + tt_flag = 'F'; 2701 + else 2702 + tt_flag = '.'; 2703 + 2704 + batadv_dbg(BATADV_DBG_TT, bat_priv, 2705 + "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag); 2706 + 2707 + /* tvlv API will re-route the packet */ 2708 + return NET_RX_DROP; 2709 + } 2710 + 2711 + return NET_RX_SUCCESS; 2712 + } 2713 + 2714 + /** 2715 + * batadv_roam_tvlv_unicast_handler_v1 - process incoming tt roam tvlv container 2716 + * @bat_priv: the bat priv with all the soft interface information 2717 + * @src: mac address of tt tvlv sender 2718 + * @dst: mac address of tt tvlv recipient 2719 + * @tvlv_value: tvlv buffer containing the tt data 2720 + * @tvlv_value_len: tvlv buffer length 2721 + * 2722 + * Returns NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS 2723 + * otherwise. 2724 + */ 2725 + static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv, 2726 + uint8_t *src, uint8_t *dst, 2727 + void *tvlv_value, 2728 + uint16_t tvlv_value_len) 2729 + { 2730 + struct batadv_tvlv_roam_adv *roaming_adv; 2731 + struct batadv_orig_node *orig_node = NULL; 2732 + 2733 + /* If this node is not the intended recipient of the 2734 + * roaming advertisement the packet is forwarded 2735 + * (the tvlv API will re-route the packet). 2736 + */ 2737 + if (!batadv_is_my_mac(bat_priv, dst)) 2738 + return NET_RX_DROP; 2739 + 2740 + /* check if it is a backbone gateway. we don't accept 2741 + * roaming advertisement from it, as it has the same 2742 + * entries as we have. 2743 + */ 2744 + if (batadv_bla_is_backbone_gw_orig(bat_priv, src)) 2745 + goto out; 2746 + 2747 + if (tvlv_value_len < sizeof(*roaming_adv)) 2748 + goto out; 2749 + 2750 + orig_node = batadv_orig_hash_find(bat_priv, src); 2751 + if (!orig_node) 2752 + goto out; 2753 + 2754 + batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); 2755 + roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value; 2756 + 2757 + batadv_dbg(BATADV_DBG_TT, bat_priv, 2758 + "Received ROAMING_ADV from %pM (client %pM)\n", 2759 + src, roaming_adv->client); 2760 + 2761 + batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client, 2762 + BATADV_TT_CLIENT_ROAM, 2763 + atomic_read(&orig_node->last_ttvn) + 1); 2764 + 2765 + out: 2766 + if (orig_node) 2767 + batadv_orig_node_free_ref(orig_node); 2768 + return NET_RX_SUCCESS; 2769 + } 2770 + 2771 + /** 2772 + * batadv_tt_init - initialise the translation table internals 2773 + * @bat_priv: the bat priv with all the soft interface information 2774 + * 2775 + * Return 0 on success or negative error number in case of failure. 2776 + */ 2777 + int batadv_tt_init(struct batadv_priv *bat_priv) 2778 + { 2779 + int ret; 2780 + 2781 + ret = batadv_tt_local_init(bat_priv); 2782 + if (ret < 0) 2783 + return ret; 2784 + 2785 + ret = batadv_tt_global_init(bat_priv); 2786 + if (ret < 0) 2787 + return ret; 2788 + 2789 + batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1, 2790 + batadv_tt_tvlv_unicast_handler_v1, 2791 + BATADV_TVLV_TT, 1, BATADV_NO_FLAGS); 2792 + 2793 + batadv_tvlv_handler_register(bat_priv, NULL, 2794 + batadv_roam_tvlv_unicast_handler_v1, 2795 + BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS); 2796 + 2797 + INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); 2798 + queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, 2799 + msecs_to_jiffies(BATADV_TT_WORK_PERIOD)); 2800 + 2801 + return 1; 2551 2802 }
+1 -12
net/batman-adv/translation-table.h
··· 20 20 #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ 21 21 #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ 22 22 23 - int batadv_tt_len(int changes_num); 24 23 int batadv_tt_init(struct batadv_priv *bat_priv); 25 24 void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 26 25 int ifindex); ··· 42 43 const uint8_t *src, 43 44 const uint8_t *addr); 44 45 void batadv_tt_free(struct batadv_priv *bat_priv); 45 - bool batadv_send_tt_response(struct batadv_priv *bat_priv, 46 - struct batadv_tt_query_packet *tt_request); 47 46 bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); 48 - void batadv_handle_tt_response(struct batadv_priv *bat_priv, 49 - struct batadv_tt_query_packet *tt_response); 50 47 bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 51 48 uint8_t *dst); 52 - void batadv_tt_update_orig(struct batadv_priv *bat_priv, 53 - struct batadv_orig_node *orig_node, 54 - const unsigned char *tt_buff, uint8_t tt_num_changes, 55 - uint8_t ttvn, uint16_t tt_crc); 56 - int batadv_tt_append_diff(struct batadv_priv *bat_priv, 57 - unsigned char **packet_buff, int *packet_buff_len, 58 - int packet_min_len); 49 + void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv); 59 50 bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 60 51 uint8_t *addr); 61 52 bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+91 -87
net/batman-adv/types.h
··· 99 99 * @last_seen: time when last packet from this node was received 100 100 * @bcast_seqno_reset: time when the broadcast seqno window was reset 101 101 * @batman_seqno_reset: time when the batman seqno window was reset 102 - * @gw_flags: flags related to gateway class 103 - * @flags: for now only VIS_SERVER flag 102 + * @capabilities: announced capabilities of this originator 104 103 * @last_ttvn: last seen translation table version number 105 104 * @tt_crc: CRC of the translation table 106 105 * @tt_buff: last tt changeset this node received from the orig node ··· 146 147 unsigned long last_seen; 147 148 unsigned long bcast_seqno_reset; 148 149 unsigned long batman_seqno_reset; 149 - uint8_t gw_flags; 150 - uint8_t flags; 150 + uint8_t capabilities; 151 151 atomic_t last_ttvn; 152 - uint16_t tt_crc; 152 + uint32_t tt_crc; 153 153 unsigned char *tt_buff; 154 154 int16_t tt_buff_len; 155 155 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ ··· 184 186 }; 185 187 186 188 /** 189 + * enum batadv_orig_capabilities - orig node capabilities 190 + * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled 191 + * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled 192 + */ 193 + enum batadv_orig_capabilities { 194 + BATADV_ORIG_CAPA_HAS_DAT = BIT(0), 195 + BATADV_ORIG_CAPA_HAS_NC = BIT(1), 196 + }; 197 + 198 + /** 187 199 * struct batadv_gw_node - structure for orig nodes announcing gw capabilities 188 200 * @list: list node for batadv_priv_gw::list 189 201 * @orig_node: pointer to corresponding orig node 202 + * @bandwidth_down: advertised uplink download bandwidth 203 + * @bandwidth_up: advertised uplink upload bandwidth 190 204 * @deleted: this struct is scheduled for deletion 191 205 * @refcount: number of contexts the object is used 192 206 * @rcu: struct used for freeing in an RCU-safe manner ··· 206 196 struct batadv_gw_node { 207 197 struct hlist_node list; 208 198 struct batadv_orig_node *orig_node; 199 + uint32_t bandwidth_down; 200 + uint32_t bandwidth_up; 209 201 unsigned long deleted; 210 202 atomic_t refcount; 211 203 struct rcu_head rcu; ··· 375 363 spinlock_t req_list_lock; /* protects req_list */ 376 364 spinlock_t roam_list_lock; /* protects roam_list */ 377 365 atomic_t local_entry_num; 378 - uint16_t local_crc; 366 + uint32_t local_crc; 379 367 unsigned char *last_changeset; 380 368 int16_t last_changeset_len; 381 369 /* protects last_changeset & last_changeset_len */ ··· 432 420 * @list: list of available gateway nodes 433 421 * @list_lock: lock protecting gw_list & curr_gw 434 422 * @curr_gw: pointer to currently selected gateway node 423 + * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) 424 + * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) 435 425 * @reselect: bool indicating a gateway re-selection is in progress 436 426 */ 437 427 struct batadv_priv_gw { 438 428 struct hlist_head list; 439 429 spinlock_t list_lock; /* protects gw_list & curr_gw */ 440 430 struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ 431 + atomic_t bandwidth_down; 432 + atomic_t bandwidth_up; 441 433 atomic_t reselect; 442 434 }; 443 435 444 436 /** 445 - * struct batadv_priv_vis - per mesh interface vis data 446 - * @send_list: list of batadv_vis_info packets to sent 447 - * @hash: hash table containing vis data from other nodes in the network 448 - * @hash_lock: lock protecting the hash table 449 - * @list_lock: lock protecting my_info::recv_list 450 - * @work: work queue callback item for vis packet sending 451 - * @my_info: holds this node's vis data sent on a regular basis 437 + * struct batadv_priv_tvlv - per mesh interface tvlv data 438 + * @container_list: list of registered tvlv containers to be sent with each OGM 439 + * @handler_list: list of the various tvlv content handlers 440 + * @container_list_lock: protects tvlv container list access 441 + * @handler_list_lock: protects handler list access 452 442 */ 453 - struct batadv_priv_vis { 454 - struct list_head send_list; 455 - struct batadv_hashtable *hash; 456 - spinlock_t hash_lock; /* protects hash */ 457 - spinlock_t list_lock; /* protects my_info::recv_list */ 458 - struct delayed_work work; 459 - struct batadv_vis_info *my_info; 443 + struct batadv_priv_tvlv { 444 + struct hlist_head container_list; 445 + struct hlist_head handler_list; 446 + spinlock_t container_list_lock; /* protects container_list */ 447 + spinlock_t handler_list_lock; /* protects handler_list */ 460 448 }; 461 449 462 450 /** ··· 516 504 * enabled 517 505 * @distributed_arp_table: bool indicating whether distributed ARP table is 518 506 * enabled 519 - * @vis_mode: vis operation: client or server (see batadv_vis_packettype) 520 507 * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) 521 508 * @gw_sel_class: gateway selection class (applies if gw_mode client) 522 - * @gw_bandwidth: gateway announced bandwidth (applies if gw_mode server) 523 509 * @orig_interval: OGM broadcast interval in milliseconds 524 510 * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop 525 511 * @log_level: configured log level (see batadv_dbg_level) ··· 541 531 * @debug_log: holding debug logging relevant data 542 532 * @gw: gateway data 543 533 * @tt: translation table data 544 - * @vis: vis data 534 + * @tvlv: type-version-length-value data 545 535 * @dat: distributed arp table data 546 536 * @network_coding: bool indicating whether network coding is enabled 547 537 * @batadv_priv_nc: network coding data ··· 561 551 #ifdef CONFIG_BATMAN_ADV_DAT 562 552 atomic_t distributed_arp_table; 563 553 #endif 564 - atomic_t vis_mode; 565 554 atomic_t gw_mode; 566 555 atomic_t gw_sel_class; 567 - atomic_t gw_bandwidth; 568 556 atomic_t orig_interval; 569 557 atomic_t hop_penalty; 570 558 #ifdef CONFIG_BATMAN_ADV_DEBUG ··· 591 583 #endif 592 584 struct batadv_priv_gw gw; 593 585 struct batadv_priv_tt tt; 594 - struct batadv_priv_vis vis; 586 + struct batadv_priv_tvlv tvlv; 595 587 #ifdef CONFIG_BATMAN_ADV_DAT 596 588 struct batadv_priv_dat dat; 597 589 #endif ··· 748 740 */ 749 741 struct batadv_tt_change_node { 750 742 struct list_head list; 751 - struct batadv_tt_change change; 743 + struct batadv_tvlv_tt_change change; 752 744 }; 753 745 754 746 /** ··· 886 878 }; 887 879 888 880 /** 889 - * struct batadv_vis_info - local data for vis information 890 - * @first_seen: timestamp used for purging stale vis info entries 891 - * @recv_list: List of server-neighbors we have received this packet from. This 892 - * packet should not be re-forward to them again. List elements are struct 893 - * batadv_vis_recvlist_node 894 - * @send_list: list of packets to be forwarded 895 - * @refcount: number of contexts the object is used 896 - * @hash_entry: hlist node for batadv_priv_vis::hash 897 - * @bat_priv: pointer to soft_iface this orig node belongs to 898 - * @skb_packet: contains the vis packet 899 - */ 900 - struct batadv_vis_info { 901 - unsigned long first_seen; 902 - struct list_head recv_list; 903 - struct list_head send_list; 904 - struct kref refcount; 905 - struct hlist_node hash_entry; 906 - struct batadv_priv *bat_priv; 907 - struct sk_buff *skb_packet; 908 - } __packed; 909 - 910 - /** 911 - * struct batadv_vis_info_entry - contains link information for vis 912 - * @src: source MAC of the link, all zero for local TT entry 913 - * @dst: destination MAC of the link, client mac address for local TT entry 914 - * @quality: transmission quality of the link, or 0 for local TT entry 915 - */ 916 - struct batadv_vis_info_entry { 917 - uint8_t src[ETH_ALEN]; 918 - uint8_t dest[ETH_ALEN]; 919 - uint8_t quality; 920 - } __packed; 921 - 922 - /** 923 - * struct batadv_vis_recvlist_node - list entry for batadv_vis_info::recv_list 924 - * @list: list node for batadv_vis_info::recv_list 925 - * @mac: MAC address of the originator from where the vis_info was received 926 - */ 927 - struct batadv_vis_recvlist_node { 928 - struct list_head list; 929 - uint8_t mac[ETH_ALEN]; 930 - }; 931 - 932 - /** 933 - * struct batadv_vis_if_list_entry - auxiliary data for vis data generation 934 - * @addr: MAC address of the interface 935 - * @primary: true if this interface is the primary interface 936 - * @list: list node the interface list 937 - * 938 - * While scanning for vis-entries of a particular vis-originator 939 - * this list collects its interfaces to create a subgraph/cluster 940 - * out of them later 941 - */ 942 - struct batadv_vis_if_list_entry { 943 - uint8_t addr[ETH_ALEN]; 944 - bool primary; 945 - struct hlist_node list; 946 - }; 947 - 948 - /** 949 881 * struct batadv_algo_ops - mesh algorithm callbacks 950 882 * @list: list node for the batadv_algo_list 951 883 * @name: name of the algorithm ··· 938 990 struct batadv_dat_candidate { 939 991 int type; 940 992 struct batadv_orig_node *orig_node; 993 + }; 994 + 995 + /** 996 + * struct batadv_tvlv_container - container for tvlv appended to OGMs 997 + * @list: hlist node for batadv_priv_tvlv::container_list 998 + * @tvlv_hdr: tvlv header information needed to construct the tvlv 999 + * @value_len: length of the buffer following this struct which contains 1000 + * the actual tvlv payload 1001 + * @refcount: number of contexts the object is used 1002 + */ 1003 + struct batadv_tvlv_container { 1004 + struct hlist_node list; 1005 + struct batadv_tvlv_hdr tvlv_hdr; 1006 + atomic_t refcount; 1007 + }; 1008 + 1009 + /** 1010 + * struct batadv_tvlv_handler - handler for specific tvlv type and version 1011 + * @list: hlist node for batadv_priv_tvlv::handler_list 1012 + * @ogm_handler: handler callback which is given the tvlv payload to process on 1013 + * incoming OGM packets 1014 + * @unicast_handler: handler callback which is given the tvlv payload to process 1015 + * on incoming unicast tvlv packets 1016 + * @type: tvlv type this handler feels responsible for 1017 + * @version: tvlv version this handler feels responsible for 1018 + * @flags: tvlv handler flags 1019 + * @refcount: number of contexts the object is used 1020 + * @rcu: struct used for freeing in an RCU-safe manner 1021 + */ 1022 + struct batadv_tvlv_handler { 1023 + struct hlist_node list; 1024 + void (*ogm_handler)(struct batadv_priv *bat_priv, 1025 + struct batadv_orig_node *orig, 1026 + uint8_t flags, 1027 + void *tvlv_value, uint16_t tvlv_value_len); 1028 + int (*unicast_handler)(struct batadv_priv *bat_priv, 1029 + uint8_t *src, uint8_t *dst, 1030 + void *tvlv_value, uint16_t tvlv_value_len); 1031 + uint8_t type; 1032 + uint8_t version; 1033 + uint8_t flags; 1034 + atomic_t refcount; 1035 + struct rcu_head rcu; 1036 + }; 1037 + 1038 + /** 1039 + * enum batadv_tvlv_handler_flags - tvlv handler flags definitions 1040 + * @BATADV_TVLV_HANDLER_OGM_CIFNOTFND: tvlv ogm processing function will call 1041 + * this handler even if its type was not found (with no data) 1042 + * @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the API marks 1043 + * a handler as being called, so it won't be called if the 1044 + * BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set 1045 + */ 1046 + enum batadv_tvlv_handler_flags { 1047 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1), 1048 + BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2), 941 1049 }; 942 1050 943 1051 #endif /* _NET_BATMAN_ADV_TYPES_H_ */
-938
net/batman-adv/vis.c
··· 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 - }
-36
net/batman-adv/vis.h
··· 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_ */