drivers/net/pfcp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/pfcp.c
Extension
.c
Size
6470 bytes
Lines
301
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops pfcp_netdev_ops = {
	.ndo_init		= pfcp_dev_init,
	.ndo_uninit		= pfcp_dev_uninit,
	.ndo_get_stats64	= dev_get_tstats64,
};

static const struct device_type pfcp_type = {
	.name = "pfcp",
};

static void pfcp_link_setup(struct net_device *dev)
{
	dev->netdev_ops = &pfcp_netdev_ops;
	dev->needs_free_netdev = true;
	SET_NETDEV_DEVTYPE(dev, &pfcp_type);

	dev->hard_header_len = 0;
	dev->addr_len = 0;

	dev->type = ARPHRD_NONE;
	dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
	dev->priv_flags |= IFF_NO_QUEUE;

	dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
	netif_keep_dst(dev);
}

static struct sock *pfcp_create_sock(struct pfcp_dev *pfcp)
{
	struct udp_tunnel_sock_cfg tuncfg = {};
	struct udp_port_cfg udp_conf = {
		.local_ip.s_addr	= htonl(INADDR_ANY),
		.family			= AF_INET,
	};
	struct net *net = pfcp->net;
	struct socket *sock;
	int err;

	udp_conf.local_udp_port = htons(PFCP_PORT);

	err = udp_sock_create(net, &udp_conf, &sock);
	if (err)
		return ERR_PTR(err);

	tuncfg.sk_user_data = pfcp;
	tuncfg.encap_rcv = pfcp_encap_recv;
	tuncfg.encap_type = 1;

	setup_udp_tunnel_sock(net, sock->sk, &tuncfg);

	return sock->sk;
}

static int pfcp_add_sock(struct pfcp_dev *pfcp)
{
	pfcp->sk = pfcp_create_sock(pfcp);

	return PTR_ERR_OR_ZERO(pfcp->sk);
}

static int pfcp_newlink(struct net_device *dev,
			struct rtnl_newlink_params *params,
			struct netlink_ext_ack *extack)
{
	struct net *link_net = rtnl_newlink_link_net(params);
	struct pfcp_dev *pfcp = netdev_priv(dev);
	struct pfcp_net *pn;
	int err;

	pfcp->net = link_net;

	err = pfcp_add_sock(pfcp);
	if (err) {
		netdev_dbg(dev, "failed to add pfcp socket %d\n", err);
		goto exit_err;
	}

	err = register_netdevice(dev);
	if (err) {
		netdev_dbg(dev, "failed to register pfcp netdev %d\n", err);
		goto exit_del_pfcp_sock;
	}

	pn = net_generic(link_net, pfcp_net_id);
	list_add(&pfcp->list, &pn->pfcp_dev_list);

	netdev_dbg(dev, "registered new PFCP interface\n");

	return 0;

Annotation

Implementation Notes