drivers/net/vxlan/vxlan_vnifilter.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/vxlan/vxlan_vnifilter.c
Extension
.c
Size
24400 bytes
Lines
1005
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 (vbegin->remote_ip.sa.sa_family == AF_INET) {
			if (nla_put_in_addr(skb, VXLAN_VNIFILTER_ENTRY_GROUP,
					    vbegin->remote_ip.sin.sin_addr.s_addr))
				goto out_err;
#if IS_ENABLED(CONFIG_IPV6)
		} else {
			if (nla_put_in6_addr(skb, VXLAN_VNIFILTER_ENTRY_GROUP6,
					     &vbegin->remote_ip.sin6.sin6_addr))
				goto out_err;
#endif
		}
	}

	if (fill_stats && __vnifilter_entry_fill_stats(skb, vbegin))
		goto out_err;

	nla_nest_end(skb, ventry);

	return true;

out_err:
	nla_nest_cancel(skb, ventry);

	return false;
}

static void vxlan_vnifilter_notify(const struct vxlan_dev *vxlan,
				   struct vxlan_vni_node *vninode, int cmd)
{
	struct tunnel_msg *tmsg;
	struct sk_buff *skb;
	struct nlmsghdr *nlh;
	struct net *net = dev_net(vxlan->dev);
	int err = -ENOBUFS;

	skb = nlmsg_new(vxlan_vnifilter_entry_nlmsg_size(), GFP_KERNEL);
	if (!skb)
		goto out_err;

	err = -EMSGSIZE;
	nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*tmsg), 0);
	if (!nlh)
		goto out_err;
	tmsg = nlmsg_data(nlh);
	memset(tmsg, 0, sizeof(*tmsg));
	tmsg->family = AF_BRIDGE;
	tmsg->ifindex = vxlan->dev->ifindex;

	if (!vxlan_fill_vni_filter_entry(skb, vninode, vninode, false))
		goto out_err;

	nlmsg_end(skb, nlh);
	rtnl_notify(skb, net, 0, RTNLGRP_TUNNEL, NULL, GFP_KERNEL);

	return;

out_err:
	rtnl_set_sk_err(net, RTNLGRP_TUNNEL, err);

	kfree_skb(skb);
}

static int vxlan_vnifilter_dump_dev(const struct net_device *dev,
				    struct sk_buff *skb,
				    struct netlink_callback *cb)
{
	struct vxlan_vni_node *tmp, *v, *vbegin = NULL, *vend = NULL;
	struct vxlan_dev *vxlan = netdev_priv(dev);
	struct tunnel_msg *new_tmsg, *tmsg;
	int idx = 0, s_idx = cb->args[1];
	struct vxlan_vni_group *vg;
	struct nlmsghdr *nlh;
	bool dump_stats;
	int err = 0;

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

	/* RCU needed because of the vni locking rules (rcu || rtnl) */
	vg = rcu_dereference(vxlan->vnigrp);
	if (!vg || !vg->num_vnis)
		return 0;

	tmsg = nlmsg_data(cb->nlh);
	dump_stats = !!(tmsg->flags & TUNNEL_MSG_FLAG_STATS);

	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
			RTM_NEWTUNNEL, sizeof(*new_tmsg), NLM_F_MULTI);
	if (!nlh)
		return -EMSGSIZE;

Annotation

Implementation Notes