net/bridge/br_mdb.c

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

File Facts

System
Linux kernel
Corpus path
net/bridge/br_mdb.c
Extension
.c
Size
43053 bytes
Lines
1723
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

struct br_mdb_flush_desc {
	u32 port_ifindex;
	u16 vid;
	u8 rt_protocol;
	u8 state;
	u8 state_mask;
};

static const struct nla_policy br_mdbe_attrs_del_bulk_pol[MDBE_ATTR_MAX + 1] = {
	[MDBE_ATTR_RTPROT] = NLA_POLICY_MIN(NLA_U8, RTPROT_STATIC),
	[MDBE_ATTR_STATE_MASK] = NLA_POLICY_MASK(NLA_U8, MDB_PERMANENT),
};

static int br_mdb_flush_desc_init(struct br_mdb_flush_desc *desc,
				  struct nlattr *tb[],
				  struct netlink_ext_ack *extack)
{
	struct br_mdb_entry *entry = nla_data(tb[MDBA_SET_ENTRY]);
	struct nlattr *mdbe_attrs[MDBE_ATTR_MAX + 1];
	int err;

	desc->port_ifindex = entry->ifindex;
	desc->vid = entry->vid;
	desc->state = entry->state;

	if (!tb[MDBA_SET_ENTRY_ATTRS])
		return 0;

	err = nla_parse_nested(mdbe_attrs, MDBE_ATTR_MAX,
			       tb[MDBA_SET_ENTRY_ATTRS],
			       br_mdbe_attrs_del_bulk_pol, extack);
	if (err)
		return err;

	if (mdbe_attrs[MDBE_ATTR_STATE_MASK])
		desc->state_mask = nla_get_u8(mdbe_attrs[MDBE_ATTR_STATE_MASK]);

	if (mdbe_attrs[MDBE_ATTR_RTPROT])
		desc->rt_protocol = nla_get_u8(mdbe_attrs[MDBE_ATTR_RTPROT]);

	return 0;
}

static void br_mdb_flush_host(struct net_bridge *br,
			      struct net_bridge_mdb_entry *mp,
			      const struct br_mdb_flush_desc *desc)
{
	u8 state;

	if (desc->port_ifindex && desc->port_ifindex != br->dev->ifindex)
		return;

	if (desc->rt_protocol)
		return;

	state = br_group_is_l2(&mp->addr) ? MDB_PERMANENT : 0;
	if (desc->state_mask && (state & desc->state_mask) != desc->state)
		return;

	br_multicast_host_leave(mp, true);
	if (!mp->ports && netif_running(br->dev))
		mod_timer(&mp->timer, jiffies);
}

static void br_mdb_flush_pgs(struct net_bridge *br,
			     struct net_bridge_mdb_entry *mp,
			     const struct br_mdb_flush_desc *desc)
{
	struct net_bridge_port_group __rcu **pp;
	struct net_bridge_port_group *p;

	for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL;) {
		u8 state;

		if (desc->port_ifindex &&
		    desc->port_ifindex != p->key.port->dev->ifindex) {
			pp = &p->next;
			continue;
		}

		if (desc->rt_protocol && desc->rt_protocol != p->rt_protocol) {
			pp = &p->next;
			continue;
		}

		state = p->flags & MDB_PG_FLAGS_PERMANENT ? MDB_PERMANENT : 0;
		if (desc->state_mask &&
		    (state & desc->state_mask) != desc->state) {
			pp = &p->next;
			continue;

Annotation

Implementation Notes