net/bridge/br_vlan_options.c

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

File Facts

System
Linux kernel
Corpus path
net/bridge/br_vlan_options.c
Extension
.c
Size
23455 bytes
Lines
781
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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 (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) {
			NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute");
			return -ENOENT;
		}
		/* when working on vlan ranges this is the starting tunnel id */
		tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]);
		/* vlan info attr is guaranteed by br_vlan_rtm_process_one */
		vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
		/* tunnel ids are mapped to each vlan in increasing order,
		 * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the
		 * current vlan, so we compute: tun_id + v - vinfo->vid
		 */
		tun_id += v->vid - vinfo->vid;
		break;
	case RTM_DELLINK:
		break;
	default:
		NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel command");
		return -EINVAL;
	}

	return br_vlan_tunnel_info(p, cmd, v->vid, tun_id, changed);
}

static int br_vlan_process_one_opts(const struct net_bridge *br,
				    const struct net_bridge_port *p,
				    struct net_bridge_vlan_group *vg,
				    struct net_bridge_vlan *v,
				    struct nlattr **tb,
				    bool *changed,
				    struct netlink_ext_ack *extack)
{
	int err;

	*changed = false;
	if (tb[BRIDGE_VLANDB_ENTRY_STATE]) {
		u8 state = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_STATE]);

		err = br_vlan_modify_state(vg, v, state, changed, extack);
		if (err)
			return err;
	}
	if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) {
		err = br_vlan_modify_tunnel(p, v, tb, changed, extack);
		if (err)
			return err;
	}

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	if (tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) {
		u8 val;

		val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]);
		err = br_multicast_set_vlan_router(v, val);
		if (err)
			return err;
		*changed = true;
	}
	if (tb[BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS]) {
		u32 val;

		if (!p) {
			NL_SET_ERR_MSG_MOD(extack, "Can't set mcast_max_groups for non-port vlans");
			return -EINVAL;
		}
		if (br_multicast_port_ctx_vlan_disabled(&v->port_mcast_ctx)) {
			NL_SET_ERR_MSG_MOD(extack, "Multicast snooping disabled on this VLAN");
			return -EINVAL;
		}

		val = nla_get_u32(tb[BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS]);
		br_multicast_ngroups_set_max(&v->port_mcast_ctx, val);
		*changed = true;
	}
#endif

	if (tb[BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS]) {
		bool enabled = v->priv_flags & BR_VLFLAG_NEIGH_SUPPRESS_ENABLED;
		bool val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS]);

		if (!p) {
			NL_SET_ERR_MSG_MOD(extack, "Can't set neigh_suppress for non-port vlans");
			return -EINVAL;
		}

		if (val != enabled) {
			v->priv_flags ^= BR_VLFLAG_NEIGH_SUPPRESS_ENABLED;
			*changed = true;
		}
	}

Annotation

Implementation Notes