drivers/net/vxlan/vxlan_multicast.c

Source file repositories/reference/linux-study-clean/drivers/net/vxlan/vxlan_multicast.c

File Facts

System
Linux kernel
Corpus path
drivers/net/vxlan/vxlan_multicast.c
Extension
.c
Size
6721 bytes
Lines
271
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
			if (!vxlan_group_used_by_vnifilter(vxlan, ip, ifindex))
				continue;
		} else {
			if (!vxlan_group_used_match(ip, ifindex,
						    &vxlan->default_dst.remote_ip,
						    vxlan->default_dst.remote_ifindex))
				continue;
		}

		return true;
	}

	return false;
}

static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
{
	struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
	struct vxlan_vni_node *v, *tmp, *vgood = NULL;
	int ret = 0;

	list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
		if (!vxlan_addr_multicast(&v->remote_ip))
			continue;
		/* skip if address is same as default address */
		if (vxlan_addr_equal(&v->remote_ip,
				     &vxlan->default_dst.remote_ip))
			continue;
		ret = vxlan_igmp_join(vxlan, &v->remote_ip, 0);
		if (ret == -EADDRINUSE)
			ret = 0;
		if (ret)
			goto out;
		vgood = v;
	}
out:
	if (ret) {
		list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
			if (!vxlan_addr_multicast(&v->remote_ip))
				continue;
			if (vxlan_addr_equal(&v->remote_ip,
					     &vxlan->default_dst.remote_ip))
				continue;
			vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
			if (v == vgood)
				break;
		}
	}

	return ret;
}

static int vxlan_multicast_leave_vnigrp(struct vxlan_dev *vxlan)
{
	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
	struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
	struct vxlan_vni_node *v, *tmp;
	int last_err = 0, ret;

	list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
		if (vxlan_addr_multicast(&v->remote_ip) &&
		    !vxlan_group_used(vn, vxlan, v->vni, &v->remote_ip,
				      0)) {
			ret = vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
			if (ret)
				last_err = ret;
		}
	}

	return last_err;
}

int vxlan_multicast_join(struct vxlan_dev *vxlan)
{
	int ret = 0;

	if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
		ret = vxlan_igmp_join(vxlan, &vxlan->default_dst.remote_ip,
				      vxlan->default_dst.remote_ifindex);
		if (ret == -EADDRINUSE)
			ret = 0;
		if (ret)
			return ret;
	}

	if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
		return vxlan_multicast_join_vnigrp(vxlan);

	return 0;

Annotation

Implementation Notes