From: Mohammed Shafi Shajakhan <[email protected]>
*if any interface type is not advertised by the driver
via ieee80211_iface_combination make sure we will have it
as a single interface only. lets that we will not add
an incompatible interface if some other interface is
already present. we cannot add any other interface,
if the already present interface is an incompatible
interface. for example in ath9k we don't advertise ADHOC in
ieee80211_iface_combination structure in the driver,
so it can only exist as an single interface
*if the driver is not advertising interface combination just
return so that we don't break their multivif operation.
Signed-off-by: Mohammed Shafi Shajakhan <[email protected]>
---
net/wireless/util.c | 62 ++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index c64d30f..7712ac6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -932,22 +932,31 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
- enum nl80211_iftype iftype)
+ enum nl80211_iftype ntype)
{
struct wireless_dev *wdev_iter;
int num[NUM_NL80211_IFTYPES];
int total = 1;
int i, j;
+ enum nl80211_iftype iftype;
+ bool ntype_single = true;
+ bool found_iface_comb = false;
+ bool iface_comb_allowed[NUM_NL80211_IFTYPES];
ASSERT_RTNL();
/* Always allow software iftypes */
- if (rdev->wiphy.software_iftypes & BIT(iftype))
+ if (rdev->wiphy.software_iftypes & BIT(ntype))
+ return 0;
+
+ /* interface combination not advertised by the driver */
+ if (!rdev->wiphy.n_iface_combinations)
return 0;
memset(num, 0, sizeof(num));
+ memset(iface_comb_allowed, 0, sizeof(iface_comb_allowed));
- num[iftype] = 1;
+ num[ntype] = 1;
mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
@@ -967,6 +976,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
if (total == 1)
return 0;
+
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
const struct ieee80211_iface_combination *c;
struct ieee80211_iface_limit *limits;
@@ -981,24 +991,50 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
goto cont;
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
- if (rdev->wiphy.software_iftypes & BIT(iftype))
+
+ if (rdev->wiphy.software_iftypes & BIT(iftype)) {
+ iface_comb_allowed[iftype] = true;
continue;
+ }
+
for (j = 0; j < c->n_limits; j++) {
- if (!(limits[j].types & BIT(iftype)))
- continue;
- if (limits[j].max < num[iftype])
- goto cont;
- limits[j].max -= num[iftype];
+
+ if (limits[j].types & BIT(ntype))
+ ntype_single = false;
+
+ if (!num[iftype] ||
+ (limits[j].types & BIT(iftype)))
+ iface_comb_allowed[iftype] = true;
+
+ if (!found_iface_comb) {
+
+ if (!(limits[j].types & BIT(iftype)))
+ continue;
+ if (limits[j].max < num[iftype])
+ goto cont;
+ limits[j].max -= num[iftype];
+
+ }
}
}
- /* yay, it fits */
- kfree(limits);
- return 0;
+
+ found_iface_comb = true;
+
cont:
kfree(limits);
}
- return -EBUSY;
+ if (ntype_single)
+ return -EOPNOTSUPP;
+
+ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++)
+ if (!iface_comb_allowed[iftype])
+ return -EOPNOTSUPP;
+
+ if (found_iface_comb)
+ return 0;
+
+ return -EOPNOTSUPP;
}
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
--
1.7.0.4
Hi Johannes,
>
> No, initialization was incorrect -- this is better:
> http://p.sipsolutions.net/e5ab0f3e38f90d6d.txt
>
thanks a lot for the patch!
with the above patch ath9k seems be working fine with the single
incompatible adhoc interface.
but i was just experimenting with ath9k(similar to iwlwifi having
hw->wiphy->n_iface_combinations > 1) with this patch.
static const struct ieee80211_iface_limit a[] = {
{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION) },
};
static const struct ieee80211_iface_limit b[] = {
{ .max = 2, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
};
static const struct ieee80211_iface_combination if_comb[] = {
{.limits = a,
.n_limits = ARRAY_SIZE(a),
.max_interfaces = 2,
.num_different_channels = 1,
},
{.limits = b,
.n_limits = ARRAY_SIZE(b),
.max_interfaces = 2,
.num_different_channels = 1,
},
};
i could not add mesh interface if a managed interface is already there
and vice versa. if this is the expected behavior, then fine.
dmesg
iteration 1: cfg80211_can_change_interface all_iftypes 4 and used_iftypes 84
iteration 2: cfg80211_can_change_interface all_iftypes 80 and
used_iftypes 84
--
thanks,
shafi
Hi Johannes,
>>> No, initialization was incorrect -- this is better:
>>> http://p.sipsolutions.net/e5ab0f3e38f90d6d.txt
>>>
>>
>> thanks a lot for the patch!
>> with the above patch ath9k seems be working fine with the single
>> incompatible adhoc interface.
>
> Ok, cool.
>
>> but i was just experimenting with ath9k(similar to iwlwifi having
>> hw->wiphy->n_iface_combinations> 1) with this patch.
>>
>> static const struct ieee80211_iface_limit a[] = {
>> { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) },
>> };
>>
>> static const struct ieee80211_iface_limit b[] = {
>> { .max = 2, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
>> };
>>
>> static const struct ieee80211_iface_combination if_comb[] = {
>> {.limits = a,
>> .n_limits = ARRAY_SIZE(a),
>> .max_interfaces = 2,
>> .num_different_channels = 1,
>> },
>> {.limits = b,
>> .n_limits = ARRAY_SIZE(b),
>> .max_interfaces = 2,
>> .num_different_channels = 1,
>> },
>>
>> };
>>
>> i could not add mesh interface if a managed interface is already there
>> and vice versa. if this is the expected behavior, then fine.
>
> No, that's not expected! Another bug!
>
> We should write some unit tests for this code I guess :-)
>
>> iteration 1: cfg80211_can_change_interface all_iftypes 4 and used_iftypes 84
>> iteration 2: cfg80211_can_change_interface all_iftypes 80 and used_iftypes 84
>
> Curious. Why did it accept it then? Where did you place the printk?
not sure whether i missed something, but it did not work for the above
case. printk just inside the condition check of your patch.
if ((all_iftypes & used_iftypes) != used_iftypes) {
+ printk("\nshafi %s all_iftypes %x and
used_iftypes %x", __func__, all_iftypes, used_iftypes);
+ goto cont;
+ }
i think we need to take 'all_iftypes' for all the
'n_interface_combinations' and then finally compare it with used_iftypes.
>
> I'm handling Linus's problem right now, so it'll be a bit until I can
> look at this in more detail again.
oh ok, sure.
--
thanks,
shafi
Hi Mohammed,
> >> static const struct ieee80211_iface_limit a[] = {
> >> { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) },
> >> };
> >>
> >> static const struct ieee80211_iface_limit b[] = {
> >> { .max = 2, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
> >> };
> >>
> >> static const struct ieee80211_iface_combination if_comb[] = {
> >> {.limits = a,
> >> .n_limits = ARRAY_SIZE(a),
> >> .max_interfaces = 2,
> >> .num_different_channels = 1,
> >> },
> >> {.limits = b,
> >> .n_limits = ARRAY_SIZE(b),
> >> .max_interfaces = 2,
> >> .num_different_channels = 1,
> >> },
> >>
> >> };
> >>
> >> i could not add mesh interface if a managed interface is already there
> >> and vice versa. if this is the expected behavior, then fine.
> >
> > No, that's not expected! Another bug!
Actually, I'm sorry -- clearly I wasn't paying attention before -- it is
expected. The above means you can add two managed or two mesh interface,
but no combinations of them. Basically, the things in if_comb are XOR,
and the things inside each limit are AND.
johannes
On Mon, 2012-06-04 at 21:46 +0530, Mohammed Shafi Shajakhan wrote:
> >> i am able to create an IBSS interface even if a STA interface is up and
> >> running in ath9k(removing the driver checks).
> >>
> >> this patch ensures that if we have an incompatible interface, it is the
> >> only one can that can exist.
> >
> > Right, ok, I see that it's broken now, trying to see if there's a better
> > fix though.
>
> sure, thank you.
I'm not really sure, but if I understand the code & problem correctly I
think this should also help:
http://p.sipsolutions.net/a57eeac50c248408.txt
Untested though.
johannes
On Tuesday 05 June 2012 03:03 PM, Johannes Berg wrote:
> Hi Mohammed,
>
>>>> static const struct ieee80211_iface_limit a[] = {
>>>> { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) },
>>>> };
>>>>
>>>> static const struct ieee80211_iface_limit b[] = {
>>>> { .max = 2, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
>>>> };
>>>>
>>>> static const struct ieee80211_iface_combination if_comb[] = {
>>>> {.limits = a,
>>>> .n_limits = ARRAY_SIZE(a),
>>>> .max_interfaces = 2,
>>>> .num_different_channels = 1,
>>>> },
>>>> {.limits = b,
>>>> .n_limits = ARRAY_SIZE(b),
>>>> .max_interfaces = 2,
>>>> .num_different_channels = 1,
>>>> },
>>>>
>>>> };
>>>>
>>>> i could not add mesh interface if a managed interface is already there
>>>> and vice versa. if this is the expected behavior, then fine.
>>>
>>> No, that's not expected! Another bug!
>
> Actually, I'm sorry -- clearly I wasn't paying attention before -- it is
> expected. The above means you can add two managed or two mesh interface,
> but no combinations of them. Basically, the things in if_comb are XOR,
> and the things inside each limit are AND.
>
thanks, then the updated http://p.sipsolutions.net/fedf39a8d08b28b7.txt
seems to solve the issue.
--
thanks,
shafi
On Monday 04 June 2012 09:22 PM, Johannes Berg wrote:
> On Mon, 2012-06-04 at 21:17 +0530, Mohammed Shafi Shajakhan wrote:
>> From: Mohammed Shafi Shajakhan<[email protected]>
>>
>> *if any interface type is not advertised by the driver
>> via ieee80211_iface_combination make sure we will have it
>> as a single interface only. lets that we will not add
>> an incompatible interface if some other interface is
>> already present. we cannot add any other interface,
>> if the already present interface is an incompatible
>> interface. for example in ath9k we don't advertise ADHOC in
>> ieee80211_iface_combination structure in the driver,
>> so it can only exist as an single interface
>
> I'm not sure I understand what you're changing here?
if an interface say ad-hoc is not advertised in iface combination,
with the current still we can add that interface with some other
interface(removing the driver checks).
in ath9k we have
static const struct ieee80211_iface_limit if_limits[] = {
{ .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_WDS) },
{ .max = 8, .types =
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) },
};
i am able to create an IBSS interface even if a STA interface is up and
running in ath9k(removing the driver checks).
this patch ensures that if we have an incompatible interface, it is the
only one can that can exist.
>
>> *if the driver is not advertising interface combination just
>> return so that we don't break their multivif operation.
>
> Actually, we want to break multivif for drivers that don't advertise it.
oh, ok.
>
> johannes
>
--
thanks,
shafi
On Mon, 2012-06-04 at 21:29 +0530, Mohammed Shafi Shajakhan wrote:
> On Monday 04 June 2012 09:22 PM, Johannes Berg wrote:
> > On Mon, 2012-06-04 at 21:17 +0530, Mohammed Shafi Shajakhan wrote:
> >> From: Mohammed Shafi Shajakhan<[email protected]>
> >>
> >> *if any interface type is not advertised by the driver
> >> via ieee80211_iface_combination make sure we will have it
> >> as a single interface only. lets that we will not add
> >> an incompatible interface if some other interface is
> >> already present. we cannot add any other interface,
> >> if the already present interface is an incompatible
> >> interface. for example in ath9k we don't advertise ADHOC in
> >> ieee80211_iface_combination structure in the driver,
> >> so it can only exist as an single interface
> >
> > I'm not sure I understand what you're changing here?
>
> if an interface say ad-hoc is not advertised in iface combination,
> with the current still we can add that interface with some other
> interface(removing the driver checks).
>
> in ath9k we have
>
> static const struct ieee80211_iface_limit if_limits[] = {
> { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
> BIT(NL80211_IFTYPE_P2P_CLIENT) |
> BIT(NL80211_IFTYPE_WDS) },
> { .max = 8, .types =
> #ifdef CONFIG_MAC80211_MESH
> BIT(NL80211_IFTYPE_MESH_POINT) |
> #endif
> BIT(NL80211_IFTYPE_AP) |
> BIT(NL80211_IFTYPE_P2P_GO) },
> };
>
> i am able to create an IBSS interface even if a STA interface is up and
> running in ath9k(removing the driver checks).
>
> this patch ensures that if we have an incompatible interface, it is the
> only one can that can exist.
Right, ok, I see that it's broken now, trying to see if there's a better
fix though.
johannes
On Mon, 2012-06-04 at 18:18 +0200, Johannes Berg wrote:
> I'm not really sure, but if I understand the code & problem correctly I
> think this should also help:
> http://p.sipsolutions.net/a57eeac50c248408.txt
No, initialization was incorrect -- this is better:
http://p.sipsolutions.net/e5ab0f3e38f90d6d.txt
johannes
On Mon, 2012-06-04 at 21:17 +0530, Mohammed Shafi Shajakhan wrote:
> From: Mohammed Shafi Shajakhan <[email protected]>
>
> *if any interface type is not advertised by the driver
> via ieee80211_iface_combination make sure we will have it
> as a single interface only. lets that we will not add
> an incompatible interface if some other interface is
> already present. we cannot add any other interface,
> if the already present interface is an incompatible
> interface. for example in ath9k we don't advertise ADHOC in
> ieee80211_iface_combination structure in the driver,
> so it can only exist as an single interface
I'm not sure I understand what you're changing here?
> *if the driver is not advertising interface combination just
> return so that we don't break their multivif operation.
Actually, we want to break multivif for drivers that don't advertise it.
johannes
Hi Mohammed,
> > No, initialization was incorrect -- this is better:
> > http://p.sipsolutions.net/e5ab0f3e38f90d6d.txt
> >
>
> thanks a lot for the patch!
> with the above patch ath9k seems be working fine with the single
> incompatible adhoc interface.
Ok, cool.
> but i was just experimenting with ath9k(similar to iwlwifi having
> hw->wiphy->n_iface_combinations > 1) with this patch.
>
> static const struct ieee80211_iface_limit a[] = {
> { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) },
> };
>
> static const struct ieee80211_iface_limit b[] = {
> { .max = 2, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
> };
>
> static const struct ieee80211_iface_combination if_comb[] = {
> {.limits = a,
> .n_limits = ARRAY_SIZE(a),
> .max_interfaces = 2,
> .num_different_channels = 1,
> },
> {.limits = b,
> .n_limits = ARRAY_SIZE(b),
> .max_interfaces = 2,
> .num_different_channels = 1,
> },
>
> };
>
> i could not add mesh interface if a managed interface is already there
> and vice versa. if this is the expected behavior, then fine.
No, that's not expected! Another bug!
We should write some unit tests for this code I guess :-)
> iteration 1: cfg80211_can_change_interface all_iftypes 4 and used_iftypes 84
> iteration 2: cfg80211_can_change_interface all_iftypes 80 and used_iftypes 84
Curious. Why did it accept it then? Where did you place the printk?
I'm handling Linus's problem right now, so it'll be a bit until I can
look at this in more detail again.
johannes
On Monday 04 June 2012 09:43 PM, Johannes Berg wrote:
> On Mon, 2012-06-04 at 21:29 +0530, Mohammed Shafi Shajakhan wrote:
>> On Monday 04 June 2012 09:22 PM, Johannes Berg wrote:
>>> On Mon, 2012-06-04 at 21:17 +0530, Mohammed Shafi Shajakhan wrote:
>>>> From: Mohammed Shafi Shajakhan<[email protected]>
>>>>
>>>> *if any interface type is not advertised by the driver
>>>> via ieee80211_iface_combination make sure we will have it
>>>> as a single interface only. lets that we will not add
>>>> an incompatible interface if some other interface is
>>>> already present. we cannot add any other interface,
>>>> if the already present interface is an incompatible
>>>> interface. for example in ath9k we don't advertise ADHOC in
>>>> ieee80211_iface_combination structure in the driver,
>>>> so it can only exist as an single interface
>>>
>>> I'm not sure I understand what you're changing here?
>>
>> if an interface say ad-hoc is not advertised in iface combination,
>> with the current still we can add that interface with some other
>> interface(removing the driver checks).
>>
>> in ath9k we have
>>
>> static const struct ieee80211_iface_limit if_limits[] = {
>> { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
>> BIT(NL80211_IFTYPE_P2P_CLIENT) |
>> BIT(NL80211_IFTYPE_WDS) },
>> { .max = 8, .types =
>> #ifdef CONFIG_MAC80211_MESH
>> BIT(NL80211_IFTYPE_MESH_POINT) |
>> #endif
>> BIT(NL80211_IFTYPE_AP) |
>> BIT(NL80211_IFTYPE_P2P_GO) },
>> };
>>
>> i am able to create an IBSS interface even if a STA interface is up and
>> running in ath9k(removing the driver checks).
>>
>> this patch ensures that if we have an incompatible interface, it is the
>> only one can that can exist.
>
> Right, ok, I see that it's broken now, trying to see if there's a better
> fix though.
sure, thank you.
>
> johannes
>
--
thanks,
shafi