1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PFCP according to 3GPP TS 29.244
5 * Copyright (C) 2022, Intel Corporation.
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/rculist.h>
11 #include <linux/skbuff.h>
12 #include <linux/types.h>
15 #include <net/udp_tunnel.h>
19 struct list_head list
;
22 struct net_device
*dev
;
25 struct gro_cells gro_cells
;
28 static unsigned int pfcp_net_id __read_mostly
;
31 struct list_head pfcp_dev_list
;
35 pfcp_session_recv(struct pfcp_dev
*pfcp
, struct sk_buff
*skb
,
36 struct pfcp_metadata
*md
)
38 struct pfcphdr_session
*unparsed
= pfcp_hdr_session(skb
);
40 md
->seid
= unparsed
->seid
;
41 md
->type
= PFCP_TYPE_SESSION
;
45 pfcp_node_recv(struct pfcp_dev
*pfcp
, struct sk_buff
*skb
,
46 struct pfcp_metadata
*md
)
48 md
->type
= PFCP_TYPE_NODE
;
51 static int pfcp_encap_recv(struct sock
*sk
, struct sk_buff
*skb
)
53 IP_TUNNEL_DECLARE_FLAGS(flags
) = { };
54 struct metadata_dst
*tun_dst
;
55 struct pfcp_metadata
*md
;
56 struct pfcphdr
*unparsed
;
57 struct pfcp_dev
*pfcp
;
59 if (unlikely(!pskb_may_pull(skb
, PFCP_HLEN
)))
62 pfcp
= rcu_dereference_sk_user_data(sk
);
66 unparsed
= pfcp_hdr(skb
);
68 ip_tunnel_flags_zero(flags
);
69 tun_dst
= udp_tun_rx_dst(skb
, sk
->sk_family
, flags
, 0,
71 if (unlikely(!tun_dst
))
74 md
= ip_tunnel_info_opts(&tun_dst
->u
.tun_info
);
78 if (unparsed
->flags
& PFCP_SEID_FLAG
)
79 pfcp_session_recv(pfcp
, skb
, md
);
81 pfcp_node_recv(pfcp
, skb
, md
);
83 __set_bit(IP_TUNNEL_PFCP_OPT_BIT
, tun_dst
->u
.tun_info
.key
.tun_flags
);
84 tun_dst
->u
.tun_info
.options_len
= sizeof(*md
);
86 if (unlikely(iptunnel_pull_header(skb
, PFCP_HLEN
, skb
->protocol
,
88 dev_net(pfcp
->dev
)))))
91 skb_dst_set(skb
, (struct dst_entry
*)tun_dst
);
93 skb_reset_network_header(skb
);
94 skb_reset_mac_header(skb
);
97 gro_cells_receive(&pfcp
->gro_cells
, skb
);
105 static void pfcp_del_sock(struct pfcp_dev
*pfcp
)
107 udp_tunnel_sock_release(pfcp
->sock
);
111 static void pfcp_dev_uninit(struct net_device
*dev
)
113 struct pfcp_dev
*pfcp
= netdev_priv(dev
);
115 gro_cells_destroy(&pfcp
->gro_cells
);
119 static int pfcp_dev_init(struct net_device
*dev
)
121 struct pfcp_dev
*pfcp
= netdev_priv(dev
);
125 return gro_cells_init(&pfcp
->gro_cells
, dev
);
128 static const struct net_device_ops pfcp_netdev_ops
= {
129 .ndo_init
= pfcp_dev_init
,
130 .ndo_uninit
= pfcp_dev_uninit
,
131 .ndo_get_stats64
= dev_get_tstats64
,
134 static const struct device_type pfcp_type
= {
138 static void pfcp_link_setup(struct net_device
*dev
)
140 dev
->netdev_ops
= &pfcp_netdev_ops
;
141 dev
->needs_free_netdev
= true;
142 SET_NETDEV_DEVTYPE(dev
, &pfcp_type
);
144 dev
->hard_header_len
= 0;
147 dev
->type
= ARPHRD_NONE
;
148 dev
->flags
= IFF_POINTOPOINT
| IFF_NOARP
| IFF_MULTICAST
;
149 dev
->priv_flags
|= IFF_NO_QUEUE
;
154 static struct socket
*pfcp_create_sock(struct pfcp_dev
*pfcp
)
156 struct udp_tunnel_sock_cfg tuncfg
= {};
157 struct udp_port_cfg udp_conf
= {
158 .local_ip
.s_addr
= htonl(INADDR_ANY
),
161 struct net
*net
= pfcp
->net
;
165 udp_conf
.local_udp_port
= htons(PFCP_PORT
);
167 err
= udp_sock_create(net
, &udp_conf
, &sock
);
171 tuncfg
.sk_user_data
= pfcp
;
172 tuncfg
.encap_rcv
= pfcp_encap_recv
;
173 tuncfg
.encap_type
= 1;
175 setup_udp_tunnel_sock(net
, sock
, &tuncfg
);
180 static int pfcp_add_sock(struct pfcp_dev
*pfcp
)
182 pfcp
->sock
= pfcp_create_sock(pfcp
);
184 return PTR_ERR_OR_ZERO(pfcp
->sock
);
187 static int pfcp_newlink(struct net
*net
, struct net_device
*dev
,
188 struct nlattr
*tb
[], struct nlattr
*data
[],
189 struct netlink_ext_ack
*extack
)
191 struct pfcp_dev
*pfcp
= netdev_priv(dev
);
197 err
= pfcp_add_sock(pfcp
);
199 netdev_dbg(dev
, "failed to add pfcp socket %d\n", err
);
203 err
= register_netdevice(dev
);
205 netdev_dbg(dev
, "failed to register pfcp netdev %d\n", err
);
206 goto exit_del_pfcp_sock
;
209 pn
= net_generic(dev_net(dev
), pfcp_net_id
);
210 list_add_rcu(&pfcp
->list
, &pn
->pfcp_dev_list
);
212 netdev_dbg(dev
, "registered new PFCP interface\n");
223 static void pfcp_dellink(struct net_device
*dev
, struct list_head
*head
)
225 struct pfcp_dev
*pfcp
= netdev_priv(dev
);
227 list_del_rcu(&pfcp
->list
);
228 unregister_netdevice_queue(dev
, head
);
231 static struct rtnl_link_ops pfcp_link_ops __read_mostly
= {
233 .priv_size
= sizeof(struct pfcp_dev
),
234 .setup
= pfcp_link_setup
,
235 .newlink
= pfcp_newlink
,
236 .dellink
= pfcp_dellink
,
239 static int __net_init
pfcp_net_init(struct net
*net
)
241 struct pfcp_net
*pn
= net_generic(net
, pfcp_net_id
);
243 INIT_LIST_HEAD(&pn
->pfcp_dev_list
);
247 static void __net_exit
pfcp_net_exit(struct net
*net
)
249 struct pfcp_net
*pn
= net_generic(net
, pfcp_net_id
);
250 struct pfcp_dev
*pfcp
;
254 list_for_each_entry(pfcp
, &pn
->pfcp_dev_list
, list
)
255 pfcp_dellink(pfcp
->dev
, &list
);
257 unregister_netdevice_many(&list
);
261 static struct pernet_operations pfcp_net_ops
= {
262 .init
= pfcp_net_init
,
263 .exit
= pfcp_net_exit
,
265 .size
= sizeof(struct pfcp_net
),
268 static int __init
pfcp_init(void)
272 err
= register_pernet_subsys(&pfcp_net_ops
);
276 err
= rtnl_link_register(&pfcp_link_ops
);
278 goto exit_unregister_subsys
;
281 exit_unregister_subsys
:
282 unregister_pernet_subsys(&pfcp_net_ops
);
284 pr_err("loading PFCP module failed: err %d\n", err
);
287 late_initcall(pfcp_init
);
289 static void __exit
pfcp_exit(void)
291 rtnl_link_unregister(&pfcp_link_ops
);
292 unregister_pernet_subsys(&pfcp_net_ops
);
294 pr_info("PFCP module unloaded\n");
296 module_exit(pfcp_exit
);
298 MODULE_LICENSE("GPL");
299 MODULE_AUTHOR("Wojciech Drewek <wojciech.drewek@intel.com>");
300 MODULE_DESCRIPTION("Interface driver for PFCP encapsulated traffic");
301 MODULE_ALIAS_RTNL_LINK("pfcp");