mesh.c revision f698d856f65c3fea091cc303a135967965c5b880
12e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo/* 22e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Copyright (c) 2008 open80211s Ltd. 32e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Authors: Luis Carlos Cobo <luisca@cozybit.com> 42e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Javier Cardona <javier@cozybit.com> 52e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 62e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * This program is free software; you can redistribute it and/or modify 72e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * it under the terms of the GNU General Public License version 2 as 82e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * published by the Free Software Foundation. 92e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 102e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1151ceddade0fb1e15f080b2555f3b3e1d68c6707eLuis Carlos Cobo#include <asm/unaligned.h> 122e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo#include "ieee80211_i.h" 132e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo#include "mesh.h" 142e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 15247367016305637fb981db020679520e354c80c4John W. Linville#define PP_OFFSET 1 /* Path Selection Protocol */ 16247367016305637fb981db020679520e354c80c4John W. Linville#define PM_OFFSET 5 /* Path Selection Metric */ 17247367016305637fb981db020679520e354c80c4John W. Linville#define CC_OFFSET 9 /* Congestion Control Mode */ 18247367016305637fb981db020679520e354c80c4John W. Linville#define CAPAB_OFFSET 17 192e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo#define ACCEPT_PLINKS 0x80 202e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 212e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Coboint mesh_allocated; 222e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobostatic struct kmem_cache *rm_cache; 232e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 242e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobovoid ieee80211s_init(void) 252e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 262e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo mesh_pathtbl_init(); 272e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo mesh_allocated = 1; 282e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), 292e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 0, 0, NULL); 302e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 312e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 322e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobovoid ieee80211s_stop(void) 332e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 342e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo mesh_pathtbl_unregister(); 352e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kmem_cache_destroy(rm_cache); 362e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 372e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 382e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo/** 392e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * mesh_matches_local - check if the config of a mesh point matches ours 402e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 412e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * @ie: information elements of a management frame from the mesh peer 42f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene * @sdata: local mesh subif 432e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 442e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * This function checks if the mesh configuration of a mesh point matches the 452e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * local mesh configuration, i.e. if both nodes belong to the same mesh network. 462e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 47f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greenebool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) 482e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 492e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct ieee80211_if_sta *sta = &sdata->u.sta; 502e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 512e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* 522e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * As support for each feature is added, check for matching 532e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - On mesh config capabilities 542e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - Power Save Support En 552e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - Sync support enabled 562e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - Sync support active 572e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - Sync support required from peer 582e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - MDA enabled 592e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * - Power management control on fc 602e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 613b091cd4941912081730ffa17948da6d148c822dLuis Carlos Cobo if (sta->mesh_id_len == ie->mesh_id_len && 623b091cd4941912081730ffa17948da6d148c822dLuis Carlos Cobo memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && 633b091cd4941912081730ffa17948da6d148c822dLuis Carlos Cobo memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && 643b091cd4941912081730ffa17948da6d148c822dLuis Carlos Cobo memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && 653b091cd4941912081730ffa17948da6d148c822dLuis Carlos Cobo memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) 662e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return true; 672e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 682e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return false; 692e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 702e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 712e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo/** 722e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links 732e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 742e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * @ie: information elements of a management frame from the mesh peer 752e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 76f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greenebool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) 772e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 782e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; 792e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 802e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 812e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo/** 822e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * mesh_accept_plinks_update: update accepting_plink in local mesh beacons 832e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 84d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg * @sdata: mesh interface in which mesh beacons are going to be updated 852e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 86d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Bergvoid mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) 872e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 882e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo bool free_plinks; 892e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 902e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, 912e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * the mesh interface might be able to establish plinks with peers that 92b4e08ea141e6d663dec31b31d6289baeaaa2a3a2Luis Carlos Cobo * are already on the table but are not on PLINK_ESTAB state. However, 93b4e08ea141e6d663dec31b31d6289baeaaa2a3a2Luis Carlos Cobo * in general the mesh interface is not accepting peer link requests 94b4e08ea141e6d663dec31b31d6289baeaaa2a3a2Luis Carlos Cobo * from new peers, and that must be reflected in the beacon 952e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 962e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo free_plinks = mesh_plink_availables(sdata); 972e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 982e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (free_plinks != sdata->u.sta.accepting_plinks) 992e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo ieee80211_sta_timer((unsigned long) sdata); 1002e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 1012e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1022e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobovoid mesh_ids_set_default(struct ieee80211_if_sta *sta) 1032e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 1042e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; 1052e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1062e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(sta->mesh_pp_id, def_id, 4); 1072e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(sta->mesh_pm_id, def_id, 4); 1082e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(sta->mesh_cc_id, def_id, 4); 1092e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 1102e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 111f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greeneint mesh_rmc_init(struct ieee80211_sub_if_data *sdata) 1122e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 1132e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int i; 1142e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1152e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); 1162e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!sdata->u.sta.rmc) 1172e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return -ENOMEM; 1182e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; 1192e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i < RMC_BUCKETS; i++) 1202e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); 1212e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return 0; 1222e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 1232e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 124f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greenevoid mesh_rmc_free(struct ieee80211_sub_if_data *sdata) 1252e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 1262e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct mesh_rmc *rmc = sdata->u.sta.rmc; 1272e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct rmc_entry *p, *n; 1282e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int i; 1292e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1302e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!sdata->u.sta.rmc) 1312e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return; 1322e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1332e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i < RMC_BUCKETS; i++) 1342e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { 1352e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo list_del(&p->list); 1362e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kmem_cache_free(rm_cache, p); 1372e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 1382e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1392e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kfree(rmc); 1402e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sdata->u.sta.rmc = NULL; 1412e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 1422e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1432e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo/** 1442e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * mesh_rmc_check - Check frame in recent multicast cache and add if absent. 1452e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 1462e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * @sa: source address 1472e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * @mesh_hdr: mesh_header 1482e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 1492e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Returns: 0 if the frame is not in the cache, nonzero otherwise. 1502e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * 1512e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Checks using the source address and the mesh sequence number if we have 1522e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * received this frame lately. If the frame is not in the cache, it is added to 1532e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * it. 1542e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 1552e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Coboint mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, 156f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene struct ieee80211_sub_if_data *sdata) 1572e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 1582e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct mesh_rmc *rmc = sdata->u.sta.rmc; 1592e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo u32 seqnum = 0; 1602e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int entries = 0; 1612e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo u8 idx; 1622e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct rmc_entry *p, *n; 1632e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1642e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Don't care about endianness since only match matters */ 16551ceddade0fb1e15f080b2555f3b3e1d68c6707eLuis Carlos Cobo memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); 16651ceddade0fb1e15f080b2555f3b3e1d68c6707eLuis Carlos Cobo idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; 1672e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { 1682e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo ++entries; 1692e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (time_after(jiffies, p->exp_time) || 1702e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo (entries == RMC_QUEUE_MAX_LEN)) { 1712e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo list_del(&p->list); 1722e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kmem_cache_free(rm_cache, p); 1732e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo --entries; 1742e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } else if ((seqnum == p->seqnum) 1752e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo && (memcmp(sa, p->sa, ETH_ALEN) == 0)) 1762e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return -1; 1772e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 1782e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1792e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); 1802e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!p) { 1812e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo printk(KERN_DEBUG "o11s: could not allocate RMC entry\n"); 1822e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return 0; 1832e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 1842e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo p->seqnum = seqnum; 1852e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo p->exp_time = jiffies + RMC_TIMEOUT; 1862e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(p->sa, sa, ETH_ALEN); 1872e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo list_add(&p->list, &rmc->bucket[idx].list); 1882e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return 0; 1892e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 1902e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 191f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greenevoid mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) 1922e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 193f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene struct ieee80211_local *local = sdata->local; 1942e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct ieee80211_supported_band *sband; 1952e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo u8 *pos; 1962e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int len, i, rate; 1972e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 1982e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 1992e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo len = sband->n_bitrates; 2002e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (len > 8) 2012e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo len = 8; 2022e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos = skb_put(skb, len + 2); 2032e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = WLAN_EID_SUPP_RATES; 2042e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = len; 2052e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i < len; i++) { 2062e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo rate = sband->bitrates[i].bitrate; 2072e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = (u8) (rate / 5); 2082e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 2092e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2102e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (sband->n_bitrates > len) { 2112e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos = skb_put(skb, sband->n_bitrates - len + 2); 2122e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = WLAN_EID_EXT_SUPP_RATES; 2132e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = sband->n_bitrates - len; 2142e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = len; i < sband->n_bitrates; i++) { 2152e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo rate = sband->bitrates[i].bitrate; 2162e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = (u8) (rate / 5); 2172e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 2182e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 2192e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2202e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); 2212e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = WLAN_EID_MESH_ID; 2222e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = sdata->u.sta.mesh_id_len; 2232e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (sdata->u.sta.mesh_id_len) 2242e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); 2252e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2262e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos = skb_put(skb, 21); 2272e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = WLAN_EID_MESH_CONFIG; 2282e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = MESH_CFG_LEN; 2292e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Version */ 2302e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = 1; 2312e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2322e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Active path selection protocol ID */ 2332e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(pos, sdata->u.sta.mesh_pp_id, 4); 2342e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos += 4; 2352e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2362e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Active path selection metric ID */ 2372e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(pos, sdata->u.sta.mesh_pm_id, 4); 2382e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos += 4; 2392e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2402e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Congestion control mode identifier */ 2412e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memcpy(pos, sdata->u.sta.mesh_cc_id, 4); 2422e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos += 4; 2432e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2442e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Channel precedence: 2452e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo * Not running simple channel unification protocol 2462e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo */ 2472e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo memset(pos, 0x00, 4); 2482e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo pos += 4; 2492e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2502e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Mesh capability */ 2512e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); 2522e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; 2532e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo *pos++ = 0x00; 2542e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2552e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return; 2562e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 2572e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 258f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greeneu32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) 2592e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 2602e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo /* Use last four bytes of hw addr and interface index as hash index */ 261f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) 2622e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo & tbl->hash_mask; 2632e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 2642e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2652e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobou8 mesh_id_hash(u8 *mesh_id, int mesh_id_len) 2662e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 2672e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!mesh_id_len) 2682e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return 1; 2692e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo else if (mesh_id_len == 1) 2702e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return (u8) mesh_id[0]; 2712e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo else 2722e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return (u8) (mesh_id[0] + 2 * mesh_id[1]); 2732e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 2742e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2752e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobostruct mesh_table *mesh_table_alloc(int size_order) 2762e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 2772e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int i; 2782e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct mesh_table *newtbl; 2792e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2802e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); 2812e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!newtbl) 2822e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return NULL; 2832e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2842e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * 2852e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo (1 << size_order), GFP_KERNEL); 2862e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2872e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!newtbl->hash_buckets) { 2882e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kfree(newtbl); 2892e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return NULL; 2902e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 2912e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 2922e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * 2932e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo (1 << size_order), GFP_KERNEL); 2942e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (!newtbl->hashwlock) { 2952e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kfree(newtbl->hash_buckets); 2962e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo kfree(newtbl); 2972e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return NULL; 2982e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 2992e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3002e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->size_order = size_order; 3012e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->hash_mask = (1 << size_order) - 1; 3022e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo atomic_set(&newtbl->entries, 0); 3032e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo get_random_bytes(&newtbl->hash_rnd, 3042e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo sizeof(newtbl->hash_rnd)); 3052e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i <= newtbl->hash_mask; i++) 3062e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo spin_lock_init(&newtbl->hashwlock[i]); 3072e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3082e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo return newtbl; 3092e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 3102e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 311bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanovstatic void __mesh_table_free(struct mesh_table *tbl) 312bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov{ 313bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov kfree(tbl->hash_buckets); 314bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov kfree(tbl->hashwlock); 315bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov kfree(tbl); 316bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov} 317bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov 3182e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobovoid mesh_table_free(struct mesh_table *tbl, bool free_leafs) 3192e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 3202e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct hlist_head *mesh_hash; 3212e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct hlist_node *p, *q; 3222e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int i; 3232e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3242e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo mesh_hash = tbl->hash_buckets; 3252e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i <= tbl->hash_mask; i++) { 3262e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo spin_lock(&tbl->hashwlock[i]); 3272e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo hlist_for_each_safe(p, q, &mesh_hash[i]) { 3282e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo tbl->free_node(p, free_leafs); 3292e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo atomic_dec(&tbl->entries); 3302e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 3312e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo spin_unlock(&tbl->hashwlock[i]); 3322e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo } 333bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov __mesh_table_free(tbl); 3342e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 3352e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3362e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobostatic void ieee80211_mesh_path_timer(unsigned long data) 3372e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 3382e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct ieee80211_sub_if_data *sdata = 3392e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo (struct ieee80211_sub_if_data *) data; 3402e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct ieee80211_if_sta *ifsta = &sdata->u.sta; 3412e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct ieee80211_local *local = wdev_priv(&sdata->wdev); 3422e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3432e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo queue_work(local->hw.workqueue, &ifsta->work); 3442e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 3452e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3462e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobostruct mesh_table *mesh_table_grow(struct mesh_table *tbl) 3472e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo{ 3482e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct mesh_table *newtbl; 3492e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo struct hlist_head *oldhash; 3504caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov struct hlist_node *p, *q; 3512e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo int i; 3522e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3532e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo if (atomic_read(&tbl->entries) 354a3538b19a6d226f9d3d9b18865468370009dec55Pavel Emelyanov < tbl->mean_chain_len * (tbl->hash_mask + 1)) 3552e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo goto endgrow; 3562e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3572e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl = mesh_table_alloc(tbl->size_order + 1); 358a3538b19a6d226f9d3d9b18865468370009dec55Pavel Emelyanov if (!newtbl) 3592e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo goto endgrow; 3602e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3612e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->free_node = tbl->free_node; 3622e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->mean_chain_len = tbl->mean_chain_len; 3632e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo newtbl->copy_node = tbl->copy_node; 3642e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); 3652e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 3662e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo oldhash = tbl->hash_buckets; 3672e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo for (i = 0; i <= tbl->hash_mask; i++) 3682e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo hlist_for_each(p, &oldhash[i]) 3694caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov if (tbl->copy_node(p, newtbl) < 0) 3704caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov goto errcopy; 3712e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo 372a3538b19a6d226f9d3d9b18865468370009dec55Pavel Emelyanov return newtbl; 3734caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov 3744caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanoverrcopy: 3754caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov for (i = 0; i <= newtbl->hash_mask; i++) { 3764caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) 3774caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov tbl->free_node(p, 0); 3784caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov } 379bd9b448f4c0a514559bdae4ca18ca3e8cd999c6dPavel Emelyanov __mesh_table_free(tbl); 380a3538b19a6d226f9d3d9b18865468370009dec55Pavel Emelyanovendgrow: 3814caf86c6928cfaca270327bc944f901c2e2a8f50Pavel Emelyanov return NULL; 3822e3c8736820bf72a8ad10721c7e31d36d4fa7790Luis Carlos Cobo} 383902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 384902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg/** 385902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg * ieee80211_new_mesh_header - create a new mesh header 386902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg * @meshhdr: uninitialized mesh header 387902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg * @sdata: mesh interface to be used 388902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg * 389902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg * Return the header length. 390902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg */ 391902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Bergint ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 392902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg struct ieee80211_sub_if_data *sdata) 393902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg{ 394902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg meshhdr->flags = 0; 395902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; 39651ceddade0fb1e15f080b2555f3b3e1d68c6707eLuis Carlos Cobo put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); 39751ceddade0fb1e15f080b2555f3b3e1d68c6707eLuis Carlos Cobo sdata->u.sta.mesh_seqnum++; 398902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 399ef269254772a0d2253c85cafe160e3f6528eb292Luis Carlos Cobo return 6; 400902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg} 401902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 402902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Bergvoid ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) 403902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg{ 404902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg struct ieee80211_if_sta *ifsta = &sdata->u.sta; 405902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 406902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; 407902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; 408902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; 409902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; 410902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshTTL = MESH_TTL; 411902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.auto_open_plinks = true; 412902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshMaxPeerLinks = 413902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_MAX_ESTAB_PLINKS; 414902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = 415902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_PATH_TIMEOUT; 416902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = 417902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_PREQ_MIN_INT; 418902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = 419902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_DIAM_TRAVERSAL_TIME; 420902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = 421902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_MAX_PREQ_RETRIES; 422902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.path_refresh_time = 423902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_PATH_REFRESH_TIME; 424902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->mshcfg.min_discovery_timeout = 425902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg MESH_MIN_DISCOVERY_TIMEOUT; 426902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->accepting_plinks = true; 427902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->preq_id = 0; 428902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->dsn = 0; 429902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg atomic_set(&ifsta->mpaths, 0); 430f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene mesh_rmc_init(sdata); 431902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ifsta->last_preq = jiffies; 432902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg /* Allocate all mesh structures when creating the first mesh interface. */ 433902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg if (!mesh_allocated) 434902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ieee80211s_init(); 435902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg mesh_ids_set_default(ifsta); 436902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg setup_timer(&ifsta->mesh_path_timer, 437902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg ieee80211_mesh_path_timer, 438902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg (unsigned long) sdata); 439902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg INIT_LIST_HEAD(&ifsta->preq_queue.list); 440902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg spin_lock_init(&ifsta->mesh_preq_queue_lock); 441902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg} 442