fan-networking: updated patches from Ubuntu
This pulls in updated Fan Networking patches from Ubuntu. (https://wiki.ubuntu.com/FanNetworking) closes #14328
This commit is contained in:
parent
aec8daed86
commit
ad7b1e24c2
@ -1,41 +1,39 @@
|
|||||||
{ stdenv, lib, fetchbzr, makeWrapper, bridge-utils, iproute, dnsmasq, iptables, kmod, utillinux }:
|
{ stdenv, lib, fetchurl, gnugrep, glibc, gawk, coreutils, bridge-utils, iproute
|
||||||
|
, dnsmasq, iptables, kmod, utillinux, gnused }:
|
||||||
|
|
||||||
let stateDir = "/var/lib/fan-networking";
|
stdenv.mkDerivation rec {
|
||||||
in stdenv.mkDerivation rec {
|
|
||||||
name = "fanctl-${version}";
|
name = "fanctl-${version}";
|
||||||
|
|
||||||
version = "0.3.0";
|
version = "0.9.0";
|
||||||
|
|
||||||
src = fetchbzr {
|
src = fetchurl {
|
||||||
url = "https://code.launchpad.net/~ubuntu-branches/ubuntu/vivid/ubuntu-fan/vivid-updates";
|
url = "https://launchpad.net/ubuntu/+archive/primary/+files/ubuntu-fan_${version}.tar.xz";
|
||||||
rev = 2;
|
sha256 = "03dv5zzb8fkl9kkbhznxm48d6j3fjms74fn0s1zip2gz53l1s14n";
|
||||||
sha256 = "1vcr2rg99g7sx1zynhiggjzc9y9z591i4535hbm21dysy3cisp7i";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ makeWrapper ];
|
# The Ubuntu package creates a number of state/config directories upon
|
||||||
|
# installation, and so the fanctl script expects those directories to exist
|
||||||
|
# before being used. Instead, we patch the fanctl script to gracefully handle
|
||||||
|
# the fact that the directories might not exist yet.
|
||||||
|
# Also, when dnsmasq is given --conf-file="", it will still attempt to read
|
||||||
|
# /etc/dnsmasq.conf; if that file does not exist, dnsmasq subsequently fails,
|
||||||
|
# so we'll use /dev/null, which actually works as intended.
|
||||||
|
patches = [ ./robustness.patch ];
|
||||||
|
|
||||||
# When given --conf-file="", dnsmasq still attempts to read /etc/dnsmasq.conf;
|
postPatch = ''
|
||||||
# if that files does not exist, dnsmasq subsequently fails,
|
|
||||||
# so we'll use /dev/null.
|
|
||||||
#
|
|
||||||
# Also, make sure the state directory before starting dnsmasq.
|
|
||||||
buildPhase = ''
|
|
||||||
substituteInPlace fanctl \
|
substituteInPlace fanctl \
|
||||||
--replace '--conf-file= ' \
|
--replace '@PATH@' \
|
||||||
'--conf-file=/dev/null ' \
|
'${lib.makeSearchPath "bin" [
|
||||||
--replace '/var/lib/misc' \
|
gnugrep gawk coreutils bridge-utils iproute dnsmasq
|
||||||
'${stateDir}'
|
iptables kmod utillinux gnused
|
||||||
|
glibc # needed for getent
|
||||||
sed -i '/dnsmasq -u/i \
|
]}'
|
||||||
mkdir -p ${stateDir}' fanctl
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin $out/man/man8
|
mkdir -p $out/bin $out/man/man8
|
||||||
cp fanctl.8 $out/man/man8
|
cp fanctl.8 $out/man/man8
|
||||||
cp fanctl $out/bin
|
cp fanctl $out/bin
|
||||||
wrapProgram $out/bin/fanctl --prefix PATH : \
|
|
||||||
${lib.makeSearchPath "bin" [ bridge-utils iproute dnsmasq iptables kmod utillinux ]};
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
85
pkgs/os-specific/linux/fanctl/robustness.patch
Normal file
85
pkgs/os-specific/linux/fanctl/robustness.patch
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
diff --git a/fanctl b/fanctl
|
||||||
|
index 4338b75..84cf987 100755
|
||||||
|
--- a/fanctl
|
||||||
|
+++ b/fanctl
|
||||||
|
@@ -5,6 +5,8 @@
|
||||||
|
# fanctl down 15 10.1.0.1
|
||||||
|
#
|
||||||
|
|
||||||
|
+export PATH="@PATH@"
|
||||||
|
+
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
echo "Usage: $0 <cmd> [<options>...]" 1>&2
|
||||||
|
@@ -23,8 +25,8 @@ run()
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
-state_dir="/run/ubuntu-fan"
|
||||||
|
-lconfig_dir="/var/lib/ubuntu-fan/config"
|
||||||
|
+state_dir="/run/fan-networking"
|
||||||
|
+lconfig_dir="/var/lib/fan-networking/config"
|
||||||
|
|
||||||
|
__ip_split()
|
||||||
|
{
|
||||||
|
@@ -931,12 +933,12 @@ dhcp_reconfigure()
|
||||||
|
--strict-order \
|
||||||
|
--bind-interfaces \
|
||||||
|
--pid-file="$state_dir/dnsmasq-$C_bridge_state.pid" \
|
||||||
|
- --conf-file= \
|
||||||
|
+ --conf-file=/dev/null \
|
||||||
|
$dhcp_flags \
|
||||||
|
--dhcp-no-override \
|
||||||
|
--except-interface=lo \
|
||||||
|
--interface="$C_bridge" \
|
||||||
|
- --dhcp-leasefile=/var/lib/misc/dnsmasq."$C_bridge_state".leases \
|
||||||
|
+ --dhcp-leasefile=/var/lib/fan-networking/dnsmasq."$C_bridge_state".leases \
|
||||||
|
--dhcp-authoritative \
|
||||||
|
|| $fail "$C_bridge: failed to start dnsmasq"
|
||||||
|
|
||||||
|
@@ -1559,21 +1561,23 @@ cmd_config()
|
||||||
|
|
||||||
|
case "$cmd" in
|
||||||
|
list|ls)
|
||||||
|
- ls -1 "$lconfig_dir" | \
|
||||||
|
- while read config
|
||||||
|
- do
|
||||||
|
- case "$config" in
|
||||||
|
- *.conf) ;;
|
||||||
|
- *) continue ;;
|
||||||
|
- esac
|
||||||
|
+ if [ -d $lconfig_dir ]; then
|
||||||
|
+ ls -1 "$lconfig_dir" | \
|
||||||
|
+ while read config
|
||||||
|
+ do
|
||||||
|
+ case "$config" in
|
||||||
|
+ *.conf) ;;
|
||||||
|
+ *) continue ;;
|
||||||
|
+ esac
|
||||||
|
|
||||||
|
- config=$( echo "$config" | sed \
|
||||||
|
- -e 's/.conf$//' \
|
||||||
|
- -e 's/--/ /g' \
|
||||||
|
- -e 's@-@/@g'
|
||||||
|
- )
|
||||||
|
- echo "$config"
|
||||||
|
- done
|
||||||
|
+ config=$( echo "$config" | sed \
|
||||||
|
+ -e 's/.conf$//' \
|
||||||
|
+ -e 's/--/ /g' \
|
||||||
|
+ -e 's@-@/@g'
|
||||||
|
+ )
|
||||||
|
+ echo "$config"
|
||||||
|
+ done
|
||||||
|
+ fi
|
||||||
|
;;
|
||||||
|
show)
|
||||||
|
cmd_decode_init
|
||||||
|
@@ -1588,6 +1592,7 @@ cmd_config()
|
||||||
|
[ -f "$uconfig" ] && cat "$uconfig"
|
||||||
|
;;
|
||||||
|
set)
|
||||||
|
+ mkdir -p $lconfig_dir || fail "could not create config directory ($lconfig_dir)"
|
||||||
|
cmd_decode_init
|
||||||
|
if ! cmd_decode_config "config set" "$@"; then
|
||||||
|
fail "invalid config"
|
@ -0,0 +1,65 @@
|
|||||||
|
Description: POC fan driver support
|
||||||
|
POC Fan driver support
|
||||||
|
Author: Jay Vosburgh <jay.vosburgh@canonical.com>
|
||||||
|
|
||||||
|
Index: iproute2-4.1.1/include/linux/if_tunnel.h
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.1.1.orig/include/linux/if_tunnel.h
|
||||||
|
+++ iproute2-4.1.1/include/linux/if_tunnel.h
|
||||||
|
@@ -57,6 +57,9 @@ enum {
|
||||||
|
IFLA_IPTUN_ENCAP_FLAGS,
|
||||||
|
IFLA_IPTUN_ENCAP_SPORT,
|
||||||
|
IFLA_IPTUN_ENCAP_DPORT,
|
||||||
|
+
|
||||||
|
+ IFLA_IPTUN_FAN_UNDERLAY = 32,
|
||||||
|
+
|
||||||
|
__IFLA_IPTUN_MAX,
|
||||||
|
};
|
||||||
|
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
|
||||||
|
Index: iproute2-4.1.1/ip/link_iptnl.c
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.1.1.orig/ip/link_iptnl.c
|
||||||
|
+++ iproute2-4.1.1/ip/link_iptnl.c
|
||||||
|
@@ -66,6 +66,7 @@ static int iptunnel_parse_opt(struct lin
|
||||||
|
__u32 link = 0;
|
||||||
|
__u32 laddr = 0;
|
||||||
|
__u32 raddr = 0;
|
||||||
|
+ __u32 underlay = 0;
|
||||||
|
__u8 ttl = 0;
|
||||||
|
__u8 tos = 0;
|
||||||
|
__u8 pmtudisc = 1;
|
||||||
|
@@ -174,6 +175,9 @@ get_failed:
|
||||||
|
raddr = get_addr32(*argv);
|
||||||
|
else
|
||||||
|
raddr = 0;
|
||||||
|
+ } else if (strcmp(*argv, "underlay") == 0) {
|
||||||
|
+ NEXT_ARG();
|
||||||
|
+ underlay = get_addr32(*argv);
|
||||||
|
} else if (strcmp(*argv, "local") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (strcmp(*argv, "any"))
|
||||||
|
@@ -318,6 +322,9 @@ get_failed:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (underlay)
|
||||||
|
+ addattr32(n, 1024, IFLA_IPTUN_FAN_UNDERLAY, underlay);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -349,6 +356,14 @@ static void iptunnel_print_opt(struct li
|
||||||
|
|
||||||
|
fprintf(f, "local %s ", local);
|
||||||
|
|
||||||
|
+ if (tb[IFLA_IPTUN_FAN_UNDERLAY]) {
|
||||||
|
+ unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_FAN_UNDERLAY]);
|
||||||
|
+
|
||||||
|
+ if (addr)
|
||||||
|
+ fprintf(f, "underlay %s ",
|
||||||
|
+ format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
|
||||||
|
unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
|
||||||
|
const char *n = if_indextoname(link, s2);
|
@ -1,27 +1,19 @@
|
|||||||
This provides support for Ubuntu's Fan Networking [1].
|
Description: Fan driver support v3
|
||||||
|
Fan driver support v3
|
||||||
These patches were pulled from:
|
Author: Jay Vosburgh <jay.vosburgh@canonical.com>
|
||||||
https://code.launchpad.net/~ubuntu-branches/ubuntu/vivid/iproute2/vivid-proposed
|
Index: iproute2-4.1.1/include/linux/if_tunnel.h
|
||||||
|
===================================================================
|
||||||
See revisions 18 and 19.
|
--- iproute2-4.1.1.orig/include/linux/if_tunnel.h
|
||||||
|
+++ iproute2-4.1.1/include/linux/if_tunnel.h
|
||||||
[1] https://wiki.ubuntu.com/FanNetworking
|
@@ -59,6 +59,7 @@ enum {
|
||||||
|
|
||||||
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
|
|
||||||
index 102ce7a..7b8f0e5 100644
|
|
||||||
--- a/include/linux/if_tunnel.h
|
|
||||||
+++ b/include/linux/if_tunnel.h
|
|
||||||
@@ -57,6 +57,9 @@ enum {
|
|
||||||
IFLA_IPTUN_ENCAP_FLAGS,
|
|
||||||
IFLA_IPTUN_ENCAP_SPORT,
|
|
||||||
IFLA_IPTUN_ENCAP_DPORT,
|
IFLA_IPTUN_ENCAP_DPORT,
|
||||||
+
|
|
||||||
+ IFLA_IPTUN_FAN_UNDERLAY = 32,
|
IFLA_IPTUN_FAN_UNDERLAY = 32,
|
||||||
+ IFLA_IPTUN_FAN_MAP = 33,
|
+ IFLA_IPTUN_FAN_MAP = 33,
|
||||||
|
|
||||||
__IFLA_IPTUN_MAX,
|
__IFLA_IPTUN_MAX,
|
||||||
};
|
};
|
||||||
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
|
@@ -134,4 +135,20 @@ enum {
|
||||||
@@ -131,4 +134,20 @@ enum {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
|
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
|
||||||
@ -42,10 +34,10 @@ index 102ce7a..7b8f0e5 100644
|
|||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
#endif /* _IF_TUNNEL_H_ */
|
#endif /* _IF_TUNNEL_H_ */
|
||||||
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
|
Index: iproute2-4.1.1/ip/link_iptnl.c
|
||||||
index 9d6bc98..ec3f05d 100644
|
===================================================================
|
||||||
--- a/ip/link_iptnl.c
|
--- iproute2-4.1.1.orig/ip/link_iptnl.c
|
||||||
+++ b/ip/link_iptnl.c
|
+++ iproute2-4.1.1/ip/link_iptnl.c
|
||||||
@@ -49,6 +49,42 @@ static void usage(int sit)
|
@@ -49,6 +49,42 @@ static void usage(int sit)
|
||||||
print_usage(stderr, sit);
|
print_usage(stderr, sit);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -89,21 +81,10 @@ index 9d6bc98..ec3f05d 100644
|
|||||||
|
|
||||||
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
|
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||||
struct nlmsghdr *n)
|
struct nlmsghdr *n)
|
||||||
@@ -66,6 +102,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
|
@@ -178,6 +214,10 @@ get_failed:
|
||||||
__u32 link = 0;
|
} else if (strcmp(*argv, "underlay") == 0) {
|
||||||
__u32 laddr = 0;
|
NEXT_ARG();
|
||||||
__u32 raddr = 0;
|
underlay = get_addr32(*argv);
|
||||||
+ __u32 underlay = 0;
|
|
||||||
__u8 ttl = 0;
|
|
||||||
__u8 tos = 0;
|
|
||||||
__u8 pmtudisc = 1;
|
|
||||||
@@ -174,6 +211,13 @@ get_failed:
|
|
||||||
raddr = get_addr32(*argv);
|
|
||||||
else
|
|
||||||
raddr = 0;
|
|
||||||
+ } else if (strcmp(*argv, "underlay") == 0) {
|
|
||||||
+ NEXT_ARG();
|
|
||||||
+ underlay = get_addr32(*argv);
|
|
||||||
+ } else if (strcmp(*argv, "fan-map") == 0) {
|
+ } else if (strcmp(*argv, "fan-map") == 0) {
|
||||||
+ NEXT_ARG();
|
+ NEXT_ARG();
|
||||||
+ if (fan_parse_map(&argc, &argv, n))
|
+ if (fan_parse_map(&argc, &argv, n))
|
||||||
@ -111,13 +92,7 @@ index 9d6bc98..ec3f05d 100644
|
|||||||
} else if (strcmp(*argv, "local") == 0) {
|
} else if (strcmp(*argv, "local") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (strcmp(*argv, "any"))
|
if (strcmp(*argv, "any"))
|
||||||
@@ -318,9 +362,32 @@ get_failed:
|
@@ -328,6 +368,28 @@ get_failed:
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (underlay)
|
|
||||||
+ addattr32(n, 1024, IFLA_IPTUN_FAN_UNDERLAY, underlay);
|
|
||||||
+
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,16 +102,18 @@ index 9d6bc98..ec3f05d 100644
|
|||||||
+ struct ip_tunnel_fan_map *m;
|
+ struct ip_tunnel_fan_map *m;
|
||||||
+ struct rtattr *i;
|
+ struct rtattr *i;
|
||||||
+ int rem;
|
+ int rem;
|
||||||
|
+ int p;
|
||||||
+
|
+
|
||||||
+ fprintf(f, "fan-map ");
|
+ fprintf(f, "fan-map ");
|
||||||
+
|
+
|
||||||
+ rem = RTA_PAYLOAD(attr);
|
+ rem = RTA_PAYLOAD(attr);
|
||||||
+ for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
+ for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||||
|
+ p = RTA_PAYLOAD(i);
|
||||||
+ m = RTA_DATA(i);
|
+ m = RTA_DATA(i);
|
||||||
+ fprintf(f, "%s/%d:%s/%d ",
|
+ fprintf(f, "%s/%d:%s/%d ",
|
||||||
+ rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->overlay, b1, INET_ADDRSTRLEN),
|
+ rt_addr_n2a(AF_INET, p, &m->overlay, b1, INET_ADDRSTRLEN),
|
||||||
+ m->overlay_prefix,
|
+ m->overlay_prefix,
|
||||||
+ rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->underlay, b2, INET_ADDRSTRLEN),
|
+ rt_addr_n2a(AF_INET, p, &m->underlay, b2, INET_ADDRSTRLEN),
|
||||||
+ m->underlay_prefix);
|
+ m->underlay_prefix);
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
@ -144,18 +121,10 @@ index 9d6bc98..ec3f05d 100644
|
|||||||
static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||||
{
|
{
|
||||||
char s1[1024];
|
char s1[1024];
|
||||||
@@ -349,6 +416,17 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
|
@@ -364,6 +426,9 @@ static void iptunnel_print_opt(struct li
|
||||||
|
format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(f, "local %s ", local);
|
|
||||||
|
|
||||||
+ if (tb[IFLA_IPTUN_FAN_UNDERLAY]) {
|
|
||||||
+ unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_FAN_UNDERLAY]);
|
|
||||||
+
|
|
||||||
+ if (addr)
|
|
||||||
+ fprintf(f, "underlay %s ",
|
|
||||||
+ format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (tb[IFLA_IPTUN_FAN_MAP])
|
+ if (tb[IFLA_IPTUN_FAN_MAP])
|
||||||
+ fan_print_map(f, tb[IFLA_IPTUN_FAN_MAP]);
|
+ fan_print_map(f, tb[IFLA_IPTUN_FAN_MAP]);
|
||||||
+
|
+
|
@ -0,0 +1,177 @@
|
|||||||
|
Description: Fan driver support VXLAN (p4)
|
||||||
|
Fan driver setup support for vxlan interfaces.
|
||||||
|
|
||||||
|
Index: iproute2-4.3.0/include/linux/if_link.h
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.3.0.orig/include/linux/if_link.h
|
||||||
|
+++ iproute2-4.3.0/include/linux/if_link.h
|
||||||
|
@@ -392,6 +392,7 @@ enum {
|
||||||
|
IFLA_VXLAN_GBP,
|
||||||
|
IFLA_VXLAN_REMCSUM_NOPARTIAL,
|
||||||
|
IFLA_VXLAN_COLLECT_METADATA,
|
||||||
|
+ IFLA_VXLAN_FAN_MAP = 33,
|
||||||
|
__IFLA_VXLAN_MAX
|
||||||
|
};
|
||||||
|
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
||||||
|
Index: iproute2-4.3.0/include/linux/if_tunnel.h
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.3.0.orig/include/linux/if_tunnel.h
|
||||||
|
+++ iproute2-4.3.0/include/linux/if_tunnel.h
|
||||||
|
@@ -145,7 +145,7 @@ enum {
|
||||||
|
|
||||||
|
#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
|
||||||
|
|
||||||
|
-struct ip_tunnel_fan_map {
|
||||||
|
+struct ifla_fan_map {
|
||||||
|
__be32 underlay;
|
||||||
|
__be32 overlay;
|
||||||
|
__u16 underlay_prefix;
|
||||||
|
Index: iproute2-4.3.0/ip/iplink_vxlan.c
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.3.0.orig/ip/iplink_vxlan.c
|
||||||
|
+++ iproute2-4.3.0/ip/iplink_vxlan.c
|
||||||
|
@@ -15,7 +15,10 @@
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
+#include <linux/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
+#include <linux/in6.h>
|
||||||
|
+#include <linux/if_tunnel.h>
|
||||||
|
|
||||||
|
#include "rt_names.h"
|
||||||
|
#include "utils.h"
|
||||||
|
@@ -43,6 +46,45 @@ static void explain(void)
|
||||||
|
print_explain(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int fan_parse_map(int *argcp, char ***argvp, struct nlmsghdr *n)
|
||||||
|
+{
|
||||||
|
+ inet_prefix underlay, overlay;
|
||||||
|
+ struct ifla_fan_map map;
|
||||||
|
+ struct rtattr *nest;
|
||||||
|
+ char **argv = *argvp;
|
||||||
|
+ int argc = *argcp;
|
||||||
|
+
|
||||||
|
+ nest = addattr_nest(n, 1024, IFLA_VXLAN_FAN_MAP);
|
||||||
|
+ while (argc > 0) {
|
||||||
|
+ char *colon = strchr(*argv, ':');
|
||||||
|
+
|
||||||
|
+ if (!colon) {
|
||||||
|
+ PREV_ARG();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ *colon = '\0';
|
||||||
|
+
|
||||||
|
+ if (get_prefix(&overlay, *argv, AF_INET))
|
||||||
|
+ invarg("invalid fan-map overlay", *argv);
|
||||||
|
+ if (get_prefix(&underlay, colon + 1, AF_INET))
|
||||||
|
+ invarg("invalid fan-map underlay", colon + 1);
|
||||||
|
+
|
||||||
|
+ memcpy(&map.underlay, underlay.data, 4);
|
||||||
|
+ map.underlay_prefix = underlay.bitlen;
|
||||||
|
+ memcpy(&map.overlay, overlay.data, 4);
|
||||||
|
+ map.overlay_prefix = overlay.bitlen;
|
||||||
|
+
|
||||||
|
+ argc--, argv++;
|
||||||
|
+
|
||||||
|
+ addattr_l(n, 1024, IFLA_FAN_MAPPING, &map, sizeof(map));
|
||||||
|
+ }
|
||||||
|
+ addattr_nest_end(n, nest);
|
||||||
|
+
|
||||||
|
+ *argcp = argc;
|
||||||
|
+ *argvp = argv;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||||
|
struct nlmsghdr *n)
|
||||||
|
{
|
||||||
|
@@ -201,6 +243,10 @@ static int vxlan_parse_opt(struct link_u
|
||||||
|
udp6zerocsumrx = 0;
|
||||||
|
} else if (!matches(*argv, "gbp")) {
|
||||||
|
gbp = 1;
|
||||||
|
+ } else if (!matches(*argv, "fan-map")) {
|
||||||
|
+ NEXT_ARG();
|
||||||
|
+ if (fan_parse_map(&argc, &argv, n))
|
||||||
|
+ invarg("invalid fan-map", *argv);
|
||||||
|
} else if (matches(*argv, "help") == 0) {
|
||||||
|
explain();
|
||||||
|
return -1;
|
||||||
|
@@ -279,6 +325,28 @@ static int vxlan_parse_opt(struct link_u
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void fan_print_map(FILE *f, struct rtattr *attr)
|
||||||
|
+{
|
||||||
|
+ char b1[INET_ADDRSTRLEN], b2[INET_ADDRSTRLEN];
|
||||||
|
+ struct ifla_fan_map *m;
|
||||||
|
+ struct rtattr *i;
|
||||||
|
+ int rem;
|
||||||
|
+ int p;
|
||||||
|
+
|
||||||
|
+ fprintf(f, "fan-map ");
|
||||||
|
+
|
||||||
|
+ rem = RTA_PAYLOAD(attr);
|
||||||
|
+ for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||||
|
+ p = RTA_PAYLOAD(i);
|
||||||
|
+ m = RTA_DATA(i);
|
||||||
|
+ fprintf(f, "%s/%d:%s/%d ",
|
||||||
|
+ rt_addr_n2a(AF_INET, p, &m->overlay, b1, INET_ADDRSTRLEN),
|
||||||
|
+ m->overlay_prefix,
|
||||||
|
+ rt_addr_n2a(AF_INET, p, &m->underlay, b2, INET_ADDRSTRLEN),
|
||||||
|
+ m->underlay_prefix);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||||
|
{
|
||||||
|
__u32 vni;
|
||||||
|
@@ -321,6 +389,9 @@ static void vxlan_print_opt(struct link_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (tb[IFLA_VXLAN_FAN_MAP])
|
||||||
|
+ fan_print_map(f, tb[IFLA_VXLAN_FAN_MAP]);
|
||||||
|
+
|
||||||
|
if (tb[IFLA_VXLAN_LOCAL]) {
|
||||||
|
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
|
||||||
|
if (addr)
|
||||||
|
Index: iproute2-4.3.0/ip/link_iptnl.c
|
||||||
|
===================================================================
|
||||||
|
--- iproute2-4.3.0.orig/ip/link_iptnl.c
|
||||||
|
+++ iproute2-4.3.0/ip/link_iptnl.c
|
||||||
|
@@ -49,10 +49,11 @@ static void usage(int sit)
|
||||||
|
print_usage(stderr, sit);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
static int fan_parse_map(int *argcp, char ***argvp, struct nlmsghdr *n)
|
||||||
|
{
|
||||||
|
inet_prefix underlay, overlay;
|
||||||
|
- struct ip_tunnel_fan_map map;
|
||||||
|
+ struct ifla_fan_map map;
|
||||||
|
struct rtattr *nest;
|
||||||
|
char **argv = *argvp;
|
||||||
|
int argc = *argcp;
|
||||||
|
@@ -61,8 +62,10 @@ static int fan_parse_map(int *argcp, cha
|
||||||
|
while (argc > 0) {
|
||||||
|
char *colon = strchr(*argv, ':');
|
||||||
|
|
||||||
|
- if (!colon)
|
||||||
|
+ if (!colon) {
|
||||||
|
+ PREV_ARG();
|
||||||
|
break;
|
||||||
|
+ }
|
||||||
|
*colon = '\0';
|
||||||
|
|
||||||
|
if (get_prefix(&overlay, *argv, AF_INET))
|
||||||
|
@@ -371,7 +374,7 @@ get_failed:
|
||||||
|
static void fan_print_map(FILE *f, struct rtattr *attr)
|
||||||
|
{
|
||||||
|
char b1[INET_ADDRSTRLEN], b2[INET_ADDRSTRLEN];
|
||||||
|
- struct ip_tunnel_fan_map *m;
|
||||||
|
+ struct ifla_fan_map *m;
|
||||||
|
struct rtattr *i;
|
||||||
|
int rem;
|
||||||
|
int p;
|
@ -10,7 +10,13 @@ stdenv.mkDerivation rec {
|
|||||||
sha256 = "159988vv3fd78bzhisfl1dl4dd7km3vjzs2d8899a0vcvn412fzh";
|
sha256 = "159988vv3fd78bzhisfl1dl4dd7km3vjzs2d8899a0vcvn412fzh";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = lib.optionals enableFan [ ./ubuntu-fan.patch ];
|
patches = lib.optionals enableFan [
|
||||||
|
# These patches were pulled from:
|
||||||
|
# https://launchpad.net/ubuntu/xenial/+source/iproute2
|
||||||
|
./1000-ubuntu-poc-fan-driver.patch
|
||||||
|
./1001-ubuntu-poc-fan-driver-v3.patch
|
||||||
|
./1002-ubuntu-poc-fan-driver-vxlan.patch
|
||||||
|
];
|
||||||
|
|
||||||
preConfigure = ''
|
preConfigure = ''
|
||||||
patchShebangs ./configure
|
patchShebangs ./configure
|
||||||
|
@ -71,14 +71,9 @@ rec {
|
|||||||
patch = ./mips-ext3-n32.patch;
|
patch = ./mips-ext3-n32.patch;
|
||||||
};
|
};
|
||||||
|
|
||||||
ubuntu_fan =
|
ubuntu_fan_4_4 =
|
||||||
{ name = "ubuntu-fan";
|
{ name = "ubuntu-fan";
|
||||||
patch = ./ubuntu-fan-3.patch;
|
patch = ./ubuntu-fan-4.4.patch;
|
||||||
};
|
|
||||||
|
|
||||||
ubuntu_fan_4 =
|
|
||||||
{ name = "ubuntu-fan";
|
|
||||||
patch = ./ubuntu-fan-4.patch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ubuntu_unprivileged_overlayfs =
|
ubuntu_unprivileged_overlayfs =
|
||||||
|
@ -1,616 +0,0 @@
|
|||||||
From f3c956096902669c3529cb01d40deb0c759ed94f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
Date: Wed, 1 Apr 2015 16:11:09 -0700
|
|
||||||
Subject: [PATCH] UBUNTU: SAUCE: fan: Proof of concept implementation (v2)
|
|
||||||
|
|
||||||
Modification to ipip tunnel driver to accept a new netlink option,
|
|
||||||
IFLA_IPTUN_FAN_UNDERLAY, which provides a /16 network prefix and enables
|
|
||||||
TX side destination address remapping for traffic entering the tunnel
|
|
||||||
(to be encapsulated).
|
|
||||||
|
|
||||||
For an overlay (inner) address Y.A.B.C, the transformation is F.G.A.B,
|
|
||||||
where "F" and "G" are the first two octets of the underlay network (the
|
|
||||||
network portion of a /16), "A" and "B" are the low order two octets of the
|
|
||||||
underlay network host (the host portion of a /16), and "Y" is a configured
|
|
||||||
first octet of the overlay network.
|
|
||||||
|
|
||||||
E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
|
|
||||||
subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to 99.6.7.8
|
|
||||||
would be directed to underlay host 10.88.6.7, which hosts overlay network
|
|
||||||
99.6.7.0/24.
|
|
||||||
|
|
||||||
Includes net.fan.version sysctl as a sentinel for availability of the
|
|
||||||
fan functionality.
|
|
||||||
|
|
||||||
NOTE: this requires an updated iproute2 to facilitate configuration of
|
|
||||||
the fan.
|
|
||||||
|
|
||||||
BugLink: http://bugs.launchpad.net/bugs/1439706
|
|
||||||
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
[apw@canonical.com: move IFLA_IPTUN_FAN_UNDERLAY up to avoid clashing
|
|
||||||
with future feature additions.]
|
|
||||||
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
||||||
---
|
|
||||||
include/net/ip_tunnels.h | 6 +++
|
|
||||||
include/uapi/linux/if_tunnel.h | 4 ++
|
|
||||||
net/ipv4/ipip.c | 112 +++++++++++++++++++++++++++++++++++++++--
|
|
||||||
3 files changed, 117 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
|
|
||||||
index 25a59eb..d7eada2 100644
|
|
||||||
--- a/include/net/ip_tunnels.h
|
|
||||||
+++ b/include/net/ip_tunnels.h
|
|
||||||
@@ -51,6 +51,11 @@ struct ip_tunnel_dst {
|
|
||||||
__be32 saddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* Underlay address prefix for ipip fan mode */
|
|
||||||
+struct ip_tunnel_fan {
|
|
||||||
+ u32 underlay;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
struct ip_tunnel {
|
|
||||||
struct ip_tunnel __rcu *next;
|
|
||||||
struct hlist_node hash_node;
|
|
||||||
@@ -82,6 +87,7 @@ struct ip_tunnel {
|
|
||||||
#endif
|
|
||||||
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
|
|
||||||
unsigned int prl_count; /* # of entries in PRL */
|
|
||||||
+ struct ip_tunnel_fan fan;
|
|
||||||
int ip_tnl_net_id;
|
|
||||||
struct gro_cells gro_cells;
|
|
||||||
};
|
|
||||||
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
|
|
||||||
index bd3cc11..8f7d269 100644
|
|
||||||
--- a/include/uapi/linux/if_tunnel.h
|
|
||||||
+++ b/include/uapi/linux/if_tunnel.h
|
|
||||||
@@ -57,6 +57,10 @@ enum {
|
|
||||||
IFLA_IPTUN_ENCAP_FLAGS,
|
|
||||||
IFLA_IPTUN_ENCAP_SPORT,
|
|
||||||
IFLA_IPTUN_ENCAP_DPORT,
|
|
||||||
+
|
|
||||||
+ __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
+ IFLA_IPTUN_FAN_UNDERLAY=32,
|
|
||||||
+
|
|
||||||
__IFLA_IPTUN_MAX,
|
|
||||||
};
|
|
||||||
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
|
|
||||||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
|
|
||||||
index 40403114..e3c27cd 100644
|
|
||||||
--- a/net/ipv4/ipip.c
|
|
||||||
+++ b/net/ipv4/ipip.c
|
|
||||||
@@ -209,13 +209,38 @@ drop:
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+ * Determine fan tunnel endpoint to send packet to, based on the inner IP
|
|
||||||
+ * address. For an overlay (inner) address Y.A.B.C, the transformation is
|
|
||||||
+ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
|
|
||||||
+ * network (the network portion of a /16), "A" and "B" are the low order
|
|
||||||
+ * two octets of the underlay network host (the host portion of a /16),
|
|
||||||
+ * and "Y" is a configured first octet of the overlay network.
|
|
||||||
+ *
|
|
||||||
+ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
|
|
||||||
+ * subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to
|
|
||||||
+ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
|
|
||||||
+ * overlay network 99.6.7.0/24.
|
|
||||||
+ */
|
|
||||||
+static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
+{
|
|
||||||
+ u32 daddr;
|
|
||||||
+
|
|
||||||
+ *iph = tunnel->parms.iph;
|
|
||||||
+
|
|
||||||
+ daddr = ntohl(ip_hdr(skb)->daddr);
|
|
||||||
+ iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
|
|
||||||
+ ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
* This function assumes it is being called from dev_queue_xmit()
|
|
||||||
* and that skb is filled properly by that function.
|
|
||||||
*/
|
|
||||||
static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
{
|
|
||||||
struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
||||||
- const struct iphdr *tiph = &tunnel->parms.iph;
|
|
||||||
+ const struct iphdr *tiph;
|
|
||||||
+ struct iphdr fiph;
|
|
||||||
|
|
||||||
if (unlikely(skb->protocol != htons(ETH_P_IP)))
|
|
||||||
goto tx_error;
|
|
||||||
@@ -224,6 +249,13 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
if (IS_ERR(skb))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
+ if (tunnel->fan.underlay) {
|
|
||||||
+ ipip_build_fan_iphdr(tunnel, skb, &fiph);
|
|
||||||
+ tiph = &fiph;
|
|
||||||
+ } else {
|
|
||||||
+ tiph = &tunnel->parms.iph;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
|
|
||||||
|
|
||||||
ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
|
|
||||||
@@ -377,21 +409,44 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
|
|
||||||
+ struct ip_tunnel_parm *parms)
|
|
||||||
+{
|
|
||||||
+ u32 net = t->fan.underlay;
|
|
||||||
+
|
|
||||||
+ if (!data[IFLA_IPTUN_FAN_UNDERLAY])
|
|
||||||
+ goto err_check;
|
|
||||||
+
|
|
||||||
+ net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
|
|
||||||
+
|
|
||||||
+err_check:
|
|
||||||
+ if (parms->iph.daddr && net)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ t->fan.underlay = net;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int ipip_newlink(struct net *src_net, struct net_device *dev,
|
|
||||||
struct nlattr *tb[], struct nlattr *data[])
|
|
||||||
{
|
|
||||||
struct ip_tunnel_parm p;
|
|
||||||
struct ip_tunnel_encap ipencap;
|
|
||||||
+ struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
if (ipip_netlink_encap_parms(data, &ipencap)) {
|
|
||||||
- struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
- int err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
+ err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipip_netlink_parms(data, &p);
|
|
||||||
+ err = ipip_netlink_fan(data, t, &p);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
return ip_tunnel_newlink(dev, tb, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -400,16 +455,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
{
|
|
||||||
struct ip_tunnel_parm p;
|
|
||||||
struct ip_tunnel_encap ipencap;
|
|
||||||
+ struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
if (ipip_netlink_encap_parms(data, &ipencap)) {
|
|
||||||
- struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
- int err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
+ err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipip_netlink_parms(data, &p);
|
|
||||||
+ err = ipip_netlink_fan(data, t, &p);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
|
|
||||||
if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
|
|
||||||
(!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
|
|
||||||
@@ -441,6 +500,8 @@ static size_t ipip_get_size(const struct net_device *dev)
|
|
||||||
nla_total_size(2) +
|
|
||||||
/* IFLA_IPTUN_ENCAP_DPORT */
|
|
||||||
nla_total_size(2) +
|
|
||||||
+ /* IFLA_IPTUN_FAN_UNDERLAY */
|
|
||||||
+ nla_total_size(4) +
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -468,6 +529,11 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
||||||
tunnel->encap.flags))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
+ if (tunnel->fan.underlay)
|
|
||||||
+ if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
|
|
||||||
+ htonl(tunnel->fan.underlay)))
|
|
||||||
+ goto nla_put_failure;
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
@@ -485,6 +551,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
|
|
||||||
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
|
|
||||||
[IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
|
|
||||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
|
|
||||||
+
|
|
||||||
+ [__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX] = { .type = NLA_BINARY },
|
|
||||||
+ [IFLA_IPTUN_FAN_UNDERLAY] = { .type = NLA_U32 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
|
|
||||||
@@ -524,6 +593,23 @@ static struct pernet_operations ipip_net_ops = {
|
|
||||||
.size = sizeof(struct ip_tunnel_net),
|
|
||||||
};
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+static struct ctl_table_header *ipip_fan_header;
|
|
||||||
+static unsigned int ipip_fan_version = 1;
|
|
||||||
+
|
|
||||||
+static struct ctl_table ipip_fan_sysctls[] = {
|
|
||||||
+ {
|
|
||||||
+ .procname = "version",
|
|
||||||
+ .data = &ipip_fan_version,
|
|
||||||
+ .maxlen = sizeof(ipip_fan_version),
|
|
||||||
+ .mode = 0444,
|
|
||||||
+ .proc_handler = proc_dointvec,
|
|
||||||
+ },
|
|
||||||
+ {},
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
+
|
|
||||||
static int __init ipip_init(void)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
@@ -542,9 +628,22 @@ static int __init ipip_init(void)
|
|
||||||
if (err < 0)
|
|
||||||
goto rtnl_link_failed;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+ ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
|
|
||||||
+ ipip_fan_sysctls);
|
|
||||||
+ if (!ipip_fan_header) {
|
|
||||||
+ err = -ENOMEM;
|
|
||||||
+ goto sysctl_failed;
|
|
||||||
+ }
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
+
|
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+sysctl_failed:
|
|
||||||
+ rtnl_link_unregister(&ipip_link_ops);
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
rtnl_link_failed:
|
|
||||||
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
|
|
||||||
xfrm_tunnel_failed:
|
|
||||||
@@ -554,6 +653,9 @@ xfrm_tunnel_failed:
|
|
||||||
|
|
||||||
static void __exit ipip_fini(void)
|
|
||||||
{
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+ unregister_net_sysctl_table(ipip_fan_header);
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
rtnl_link_unregister(&ipip_link_ops);
|
|
||||||
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
|
|
||||||
pr_info("%s: can't deregister tunnel\n", __func__);
|
|
||||||
--
|
|
||||||
2.4.1
|
|
||||||
|
|
||||||
From 4ea8011656dfdd76e7a2391bdad47c06f85a9d02 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andy Whitcroft <apw@canonical.com>
|
|
||||||
Date: Tue, 21 Jul 2015 16:52:10 +0100
|
|
||||||
Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
|
|
||||||
|
|
||||||
Switch to a single tunnel for all mappings, this removes the limitations
|
|
||||||
on how many mappings each tunnel can handle, and therefore how many Fan
|
|
||||||
slices each local address may hold.
|
|
||||||
|
|
||||||
NOTE: This introduces a new kernel netlink interface which needs updated
|
|
||||||
iproute2 support.
|
|
||||||
|
|
||||||
BugLink: http://bugs.launchpad.net/bugs/1470091
|
|
||||||
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
||||||
Acked-by: Tim Gardner <tim.gardner@canonical.com>
|
|
||||||
Acked-by: Brad Figg <brad.figg@canonical.com>
|
|
||||||
Signed-off-by: Brad Figg <brad.figg@canonical.com>
|
|
||||||
---
|
|
||||||
include/net/ip_tunnels.h | 14 ++++-
|
|
||||||
include/uapi/linux/if_tunnel.h | 20 ++++++-
|
|
||||||
net/ipv4/ip_tunnel.c | 7 ++-
|
|
||||||
net/ipv4/ipip.c | 120 +++++++++++++++++++++++++++++++++--------
|
|
||||||
4 files changed, 133 insertions(+), 28 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
|
|
||||||
index d7eada2..2f7bc8c 100644
|
|
||||||
--- a/include/net/ip_tunnels.h
|
|
||||||
+++ b/include/net/ip_tunnels.h
|
|
||||||
@@ -51,9 +51,18 @@ struct ip_tunnel_dst {
|
|
||||||
__be32 saddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* Underlay address prefix for ipip fan mode */
|
|
||||||
+/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
|
|
||||||
+ * underlay (10.88.0.0/16, for example). Multiple local addresses within
|
|
||||||
+ * the /16 may be used, but a particular overlay may not span
|
|
||||||
+ * multiple underlay subnets.
|
|
||||||
+ *
|
|
||||||
+ * We store one underlay, indexed by the overlay's high order octet.
|
|
||||||
+ */
|
|
||||||
+#define FAN_OVERLAY_CNT 256
|
|
||||||
+
|
|
||||||
struct ip_tunnel_fan {
|
|
||||||
- u32 underlay;
|
|
||||||
+/* u32 __rcu *map;*/
|
|
||||||
+ u32 map[FAN_OVERLAY_CNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ip_tunnel {
|
|
||||||
@@ -104,6 +113,7 @@ struct ip_tunnel {
|
|
||||||
#define TUNNEL_OAM __cpu_to_be16(0x0200)
|
|
||||||
#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400)
|
|
||||||
#define TUNNEL_OPTIONS_PRESENT __cpu_to_be16(0x0800)
|
|
||||||
+#define TUNNEL_FAN __cpu_to_be16(0x4000)
|
|
||||||
|
|
||||||
struct tnl_ptk_info {
|
|
||||||
__be16 flags;
|
|
||||||
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
|
|
||||||
index 8f7d269..9625934 100644
|
|
||||||
--- a/include/uapi/linux/if_tunnel.h
|
|
||||||
+++ b/include/uapi/linux/if_tunnel.h
|
|
||||||
@@ -58,8 +58,8 @@ enum {
|
|
||||||
IFLA_IPTUN_ENCAP_SPORT,
|
|
||||||
IFLA_IPTUN_ENCAP_DPORT,
|
|
||||||
|
|
||||||
- __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
- IFLA_IPTUN_FAN_UNDERLAY=32,
|
|
||||||
+ __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
+ IFLA_IPTUN_FAN_MAP = 33,
|
|
||||||
|
|
||||||
__IFLA_IPTUN_MAX,
|
|
||||||
};
|
|
||||||
@@ -135,4 +135,20 @@ enum {
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
|
|
||||||
+
|
|
||||||
+enum {
|
|
||||||
+ IFLA_FAN_UNSPEC,
|
|
||||||
+ IFLA_FAN_MAPPING,
|
|
||||||
+ __IFLA_FAN_MAX,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
|
|
||||||
+
|
|
||||||
+struct ip_tunnel_fan_map {
|
|
||||||
+ __be32 underlay;
|
|
||||||
+ __be32 overlay;
|
|
||||||
+ __u16 underlay_prefix;
|
|
||||||
+ __u16 overlay_prefix;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#endif /* _UAPI_IF_TUNNEL_H_ */
|
|
||||||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
|
|
||||||
index d3e4479..60bd10f 100644
|
|
||||||
--- a/net/ipv4/ip_tunnel.c
|
|
||||||
+++ b/net/ipv4/ip_tunnel.c
|
|
||||||
@@ -1078,6 +1078,11 @@ out:
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
|
|
||||||
|
|
||||||
+static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
|
|
||||||
+{
|
|
||||||
+ return tunnel->parms.i_flags & TUNNEL_FAN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
struct ip_tunnel_parm *p)
|
|
||||||
{
|
|
||||||
@@ -1087,7 +1092,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
|
|
||||||
|
|
||||||
if (dev == itn->fb_tunnel_dev)
|
|
||||||
- return -EINVAL;
|
|
||||||
+ return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
|
|
||||||
|
|
||||||
t = ip_tunnel_find(itn, p, dev->type);
|
|
||||||
|
|
||||||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
|
|
||||||
index e3c27cd..d6ebc66 100644
|
|
||||||
--- a/net/ipv4/ipip.c
|
|
||||||
+++ b/net/ipv4/ipip.c
|
|
||||||
@@ -107,6 +107,7 @@
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/netfilter_ipv4.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
+#include <linux/inetdevice.h>
|
|
||||||
|
|
||||||
#include <net/sock.h>
|
|
||||||
#include <net/ip.h>
|
|
||||||
@@ -208,6 +209,11 @@ drop:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
|
|
||||||
+{
|
|
||||||
+ return tunnel->parms.i_flags & TUNNEL_FAN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Determine fan tunnel endpoint to send packet to, based on the inner IP
|
|
||||||
* address. For an overlay (inner) address Y.A.B.C, the transformation is
|
|
||||||
@@ -221,15 +227,20 @@ drop:
|
|
||||||
* 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
|
|
||||||
* overlay network 99.6.7.0/24.
|
|
||||||
*/
|
|
||||||
-static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
+static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
{
|
|
||||||
- u32 daddr;
|
|
||||||
-
|
|
||||||
- *iph = tunnel->parms.iph;
|
|
||||||
+ unsigned int overlay;
|
|
||||||
+ u32 daddr, underlay;
|
|
||||||
|
|
||||||
daddr = ntohl(ip_hdr(skb)->daddr);
|
|
||||||
- iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
|
|
||||||
- ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+ overlay = daddr >> 24;
|
|
||||||
+ underlay = tunnel->fan.map[overlay];
|
|
||||||
+ if (!underlay)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ *iph = tunnel->parms.iph;
|
|
||||||
+ iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -249,8 +260,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
if (IS_ERR(skb))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
- if (tunnel->fan.underlay) {
|
|
||||||
- ipip_build_fan_iphdr(tunnel, skb, &fiph);
|
|
||||||
+ if (ipip_tunnel_is_fan(tunnel)) {
|
|
||||||
+ if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
|
|
||||||
+ goto tx_error;
|
|
||||||
tiph = &fiph;
|
|
||||||
} else {
|
|
||||||
tiph = &tunnel->parms.iph;
|
|
||||||
@@ -409,21 +421,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void ipip_fan_free_map(struct ip_tunnel *t)
|
|
||||||
+{
|
|
||||||
+ memset(&t->fan.map, 0, sizeof(t->fan.map));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
|
|
||||||
+{
|
|
||||||
+ u32 overlay, overlay_mask, underlay, underlay_mask;
|
|
||||||
+
|
|
||||||
+ if ((map->underlay_prefix && map->underlay_prefix != 16) ||
|
|
||||||
+ (map->overlay_prefix && map->overlay_prefix != 8))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ overlay = ntohl(map->overlay);
|
|
||||||
+ overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
|
|
||||||
+
|
|
||||||
+ underlay = ntohl(map->underlay);
|
|
||||||
+ underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
|
|
||||||
+
|
|
||||||
+ if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if (!(overlay & overlay_mask) && (underlay & underlay_mask))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ t->parms.i_flags |= TUNNEL_FAN;
|
|
||||||
+
|
|
||||||
+ /* Special case: overlay 0 and underlay 0 clears all mappings */
|
|
||||||
+ if (!overlay && !underlay) {
|
|
||||||
+ ipip_fan_free_map(t);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ overlay >>= (32 - map->overlay_prefix);
|
|
||||||
+ t->fan.map[overlay] = underlay;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
|
|
||||||
struct ip_tunnel_parm *parms)
|
|
||||||
{
|
|
||||||
- u32 net = t->fan.underlay;
|
|
||||||
-
|
|
||||||
- if (!data[IFLA_IPTUN_FAN_UNDERLAY])
|
|
||||||
- goto err_check;
|
|
||||||
+ struct ip_tunnel_fan_map *map;
|
|
||||||
+ struct nlattr *attr;
|
|
||||||
+ int rem, rv;
|
|
||||||
|
|
||||||
- net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
|
|
||||||
+ if (!data[IFLA_IPTUN_FAN_MAP])
|
|
||||||
+ return 0;
|
|
||||||
|
|
||||||
-err_check:
|
|
||||||
- if (parms->iph.daddr && net)
|
|
||||||
+ if (parms->iph.daddr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
- t->fan.underlay = net;
|
|
||||||
+ nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
|
|
||||||
+ map = nla_data(attr);
|
|
||||||
+ rv = ipip_fan_set_map(t, map);
|
|
||||||
+ if (rv)
|
|
||||||
+ return rv;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -500,8 +556,8 @@ static size_t ipip_get_size(const struct net_device *dev)
|
|
||||||
nla_total_size(2) +
|
|
||||||
/* IFLA_IPTUN_ENCAP_DPORT */
|
|
||||||
nla_total_size(2) +
|
|
||||||
- /* IFLA_IPTUN_FAN_UNDERLAY */
|
|
||||||
- nla_total_size(4) +
|
|
||||||
+ /* IFLA_IPTUN_FAN_MAP */
|
|
||||||
+ nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -529,10 +585,28 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
||||||
tunnel->encap.flags))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
- if (tunnel->fan.underlay)
|
|
||||||
- if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
|
|
||||||
- htonl(tunnel->fan.underlay)))
|
|
||||||
+ if (tunnel->parms.i_flags & TUNNEL_FAN) {
|
|
||||||
+ struct nlattr *fan_nest;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
|
|
||||||
+ if (!fan_nest)
|
|
||||||
goto nla_put_failure;
|
|
||||||
+ for (i = 0; i < 256; i++) {
|
|
||||||
+ if (tunnel->fan.map[i]) {
|
|
||||||
+ struct ip_tunnel_fan_map map;
|
|
||||||
+
|
|
||||||
+ map.underlay = htonl(tunnel->fan.map[i]);
|
|
||||||
+ map.underlay_prefix = 16;
|
|
||||||
+ map.overlay = htonl(i << 24);
|
|
||||||
+ map.overlay_prefix = 8;
|
|
||||||
+ if (nla_put(skb, IFLA_FAN_MAPPING,
|
|
||||||
+ sizeof(map), &map))
|
|
||||||
+ goto nla_put_failure;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ nla_nest_end(skb, fan_nest);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
@@ -553,7 +627,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
|
|
||||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
|
|
||||||
|
|
||||||
[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX] = { .type = NLA_BINARY },
|
|
||||||
- [IFLA_IPTUN_FAN_UNDERLAY] = { .type = NLA_U32 },
|
|
||||||
+ [IFLA_IPTUN_FAN_MAP] = { .type = NLA_NESTED },
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
|
|
||||||
@@ -595,7 +669,7 @@ static struct pernet_operations ipip_net_ops = {
|
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
|
||||||
static struct ctl_table_header *ipip_fan_header;
|
|
||||||
-static unsigned int ipip_fan_version = 1;
|
|
||||||
+static unsigned int ipip_fan_version = 3;
|
|
||||||
|
|
||||||
static struct ctl_table ipip_fan_sysctls[] = {
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.4.1
|
|
||||||
|
|
1240
pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch
Normal file
1240
pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,616 +0,0 @@
|
|||||||
From f3c956096902669c3529cb01d40deb0c759ed94f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
Date: Wed, 1 Apr 2015 16:11:09 -0700
|
|
||||||
Subject: [PATCH] UBUNTU: SAUCE: fan: Proof of concept implementation (v2)
|
|
||||||
|
|
||||||
Modification to ipip tunnel driver to accept a new netlink option,
|
|
||||||
IFLA_IPTUN_FAN_UNDERLAY, which provides a /16 network prefix and enables
|
|
||||||
TX side destination address remapping for traffic entering the tunnel
|
|
||||||
(to be encapsulated).
|
|
||||||
|
|
||||||
For an overlay (inner) address Y.A.B.C, the transformation is F.G.A.B,
|
|
||||||
where "F" and "G" are the first two octets of the underlay network (the
|
|
||||||
network portion of a /16), "A" and "B" are the low order two octets of the
|
|
||||||
underlay network host (the host portion of a /16), and "Y" is a configured
|
|
||||||
first octet of the overlay network.
|
|
||||||
|
|
||||||
E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
|
|
||||||
subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to 99.6.7.8
|
|
||||||
would be directed to underlay host 10.88.6.7, which hosts overlay network
|
|
||||||
99.6.7.0/24.
|
|
||||||
|
|
||||||
Includes net.fan.version sysctl as a sentinel for availability of the
|
|
||||||
fan functionality.
|
|
||||||
|
|
||||||
NOTE: this requires an updated iproute2 to facilitate configuration of
|
|
||||||
the fan.
|
|
||||||
|
|
||||||
BugLink: http://bugs.launchpad.net/bugs/1439706
|
|
||||||
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
[apw@canonical.com: move IFLA_IPTUN_FAN_UNDERLAY up to avoid clashing
|
|
||||||
with future feature additions.]
|
|
||||||
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
||||||
---
|
|
||||||
include/net/ip_tunnels.h | 6 +++
|
|
||||||
include/uapi/linux/if_tunnel.h | 4 ++
|
|
||||||
net/ipv4/ipip.c | 112 +++++++++++++++++++++++++++++++++++++++--
|
|
||||||
3 files changed, 117 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
|
|
||||||
index 25a59eb..d7eada2 100644
|
|
||||||
--- a/include/net/ip_tunnels.h
|
|
||||||
+++ b/include/net/ip_tunnels.h
|
|
||||||
@@ -51,6 +51,11 @@ struct ip_tunnel_dst {
|
|
||||||
__be32 saddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* Underlay address prefix for ipip fan mode */
|
|
||||||
+struct ip_tunnel_fan {
|
|
||||||
+ u32 underlay;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
struct ip_tunnel {
|
|
||||||
struct ip_tunnel __rcu *next;
|
|
||||||
struct hlist_node hash_node;
|
|
||||||
@@ -82,6 +87,7 @@ struct ip_tunnel {
|
|
||||||
#endif
|
|
||||||
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
|
|
||||||
unsigned int prl_count; /* # of entries in PRL */
|
|
||||||
+ struct ip_tunnel_fan fan;
|
|
||||||
int ip_tnl_net_id;
|
|
||||||
struct gro_cells gro_cells;
|
|
||||||
};
|
|
||||||
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
|
|
||||||
index bd3cc11..8f7d269 100644
|
|
||||||
--- a/include/uapi/linux/if_tunnel.h
|
|
||||||
+++ b/include/uapi/linux/if_tunnel.h
|
|
||||||
@@ -57,6 +57,10 @@ enum {
|
|
||||||
IFLA_IPTUN_ENCAP_FLAGS,
|
|
||||||
IFLA_IPTUN_ENCAP_SPORT,
|
|
||||||
IFLA_IPTUN_ENCAP_DPORT,
|
|
||||||
+
|
|
||||||
+ __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
+ IFLA_IPTUN_FAN_UNDERLAY=32,
|
|
||||||
+
|
|
||||||
__IFLA_IPTUN_MAX,
|
|
||||||
};
|
|
||||||
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
|
|
||||||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
|
|
||||||
index 40403114..e3c27cd 100644
|
|
||||||
--- a/net/ipv4/ipip.c
|
|
||||||
+++ b/net/ipv4/ipip.c
|
|
||||||
@@ -209,13 +209,38 @@ drop:
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
+ * Determine fan tunnel endpoint to send packet to, based on the inner IP
|
|
||||||
+ * address. For an overlay (inner) address Y.A.B.C, the transformation is
|
|
||||||
+ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
|
|
||||||
+ * network (the network portion of a /16), "A" and "B" are the low order
|
|
||||||
+ * two octets of the underlay network host (the host portion of a /16),
|
|
||||||
+ * and "Y" is a configured first octet of the overlay network.
|
|
||||||
+ *
|
|
||||||
+ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
|
|
||||||
+ * subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to
|
|
||||||
+ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
|
|
||||||
+ * overlay network 99.6.7.0/24.
|
|
||||||
+ */
|
|
||||||
+static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
+{
|
|
||||||
+ u32 daddr;
|
|
||||||
+
|
|
||||||
+ *iph = tunnel->parms.iph;
|
|
||||||
+
|
|
||||||
+ daddr = ntohl(ip_hdr(skb)->daddr);
|
|
||||||
+ iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
|
|
||||||
+ ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
* This function assumes it is being called from dev_queue_xmit()
|
|
||||||
* and that skb is filled properly by that function.
|
|
||||||
*/
|
|
||||||
static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
{
|
|
||||||
struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
||||||
- const struct iphdr *tiph = &tunnel->parms.iph;
|
|
||||||
+ const struct iphdr *tiph;
|
|
||||||
+ struct iphdr fiph;
|
|
||||||
|
|
||||||
if (unlikely(skb->protocol != htons(ETH_P_IP)))
|
|
||||||
goto tx_error;
|
|
||||||
@@ -224,6 +249,13 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
if (IS_ERR(skb))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
+ if (tunnel->fan.underlay) {
|
|
||||||
+ ipip_build_fan_iphdr(tunnel, skb, &fiph);
|
|
||||||
+ tiph = &fiph;
|
|
||||||
+ } else {
|
|
||||||
+ tiph = &tunnel->parms.iph;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
|
|
||||||
|
|
||||||
ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
|
|
||||||
@@ -377,21 +409,44 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
|
|
||||||
+ struct ip_tunnel_parm *parms)
|
|
||||||
+{
|
|
||||||
+ u32 net = t->fan.underlay;
|
|
||||||
+
|
|
||||||
+ if (!data[IFLA_IPTUN_FAN_UNDERLAY])
|
|
||||||
+ goto err_check;
|
|
||||||
+
|
|
||||||
+ net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
|
|
||||||
+
|
|
||||||
+err_check:
|
|
||||||
+ if (parms->iph.daddr && net)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ t->fan.underlay = net;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int ipip_newlink(struct net *src_net, struct net_device *dev,
|
|
||||||
struct nlattr *tb[], struct nlattr *data[])
|
|
||||||
{
|
|
||||||
struct ip_tunnel_parm p;
|
|
||||||
struct ip_tunnel_encap ipencap;
|
|
||||||
+ struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
if (ipip_netlink_encap_parms(data, &ipencap)) {
|
|
||||||
- struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
- int err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
+ err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipip_netlink_parms(data, &p);
|
|
||||||
+ err = ipip_netlink_fan(data, t, &p);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
return ip_tunnel_newlink(dev, tb, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -400,16 +455,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
{
|
|
||||||
struct ip_tunnel_parm p;
|
|
||||||
struct ip_tunnel_encap ipencap;
|
|
||||||
+ struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
if (ipip_netlink_encap_parms(data, &ipencap)) {
|
|
||||||
- struct ip_tunnel *t = netdev_priv(dev);
|
|
||||||
- int err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
+ err = ip_tunnel_encap_setup(t, &ipencap);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipip_netlink_parms(data, &p);
|
|
||||||
+ err = ipip_netlink_fan(data, t, &p);
|
|
||||||
+ if (err < 0)
|
|
||||||
+ return err;
|
|
||||||
|
|
||||||
if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
|
|
||||||
(!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
|
|
||||||
@@ -441,6 +500,8 @@ static size_t ipip_get_size(const struct net_device *dev)
|
|
||||||
nla_total_size(2) +
|
|
||||||
/* IFLA_IPTUN_ENCAP_DPORT */
|
|
||||||
nla_total_size(2) +
|
|
||||||
+ /* IFLA_IPTUN_FAN_UNDERLAY */
|
|
||||||
+ nla_total_size(4) +
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -468,6 +529,11 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
||||||
tunnel->encap.flags))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
+ if (tunnel->fan.underlay)
|
|
||||||
+ if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
|
|
||||||
+ htonl(tunnel->fan.underlay)))
|
|
||||||
+ goto nla_put_failure;
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
@@ -485,6 +551,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
|
|
||||||
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
|
|
||||||
[IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
|
|
||||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
|
|
||||||
+
|
|
||||||
+ [__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX] = { .type = NLA_BINARY },
|
|
||||||
+ [IFLA_IPTUN_FAN_UNDERLAY] = { .type = NLA_U32 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
|
|
||||||
@@ -524,6 +593,23 @@ static struct pernet_operations ipip_net_ops = {
|
|
||||||
.size = sizeof(struct ip_tunnel_net),
|
|
||||||
};
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+static struct ctl_table_header *ipip_fan_header;
|
|
||||||
+static unsigned int ipip_fan_version = 1;
|
|
||||||
+
|
|
||||||
+static struct ctl_table ipip_fan_sysctls[] = {
|
|
||||||
+ {
|
|
||||||
+ .procname = "version",
|
|
||||||
+ .data = &ipip_fan_version,
|
|
||||||
+ .maxlen = sizeof(ipip_fan_version),
|
|
||||||
+ .mode = 0444,
|
|
||||||
+ .proc_handler = proc_dointvec,
|
|
||||||
+ },
|
|
||||||
+ {},
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
+
|
|
||||||
static int __init ipip_init(void)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
@@ -542,9 +628,22 @@ static int __init ipip_init(void)
|
|
||||||
if (err < 0)
|
|
||||||
goto rtnl_link_failed;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+ ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
|
|
||||||
+ ipip_fan_sysctls);
|
|
||||||
+ if (!ipip_fan_header) {
|
|
||||||
+ err = -ENOMEM;
|
|
||||||
+ goto sysctl_failed;
|
|
||||||
+ }
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
+
|
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+sysctl_failed:
|
|
||||||
+ rtnl_link_unregister(&ipip_link_ops);
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
rtnl_link_failed:
|
|
||||||
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
|
|
||||||
xfrm_tunnel_failed:
|
|
||||||
@@ -554,6 +653,9 @@ xfrm_tunnel_failed:
|
|
||||||
|
|
||||||
static void __exit ipip_fini(void)
|
|
||||||
{
|
|
||||||
+#ifdef CONFIG_SYSCTL
|
|
||||||
+ unregister_net_sysctl_table(ipip_fan_header);
|
|
||||||
+#endif /* CONFIG_SYSCTL */
|
|
||||||
rtnl_link_unregister(&ipip_link_ops);
|
|
||||||
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
|
|
||||||
pr_info("%s: can't deregister tunnel\n", __func__);
|
|
||||||
--
|
|
||||||
2.4.1
|
|
||||||
|
|
||||||
From 4ea8011656dfdd76e7a2391bdad47c06f85a9d02 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andy Whitcroft <apw@canonical.com>
|
|
||||||
Date: Tue, 21 Jul 2015 16:52:10 +0100
|
|
||||||
Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
|
|
||||||
|
|
||||||
Switch to a single tunnel for all mappings, this removes the limitations
|
|
||||||
on how many mappings each tunnel can handle, and therefore how many Fan
|
|
||||||
slices each local address may hold.
|
|
||||||
|
|
||||||
NOTE: This introduces a new kernel netlink interface which needs updated
|
|
||||||
iproute2 support.
|
|
||||||
|
|
||||||
BugLink: http://bugs.launchpad.net/bugs/1470091
|
|
||||||
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
|
|
||||||
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
||||||
Acked-by: Tim Gardner <tim.gardner@canonical.com>
|
|
||||||
Acked-by: Brad Figg <brad.figg@canonical.com>
|
|
||||||
Signed-off-by: Brad Figg <brad.figg@canonical.com>
|
|
||||||
---
|
|
||||||
include/net/ip_tunnels.h | 14 ++++-
|
|
||||||
include/uapi/linux/if_tunnel.h | 20 ++++++-
|
|
||||||
net/ipv4/ip_tunnel.c | 7 ++-
|
|
||||||
net/ipv4/ipip.c | 120 +++++++++++++++++++++++++++++++++--------
|
|
||||||
4 files changed, 133 insertions(+), 28 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
|
|
||||||
index d7eada2..2f7bc8c 100644
|
|
||||||
--- a/include/net/ip_tunnels.h
|
|
||||||
+++ b/include/net/ip_tunnels.h
|
|
||||||
@@ -51,9 +51,18 @@ struct ip_tunnel_dst {
|
|
||||||
__be32 saddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* Underlay address prefix for ipip fan mode */
|
|
||||||
+/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
|
|
||||||
+ * underlay (10.88.0.0/16, for example). Multiple local addresses within
|
|
||||||
+ * the /16 may be used, but a particular overlay may not span
|
|
||||||
+ * multiple underlay subnets.
|
|
||||||
+ *
|
|
||||||
+ * We store one underlay, indexed by the overlay's high order octet.
|
|
||||||
+ */
|
|
||||||
+#define FAN_OVERLAY_CNT 256
|
|
||||||
+
|
|
||||||
struct ip_tunnel_fan {
|
|
||||||
- u32 underlay;
|
|
||||||
+/* u32 __rcu *map;*/
|
|
||||||
+ u32 map[FAN_OVERLAY_CNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ip_tunnel {
|
|
||||||
@@ -104,6 +113,7 @@ struct ip_tunnel {
|
|
||||||
#define TUNNEL_OAM __cpu_to_be16(0x0200)
|
|
||||||
#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400)
|
|
||||||
#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800)
|
|
||||||
#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000)
|
|
||||||
+#define TUNNEL_FAN __cpu_to_be16(0x4000)
|
|
||||||
|
|
||||||
#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
|
|
||||||
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
|
|
||||||
index 8f7d269..9625934 100644
|
|
||||||
--- a/include/uapi/linux/if_tunnel.h
|
|
||||||
+++ b/include/uapi/linux/if_tunnel.h
|
|
||||||
@@ -58,8 +58,8 @@ enum {
|
|
||||||
IFLA_IPTUN_ENCAP_SPORT,
|
|
||||||
IFLA_IPTUN_ENCAP_DPORT,
|
|
||||||
|
|
||||||
- __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
- IFLA_IPTUN_FAN_UNDERLAY=32,
|
|
||||||
+ __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
|
|
||||||
+ IFLA_IPTUN_FAN_MAP = 33,
|
|
||||||
|
|
||||||
__IFLA_IPTUN_MAX,
|
|
||||||
};
|
|
||||||
@@ -135,4 +135,20 @@ enum {
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
|
|
||||||
+
|
|
||||||
+enum {
|
|
||||||
+ IFLA_FAN_UNSPEC,
|
|
||||||
+ IFLA_FAN_MAPPING,
|
|
||||||
+ __IFLA_FAN_MAX,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
|
|
||||||
+
|
|
||||||
+struct ip_tunnel_fan_map {
|
|
||||||
+ __be32 underlay;
|
|
||||||
+ __be32 overlay;
|
|
||||||
+ __u16 underlay_prefix;
|
|
||||||
+ __u16 overlay_prefix;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#endif /* _UAPI_IF_TUNNEL_H_ */
|
|
||||||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
|
|
||||||
index d3e4479..60bd10f 100644
|
|
||||||
--- a/net/ipv4/ip_tunnel.c
|
|
||||||
+++ b/net/ipv4/ip_tunnel.c
|
|
||||||
@@ -1078,6 +1078,11 @@ out:
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
|
|
||||||
|
|
||||||
+static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
|
|
||||||
+{
|
|
||||||
+ return tunnel->parms.i_flags & TUNNEL_FAN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
struct ip_tunnel_parm *p)
|
|
||||||
{
|
|
||||||
@@ -1087,7 +1092,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
||||||
struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
|
|
||||||
|
|
||||||
if (dev == itn->fb_tunnel_dev)
|
|
||||||
- return -EINVAL;
|
|
||||||
+ return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
|
|
||||||
|
|
||||||
t = ip_tunnel_find(itn, p, dev->type);
|
|
||||||
|
|
||||||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
|
|
||||||
index e3c27cd..d6ebc66 100644
|
|
||||||
--- a/net/ipv4/ipip.c
|
|
||||||
+++ b/net/ipv4/ipip.c
|
|
||||||
@@ -107,6 +107,7 @@
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/netfilter_ipv4.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
+#include <linux/inetdevice.h>
|
|
||||||
|
|
||||||
#include <net/sock.h>
|
|
||||||
#include <net/ip.h>
|
|
||||||
@@ -208,6 +209,11 @@ drop:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
|
|
||||||
+{
|
|
||||||
+ return tunnel->parms.i_flags & TUNNEL_FAN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Determine fan tunnel endpoint to send packet to, based on the inner IP
|
|
||||||
* address. For an overlay (inner) address Y.A.B.C, the transformation is
|
|
||||||
@@ -221,15 +227,20 @@ drop:
|
|
||||||
* 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
|
|
||||||
* overlay network 99.6.7.0/24.
|
|
||||||
*/
|
|
||||||
-static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
+static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
|
|
||||||
{
|
|
||||||
- u32 daddr;
|
|
||||||
-
|
|
||||||
- *iph = tunnel->parms.iph;
|
|
||||||
+ unsigned int overlay;
|
|
||||||
+ u32 daddr, underlay;
|
|
||||||
|
|
||||||
daddr = ntohl(ip_hdr(skb)->daddr);
|
|
||||||
- iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
|
|
||||||
- ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+ overlay = daddr >> 24;
|
|
||||||
+ underlay = tunnel->fan.map[overlay];
|
|
||||||
+ if (!underlay)
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ *iph = tunnel->parms.iph;
|
|
||||||
+ iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -249,8 +260,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
||||||
if (IS_ERR(skb))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
- if (tunnel->fan.underlay) {
|
|
||||||
- ipip_build_fan_iphdr(tunnel, skb, &fiph);
|
|
||||||
+ if (ipip_tunnel_is_fan(tunnel)) {
|
|
||||||
+ if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
|
|
||||||
+ goto tx_error;
|
|
||||||
tiph = &fiph;
|
|
||||||
} else {
|
|
||||||
tiph = &tunnel->parms.iph;
|
|
||||||
@@ -409,21 +421,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void ipip_fan_free_map(struct ip_tunnel *t)
|
|
||||||
+{
|
|
||||||
+ memset(&t->fan.map, 0, sizeof(t->fan.map));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
|
|
||||||
+{
|
|
||||||
+ u32 overlay, overlay_mask, underlay, underlay_mask;
|
|
||||||
+
|
|
||||||
+ if ((map->underlay_prefix && map->underlay_prefix != 16) ||
|
|
||||||
+ (map->overlay_prefix && map->overlay_prefix != 8))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ overlay = ntohl(map->overlay);
|
|
||||||
+ overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
|
|
||||||
+
|
|
||||||
+ underlay = ntohl(map->underlay);
|
|
||||||
+ underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
|
|
||||||
+
|
|
||||||
+ if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if (!(overlay & overlay_mask) && (underlay & underlay_mask))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ t->parms.i_flags |= TUNNEL_FAN;
|
|
||||||
+
|
|
||||||
+ /* Special case: overlay 0 and underlay 0 clears all mappings */
|
|
||||||
+ if (!overlay && !underlay) {
|
|
||||||
+ ipip_fan_free_map(t);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ overlay >>= (32 - map->overlay_prefix);
|
|
||||||
+ t->fan.map[overlay] = underlay;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
|
|
||||||
struct ip_tunnel_parm *parms)
|
|
||||||
{
|
|
||||||
- u32 net = t->fan.underlay;
|
|
||||||
-
|
|
||||||
- if (!data[IFLA_IPTUN_FAN_UNDERLAY])
|
|
||||||
- goto err_check;
|
|
||||||
+ struct ip_tunnel_fan_map *map;
|
|
||||||
+ struct nlattr *attr;
|
|
||||||
+ int rem, rv;
|
|
||||||
|
|
||||||
- net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
|
|
||||||
+ if (!data[IFLA_IPTUN_FAN_MAP])
|
|
||||||
+ return 0;
|
|
||||||
|
|
||||||
-err_check:
|
|
||||||
- if (parms->iph.daddr && net)
|
|
||||||
+ if (parms->iph.daddr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
- t->fan.underlay = net;
|
|
||||||
+ nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
|
|
||||||
+ map = nla_data(attr);
|
|
||||||
+ rv = ipip_fan_set_map(t, map);
|
|
||||||
+ if (rv)
|
|
||||||
+ return rv;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -500,8 +556,8 @@ static size_t ipip_get_size(const struct net_device *dev)
|
|
||||||
nla_total_size(2) +
|
|
||||||
/* IFLA_IPTUN_ENCAP_DPORT */
|
|
||||||
nla_total_size(2) +
|
|
||||||
- /* IFLA_IPTUN_FAN_UNDERLAY */
|
|
||||||
- nla_total_size(4) +
|
|
||||||
+ /* IFLA_IPTUN_FAN_MAP */
|
|
||||||
+ nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -529,10 +585,28 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
||||||
tunnel->encap.flags))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
- if (tunnel->fan.underlay)
|
|
||||||
- if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
|
|
||||||
- htonl(tunnel->fan.underlay)))
|
|
||||||
+ if (tunnel->parms.i_flags & TUNNEL_FAN) {
|
|
||||||
+ struct nlattr *fan_nest;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
|
|
||||||
+ if (!fan_nest)
|
|
||||||
goto nla_put_failure;
|
|
||||||
+ for (i = 0; i < 256; i++) {
|
|
||||||
+ if (tunnel->fan.map[i]) {
|
|
||||||
+ struct ip_tunnel_fan_map map;
|
|
||||||
+
|
|
||||||
+ map.underlay = htonl(tunnel->fan.map[i]);
|
|
||||||
+ map.underlay_prefix = 16;
|
|
||||||
+ map.overlay = htonl(i << 24);
|
|
||||||
+ map.overlay_prefix = 8;
|
|
||||||
+ if (nla_put(skb, IFLA_FAN_MAPPING,
|
|
||||||
+ sizeof(map), &map))
|
|
||||||
+ goto nla_put_failure;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ nla_nest_end(skb, fan_nest);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
@@ -553,7 +627,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
|
|
||||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
|
|
||||||
|
|
||||||
[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX] = { .type = NLA_BINARY },
|
|
||||||
- [IFLA_IPTUN_FAN_UNDERLAY] = { .type = NLA_U32 },
|
|
||||||
+ [IFLA_IPTUN_FAN_MAP] = { .type = NLA_NESTED },
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
|
|
||||||
@@ -595,7 +669,7 @@ static struct pernet_operations ipip_net_ops = {
|
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
|
||||||
static struct ctl_table_header *ipip_fan_header;
|
|
||||||
-static unsigned int ipip_fan_version = 1;
|
|
||||||
+static unsigned int ipip_fan_version = 3;
|
|
||||||
|
|
||||||
static struct ctl_table ipip_fan_sysctls[] = {
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.4.1
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user