This option allows some control over the output interface for tunnels. It is similar to the 'link' option for Linux network-device based GRE tunnels. I didn't, however, make 'link' part of the tunnel key as with those tunnels, which means that two tunnels cannot be distinguished on the basis of 'link' alone. That would slightly complicate tnl_find_port() and didn't seem the effort overall.
I'm not sure that this is really needed at all, to be honest, but it seemed like a missing bit of feature parity between ip_gre and OVS tunnels. Signed-off-by: Ben Pfaff <b...@nicira.com> --- datapath/tunnel.c | 7 +++++++ datapath/tunnel.h | 1 + lib/netdev-vport.c | 19 +++++++++++++++++++ vswitchd/vswitch.xml | 6 ++++++ 4 files changed, 33 insertions(+), 0 deletions(-) diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 6fde389..ef7891f 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -966,6 +966,7 @@ static struct rtable *__find_route(const struct tnl_mutable_config *mutable, #else struct flowi4 fl = { .daddr = mutable->key.daddr, .saddr = mutable->key.saddr, + .flowi4_oif = mutable->link, .flowi4_tos = tos, .flowi4_proto = ipproto }; @@ -1312,6 +1313,7 @@ static const struct nla_policy tnl_policy[OVS_TUNNEL_ATTR_MAX + 1] = { [OVS_TUNNEL_ATTR_IN_KEY] = { .type = NLA_U64 }, [OVS_TUNNEL_ATTR_TOS] = { .type = NLA_U8 }, [OVS_TUNNEL_ATTR_TTL] = { .type = NLA_U8 }, + [OVS_TUNNEL_ATTR_LINK] = { .type = NLA_U32 }, }; /* Sets OVS_TUNNEL_ATTR_* fields in 'mutable', which must initially be zeroed. */ @@ -1363,6 +1365,9 @@ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops, else mutable->out_key = nla_get_be64(a[OVS_TUNNEL_ATTR_OUT_KEY]); + if (a[OVS_TUNNEL_ATTR_LINK]) + mutable->link = nla_get_u32(a[OVS_TUNNEL_ATTR_LINK]); + mutable->tunnel_hlen = tnl_ops->hdr_len(mutable); if (mutable->tunnel_hlen < 0) return mutable->tunnel_hlen; @@ -1504,6 +1509,8 @@ int tnl_get_options(const struct vport *vport, struct sk_buff *skb) NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TOS, mutable->tos); if (mutable->ttl) NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TTL, mutable->ttl); + if (mutable->link) + NLA_PUT_U32(skb, OVS_TUNNEL_ATTR_LINK, mutable->link); return 0; diff --git a/datapath/tunnel.h b/datapath/tunnel.h index 1e707a9..dcc6747 100644 --- a/datapath/tunnel.h +++ b/datapath/tunnel.h @@ -89,6 +89,7 @@ struct tnl_mutable_config { u32 flags; u8 tos; u8 ttl; + int link; /* Multicast configuration. */ int mlink; diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 301bb43..0cf5257 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -618,6 +618,15 @@ parse_tunnel_config(const char *name, const char *type, } else { nl_msg_put_u8(options, OVS_TUNNEL_ATTR_TTL, atoi(node->data)); } + } else if (!strcmp(node->name, "link")) { + const char *ifname = node->data; + int ifindex = if_nametoindex(ifname); + if (ifindex) { + nl_msg_put_u32(options, OVS_TUNNEL_ATTR_LINK, ifindex); + } else { + VLOG_WARN("%s: network device \"%s\" does not exist, " + "cannot link", name, ifname); + } } else if (!strcmp(node->name, "csum") && is_gre) { if (!strcmp(node->data, "true")) { flags |= TNL_F_CSUM; @@ -724,6 +733,7 @@ tnl_port_config_from_nlattr(const struct nlattr *options, size_t options_len, [OVS_TUNNEL_ATTR_OUT_KEY] = { .type = NL_A_BE64, .optional = true }, [OVS_TUNNEL_ATTR_TOS] = { .type = NL_A_U8, .optional = true }, [OVS_TUNNEL_ATTR_TTL] = { .type = NL_A_U8, .optional = true }, + [OVS_TUNNEL_ATTR_LINK] = { .type = NL_A_U32, .optional = true }, }; struct ofpbuf buf; @@ -807,6 +817,15 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED, shash_add(args, "tos", xasprintf("%d", tos)); } + if (a[OVS_TUNNEL_ATTR_LINK]) { + int ifindex = nl_attr_get_u32(a[OVS_TUNNEL_ATTR_LINK]); + char ifname[IFNAMSIZ]; + + if (if_indextoname(ifindex, ifname)) { + smap_add(args, "link", ifname); + } + } + if (flags & TNL_F_CSUM) { smap_add(args, "csum", "true"); } diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index d09ade4..dc154e1 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1043,6 +1043,12 @@ from the inner packet if it is IPv4 or IPv6 (otherwise it will be the system default, typically 64). Default is the system default TTL. </column> + + <column name="options" key="link"> + Optional. The name of the network device to use for tunnel output, + superseding the decision that the kernel would ordinarily make through + routing. + </column> <column name="options" key="df_inherit" type='{"type": "boolean"}'> Optional. If enabled, the Don't Fragment bit will be copied from the -- 1.7.4.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev