aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-19 05:55:19 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-19 11:08:53 -0500
commit9bc383de37090ba7ca3ff32a12c9d809dc5867f0 (patch)
tree2b502b918f585427b45357e5a9a781ea9f06c263 /net/mac80211
parent5be83de54c16944dea9c16c6a5a53c1fa75ed304 (diff)
cfg80211: introduce capability for 4addr mode
It's very likely that not many devices will support four-address mode in station or AP mode so introduce capability bits for both modes, set them in mac80211 and check them when userspace tries to use the mode. Also, keep track of 4addr in cfg80211 (wireless_dev) and not in mac80211 any more. mac80211 can also be improved for the VLAN case by not looking at the 4addr flag but maintaining the station pointer for it correctly. However, keep track of use_4addr for station mode in mac80211 to avoid all the derefs. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/iface.c12
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/rx.c14
-rw-r--r--net/mac80211/tx.c7
6 files changed, 33 insertions, 29 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7d591816ed10..c484a882140e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -42,15 +42,6 @@ static bool nl80211_params_check(enum nl80211_iftype type,
42 if (!nl80211_type_check(type)) 42 if (!nl80211_type_check(type))
43 return false; 43 return false;
44 44
45 if (params->use_4addr > 0) {
46 switch(type) {
47 case NL80211_IFTYPE_AP_VLAN:
48 case NL80211_IFTYPE_STATION:
49 break;
50 default:
51 return false;
52 }
53 }
54 return true; 45 return true;
55} 46}
56 47
@@ -107,12 +98,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
107 params->mesh_id_len, 98 params->mesh_id_len,
108 params->mesh_id); 99 params->mesh_id);
109 100
110 if (params->use_4addr >= 0)
111 sdata->use_4addr = !!params->use_4addr;
112
113 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) 101 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
114 return 0; 102 return 0;
115 103
104 if (type == NL80211_IFTYPE_AP_VLAN &&
105 params && params->use_4addr == 0)
106 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
107 else if (type == NL80211_IFTYPE_STATION &&
108 params && params->use_4addr >= 0)
109 sdata->u.mgd.use_4addr = params->use_4addr;
110
116 sdata->u.mntr_flags = *flags; 111 sdata->u.mntr_flags = *flags;
117 return 0; 112 return 0;
118} 113}
@@ -827,7 +822,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
827 return -EINVAL; 822 return -EINVAL;
828 } 823 }
829 824
830 if (vlansdata->use_4addr) { 825 if (params->vlan->ieee80211_ptr->use_4addr) {
831 if (vlansdata->u.vlan.sta) 826 if (vlansdata->u.vlan.sta)
832 return -EBUSY; 827 return -EBUSY;
833 828
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 87d27f450a05..f13d76c9b575 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -312,6 +312,8 @@ struct ieee80211_if_managed {
312 } mfp; /* management frame protection */ 312 } mfp; /* management frame protection */
313 313
314 int wmm_last_param_set; 314 int wmm_last_param_set;
315
316 u8 use_4addr;
315}; 317};
316 318
317enum ieee80211_ibss_request { 319enum ieee80211_ibss_request {
@@ -459,8 +461,6 @@ struct ieee80211_sub_if_data {
459 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ 461 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
460 int max_ratectrl_rateidx; /* max TX rateidx for rate control */ 462 int max_ratectrl_rateidx; /* max TX rateidx for rate control */
461 463
462 bool use_4addr; /* use 4-address frames */
463
464 union { 464 union {
465 struct ieee80211_if_ap ap; 465 struct ieee80211_if_ap ap;
466 struct ieee80211_if_wds wds; 466 struct ieee80211_if_wds wds;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1f02b0610e82..1bf12a26b45e 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -752,7 +752,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
752 ieee80211_mandatory_rates(sdata->local, 752 ieee80211_mandatory_rates(sdata->local,
753 sdata->local->hw.conf.channel->band); 753 sdata->local->hw.conf.channel->band);
754 sdata->drop_unencrypted = 0; 754 sdata->drop_unencrypted = 0;
755 sdata->use_4addr = 0; 755 if (type == NL80211_IFTYPE_STATION)
756 sdata->u.mgd.use_4addr = false;
756 757
757 return 0; 758 return 0;
758} 759}
@@ -810,6 +811,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
810 /* setup type-dependent data */ 811 /* setup type-dependent data */
811 ieee80211_setup_sdata(sdata, type); 812 ieee80211_setup_sdata(sdata, type);
812 813
814 if (params) {
815 ndev->ieee80211_ptr->use_4addr = params->use_4addr;
816 if (type == NL80211_IFTYPE_STATION)
817 sdata->u.mgd.use_4addr = params->use_4addr;
818 }
819
813 ret = register_netdevice(ndev); 820 ret = register_netdevice(ndev);
814 if (ret) 821 if (ret)
815 goto fail; 822 goto fail;
@@ -820,9 +827,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
820 params->mesh_id_len, 827 params->mesh_id_len,
821 params->mesh_id); 828 params->mesh_id);
822 829
823 if (params && params->use_4addr >= 0)
824 sdata->use_4addr = !!params->use_4addr;
825
826 mutex_lock(&local->iflist_mtx); 830 mutex_lock(&local->iflist_mtx);
827 list_add_tail_rcu(&sdata->list, &local->interfaces); 831 list_add_tail_rcu(&sdata->list, &local->interfaces);
828 mutex_unlock(&local->iflist_mtx); 832 mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8084b622e97e..dd8ec8d5e8b2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -328,7 +328,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
328 if (!wiphy) 328 if (!wiphy)
329 return NULL; 329 return NULL;
330 330
331 wiphy->flags |= WIPHY_FLAG_NETNS_OK; 331 wiphy->flags |= WIPHY_FLAG_NETNS_OK |
332 WIPHY_FLAG_4ADDR_AP |
333 WIPHY_FLAG_4ADDR_STATION;
332 wiphy->privid = mac80211_wiphy_privid; 334 wiphy->privid = mac80211_wiphy_privid;
333 335
334 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ 336 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 775365f856c9..96f13ad05d3c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1192,10 +1192,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1192 struct net_device *dev = sdata->dev; 1192 struct net_device *dev = sdata->dev;
1193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 1193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1194 1194
1195 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr && 1195 if (ieee80211_has_a4(hdr->frame_control) &&
1196 ieee80211_has_a4(hdr->frame_control)) 1196 sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
1197 return -1; 1197 return -1;
1198 if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1)) 1198
1199 if (is_multicast_ether_addr(hdr->addr1) &&
1200 ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) ||
1201 (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
1199 return -1; 1202 return -1;
1200 1203
1201 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); 1204 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
@@ -1245,7 +1248,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1245 if ((sdata->vif.type == NL80211_IFTYPE_AP || 1248 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
1246 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && 1249 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
1247 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && 1250 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
1248 (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) { 1251 (rx->flags & IEEE80211_RX_RA_MATCH) &&
1252 (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
1249 if (is_multicast_ether_addr(ehdr->h_dest)) { 1253 if (is_multicast_ether_addr(ehdr->h_dest)) {
1250 /* 1254 /*
1251 * send multicast frames both to higher layers in 1255 * send multicast frames both to higher layers in
@@ -2007,7 +2011,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
2007 2011
2008 switch (sdata->vif.type) { 2012 switch (sdata->vif.type) {
2009 case NL80211_IFTYPE_STATION: 2013 case NL80211_IFTYPE_STATION:
2010 if (!bssid && !sdata->use_4addr) 2014 if (!bssid && !sdata->u.mgd.use_4addr)
2011 return 0; 2015 return 0;
2012 if (!multicast && 2016 if (!multicast &&
2013 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { 2017 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b3c1faeb5927..5af2f40ea4db 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1051,7 +1051,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1051 1051
1052 hdr = (struct ieee80211_hdr *) skb->data; 1052 hdr = (struct ieee80211_hdr *) skb->data;
1053 1053
1054 if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr) 1054 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1055 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1055 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1056 if (!tx->sta) 1056 if (!tx->sta)
1057 tx->sta = sta_info_get(local, hdr->addr1); 1057 tx->sta = sta_info_get(local, hdr->addr1);
@@ -1632,8 +1632,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1632 switch (sdata->vif.type) { 1632 switch (sdata->vif.type) {
1633 case NL80211_IFTYPE_AP_VLAN: 1633 case NL80211_IFTYPE_AP_VLAN:
1634 rcu_read_lock(); 1634 rcu_read_lock();
1635 if (sdata->use_4addr) 1635 sta = rcu_dereference(sdata->u.vlan.sta);
1636 sta = rcu_dereference(sdata->u.vlan.sta);
1637 if (sta) { 1636 if (sta) {
1638 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1637 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1639 /* RA TA DA SA */ 1638 /* RA TA DA SA */
@@ -1727,7 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1727#endif 1726#endif
1728 case NL80211_IFTYPE_STATION: 1727 case NL80211_IFTYPE_STATION:
1729 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 1728 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1730 if (sdata->use_4addr && ethertype != ETH_P_PAE) { 1729 if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
1731 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1730 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1732 /* RA TA DA SA */ 1731 /* RA TA DA SA */
1733 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1732 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);