Skip to content

Commit

Permalink
net: Move fou_build_header into fou.c and refactor
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tom Herbert authored and David S. Miller committed Nov 5, 2014
1 parent 890b791 commit 63487ba
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 49 deletions.
26 changes: 26 additions & 0 deletions include/net/fou.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef __NET_FOU_H
#define __NET_FOU_H

#include <linux/skbuff.h>

#include <net/flow.h>
#include <net/gue.h>
#include <net/ip_tunnels.h>
#include <net/udp.h>

int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, struct flowi4 *fl4);
int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, struct flowi4 *fl4);

static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
{
return sizeof(struct udphdr);
}

static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
{
return sizeof(struct udphdr) + sizeof(struct guehdr);
}

#endif
9 changes: 9 additions & 0 deletions net/ipv4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,15 @@ config NET_FOU
network mechanisms and optimizations for UDP (such as ECMP
and RSS) can be leveraged to provide better service.

config NET_FOU_IP_TUNNELS
bool "IP: FOU encapsulation of IP tunnels"
depends on NET_IPIP || NET_IPGRE || IPV6_SIT
select NET_FOU
---help---
Allow configuration of FOU or GUE encapsulation for IP tunnels.
When this option is enabled IP tunnels can be configured to use
FOU or GUE encapsulation.

config GENEVE
tristate "Generic Network Virtualization Encapsulation (Geneve)"
depends on INET
Expand Down
73 changes: 73 additions & 0 deletions net/ipv4/fou.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,79 @@ static const struct genl_ops fou_nl_ops[] = {
},
};

static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
struct flowi4 *fl4, u8 *protocol, __be16 sport)
{
struct udphdr *uh;

skb_push(skb, sizeof(struct udphdr));
skb_reset_transport_header(skb);

uh = udp_hdr(skb);

uh->dest = e->dport;
uh->source = sport;
uh->len = htons(skb->len);
uh->check = 0;
udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
fl4->saddr, fl4->daddr, skb->len);

*protocol = IPPROTO_UDP;
}

int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, struct flowi4 *fl4)
{
bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
__be16 sport;

skb = iptunnel_handle_offloads(skb, csum, type);

if (IS_ERR(skb))
return PTR_ERR(skb);

sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
skb, 0, 0, false);
fou_build_udp(skb, e, fl4, protocol, sport);

return 0;
}
EXPORT_SYMBOL(fou_build_header);

int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, struct flowi4 *fl4)
{
bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
struct guehdr *guehdr;
size_t hdr_len = sizeof(struct guehdr);
__be16 sport;

skb = iptunnel_handle_offloads(skb, csum, type);

if (IS_ERR(skb))
return PTR_ERR(skb);

/* Get source port (based on flow hash) before skb_push */
sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
skb, 0, 0, false);

skb_push(skb, hdr_len);

guehdr = (struct guehdr *)skb->data;

guehdr->version = 0;
guehdr->hlen = 0;
guehdr->flags = 0;
guehdr->next_hdr = *protocol;

fou_build_udp(skb, e, fl4, protocol, sport);

return 0;
}
EXPORT_SYMBOL(gue_build_header);

static int __init fou_init(void)
{
int ret;
Expand Down
61 changes: 12 additions & 49 deletions net/ipv4/ip_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
#include <net/udp.h>
#include <net/gue.h>

#if IS_ENABLED(CONFIG_NET_FOU)
#include <net/fou.h>
#endif

#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
Expand Down Expand Up @@ -494,10 +497,12 @@ static int ip_encap_hlen(struct ip_tunnel_encap *e)
switch (e->type) {
case TUNNEL_ENCAP_NONE:
return 0;
#if IS_ENABLED(CONFIG_NET_FOU)
case TUNNEL_ENCAP_FOU:
return sizeof(struct udphdr);
return fou_encap_hlen(e);
case TUNNEL_ENCAP_GUE:
return sizeof(struct udphdr) + sizeof(struct guehdr);
return gue_encap_hlen(e);
#endif
default:
return -EINVAL;
}
Expand Down Expand Up @@ -526,60 +531,18 @@ int ip_tunnel_encap_setup(struct ip_tunnel *t,
}
EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);

static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
size_t hdr_len, u8 *protocol, struct flowi4 *fl4)
{
struct udphdr *uh;
__be16 sport;
bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;

skb = iptunnel_handle_offloads(skb, csum, type);

if (IS_ERR(skb))
return PTR_ERR(skb);

/* Get length and hash before making space in skb */

sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
skb, 0, 0, false);

skb_push(skb, hdr_len);

skb_reset_transport_header(skb);
uh = udp_hdr(skb);

if (e->type == TUNNEL_ENCAP_GUE) {
struct guehdr *guehdr = (struct guehdr *)&uh[1];

guehdr->version = 0;
guehdr->hlen = 0;
guehdr->flags = 0;
guehdr->next_hdr = *protocol;
}

uh->dest = e->dport;
uh->source = sport;
uh->len = htons(skb->len);
uh->check = 0;
udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
fl4->saddr, fl4->daddr, skb->len);

*protocol = IPPROTO_UDP;

return 0;
}

int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
u8 *protocol, struct flowi4 *fl4)
{
switch (t->encap.type) {
case TUNNEL_ENCAP_NONE:
return 0;
#if IS_ENABLED(CONFIG_NET_FOU)
case TUNNEL_ENCAP_FOU:
return fou_build_header(skb, &t->encap, protocol, fl4);
case TUNNEL_ENCAP_GUE:
return fou_build_header(skb, &t->encap, t->encap_hlen,
protocol, fl4);
return gue_build_header(skb, &t->encap, protocol, fl4);
#endif
default:
return -EINVAL;
}
Expand Down

0 comments on commit 63487ba

Please sign in to comment.