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");