blob: 108a8cafc4f8e7c5e5ae3e5b7898a8004445cbe8 [file] [log] [blame]
Martin Varghese571912c2020-02-24 10:57:50 +05301// SPDX-License-Identifier: GPL-2.0
2/* Bareudp: UDP tunnel encasulation for different Payload types like
3 * MPLS, NSH, IP, etc.
4 * Copyright (c) 2019 Nokia, Inc.
5 * Authors: Martin Varghese, <martin.varghese@nokia.com>
6 */
7
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/etherdevice.h>
13#include <linux/hash.h>
14#include <net/dst_metadata.h>
15#include <net/gro_cells.h>
16#include <net/rtnetlink.h>
17#include <net/protocol.h>
18#include <net/ip6_tunnel.h>
19#include <net/ip_tunnels.h>
20#include <net/udp_tunnel.h>
21#include <net/bareudp.h>
22
23#define BAREUDP_BASE_HLEN sizeof(struct udphdr)
24#define BAREUDP_IPV4_HLEN (sizeof(struct iphdr) + \
25 sizeof(struct udphdr))
26#define BAREUDP_IPV6_HLEN (sizeof(struct ipv6hdr) + \
27 sizeof(struct udphdr))
28
29static bool log_ecn_error = true;
30module_param(log_ecn_error, bool, 0644);
31MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
32
33/* per-network namespace private data for this module */
34
35static unsigned int bareudp_net_id;
36
37struct bareudp_net {
38 struct list_head bareudp_list;
39};
40
41/* Pseudo network device */
42struct bareudp_dev {
43 struct net *net; /* netns for packet i/o */
44 struct net_device *dev; /* netdev for bareudp tunnel */
45 __be16 ethertype;
46 __be16 port;
47 u16 sport_min;
Martin Varghese4b5f6722020-02-24 10:58:35 +053048 bool multi_proto_mode;
Martinfe805362020-06-28 23:18:23 +053049 bool rx_collect_metadata;
Martin Varghese571912c2020-02-24 10:57:50 +053050 struct socket __rcu *sock;
51 struct list_head next; /* bareudp node on namespace list */
52 struct gro_cells gro_cells;
53};
54
55static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
56{
57 struct metadata_dst *tun_dst = NULL;
58 struct pcpu_sw_netstats *stats;
59 struct bareudp_dev *bareudp;
60 unsigned short family;
61 unsigned int len;
62 __be16 proto;
63 void *oiph;
64 int err;
65
66 bareudp = rcu_dereference_sk_user_data(sk);
67 if (!bareudp)
68 goto drop;
69
70 if (skb->protocol == htons(ETH_P_IP))
71 family = AF_INET;
72 else
73 family = AF_INET6;
74
Martin Varghese4b5f6722020-02-24 10:58:35 +053075 if (bareudp->ethertype == htons(ETH_P_IP)) {
76 struct iphdr *iphdr;
77
78 iphdr = (struct iphdr *)(skb->data + BAREUDP_BASE_HLEN);
79 if (iphdr->version == 4) {
80 proto = bareudp->ethertype;
81 } else if (bareudp->multi_proto_mode && (iphdr->version == 6)) {
82 proto = htons(ETH_P_IPV6);
83 } else {
84 bareudp->dev->stats.rx_dropped++;
85 goto drop;
86 }
87 } else if (bareudp->ethertype == htons(ETH_P_MPLS_UC)) {
88 struct iphdr *tunnel_hdr;
89
90 tunnel_hdr = (struct iphdr *)skb_network_header(skb);
91 if (tunnel_hdr->version == 4) {
92 if (!ipv4_is_multicast(tunnel_hdr->daddr)) {
93 proto = bareudp->ethertype;
94 } else if (bareudp->multi_proto_mode &&
95 ipv4_is_multicast(tunnel_hdr->daddr)) {
96 proto = htons(ETH_P_MPLS_MC);
97 } else {
98 bareudp->dev->stats.rx_dropped++;
99 goto drop;
100 }
101 } else {
102 int addr_type;
103 struct ipv6hdr *tunnel_hdr_v6;
104
105 tunnel_hdr_v6 = (struct ipv6hdr *)skb_network_header(skb);
106 addr_type =
107 ipv6_addr_type((struct in6_addr *)&tunnel_hdr_v6->daddr);
108 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
109 proto = bareudp->ethertype;
110 } else if (bareudp->multi_proto_mode &&
111 (addr_type & IPV6_ADDR_MULTICAST)) {
112 proto = htons(ETH_P_MPLS_MC);
113 } else {
114 bareudp->dev->stats.rx_dropped++;
115 goto drop;
116 }
117 }
118 } else {
119 proto = bareudp->ethertype;
120 }
Martin Varghese571912c2020-02-24 10:57:50 +0530121
122 if (iptunnel_pull_header(skb, BAREUDP_BASE_HLEN,
123 proto,
124 !net_eq(bareudp->net,
125 dev_net(bareudp->dev)))) {
126 bareudp->dev->stats.rx_dropped++;
127 goto drop;
128 }
Martinfe805362020-06-28 23:18:23 +0530129 if (bareudp->rx_collect_metadata) {
130 tun_dst = udp_tun_rx_dst(skb, family, TUNNEL_KEY, 0, 0);
131 if (!tun_dst) {
132 bareudp->dev->stats.rx_dropped++;
133 goto drop;
134 }
135 skb_dst_set(skb, &tun_dst->dst);
Martin Varghese571912c2020-02-24 10:57:50 +0530136 }
Martin Varghese571912c2020-02-24 10:57:50 +0530137 skb->dev = bareudp->dev;
138 oiph = skb_network_header(skb);
139 skb_reset_network_header(skb);
140
Arnd Bergmannee287552020-05-05 19:22:14 +0200141 if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET)
Martin Varghese571912c2020-02-24 10:57:50 +0530142 err = IP_ECN_decapsulate(oiph, skb);
Martin Varghese571912c2020-02-24 10:57:50 +0530143 else
144 err = IP6_ECN_decapsulate(oiph, skb);
Martin Varghese571912c2020-02-24 10:57:50 +0530145
146 if (unlikely(err)) {
147 if (log_ecn_error) {
Arnd Bergmannee287552020-05-05 19:22:14 +0200148 if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET)
Martin Varghese571912c2020-02-24 10:57:50 +0530149 net_info_ratelimited("non-ECT from %pI4 "
150 "with TOS=%#x\n",
151 &((struct iphdr *)oiph)->saddr,
152 ((struct iphdr *)oiph)->tos);
Martin Varghese571912c2020-02-24 10:57:50 +0530153 else
154 net_info_ratelimited("non-ECT from %pI6\n",
155 &((struct ipv6hdr *)oiph)->saddr);
Martin Varghese571912c2020-02-24 10:57:50 +0530156 }
157 if (err > 1) {
158 ++bareudp->dev->stats.rx_frame_errors;
159 ++bareudp->dev->stats.rx_errors;
160 goto drop;
161 }
162 }
163
164 len = skb->len;
165 err = gro_cells_receive(&bareudp->gro_cells, skb);
166 if (likely(err == NET_RX_SUCCESS)) {
167 stats = this_cpu_ptr(bareudp->dev->tstats);
168 u64_stats_update_begin(&stats->syncp);
169 stats->rx_packets++;
170 stats->rx_bytes += len;
171 u64_stats_update_end(&stats->syncp);
172 }
173 return 0;
174drop:
175 /* Consume bad packet */
176 kfree_skb(skb);
177
178 return 0;
179}
180
181static int bareudp_err_lookup(struct sock *sk, struct sk_buff *skb)
182{
183 return 0;
184}
185
186static int bareudp_init(struct net_device *dev)
187{
188 struct bareudp_dev *bareudp = netdev_priv(dev);
189 int err;
190
191 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
192 if (!dev->tstats)
193 return -ENOMEM;
194
195 err = gro_cells_init(&bareudp->gro_cells, dev);
196 if (err) {
197 free_percpu(dev->tstats);
198 return err;
199 }
200 return 0;
201}
202
203static void bareudp_uninit(struct net_device *dev)
204{
205 struct bareudp_dev *bareudp = netdev_priv(dev);
206
207 gro_cells_destroy(&bareudp->gro_cells);
208 free_percpu(dev->tstats);
209}
210
211static struct socket *bareudp_create_sock(struct net *net, __be16 port)
212{
213 struct udp_port_cfg udp_conf;
214 struct socket *sock;
215 int err;
216
217 memset(&udp_conf, 0, sizeof(udp_conf));
218#if IS_ENABLED(CONFIG_IPV6)
219 udp_conf.family = AF_INET6;
220#else
221 udp_conf.family = AF_INET;
222#endif
223 udp_conf.local_udp_port = port;
224 /* Open UDP socket */
225 err = udp_sock_create(net, &udp_conf, &sock);
226 if (err < 0)
227 return ERR_PTR(err);
228
229 return sock;
230}
231
232/* Create new listen socket if needed */
233static int bareudp_socket_create(struct bareudp_dev *bareudp, __be16 port)
234{
235 struct udp_tunnel_sock_cfg tunnel_cfg;
236 struct socket *sock;
237
238 sock = bareudp_create_sock(bareudp->net, port);
239 if (IS_ERR(sock))
240 return PTR_ERR(sock);
241
242 /* Mark socket as an encapsulation socket */
243 memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
244 tunnel_cfg.sk_user_data = bareudp;
245 tunnel_cfg.encap_type = 1;
246 tunnel_cfg.encap_rcv = bareudp_udp_encap_recv;
247 tunnel_cfg.encap_err_lookup = bareudp_err_lookup;
248 tunnel_cfg.encap_destroy = NULL;
249 setup_udp_tunnel_sock(bareudp->net, sock, &tunnel_cfg);
250
Martin Varghese81f954a2020-03-12 08:33:51 +0530251 /* As the setup_udp_tunnel_sock does not call udp_encap_enable if the
252 * socket type is v6 an explicit call to udp_encap_enable is needed.
253 */
254 if (sock->sk->sk_family == AF_INET6)
255 udp_encap_enable();
256
Martin Varghese571912c2020-02-24 10:57:50 +0530257 rcu_assign_pointer(bareudp->sock, sock);
258 return 0;
259}
260
261static int bareudp_open(struct net_device *dev)
262{
263 struct bareudp_dev *bareudp = netdev_priv(dev);
264 int ret = 0;
265
266 ret = bareudp_socket_create(bareudp, bareudp->port);
267 return ret;
268}
269
270static void bareudp_sock_release(struct bareudp_dev *bareudp)
271{
272 struct socket *sock;
273
274 sock = bareudp->sock;
275 rcu_assign_pointer(bareudp->sock, NULL);
276 synchronize_net();
277 udp_tunnel_sock_release(sock);
278}
279
280static int bareudp_stop(struct net_device *dev)
281{
282 struct bareudp_dev *bareudp = netdev_priv(dev);
283
284 bareudp_sock_release(bareudp);
285 return 0;
286}
287
288static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
289 struct bareudp_dev *bareudp,
290 const struct ip_tunnel_info *info)
291{
292 bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev));
293 bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
294 struct socket *sock = rcu_dereference(bareudp->sock);
295 bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
296 const struct ip_tunnel_key *key = &info->key;
297 struct rtable *rt;
298 __be16 sport, df;
299 int min_headroom;
300 __u8 tos, ttl;
301 __be32 saddr;
302 int err;
303
304 if (!sock)
305 return -ESHUTDOWN;
306
307 rt = ip_route_output_tunnel(skb, dev, bareudp->net, &saddr, info,
308 IPPROTO_UDP, use_cache);
309
310 if (IS_ERR(rt))
311 return PTR_ERR(rt);
312
313 skb_tunnel_check_pmtu(skb, &rt->dst,
314 BAREUDP_IPV4_HLEN + info->options_len);
315
316 sport = udp_flow_src_port(bareudp->net, skb,
317 bareudp->sport_min, USHRT_MAX,
318 true);
319 tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
320 ttl = key->ttl;
321 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
322 skb_scrub_packet(skb, xnet);
323
David S. Millerc102b6f2020-02-24 14:40:54 -0800324 err = -ENOSPC;
Martin Varghese571912c2020-02-24 10:57:50 +0530325 if (!skb_pull(skb, skb_network_offset(skb)))
326 goto free_dst;
327
328 min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len +
329 BAREUDP_BASE_HLEN + info->options_len + sizeof(struct iphdr);
330
331 err = skb_cow_head(skb, min_headroom);
332 if (unlikely(err))
333 goto free_dst;
334
335 err = udp_tunnel_handle_offloads(skb, udp_sum);
336 if (err)
337 goto free_dst;
338
339 skb_set_inner_protocol(skb, bareudp->ethertype);
340 udp_tunnel_xmit_skb(rt, sock->sk, skb, saddr, info->key.u.ipv4.dst,
341 tos, ttl, df, sport, bareudp->port,
342 !net_eq(bareudp->net, dev_net(bareudp->dev)),
343 !(info->key.tun_flags & TUNNEL_CSUM));
344 return 0;
345
346free_dst:
347 dst_release(&rt->dst);
348 return err;
349}
350
Martin Varghese571912c2020-02-24 10:57:50 +0530351static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
352 struct bareudp_dev *bareudp,
353 const struct ip_tunnel_info *info)
354{
355 bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev));
356 bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
357 struct socket *sock = rcu_dereference(bareudp->sock);
358 bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
359 const struct ip_tunnel_key *key = &info->key;
360 struct dst_entry *dst = NULL;
361 struct in6_addr saddr, daddr;
362 int min_headroom;
363 __u8 prio, ttl;
364 __be16 sport;
365 int err;
366
367 if (!sock)
368 return -ESHUTDOWN;
369
370 dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock, &saddr, info,
371 IPPROTO_UDP, use_cache);
372 if (IS_ERR(dst))
373 return PTR_ERR(dst);
374
375 skb_tunnel_check_pmtu(skb, dst, BAREUDP_IPV6_HLEN + info->options_len);
376
377 sport = udp_flow_src_port(bareudp->net, skb,
378 bareudp->sport_min, USHRT_MAX,
379 true);
380 prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
381 ttl = key->ttl;
382
383 skb_scrub_packet(skb, xnet);
384
David S. Millerc102b6f2020-02-24 14:40:54 -0800385 err = -ENOSPC;
Martin Varghese571912c2020-02-24 10:57:50 +0530386 if (!skb_pull(skb, skb_network_offset(skb)))
387 goto free_dst;
388
389 min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
390 BAREUDP_BASE_HLEN + info->options_len + sizeof(struct iphdr);
391
392 err = skb_cow_head(skb, min_headroom);
393 if (unlikely(err))
394 goto free_dst;
395
396 err = udp_tunnel_handle_offloads(skb, udp_sum);
397 if (err)
398 goto free_dst;
399
400 daddr = info->key.u.ipv6.dst;
401 udp_tunnel6_xmit_skb(dst, sock->sk, skb, dev,
402 &saddr, &daddr, prio, ttl,
403 info->key.label, sport, bareudp->port,
404 !(info->key.tun_flags & TUNNEL_CSUM));
405 return 0;
406
407free_dst:
408 dst_release(dst);
409 return err;
410}
Martin Varghese571912c2020-02-24 10:57:50 +0530411
412static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev)
413{
414 struct bareudp_dev *bareudp = netdev_priv(dev);
415 struct ip_tunnel_info *info = NULL;
416 int err;
417
418 if (skb->protocol != bareudp->ethertype) {
Martin Varghese4b5f6722020-02-24 10:58:35 +0530419 if (!bareudp->multi_proto_mode ||
420 (skb->protocol != htons(ETH_P_MPLS_MC) &&
421 skb->protocol != htons(ETH_P_IPV6))) {
422 err = -EINVAL;
423 goto tx_error;
424 }
Martin Varghese571912c2020-02-24 10:57:50 +0530425 }
426
427 info = skb_tunnel_info(skb);
428 if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
429 err = -EINVAL;
430 goto tx_error;
431 }
432
433 rcu_read_lock();
Arnd Bergmannee287552020-05-05 19:22:14 +0200434 if (IS_ENABLED(CONFIG_IPV6) && info->mode & IP_TUNNEL_INFO_IPV6)
Martin Varghese571912c2020-02-24 10:57:50 +0530435 err = bareudp6_xmit_skb(skb, dev, bareudp, info);
436 else
Martin Varghese571912c2020-02-24 10:57:50 +0530437 err = bareudp_xmit_skb(skb, dev, bareudp, info);
438
439 rcu_read_unlock();
440
441 if (likely(!err))
442 return NETDEV_TX_OK;
443tx_error:
444 dev_kfree_skb(skb);
445
446 if (err == -ELOOP)
447 dev->stats.collisions++;
448 else if (err == -ENETUNREACH)
449 dev->stats.tx_carrier_errors++;
450
451 dev->stats.tx_errors++;
452 return NETDEV_TX_OK;
453}
454
455static int bareudp_fill_metadata_dst(struct net_device *dev,
456 struct sk_buff *skb)
457{
458 struct ip_tunnel_info *info = skb_tunnel_info(skb);
459 struct bareudp_dev *bareudp = netdev_priv(dev);
460 bool use_cache;
461
462 use_cache = ip_tunnel_dst_cache_usable(skb, info);
463
Arnd Bergmannee287552020-05-05 19:22:14 +0200464 if (!IS_ENABLED(CONFIG_IPV6) || ip_tunnel_info_af(info) == AF_INET) {
Martin Varghese571912c2020-02-24 10:57:50 +0530465 struct rtable *rt;
466 __be32 saddr;
467
468 rt = ip_route_output_tunnel(skb, dev, bareudp->net, &saddr,
469 info, IPPROTO_UDP, use_cache);
470 if (IS_ERR(rt))
471 return PTR_ERR(rt);
472
473 ip_rt_put(rt);
474 info->key.u.ipv4.src = saddr;
Martin Varghese571912c2020-02-24 10:57:50 +0530475 } else if (ip_tunnel_info_af(info) == AF_INET6) {
476 struct dst_entry *dst;
477 struct in6_addr saddr;
478 struct socket *sock = rcu_dereference(bareudp->sock);
479
480 dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock,
481 &saddr, info, IPPROTO_UDP,
482 use_cache);
483 if (IS_ERR(dst))
484 return PTR_ERR(dst);
485
486 dst_release(dst);
487 info->key.u.ipv6.src = saddr;
Martin Varghese571912c2020-02-24 10:57:50 +0530488 } else {
489 return -EINVAL;
490 }
491
492 info->key.tp_src = udp_flow_src_port(bareudp->net, skb,
493 bareudp->sport_min,
494 USHRT_MAX, true);
495 info->key.tp_dst = bareudp->port;
496 return 0;
497}
498
499static const struct net_device_ops bareudp_netdev_ops = {
500 .ndo_init = bareudp_init,
501 .ndo_uninit = bareudp_uninit,
502 .ndo_open = bareudp_open,
503 .ndo_stop = bareudp_stop,
504 .ndo_start_xmit = bareudp_xmit,
505 .ndo_get_stats64 = ip_tunnel_get_stats64,
506 .ndo_fill_metadata_dst = bareudp_fill_metadata_dst,
507};
508
509static const struct nla_policy bareudp_policy[IFLA_BAREUDP_MAX + 1] = {
510 [IFLA_BAREUDP_PORT] = { .type = NLA_U16 },
511 [IFLA_BAREUDP_ETHERTYPE] = { .type = NLA_U16 },
512 [IFLA_BAREUDP_SRCPORT_MIN] = { .type = NLA_U16 },
Martin Varghese4b5f6722020-02-24 10:58:35 +0530513 [IFLA_BAREUDP_MULTIPROTO_MODE] = { .type = NLA_FLAG },
Martin Varghese571912c2020-02-24 10:57:50 +0530514};
515
516/* Info for udev, that this is a virtual tunnel endpoint */
517static struct device_type bareudp_type = {
518 .name = "bareudp",
519};
520
521/* Initialize the device structure. */
522static void bareudp_setup(struct net_device *dev)
523{
524 dev->netdev_ops = &bareudp_netdev_ops;
525 dev->needs_free_netdev = true;
526 SET_NETDEV_DEVTYPE(dev, &bareudp_type);
527 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
528 dev->features |= NETIF_F_RXCSUM;
529 dev->features |= NETIF_F_GSO_SOFTWARE;
530 dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
531 dev->hw_features |= NETIF_F_GSO_SOFTWARE;
532 dev->hard_header_len = 0;
533 dev->addr_len = 0;
534 dev->mtu = ETH_DATA_LEN;
535 dev->min_mtu = IPV4_MIN_MTU;
536 dev->max_mtu = IP_MAX_MTU - BAREUDP_BASE_HLEN;
537 dev->type = ARPHRD_NONE;
538 netif_keep_dst(dev);
539 dev->priv_flags |= IFF_NO_QUEUE;
540 dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
541}
542
543static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
544 struct netlink_ext_ack *extack)
545{
546 if (!data) {
547 NL_SET_ERR_MSG(extack,
548 "Not enough attributes provided to perform the operation");
549 return -EINVAL;
550 }
551 return 0;
552}
553
Taehee Yooc46a49a2020-03-08 01:19:17 +0000554static int bareudp2info(struct nlattr *data[], struct bareudp_conf *conf,
555 struct netlink_ext_ack *extack)
Martin Varghese571912c2020-02-24 10:57:50 +0530556{
Martinb15bb882020-06-16 11:18:58 +0530557 memset(conf, 0, sizeof(*conf));
558
Taehee Yooc46a49a2020-03-08 01:19:17 +0000559 if (!data[IFLA_BAREUDP_PORT]) {
560 NL_SET_ERR_MSG(extack, "port not specified");
Martin Varghese571912c2020-02-24 10:57:50 +0530561 return -EINVAL;
Taehee Yooc46a49a2020-03-08 01:19:17 +0000562 }
563 if (!data[IFLA_BAREUDP_ETHERTYPE]) {
564 NL_SET_ERR_MSG(extack, "ethertype not specified");
565 return -EINVAL;
566 }
Martin Varghese571912c2020-02-24 10:57:50 +0530567
568 if (data[IFLA_BAREUDP_PORT])
569 conf->port = nla_get_u16(data[IFLA_BAREUDP_PORT]);
570
571 if (data[IFLA_BAREUDP_ETHERTYPE])
572 conf->ethertype = nla_get_u16(data[IFLA_BAREUDP_ETHERTYPE]);
573
574 if (data[IFLA_BAREUDP_SRCPORT_MIN])
575 conf->sport_min = nla_get_u16(data[IFLA_BAREUDP_SRCPORT_MIN]);
576
Martin4c980452020-06-17 22:30:23 +0530577 if (data[IFLA_BAREUDP_MULTIPROTO_MODE])
578 conf->multi_proto_mode = true;
579
Martinfe805362020-06-28 23:18:23 +0530580 if (data[IFLA_BAREUDP_RX_COLLECT_METADATA])
581 conf->rx_collect_metadata = true;
582
Martin Varghese571912c2020-02-24 10:57:50 +0530583 return 0;
584}
585
586static struct bareudp_dev *bareudp_find_dev(struct bareudp_net *bn,
587 const struct bareudp_conf *conf)
588{
589 struct bareudp_dev *bareudp, *t = NULL;
590
591 list_for_each_entry(bareudp, &bn->bareudp_list, next) {
592 if (conf->port == bareudp->port)
593 t = bareudp;
594 }
595 return t;
596}
597
598static int bareudp_configure(struct net *net, struct net_device *dev,
599 struct bareudp_conf *conf)
600{
601 struct bareudp_net *bn = net_generic(net, bareudp_net_id);
602 struct bareudp_dev *t, *bareudp = netdev_priv(dev);
603 int err;
604
605 bareudp->net = net;
606 bareudp->dev = dev;
607 t = bareudp_find_dev(bn, conf);
608 if (t)
609 return -EBUSY;
610
Martin Varghese4b5f6722020-02-24 10:58:35 +0530611 if (conf->multi_proto_mode &&
612 (conf->ethertype != htons(ETH_P_MPLS_UC) &&
613 conf->ethertype != htons(ETH_P_IP)))
614 return -EINVAL;
615
Martin Varghese571912c2020-02-24 10:57:50 +0530616 bareudp->port = conf->port;
617 bareudp->ethertype = conf->ethertype;
618 bareudp->sport_min = conf->sport_min;
Martin Varghese4b5f6722020-02-24 10:58:35 +0530619 bareudp->multi_proto_mode = conf->multi_proto_mode;
Martinfe805362020-06-28 23:18:23 +0530620 bareudp->rx_collect_metadata = conf->rx_collect_metadata;
621
Martin Varghese571912c2020-02-24 10:57:50 +0530622 err = register_netdevice(dev);
623 if (err)
624 return err;
625
626 list_add(&bareudp->next, &bn->bareudp_list);
627 return 0;
628}
629
630static int bareudp_link_config(struct net_device *dev,
631 struct nlattr *tb[])
632{
633 int err;
634
635 if (tb[IFLA_MTU]) {
636 err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
637 if (err)
638 return err;
639 }
640 return 0;
641}
642
643static int bareudp_newlink(struct net *net, struct net_device *dev,
644 struct nlattr *tb[], struct nlattr *data[],
645 struct netlink_ext_ack *extack)
646{
647 struct bareudp_conf conf;
648 int err;
649
Taehee Yooc46a49a2020-03-08 01:19:17 +0000650 err = bareudp2info(data, &conf, extack);
Martin Varghese571912c2020-02-24 10:57:50 +0530651 if (err)
652 return err;
653
654 err = bareudp_configure(net, dev, &conf);
655 if (err)
656 return err;
657
658 err = bareudp_link_config(dev, tb);
659 if (err)
660 return err;
661
662 return 0;
663}
664
665static void bareudp_dellink(struct net_device *dev, struct list_head *head)
666{
667 struct bareudp_dev *bareudp = netdev_priv(dev);
668
669 list_del(&bareudp->next);
670 unregister_netdevice_queue(dev, head);
671}
672
673static size_t bareudp_get_size(const struct net_device *dev)
674{
675 return nla_total_size(sizeof(__be16)) + /* IFLA_BAREUDP_PORT */
676 nla_total_size(sizeof(__be16)) + /* IFLA_BAREUDP_ETHERTYPE */
677 nla_total_size(sizeof(__u16)) + /* IFLA_BAREUDP_SRCPORT_MIN */
Martin Varghese4b5f6722020-02-24 10:58:35 +0530678 nla_total_size(0) + /* IFLA_BAREUDP_MULTIPROTO_MODE */
Martinfe805362020-06-28 23:18:23 +0530679 nla_total_size(0) + /* IFLA_BAREUDP_RX_COLLECT_METADATA */
Martin Varghese571912c2020-02-24 10:57:50 +0530680 0;
681}
682
683static int bareudp_fill_info(struct sk_buff *skb, const struct net_device *dev)
684{
685 struct bareudp_dev *bareudp = netdev_priv(dev);
686
687 if (nla_put_be16(skb, IFLA_BAREUDP_PORT, bareudp->port))
688 goto nla_put_failure;
689 if (nla_put_be16(skb, IFLA_BAREUDP_ETHERTYPE, bareudp->ethertype))
690 goto nla_put_failure;
691 if (nla_put_u16(skb, IFLA_BAREUDP_SRCPORT_MIN, bareudp->sport_min))
692 goto nla_put_failure;
Martin Varghese4b5f6722020-02-24 10:58:35 +0530693 if (bareudp->multi_proto_mode &&
694 nla_put_flag(skb, IFLA_BAREUDP_MULTIPROTO_MODE))
695 goto nla_put_failure;
Martinfe805362020-06-28 23:18:23 +0530696 if (bareudp->rx_collect_metadata &&
697 nla_put_flag(skb, IFLA_BAREUDP_RX_COLLECT_METADATA))
698 goto nla_put_failure;
Martin Varghese571912c2020-02-24 10:57:50 +0530699
700 return 0;
701
702nla_put_failure:
703 return -EMSGSIZE;
704}
705
706static struct rtnl_link_ops bareudp_link_ops __read_mostly = {
707 .kind = "bareudp",
708 .maxtype = IFLA_BAREUDP_MAX,
709 .policy = bareudp_policy,
710 .priv_size = sizeof(struct bareudp_dev),
711 .setup = bareudp_setup,
712 .validate = bareudp_validate,
713 .newlink = bareudp_newlink,
714 .dellink = bareudp_dellink,
715 .get_size = bareudp_get_size,
716 .fill_info = bareudp_fill_info,
717};
718
719struct net_device *bareudp_dev_create(struct net *net, const char *name,
720 u8 name_assign_type,
721 struct bareudp_conf *conf)
722{
723 struct nlattr *tb[IFLA_MAX + 1];
724 struct net_device *dev;
725 LIST_HEAD(list_kill);
726 int err;
727
728 memset(tb, 0, sizeof(tb));
729 dev = rtnl_create_link(net, name, name_assign_type,
730 &bareudp_link_ops, tb, NULL);
731 if (IS_ERR(dev))
732 return dev;
733
734 err = bareudp_configure(net, dev, conf);
735 if (err) {
736 free_netdev(dev);
737 return ERR_PTR(err);
738 }
739 err = dev_set_mtu(dev, IP_MAX_MTU - BAREUDP_BASE_HLEN);
740 if (err)
741 goto err;
742
743 err = rtnl_configure_link(dev, NULL);
744 if (err < 0)
745 goto err;
746
747 return dev;
748err:
749 bareudp_dellink(dev, &list_kill);
750 unregister_netdevice_many(&list_kill);
751 return ERR_PTR(err);
752}
753EXPORT_SYMBOL_GPL(bareudp_dev_create);
754
755static __net_init int bareudp_init_net(struct net *net)
756{
757 struct bareudp_net *bn = net_generic(net, bareudp_net_id);
758
759 INIT_LIST_HEAD(&bn->bareudp_list);
760 return 0;
761}
762
763static void bareudp_destroy_tunnels(struct net *net, struct list_head *head)
764{
765 struct bareudp_net *bn = net_generic(net, bareudp_net_id);
766 struct bareudp_dev *bareudp, *next;
767
768 list_for_each_entry_safe(bareudp, next, &bn->bareudp_list, next)
769 unregister_netdevice_queue(bareudp->dev, head);
770}
771
772static void __net_exit bareudp_exit_batch_net(struct list_head *net_list)
773{
774 struct net *net;
775 LIST_HEAD(list);
776
777 rtnl_lock();
778 list_for_each_entry(net, net_list, exit_list)
779 bareudp_destroy_tunnels(net, &list);
780
781 /* unregister the devices gathered above */
782 unregister_netdevice_many(&list);
783 rtnl_unlock();
784}
785
786static struct pernet_operations bareudp_net_ops = {
787 .init = bareudp_init_net,
788 .exit_batch = bareudp_exit_batch_net,
789 .id = &bareudp_net_id,
790 .size = sizeof(struct bareudp_net),
791};
792
793static int __init bareudp_init_module(void)
794{
795 int rc;
796
797 rc = register_pernet_subsys(&bareudp_net_ops);
798 if (rc)
799 goto out1;
800
801 rc = rtnl_link_register(&bareudp_link_ops);
802 if (rc)
803 goto out2;
804
805 return 0;
806out2:
807 unregister_pernet_subsys(&bareudp_net_ops);
808out1:
809 return rc;
810}
811late_initcall(bareudp_init_module);
812
813static void __exit bareudp_cleanup_module(void)
814{
815 rtnl_link_unregister(&bareudp_link_ops);
816 unregister_pernet_subsys(&bareudp_net_ops);
817}
818module_exit(bareudp_cleanup_module);
819
Taehee Yooeea45da2020-03-08 01:19:07 +0000820MODULE_ALIAS_RTNL_LINK("bareudp");
Martin Varghese571912c2020-02-24 10:57:50 +0530821MODULE_LICENSE("GPL");
822MODULE_AUTHOR("Martin Varghese <martin.varghese@nokia.com>");
823MODULE_DESCRIPTION("Interface driver for UDP encapsulated traffic");