aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-11-04 12:06:51 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-05 16:30:02 -0500
commit63487babf08d6d67483c67ed21d8cea6674a44ec (patch)
treef0e11d54e33a689a25bed43f7bd3c720b49a6bcd
parent890b7916d0965829ad1c457aa61f049a210c19f8 (diff)
net: Move fou_build_header into fou.c and refactor
Move fou_build_header out of ip_tunnel.c and into fou.c splitting it up into fou_build_header, gue_build_header, and fou_build_udp. This allows for other users for TX of FOU or GUE. Change ip_tunnel_encap to call fou_build_header or gue_build_header based on the tunnel encapsulation type. Similarly, added fou_encap_hlen and gue_encap_hlen functions which are called by ip_encap_hlen. New net/fou.h has prototypes and defines for this. Added NET_FOU_IP_TUNNELS configuration. When this is set, IP tunnels can use FOU/GUE and fou module is also selected. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/fou.h26
-rw-r--r--net/ipv4/Kconfig9
-rw-r--r--net/ipv4/fou.c73
-rw-r--r--net/ipv4/ip_tunnel.c61
4 files changed, 120 insertions, 49 deletions
diff --git a/include/net/fou.h b/include/net/fou.h
new file mode 100644
index 000000000000..cf4ce8874f92
--- /dev/null
+++ b/include/net/fou.h
@@ -0,0 +1,26 @@
1#ifndef __NET_FOU_H
2#define __NET_FOU_H
3
4#include <linux/skbuff.h>
5
6#include <net/flow.h>
7#include <net/gue.h>
8#include <net/ip_tunnels.h>
9#include <net/udp.h>
10
11int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
12 u8 *protocol, struct flowi4 *fl4);
13int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
14 u8 *protocol, struct flowi4 *fl4);
15
16static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
17{
18 return sizeof(struct udphdr);
19}
20
21static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
22{
23 return sizeof(struct udphdr) + sizeof(struct guehdr);
24}
25
26#endif
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e682b48e0709..bd2901604842 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -322,6 +322,15 @@ config NET_FOU
322 network mechanisms and optimizations for UDP (such as ECMP 322 network mechanisms and optimizations for UDP (such as ECMP
323 and RSS) can be leveraged to provide better service. 323 and RSS) can be leveraged to provide better service.
324 324
325config NET_FOU_IP_TUNNELS
326 bool "IP: FOU encapsulation of IP tunnels"
327 depends on NET_IPIP || NET_IPGRE || IPV6_SIT
328 select NET_FOU
329 ---help---
330 Allow configuration of FOU or GUE encapsulation for IP tunnels.
331 When this option is enabled IP tunnels can be configured to use
332 FOU or GUE encapsulation.
333
325config GENEVE 334config GENEVE
326 tristate "Generic Network Virtualization Encapsulation (Geneve)" 335 tristate "Generic Network Virtualization Encapsulation (Geneve)"
327 depends on INET 336 depends on INET
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 32e78924e246..5446c1c8c26c 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -487,6 +487,79 @@ static const struct genl_ops fou_nl_ops[] = {
487 }, 487 },
488}; 488};
489 489
490static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
491 struct flowi4 *fl4, u8 *protocol, __be16 sport)
492{
493 struct udphdr *uh;
494
495 skb_push(skb, sizeof(struct udphdr));
496 skb_reset_transport_header(skb);
497
498 uh = udp_hdr(skb);
499
500 uh->dest = e->dport;
501 uh->source = sport;
502 uh->len = htons(skb->len);
503 uh->check = 0;
504 udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
505 fl4->saddr, fl4->daddr, skb->len);
506
507 *protocol = IPPROTO_UDP;
508}
509
510int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
511 u8 *protocol, struct flowi4 *fl4)
512{
513 bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
514 int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
515 __be16 sport;
516
517 skb = iptunnel_handle_offloads(skb, csum, type);
518
519 if (IS_ERR(skb))
520 return PTR_ERR(skb);
521
522 sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
523 skb, 0, 0, false);
524 fou_build_udp(skb, e, fl4, protocol, sport);
525
526 return 0;
527}
528EXPORT_SYMBOL(fou_build_header);
529
530int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
531 u8 *protocol, struct flowi4 *fl4)
532{
533 bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
534 int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
535 struct guehdr *guehdr;
536 size_t hdr_len = sizeof(struct guehdr);
537 __be16 sport;
538
539 skb = iptunnel_handle_offloads(skb, csum, type);
540
541 if (IS_ERR(skb))
542 return PTR_ERR(skb);
543
544 /* Get source port (based on flow hash) before skb_push */
545 sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
546 skb, 0, 0, false);
547
548 skb_push(skb, hdr_len);
549
550 guehdr = (struct guehdr *)skb->data;
551
552 guehdr->version = 0;
553 guehdr->hlen = 0;
554 guehdr->flags = 0;
555 guehdr->next_hdr = *protocol;
556
557 fou_build_udp(skb, e, fl4, protocol, sport);
558
559 return 0;
560}
561EXPORT_SYMBOL(gue_build_header);
562
490static int __init fou_init(void) 563static int __init fou_init(void)
491{ 564{
492 int ret; 565 int ret;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 0bb8e141eacc..c3587e1c8b82 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -56,7 +56,10 @@
56#include <net/netns/generic.h> 56#include <net/netns/generic.h>
57#include <net/rtnetlink.h> 57#include <net/rtnetlink.h>
58#include <net/udp.h> 58#include <net/udp.h>
59#include <net/gue.h> 59
60#if IS_ENABLED(CONFIG_NET_FOU)
61#include <net/fou.h>
62#endif
60 63
61#if IS_ENABLED(CONFIG_IPV6) 64#if IS_ENABLED(CONFIG_IPV6)
62#include <net/ipv6.h> 65#include <net/ipv6.h>
@@ -494,10 +497,12 @@ static int ip_encap_hlen(struct ip_tunnel_encap *e)
494 switch (e->type) { 497 switch (e->type) {
495 case TUNNEL_ENCAP_NONE: 498 case TUNNEL_ENCAP_NONE:
496 return 0; 499 return 0;
500#if IS_ENABLED(CONFIG_NET_FOU)
497 case TUNNEL_ENCAP_FOU: 501 case TUNNEL_ENCAP_FOU:
498 return sizeof(struct udphdr); 502 return fou_encap_hlen(e);
499 case TUNNEL_ENCAP_GUE: 503 case TUNNEL_ENCAP_GUE:
500 return sizeof(struct udphdr) + sizeof(struct guehdr); 504 return gue_encap_hlen(e);
505#endif
501 default: 506 default:
502 return -EINVAL; 507 return -EINVAL;
503 } 508 }
@@ -526,60 +531,18 @@ int ip_tunnel_encap_setup(struct ip_tunnel *t,
526} 531}
527EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup); 532EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
528 533
529static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
530 size_t hdr_len, u8 *protocol, struct flowi4 *fl4)
531{
532 struct udphdr *uh;
533 __be16 sport;
534 bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
535 int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
536
537 skb = iptunnel_handle_offloads(skb, csum, type);
538
539 if (IS_ERR(skb))
540 return PTR_ERR(skb);
541
542 /* Get length and hash before making space in skb */
543
544 sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
545 skb, 0, 0, false);
546
547 skb_push(skb, hdr_len);
548
549 skb_reset_transport_header(skb);
550 uh = udp_hdr(skb);
551
552 if (e->type == TUNNEL_ENCAP_GUE) {
553 struct guehdr *guehdr = (struct guehdr *)&uh[1];
554
555 guehdr->version = 0;
556 guehdr->hlen = 0;
557 guehdr->flags = 0;
558 guehdr->next_hdr = *protocol;
559 }
560
561 uh->dest = e->dport;
562 uh->source = sport;
563 uh->len = htons(skb->len);
564 uh->check = 0;
565 udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
566 fl4->saddr, fl4->daddr, skb->len);
567
568 *protocol = IPPROTO_UDP;
569
570 return 0;
571}
572
573int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, 534int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
574 u8 *protocol, struct flowi4 *fl4) 535 u8 *protocol, struct flowi4 *fl4)
575{ 536{
576 switch (t->encap.type) { 537 switch (t->encap.type) {
577 case TUNNEL_ENCAP_NONE: 538 case TUNNEL_ENCAP_NONE:
578 return 0; 539 return 0;
540#if IS_ENABLED(CONFIG_NET_FOU)
579 case TUNNEL_ENCAP_FOU: 541 case TUNNEL_ENCAP_FOU:
542 return fou_build_header(skb, &t->encap, protocol, fl4);
580 case TUNNEL_ENCAP_GUE: 543 case TUNNEL_ENCAP_GUE:
581 return fou_build_header(skb, &t->encap, t->encap_hlen, 544 return gue_build_header(skb, &t->encap, protocol, fl4);
582 protocol, fl4); 545#endif
583 default: 546 default:
584 return -EINVAL; 547 return -EINVAL;
585 } 548 }