dpif: When executing actions needs help, use "set" action to set tunnel.
authorBen Pfaff <blp@nicira.com>
Tue, 24 Jun 2014 23:39:33 +0000 (16:39 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 25 Jun 2014 16:42:08 +0000 (09:42 -0700)
Open vSwitch userspace is able to implement some actions that the kernel
doesn't support, such as modifying ARP fields.  When it does this for a
tunneled packet, it needs to supply the tunnel information with a "set"
action, because the Linux kernel datapath throws away tunnel information
supplied in the OVS_PACKET_CMD_EXECUTE metadata argument.

VMware-BZ: #1270110
Reported-by: Srinivas Neginhal <sneginha@vmware.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
lib/dpif.c

index 6b519b8..e333d98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1073,15 +1073,30 @@ dpif_execute_helper_execute__(void *aux_, struct ofpbuf *packet,
     struct dpif_execute execute;
     struct odputil_keybuf key_stub;
     struct ofpbuf key;
+    struct ofpbuf execute_actions;
+    uint64_t stub[256 / 8];
     int error;
 
     ofpbuf_use_stub(&key, &key_stub, sizeof key_stub);
     odp_flow_key_from_flow(&key, flow, flow->in_port.odp_port);
 
+    if (flow->tunnel.ip_dst) {
+        /* The Linux kernel datapath throws away the tunnel information
+         * that we supply as metadata.  We have to use a "set" action to
+         * supply it. */
+        ofpbuf_use_stub(&execute_actions, stub, sizeof stub);
+        odp_put_tunnel_action(&flow->tunnel, &execute_actions);
+        ofpbuf_put(&execute_actions, actions, actions_len);
+
+        execute.actions = execute_actions.data;
+        execute.actions_len = execute_actions.size;
+    } else {
+        execute.actions = actions;
+        execute.actions_len = actions_len;
+    }
+
     execute.key = key.data;
     execute.key_len = key.size;
-    execute.actions = actions;
-    execute.actions_len = actions_len;
     execute.packet = packet;
     execute.needs_help = false;
 
@@ -1089,6 +1104,10 @@ dpif_execute_helper_execute__(void *aux_, struct ofpbuf *packet,
     if (error) {
         aux->error = error;
     }
+
+    if (flow->tunnel.ip_dst) {
+        ofpbuf_uninit(&execute_actions);
+    }
 }
 
 static void