Skip to content

Commit

Permalink
MFC r346630:
Browse files Browse the repository at this point in the history
  Add GRE-in-UDP encapsulation support as defined in RFC8086.

  This GRE-in-UDP encapsulation allows the UDP source port field to be
  used as an entropy field for load-balancing of GRE traffic in transit
  networks. Also most of multiqueue network cards are able distribute
  incoming UDP datagrams to different NIC queues, while very little are
  able do this for GRE packets.

  When an administrator enables UDP encapsulation with command
  `ifconfig gre0 udpencap`, the driver creates kernel socket, that binds
  to tunnel source address and after udp_set_kernel_tunneling() starts
  receiving of all UDP packets destined to 4754 port. Each kernel socket
  maintains list of tunnels with different destination addresses. Thus
  when several tunnels use the same source address, they all handled by
  single socket.  The IP[V6]_BINDANY socket option is used to be able bind
  socket to source address even if it is not yet available in the system.
  This may happen on system boot, when gre(4) interface is created before
  source address become available. The encapsulation and sending of packets
  is done directly from gre(4) into ip[6]_output() without using sockets.

  Reviewed by:	eugen
  Relnotes:	yes
  Differential Revision:	https://reviews.freebsd.org/D19921
  • Loading branch information
bu7cher committed May 24, 2019
1 parent 32697a5 commit fdaf572
Show file tree
Hide file tree
Showing 7 changed files with 783 additions and 59 deletions.
25 changes: 23 additions & 2 deletions sbin/ifconfig/ifgre.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,28 @@ __FBSDID("$FreeBSD$");

#include "ifconfig.h"

#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ"
#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP"

static void gre_status(int s);

static void
gre_status(int s)
{
uint32_t opts = 0;
uint32_t opts, port;

opts = 0;
ifr.ifr_data = (caddr_t)&opts;
if (ioctl(s, GREGKEY, &ifr) == 0)
if (opts != 0)
printf("\tgrekey: 0x%x (%u)\n", opts, opts);
opts = 0;
if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0)
return;

port = 0;
ifr.ifr_data = (caddr_t)&port;
if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0)
printf("\tudpport: %u\n", port);
printb("\toptions", opts, GREBITS);
putchar('\n');
}
Expand All @@ -76,6 +82,18 @@ setifgrekey(const char *val, int dummy __unused, int s,
warn("ioctl (set grekey)");
}

static void
setifgreport(const char *val, int dummy __unused, int s,
const struct afswtch *afp)
{
uint32_t udpport = strtol(val, NULL, 0);

strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
ifr.ifr_data = (caddr_t)&udpport;
if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0)
warn("ioctl (set udpport)");
}

static void
setifgreopts(const char *val, int d, int s, const struct afswtch *afp)
{
Expand All @@ -101,10 +119,13 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp)

static struct cmd gre_cmds[] = {
DEF_CMD_ARG("grekey", setifgrekey),
DEF_CMD_ARG("udpport", setifgreport),
DEF_CMD("enable_csum", GRE_ENABLE_CSUM, setifgreopts),
DEF_CMD("-enable_csum",-GRE_ENABLE_CSUM,setifgreopts),
DEF_CMD("enable_seq", GRE_ENABLE_SEQ, setifgreopts),
DEF_CMD("-enable_seq",-GRE_ENABLE_SEQ, setifgreopts),
DEF_CMD("udpencap", GRE_UDPENCAP, setifgreopts),
DEF_CMD("-udpencap",-GRE_UDPENCAP, setifgreopts),
};
static struct afswtch af_gre = {
.af_name = "af_gre",
Expand Down
40 changes: 39 additions & 1 deletion share/man/man4/gre.4
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd June 2, 2015
.Dd April 24, 2019
.Dt GRE 4
.Os
.Sh NAME
Expand Down Expand Up @@ -89,7 +89,45 @@ A value of 0 disables the key option.
Enables checksum calculation for outgoing packets.
.It Ar enable_seq
Enables use of sequence number field in the GRE header for outgoing packets.
.It Ar udpencap
Enables UDP-in-GRE encapsulation (see the
.Sx GRE-IN-UDP ENCAPSULATION
Section below for details).
.It Ar udpport
Set the source UDP port for outgoing packets.
A value of 0 disables the persistence of source UDP port for outgoing packets.
See the
.Sx GRE-IN-UDP ENCAPSULATION
Section below for details.
.El
.Sh GRE-IN-UDP ENCAPSULATION
The
.Nm
supports GRE in UDP encapsulation as defined in RFC 8086.
A GRE in UDP tunnel offers the possibility of better performance for
load-balancing GRE traffic in transit networks.
Encapsulating GRE in UDP enables use of the UDP source port to provide
entropy to ECMP hashing.
.Pp
The GRE in UDP tunnel uses single value 4754 as UDP destination port.
The UDP source port contains a 14-bit entropy value that is generated
by the encapsulator to identify a flow for the encapsulated packet.
The
.Ar udpport
option can be used to disable this behaviour and use single source UDP
port value.
The value of
.Ar udpport
should be within the ephemeral port range, i.e., 49152 to 65535 by default.
.Pp
Note that a GRE in UDP tunnel is unidirectional; the tunnel traffic is not
expected to be returned back to the UDP source port values used to generate
entropy.
This may impact NAPT (Network Address Port Translator) middleboxes.
If such tunnels are expected to be used on a path with a middlebox,
the tunnel can be configured either to disable use of the UDP source port
for entropy or to enable middleboxes to pass packets with UDP source port
entropy.
.Sh EXAMPLES
.Bd -literal
192.168.1.* --- Router A -------tunnel-------- Router B --- 192.168.2.*
Expand Down
2 changes: 1 addition & 1 deletion sys/modules/if_gre/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SYSDIR?=${SRCTOP}/sys
.include "${SYSDIR}/conf/kern.opts.mk"

KMOD= if_gre
SRCS= if_gre.c opt_inet.h opt_inet6.h
SRCS= if_gre.c opt_inet.h opt_inet6.h opt_rss.h
SRCS.INET= ip_gre.c
SRCS.INET6= ip6_gre.c

Expand Down
Loading

0 comments on commit fdaf572

Please sign in to comment.