Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd37a78d authored by Alexander Aring's avatar Alexander Aring Committed by Marcel Holtmann
Browse files

mac802154: iface: check concurrent ifaces



This patch adds a check for concurrent interfaces while calling
interface up. This avoids to have different mac parameters on one phy.
Otherwise it could be that a interface can overwrite current phy mac
settings which is set by an another interface.

Signed-off-by: default avatarAlexander Aring <alex.aring@gmail.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 405a2611
Loading
Loading
Loading
Loading
+77 −0
Original line number Original line Diff line number Diff line
@@ -175,6 +175,79 @@ static int mac802154_slave_open(struct net_device *dev)
	return res;
	return res;
}
}


static int
ieee802154_check_mac_settings(struct ieee802154_local *local,
			      struct wpan_dev *wpan_dev,
			      struct wpan_dev *nwpan_dev)
{
	ASSERT_RTNL();

	if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
		if (wpan_dev->promiscuous_mode != nwpan_dev->promiscuous_mode)
			return -EBUSY;
	}

	if (local->hw.flags & IEEE802154_HW_AFILT) {
		if (wpan_dev->pan_id != nwpan_dev->pan_id)
			return -EBUSY;

		if (wpan_dev->short_addr != nwpan_dev->short_addr)
			return -EBUSY;

		if (wpan_dev->extended_addr != nwpan_dev->extended_addr)
			return -EBUSY;
	}

	if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) {
		if (wpan_dev->min_be != nwpan_dev->min_be)
			return -EBUSY;

		if (wpan_dev->max_be != nwpan_dev->max_be)
			return -EBUSY;

		if (wpan_dev->csma_retries != nwpan_dev->csma_retries)
			return -EBUSY;
	}

	if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) {
		if (wpan_dev->frame_retries != nwpan_dev->frame_retries)
			return -EBUSY;
	}

	if (local->hw.flags & IEEE802154_HW_LBT) {
		if (wpan_dev->lbt != nwpan_dev->lbt)
			return -EBUSY;
	}

	return 0;
}

static int
ieee802154_check_concurrent_iface(struct ieee802154_sub_if_data *sdata,
				  enum nl802154_iftype iftype)
{
	struct ieee802154_local *local = sdata->local;
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
	struct ieee802154_sub_if_data *nsdata;

	/* we hold the RTNL here so can safely walk the list */
	list_for_each_entry(nsdata, &local->interfaces, list) {
		if (nsdata != sdata && ieee802154_sdata_running(nsdata)) {
			int ret;

			/* check all phy mac sublayer settings are the same.
			 * We have only one phy, different values makes trouble.
			 */
			ret = ieee802154_check_mac_settings(local, wpan_dev,
							    &nsdata->wpan_dev);
			if (ret < 0)
				return ret;
		}
	}

	return 0;
}

static int mac802154_wpan_open(struct net_device *dev)
static int mac802154_wpan_open(struct net_device *dev)
{
{
	int rc;
	int rc;
@@ -183,6 +256,10 @@ static int mac802154_wpan_open(struct net_device *dev)
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
	struct wpan_phy *phy = sdata->local->phy;
	struct wpan_phy *phy = sdata->local->phy;


	rc = ieee802154_check_concurrent_iface(sdata, sdata->vif.type);
	if (rc < 0)
		return rc;

	rc = mac802154_slave_open(dev);
	rc = mac802154_slave_open(dev);
	if (rc < 0)
	if (rc < 0)
		return rc;
		return rc;