VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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