Now that both the kernel and userspace can handle information about
the tunnel outer headers this adds userspace support for communicating
between the two.  At the moment userspace doesn't know how to do
anything with the extra information on receive and will only generate
actions containing tun_id.  However, both sides know how to ignore the
extra information.

Signed-off-by: Jesse Gross <je...@nicira.com>
---
 NEWS                  |    2 ++
 lib/odp-util.c        |   75 +++++++++++++++++++++++++++++++++++++++++--------
 tests/odp.at          |   12 ++++----
 tests/ofproto-dpif.at |    2 +-
 4 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/NEWS b/NEWS
index ae831e3..6265e2f 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,8 @@ post-v1.8.0
         - The autopath action.
         - Interface type "null".
         - Numeric values for reserved ports (see "ovs-ofctl" note above).
+    - Tunneling requires the version of the kernel module paired with this
+      release (or a newer release).
 
 
 v1.8.0 - xx xxx xxxx
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 9ed17ed..ac0042c 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -925,6 +925,30 @@ parse_odp_key_attr(const char *s, const struct simap 
*port_names,
     }
 
     {
+        char tun_id_s[32];
+        unsigned long long int flags;
+        int tos, ttl;
+        struct ovs_key_ipv4_tunnel tun_key;
+        int n = -1;
+
+        if (sscanf(s, "ipv4_tunnel(tun_id=%31[x0123456789abcdefABCDEF],"
+                   "flags=%lli,src="IP_SCAN_FMT",dst="IP_SCAN_FMT
+                   ",tos=%i,ttl=%i)%n", tun_id_s, &flags,
+                    IP_SCAN_ARGS(&tun_key.ipv4_src),
+                    IP_SCAN_ARGS(&tun_key.ipv4_dst), &tos, &ttl,
+                    &n) > 0 && n > 0) {
+            tun_key.tun_id = htonll(strtoull(tun_id_s, NULL, 0));
+            tun_key.tun_flags = flags;
+            tun_key.ipv4_tos = tos;
+            tun_key.ipv4_ttl = ttl;
+            memset(&tun_key.pad, 0, sizeof tun_key.pad);
+            nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key,
+                              sizeof tun_key);
+            return n;
+        }
+    }
+
+    {
         unsigned long long int in_port;
         int n = -1;
 
@@ -1273,8 +1297,18 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct 
flow *flow)
         nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, flow->skb_priority);
     }
 
-    if (flow->tunnel.tun_id != htonll(0)) {
-        nl_msg_put_be64(buf, OVS_KEY_ATTR_TUN_ID, flow->tunnel.tun_id);
+    if (flow->tunnel.ip_dst != 0) {
+        struct ovs_key_ipv4_tunnel *tun_key;
+
+        tun_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV4_TUNNEL,
+                                           sizeof *tun_key);
+        tun_key->tun_id = flow->tunnel.tun_id;
+        tun_key->ipv4_src = flow->tunnel.ip_src;
+        tun_key->ipv4_dst = flow->tunnel.ip_dst;
+        tun_key->tun_flags = 0; // XXX: Need flags
+        tun_key->ipv4_tos = flow->tunnel.ip_tos;
+        tun_key->ipv4_ttl = flow->tunnel.ip_ttl;
+        memset(&tun_key->pad, 0, sizeof tun_key->pad);
     }
 
     if (flow->in_port != OFPP_NONE && flow->in_port != OFPP_CONTROLLER) {
@@ -1765,9 +1799,17 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t 
key_len,
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PRIORITY;
     }
 
-    if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUN_ID)) {
-        flow->tunnel.tun_id = nl_attr_get_be64(attrs[OVS_KEY_ATTR_TUN_ID]);
-        expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TUN_ID;
+    if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4_TUNNEL)) {
+        const struct ovs_key_ipv4_tunnel *tun_key;
+
+        tun_key = nl_attr_get(attrs[OVS_KEY_ATTR_IPV4_TUNNEL]);
+        flow->tunnel.tun_id = tun_key->tun_id;
+        flow->tunnel.ip_src = tun_key->ipv4_src;
+        flow->tunnel.ip_dst = tun_key->ipv4_dst;
+        flow->tunnel.flags = 0; // XXX need flags
+        flow->tunnel.ip_tos = tun_key->ipv4_tos;
+        flow->tunnel.ip_ttl = tun_key->ipv4_ttl;
+        expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4_TUNNEL;
     }
 
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IN_PORT)) {
@@ -1858,16 +1900,27 @@ commit_set_action(struct ofpbuf *odp_actions, enum 
ovs_key_attr key_type,
 }
 
 static void
-commit_set_tun_id_action(const struct flow *flow, struct flow *base,
+commit_set_tunnel_action(const struct flow *flow, struct flow *base,
                          struct ofpbuf *odp_actions)
 {
-    if (base->tunnel.tun_id == flow->tunnel.tun_id) {
+    struct ovs_key_ipv4_tunnel tun_key;
+
+    if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
         return;
     }
-    base->tunnel.tun_id = flow->tunnel.tun_id;
 
-    commit_set_action(odp_actions, OVS_KEY_ATTR_TUN_ID,
-                      &base->tunnel.tun_id, sizeof(base->tunnel.tun_id));
+    memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel);
+
+    tun_key.tun_id = base->tunnel.tun_id;
+    tun_key.ipv4_src = base->tunnel.ip_src;
+    tun_key.ipv4_dst = base->tunnel.ip_dst;
+    tun_key.tun_flags = 0; // XXX: Need flags
+    tun_key.ipv4_tos = base->tunnel.ip_tos;
+    tun_key.ipv4_ttl = base->tunnel.ip_ttl;
+    memset(&tun_key.pad, 0, sizeof tun_key.pad);
+
+    commit_set_action(odp_actions, OVS_KEY_ATTR_IPV4_TUNNEL,
+                      &tun_key, sizeof tun_key);
 }
 
 static void
@@ -2038,7 +2091,7 @@ void
 commit_odp_actions(const struct flow *flow, struct flow *base,
                    struct ofpbuf *odp_actions)
 {
-    commit_set_tun_id_action(flow, base, odp_actions);
+    commit_set_tunnel_action(flow, base, odp_actions);
     commit_set_ether_addr_action(flow, base, odp_actions);
     commit_vlan_action(flow, base, odp_actions);
     commit_set_nw_action(flow, base, odp_actions);
diff --git a/tests/odp.at b/tests/odp.at
index 9617af2..3eb163e 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -30,8 +30,8 @@ 
in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0806),arp
  cat odp-base.txt
 
  echo
- echo '# Valid forms with tun_id header.'
- sed 's/^/tun_id(0x7f10354),/' odp-base.txt
+ echo '# Valid forms with tunnel header.'
+ sed 
's/^/ipv4_tunnel(tun_id=0x7f10354,flags=0x0,src=10.10.10.10,dst=20.20.20.20,tos=0x0,ttl=64),/'
 odp-base.txt
 
  echo
  echo '# Valid forms with VLAN header.'
@@ -43,14 +43,14 @@ s/$/)/' odp-base.txt
  sed 's/^/priority(1234),/' odp-base.txt
 
  echo
- echo '# Valid forms with tun_id and VLAN headers.'
- sed 's/^/tun_id(0xfedcba9876543210),/
+ echo '# Valid forms with tunnel and VLAN headers.'
+ sed 
's/^/ipv4_tunnel(tun_id=0xfedcba9876543210,flags=0x0,src=10.0.0.1,dst=10.0.0.2,tos=0x8,ttl=128),/
 s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/
 s/$/)/' odp-base.txt
 
  echo
- echo '# Valid forms with QOS priority, tun_id, and VLAN headers.'
- sed 's/^/priority(1234),tun_id(0xfedcba9876543210),/
+ echo '# Valid forms with QOS priority, tunnel, and VLAN headers.'
+ sed 
's/^/priority(1234),ipv4_tunnel(tun_id=0xfedcba9876543210,flags=0x0,src=10.0.0.1,dst=10.0.0.2,tos=0x8,ttl=128),/
 s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/
 s/$/)/' odp-base.txt
 
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 80ba333..1d9ccd9 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -227,7 +227,7 @@ in_port=5 actions=set_tunnel:5
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 AT_CHECK([ovs-appctl ofproto/trace br0 
'tun_id(0x1),in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'],
 [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
-  [Datapath actions: set(tun_id(0x1)),1,2,set(tun_id(0x3)),3,4
+  [Datapath actions: 
set(ipv4_tunnel(tun_id=0x1,flags=0x0,src=0.0.0.0,dst=0.0.0.0,tos=0x0,ttl=0)),1,2,set(ipv4_tunnel(tun_id=0x3,flags=0x0,src=0.0.0.0,dst=0.0.0.0,tos=0x0,ttl=0)),3,4
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to