[ovs-dev] [RFC PATCH 03/13] tunneling: add ipv6 fields to netdev_tunnel_config
Jiri Benc
jbenc at redhat.com
Thu May 14 18:12:34 UTC 2015
Allow configuration of ipv6 tunnel endpoints.
Signed-off-by: Jiri Benc <jbenc at redhat.com>
---
lib/dpif-netlink.c | 6 +++-
lib/netdev-vport.c | 88 ++++++++++++++++++++++++++++++++++++++++--------------
lib/netdev.h | 3 ++
3 files changed, 74 insertions(+), 23 deletions(-)
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 6838def7d9ad..73ad0cb046e2 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -854,12 +854,16 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif, struct netdev *netdev,
}
tnl_cfg = netdev_get_tunnel_config(netdev);
- if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
+ if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->protocol != 0
+ || tnl_cfg->exts)) {
ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
if (tnl_cfg->dst_port) {
nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
ntohs(tnl_cfg->dst_port));
}
+ if (tnl_cfg->protocol == ETH_TYPE_IPV6) {
+ nl_msg_put_flag(&options, OVS_TUNNEL_ATTR_OVER_IPV6);
+ }
if (tnl_cfg->exts) {
size_t ext_ofs;
int i;
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index ea9abf9e7a78..6bcb844608a4 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -427,12 +427,43 @@ parse_key(const struct smap *args, const char *name,
}
static int
+parse_tunnel_ip(const char *value, bool accept_mcast, bool *flow,
+ ovs_be32 *ip, struct in6_addr *ipv6, uint16_t *protocol)
+{
+ if (!strcmp(value, "flow")) {
+ *flow = true;
+ *protocol = ETH_TYPE_IP;
+ return 0;
+ }
+ if (!strcmp(value, "flow6")) {
+ *flow = true;
+ *protocol = ETH_TYPE_IPV6;
+ return 0;
+ }
+ if (addr_is_ipv6(value)) {
+ if (lookup_ipv6(value, ipv6))
+ return ENOENT;
+ if (!accept_mcast && ipv6_addr_is_multicast(ipv6))
+ return EINVAL;
+ *protocol = ETH_TYPE_IPV6;
+ } else {
+ if (lookup_ip(value, (struct in_addr *)ip))
+ return ENOENT;
+ if (!accept_mcast && ip_is_multicast(*ip))
+ return EINVAL;
+ *protocol = ETH_TYPE_IP;
+ }
+ return 0;
+}
+
+static int
set_tunnel_config(struct netdev *dev_, const struct smap *args)
{
struct netdev_vport *dev = netdev_vport_cast(dev_);
const char *name = netdev_get_name(dev_);
const char *type = netdev_get_type(dev_);
bool ipsec_mech_set, needs_dst_port, has_csum;
+ uint16_t dst_proto = 0, src_proto = 0;
struct netdev_tunnel_config tnl_cfg;
struct smap_node *node;
@@ -464,28 +495,28 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
SMAP_FOR_EACH (node, args) {
if (!strcmp(node->key, "remote_ip")) {
- struct in_addr in_addr;
- if (!strcmp(node->value, "flow")) {
- tnl_cfg.ip_dst_flow = true;
- tnl_cfg.ip_dst = htonl(0);
- } else if (lookup_ip(node->value, &in_addr)) {
+ int err;
+ err = parse_tunnel_ip(node->value, false, &tnl_cfg.ip_dst_flow,
+ &tnl_cfg.ip_dst, &tnl_cfg.ipv6_dst,
+ &dst_proto);
+ switch (err) {
+ case ENOENT:
VLOG_WARN("%s: bad %s 'remote_ip'", name, type);
- } else if (ip_is_multicast(in_addr.s_addr)) {
- VLOG_WARN("%s: multicast remote_ip="IP_FMT" not allowed",
- name, IP_ARGS(in_addr.s_addr));
+ break;
+ case EINVAL:
+ VLOG_WARN("%s: multicast remote_ip=%s not allowed",
+ name, node->value);
return EINVAL;
- } else {
- tnl_cfg.ip_dst = in_addr.s_addr;
}
} else if (!strcmp(node->key, "local_ip")) {
- struct in_addr in_addr;
- if (!strcmp(node->value, "flow")) {
- tnl_cfg.ip_src_flow = true;
- tnl_cfg.ip_src = htonl(0);
- } else if (lookup_ip(node->value, &in_addr)) {
+ int err;
+ err = parse_tunnel_ip(node->value, true, &tnl_cfg.ip_src_flow,
+ &tnl_cfg.ip_src, &tnl_cfg.ipv6_src,
+ &src_proto);
+ switch (err) {
+ case ENOENT:
VLOG_WARN("%s: bad %s 'local_ip'", name, type);
- } else {
- tnl_cfg.ip_src = in_addr.s_addr;
+ break;
}
} else if (!strcmp(node->key, "tos")) {
if (!strcmp(node->value, "inherit")) {
@@ -603,16 +634,25 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
}
}
- if (!tnl_cfg.ip_dst && !tnl_cfg.ip_dst_flow) {
+ if (!tnl_cfg.ip_dst && !ipv6_addr_is_set(&tnl_cfg.ipv6_dst) &&
+ !tnl_cfg.ip_dst_flow) {
VLOG_ERR("%s: %s type requires valid 'remote_ip' argument",
name, type);
return EINVAL;
}
if (tnl_cfg.ip_src_flow && !tnl_cfg.ip_dst_flow) {
- VLOG_ERR("%s: %s type requires 'remote_ip=flow' with 'local_ip=flow'",
- name, type);
+ VLOG_ERR("%s: %s type requires 'remote_ip=flow%s' with 'local_ip=flow%s'",
+ name, type,
+ src_proto == ETH_TYPE_IPV6 ? "6" : "",
+ src_proto == ETH_TYPE_IPV6 ? "6" : "");
+ return EINVAL;
+ }
+ if (src_proto && src_proto != dst_proto) {
+ VLOG_ERR("%s: 'remote_ip' and 'local_ip' has to be of the same address family",
+ name);
return EINVAL;
}
+ tnl_cfg.protocol = dst_proto;
if (!tnl_cfg.ttl) {
tnl_cfg.ttl = DEFAULT_TTL;
}
@@ -648,14 +688,18 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
if (tnl_cfg.ip_dst) {
smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_dst));
+ } else if (ipv6_addr_is_set(&tnl_cfg.ipv6_dst)) {
+ smap_add_ipv6(args, "remote_ip", &tnl_cfg.ipv6_dst);
} else if (tnl_cfg.ip_dst_flow) {
- smap_add(args, "remote_ip", "flow");
+ smap_add(args, "remote_ip", tnl_cfg.protocol == ETH_TYPE_IPV6 ? "flow6" : "flow");
}
if (tnl_cfg.ip_src) {
smap_add_format(args, "local_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_src));
+ } else if (ipv6_addr_is_set(&tnl_cfg.ipv6_src)) {
+ smap_add_ipv6(args, "local_ip", &tnl_cfg.ipv6_src);
} else if (tnl_cfg.ip_src_flow) {
- smap_add(args, "local_ip", "flow");
+ smap_add(args, "local_ip", tnl_cfg.protocol == ETH_TYPE_IPV6 ? "flow6" : "flow");
}
if (tnl_cfg.in_key_flow && tnl_cfg.out_key_flow) {
diff --git a/lib/netdev.h b/lib/netdev.h
index 71c0af1b56a0..809a4d58e512 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -114,12 +114,15 @@ struct netdev_tunnel_config {
bool out_key_flow;
ovs_be64 out_key;
+ uint16_t protocol;
ovs_be16 dst_port;
bool ip_src_flow;
bool ip_dst_flow;
ovs_be32 ip_src;
ovs_be32 ip_dst;
+ struct in6_addr ipv6_src;
+ struct in6_addr ipv6_dst;
uint32_t exts;
--
1.8.3.1
More information about the dev
mailing list