Merge pull request #12155 from yuwata/network-fix-and-extend-foo-over-udp-support

network: fix and extend Foo over UDP
This commit is contained in:
Yu Watanabe
2019-04-02 06:10:07 +09:00
committed by GitHub
17 changed files with 294 additions and 43 deletions
+93 -16
View File
@@ -5,8 +5,10 @@
#include <linux/ip.h>
#include "conf-parser.h"
#include "ip-protocol-list.h"
#include "missing.h"
#include "netdev/fou-tunnel.h"
#include "netlink-util.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "parse-util.h"
@@ -27,6 +29,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_fou_encap_type, fou_encap_type, FooOverUDP
static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
FouTunnel *t;
uint8_t encap_type;
int r;
assert(netdev);
@@ -43,7 +46,18 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PORT attribute: %m");
r = sd_netlink_message_append_u8(m, FOU_ATTR_TYPE, FOU_ENCAP_GUE);
switch (t->fou_encap_type) {
case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT:
encap_type = FOU_ENCAP_DIRECT;
break;
case NETDEV_FOO_OVER_UDP_ENCAP_GUE:
encap_type = FOU_ENCAP_GUE;
break;
default:
assert_not_reached("invalid encap type");
}
r = sd_netlink_message_append_u8(m, FOU_ATTR_TYPE, encap_type);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_TYPE attribute: %m");
@@ -55,15 +69,32 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_IPPROTO attribute: %m");
*ret = m;
m = NULL;
*ret = TAKE_PTR(m);
return 0;
}
static int fou_tunnel_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
int r;
assert(netdev);
assert(netdev->state != _NETDEV_STATE_INVALID);
r = sd_netlink_message_get_errno(m);
if (r == -EEXIST)
log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
else if (r < 0) {
log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
netdev_drop(netdev);
return 1;
}
log_netdev_debug(netdev, "FooOverUDP tunnel is created");
return 1;
}
static int netdev_fou_tunnel_create(NetDev *netdev) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint32_t serial;
int r;
assert(netdev);
@@ -73,10 +104,49 @@ static int netdev_fou_tunnel_create(NetDev *netdev) {
if (r < 0)
return r;
r = sd_netlink_send(netdev->manager->genl, m, &serial);
if (r < 0 && r != -EADDRINUSE)
return log_netdev_error_errno(netdev, r, "Failed to add FooOverUDP tunnel: %m");
r = netlink_call_async(netdev->manager->genl, NULL, m, fou_tunnel_create_handler,
netdev_destroy_callback, netdev);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Failed to create FooOverUDP tunnel: %m");
netdev_ref(netdev);
return 0;
}
int config_parse_ip_protocol(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint8_t *protocol = data;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert_cc(IPPROTO_MAX-1 <= UINT8_MAX);
r = parse_ip_protocol(rvalue);
if (r < 0) {
r = safe_atou8(rvalue, protocol);
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse IP protocol '%s' for Foo over UDP tunnel, "
"ignoring assignment: %m", rvalue);
return 0;
}
*protocol = r;
return 0;
}
@@ -90,14 +160,21 @@ static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
assert(t);
if (t->fou_encap_type == NETDEV_FOO_OVER_UDP_ENCAP_DIRECT && t->fou_protocol <= 0) {
log_netdev_error(netdev, "FooOverUDP protocol not configured in %s. Rejecting configuration.", filename);
return -EINVAL;
}
if (t->fou_encap_type == NETDEV_FOO_OVER_UDP_ENCAP_GUE && t->fou_protocol > 0) {
log_netdev_error(netdev, "FooOverUDP GUE can't be set with protocol configured in %s. Rejecting configuration.", filename);
return -EINVAL;
switch (t->fou_encap_type) {
case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT:
if (t->fou_protocol <= 0)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"FooOverUDP protocol not configured in %s. Rejecting configuration.",
filename);
break;
case NETDEV_FOO_OVER_UDP_ENCAP_GUE:
if (t->fou_protocol > 0)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"FooOverUDP GUE can't be set with protocol configured in %s. Rejecting configuration.",
filename);
break;
default:
assert_not_reached("Invalid fou encap type");
}
return 0;
+1
View File
@@ -34,3 +34,4 @@ const char *fou_encap_type_to_string(FooOverUDPEncapType d) _const_;
FooOverUDPEncapType fou_encap_type_from_string(const char *d) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_fou_encap_type);
CONFIG_PARSER_PROTOTYPE(config_parse_ip_protocol);
+1 -1
View File
@@ -75,7 +75,7 @@ Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix, 0,
Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index)
Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, gre_erspan_sequence)
Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap)
FooOverUDP.Protocol, config_parse_uint8, 0, offsetof(FouTunnel, fou_protocol)
FooOverUDP.Protocol, config_parse_ip_protocol, 0, offsetof(FouTunnel, fou_protocol)
FooOverUDP.Encapsulation, config_parse_fou_encap_type, 0, offsetof(FouTunnel, fou_encap_type)
FooOverUDP.Port, config_parse_ip_port, 0, offsetof(FouTunnel, port)
L2TP.TunnelId, config_parse_l2tp_tunnel_id, 0, offsetof(L2tpTunnel, tunnel_id)
+32 -14
View File
@@ -72,7 +72,7 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
if (netdev->kind == NETDEV_KIND_IPIP && t->fou_tunnel) {
if (t->fou_tunnel) {
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_TYPE attribute: %m");
@@ -214,6 +214,20 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m");
if (t->fou_tunnel) {
r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_TYPE, t->fou_encap_type);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_TYPE attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_SPORT, htobe16(t->encap_src_port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_SPORT attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_DPORT, htobe16(t->fou_destination_port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_DPORT attribute: %m");
}
return r;
}
@@ -669,23 +683,26 @@ int config_parse_6rd_prefix(const char* unit,
return 0;
}
static void ipip_init(NetDev *n) {
Tunnel *t = IPIP(n);
static void ipip_sit_init(NetDev *n) {
Tunnel *t;
assert(n);
switch (n->kind) {
case NETDEV_KIND_IPIP:
t = IPIP(n);
break;
case NETDEV_KIND_SIT:
t = SIT(n);
break;
default:
assert_not_reached("invalid netdev kind");
}
assert(t);
t->pmtudisc = true;
t->fou_encap_type = FOU_ENCAP_DIRECT;
}
static void sit_init(NetDev *n) {
Tunnel *t = SIT(n);
assert(n);
assert(t);
t->pmtudisc = true;
t->isatap = -1;
}
@@ -727,6 +744,7 @@ static void gre_erspan_init(NetDev *n) {
t->pmtudisc = true;
t->gre_erspan_sequence = -1;
t->fou_encap_type = FOU_ENCAP_DIRECT;
}
static void ip6gre_init(NetDev *n) {
@@ -759,7 +777,7 @@ static void ip6tnl_init(NetDev *n) {
const NetDevVTable ipip_vtable = {
.object_size = sizeof(Tunnel),
.init = ipip_init,
.init = ipip_sit_init,
.sections = "Match\0NetDev\0Tunnel\0",
.fill_message_create = netdev_ipip_sit_fill_message_create,
.create_type = NETDEV_CREATE_STACKED,
@@ -768,7 +786,7 @@ const NetDevVTable ipip_vtable = {
const NetDevVTable sit_vtable = {
.object_size = sizeof(Tunnel),
.init = sit_init,
.init = ipip_sit_init,
.sections = "Match\0NetDev\0Tunnel\0",
.fill_message_create = netdev_ipip_sit_fill_message_create,
.create_type = NETDEV_CREATE_STACKED,