Allow configuration of ipv6 tunnel endpoints. Signed-off-by: Jiri Benc <jb...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev