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