Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fou: Add encap ops for IPv6 tunnels

This patch add a new fou6 module that provides encapsulation
operations for IPv6.

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tom Herbert and committed by
David S. Miller
aa3463d6 058214a4

+142 -1
+1 -1
include/net/fou.h
··· 9 9 #include <net/udp.h> 10 10 11 11 size_t fou_encap_hlen(struct ip_tunnel_encap *e); 12 - static size_t gue_encap_hlen(struct ip_tunnel_encap *e); 12 + size_t gue_encap_hlen(struct ip_tunnel_encap *e); 13 13 14 14 int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, 15 15 u8 *protocol, __be16 *sport, int type);
+1
net/ipv6/Makefile
··· 42 42 obj-$(CONFIG_IPV6_SIT) += sit.o 43 43 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 44 44 obj-$(CONFIG_IPV6_GRE) += ip6_gre.o 45 + obj-$(CONFIG_NET_FOU) += fou6.o 45 46 46 47 obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o 47 48 obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
+140
net/ipv6/fou6.c
··· 1 + #include <linux/module.h> 2 + #include <linux/errno.h> 3 + #include <linux/socket.h> 4 + #include <linux/skbuff.h> 5 + #include <linux/ip.h> 6 + #include <linux/udp.h> 7 + #include <linux/types.h> 8 + #include <linux/kernel.h> 9 + #include <net/fou.h> 10 + #include <net/ip.h> 11 + #include <net/ip6_tunnel.h> 12 + #include <net/ip6_checksum.h> 13 + #include <net/protocol.h> 14 + #include <net/udp.h> 15 + #include <net/udp_tunnel.h> 16 + 17 + static void fou6_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e, 18 + struct flowi6 *fl6, u8 *protocol, __be16 sport) 19 + { 20 + struct udphdr *uh; 21 + 22 + skb_push(skb, sizeof(struct udphdr)); 23 + skb_reset_transport_header(skb); 24 + 25 + uh = udp_hdr(skb); 26 + 27 + uh->dest = e->dport; 28 + uh->source = sport; 29 + uh->len = htons(skb->len); 30 + udp6_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM6), skb, 31 + &fl6->saddr, &fl6->daddr, skb->len); 32 + 33 + *protocol = IPPROTO_UDP; 34 + } 35 + 36 + int fou6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, 37 + u8 *protocol, struct flowi6 *fl6) 38 + { 39 + __be16 sport; 40 + int err; 41 + int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ? 42 + SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 43 + 44 + err = __fou_build_header(skb, e, protocol, &sport, type); 45 + if (err) 46 + return err; 47 + 48 + fou6_build_udp(skb, e, fl6, protocol, sport); 49 + 50 + return 0; 51 + } 52 + EXPORT_SYMBOL(fou6_build_header); 53 + 54 + int gue6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, 55 + u8 *protocol, struct flowi6 *fl6) 56 + { 57 + __be16 sport; 58 + int err; 59 + int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ? 60 + SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 61 + 62 + err = __gue_build_header(skb, e, protocol, &sport, type); 63 + if (err) 64 + return err; 65 + 66 + fou6_build_udp(skb, e, fl6, protocol, sport); 67 + 68 + return 0; 69 + } 70 + EXPORT_SYMBOL(gue6_build_header); 71 + 72 + #ifdef CONFIG_NET_FOU_IP_TUNNELS 73 + 74 + static const struct ip6_tnl_encap_ops fou_ip6tun_ops = { 75 + .encap_hlen = fou_encap_hlen, 76 + .build_header = fou6_build_header, 77 + }; 78 + 79 + static const struct ip6_tnl_encap_ops gue_ip6tun_ops = { 80 + .encap_hlen = gue_encap_hlen, 81 + .build_header = gue6_build_header, 82 + }; 83 + 84 + static int ip6_tnl_encap_add_fou_ops(void) 85 + { 86 + int ret; 87 + 88 + ret = ip6_tnl_encap_add_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU); 89 + if (ret < 0) { 90 + pr_err("can't add fou6 ops\n"); 91 + return ret; 92 + } 93 + 94 + ret = ip6_tnl_encap_add_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE); 95 + if (ret < 0) { 96 + pr_err("can't add gue6 ops\n"); 97 + ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU); 98 + return ret; 99 + } 100 + 101 + return 0; 102 + } 103 + 104 + static void ip6_tnl_encap_del_fou_ops(void) 105 + { 106 + ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU); 107 + ip6_tnl_encap_del_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE); 108 + } 109 + 110 + #else 111 + 112 + static int ip6_tnl_encap_add_fou_ops(void) 113 + { 114 + return 0; 115 + } 116 + 117 + static void ip6_tnl_encap_del_fou_ops(void) 118 + { 119 + } 120 + 121 + #endif 122 + 123 + static int __init fou6_init(void) 124 + { 125 + int ret; 126 + 127 + ret = ip6_tnl_encap_add_fou_ops(); 128 + 129 + return ret; 130 + } 131 + 132 + static void __exit fou6_fini(void) 133 + { 134 + ip6_tnl_encap_del_fou_ops(); 135 + } 136 + 137 + module_init(fou6_init); 138 + module_exit(fou6_fini); 139 + MODULE_AUTHOR("Tom Herbert <therbert@google.com>"); 140 + MODULE_LICENSE("GPL");