[ovs-dev] [tunnels2 5/5] datapath: Add 'link' option to tunnels.

Ben Pfaff blp at nicira.com
Mon Oct 17 22:14:02 UTC 2011


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 <blp at 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




More information about the dev mailing list