net/bridge/br_mst.c

Source file repositories/reference/linux-study-clean/net/bridge/br_mst.c

File Facts

System
Linux kernel
Corpus path
net/bridge/br_mst.c
Extension
.c
Size
7898 bytes
Lines
367
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (v->brvlan->msti == msti) {
			*state = v->state;
			return 0;
		}
	}

	return -ENOENT;
}
EXPORT_SYMBOL_GPL(br_mst_get_state);

static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
				  struct net_bridge_vlan *v,
				  u8 state)
{
	if (br_vlan_get_state(v) == state)
		return;

	if (v->vid == vg->pvid)
		br_vlan_set_pvid_state(vg, state);

	br_vlan_set_state(v, state);
}

int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
		     struct netlink_ext_ack *extack)
{
	struct switchdev_attr attr = {
		.id = SWITCHDEV_ATTR_ID_PORT_MST_STATE,
		.orig_dev = p->dev,
		.u.mst_state = {
			.msti = msti,
			.state = state,
		},
	};
	struct net_bridge_vlan_group *vg;
	struct net_bridge_vlan *v;
	int err = 0;

	rcu_read_lock();
	vg = nbp_vlan_group_rcu(p);
	if (!vg)
		goto out;

	/* MSTI 0 (CST) state changes are notified via the regular
	 * SWITCHDEV_ATTR_ID_PORT_STP_STATE.
	 */
	if (msti) {
		err = switchdev_port_attr_set(p->dev, &attr, extack);
		if (err && err != -EOPNOTSUPP)
			goto out;
	}

	err = 0;
	list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
		if (v->brvlan->msti != msti)
			continue;

		br_mst_vlan_set_state(vg, v, state);
	}

out:
	rcu_read_unlock();
	return err;
}

static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)
{
	struct net_bridge_vlan_group *vg = nbp_vlan_group(pv->port);
	struct net_bridge_vlan *v;

	list_for_each_entry(v, &vg->vlan_list, vlist) {
		/* If this port already has a defined state in this
		 * MSTI (through some other VLAN membership), inherit
		 * it.
		 */
		if (v != pv && v->brvlan->msti == msti) {
			br_mst_vlan_set_state(vg, pv, v->state);
			return;
		}
	}

	/* Otherwise, start out in a new MSTI with all ports disabled. */
	return br_mst_vlan_set_state(vg, pv, BR_STATE_DISABLED);
}

int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti)
{
	struct switchdev_attr attr = {
		.id = SWITCHDEV_ATTR_ID_VLAN_MSTI,
		.orig_dev = mv->br->dev,

Annotation

Implementation Notes