From: Ben Pfaff Date: Tue, 24 Jun 2014 23:39:33 +0000 (-0700) Subject: dpif: When executing actions needs help, use "set" action to set tunnel. X-Git-Tag: v2.3~54 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=2187d8c72ad9695379f6ba30619bf25fb09db699 dpif: When executing actions needs help, use "set" action to set tunnel. 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 Signed-off-by: Ben Pfaff Acked-by: Jesse Gross --- diff --git a/lib/dpif.c b/lib/dpif.c index 48b2d1e92..8ec8200f7 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1112,20 +1112,41 @@ dpif_execute_helper_cb(void *aux_, struct ofpbuf *packet, const struct nlattr *action, bool may_steal OVS_UNUSED) { struct dpif_execute_helper_aux *aux = aux_; - struct dpif_execute execute; int type = nl_attr_type(action); switch ((enum ovs_action_attr)type) { case OVS_ACTION_ATTR_OUTPUT: case OVS_ACTION_ATTR_USERSPACE: - case OVS_ACTION_ATTR_RECIRC: - execute.actions = action; - execute.actions_len = NLA_ALIGN(action->nla_len); + case OVS_ACTION_ATTR_RECIRC: { + struct dpif_execute execute; + struct ofpbuf execute_actions; + uint64_t stub[256 / 8]; + + if (md->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(&md->tunnel, &execute_actions); + ofpbuf_put(&execute_actions, action, NLA_ALIGN(action->nla_len)); + + execute.actions = ofpbuf_data(&execute_actions); + execute.actions_len = ofpbuf_size(&execute_actions); + } else { + execute.actions = action; + execute.actions_len = NLA_ALIGN(action->nla_len); + } + execute.packet = packet; execute.md = *md; execute.needs_help = false; aux->error = aux->dpif->dpif_class->execute(aux->dpif, &execute); + + if (md->tunnel.ip_dst) { + ofpbuf_uninit(&execute_actions); + } break; + } case OVS_ACTION_ATTR_HASH: case OVS_ACTION_ATTR_PUSH_VLAN: