This helps reduce confusion about when a flow is a flow and when it is just metadata.
Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/dpif-linux.c | 9 ++++-- lib/dpif-netdev.c | 59 ++++++++++++++-------------------- lib/dpif-provider.h | 8 ++--- lib/dpif.c | 57 +++++++-------------------------- lib/dpif.h | 23 +++++++++---- lib/odp-execute.c | 7 ++-- lib/odp-execute.h | 6 ++-- lib/odp-util.c | 71 ++++++++++++++++++++++++++++++++++++++++- lib/odp-util.h | 6 ++++ ofproto/ofproto-dpif-upcall.c | 5 +-- ofproto/ofproto-dpif-xlate.c | 8 ++--- ofproto/ofproto-dpif.c | 13 ++++---- 12 files changed, 158 insertions(+), 114 deletions(-) diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index bfea02d..d61226b 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -1051,10 +1051,11 @@ dpif_linux_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, struct ofpbuf *buf) { struct ovs_header *k_exec; + size_t key_ofs; ofpbuf_prealloc_tailroom(buf, (64 + d_exec->packet->size - + d_exec->key_len + + ODP_KEY_METADATA_SIZE + d_exec->actions_len)); nl_msg_put_genlmsghdr(buf, 0, ovs_packet_family, NLM_F_REQUEST, @@ -1065,7 +1066,11 @@ dpif_linux_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET, d_exec->packet->data, d_exec->packet->size); - nl_msg_put_unspec(buf, OVS_PACKET_ATTR_KEY, d_exec->key, d_exec->key_len); + + key_ofs = nl_msg_start_nested(buf, OVS_PACKET_ATTR_KEY); + odp_key_from_dpif_metadata(buf, d_exec->md); + nl_msg_end_nested(buf, key_ofs); + nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS, d_exec->actions, d_exec->actions_len); } diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 9c79ad1..ac81461 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -160,13 +160,11 @@ static int dp_netdev_output_userspace(struct dp_netdev *, const struct ofpbuf *, int queue_no, const struct flow *, const struct nlattr *userdata); static void dp_netdev_execute_actions(struct dp_netdev *, const struct flow *, - struct ofpbuf *, + struct ofpbuf *, struct dpif_metadata *, const struct nlattr *actions, size_t actions_len); -static void dp_netdev_port_input(struct dp_netdev *dp, - struct dp_netdev_port *port, - struct ofpbuf *packet, uint32_t skb_priority, - uint32_t pkt_mark, const struct flow_tnl *tnl); +static void dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet, + struct dpif_metadata *md); static struct dpif_netdev * dpif_netdev_cast(const struct dpif *dpif) @@ -1030,28 +1028,22 @@ static int dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) { struct dp_netdev *dp = get_dp_netdev(dpif); - struct flow md; - int error; + struct dpif_metadata *md = execute->md; + struct flow key; if (execute->packet->size < ETH_HEADER_LEN || execute->packet->size > UINT16_MAX) { return EINVAL; } - /* Get packet metadata. */ - error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len, &md); - if (!error) { - struct flow key; - - /* Extract flow key. */ - flow_extract(execute->packet, md.skb_priority, md.pkt_mark, &md.tunnel, - &md.in_port, &key); - ovs_mutex_lock(&dp_netdev_mutex); - dp_netdev_execute_actions(dp, &key, execute->packet, - execute->actions, execute->actions_len); - ovs_mutex_unlock(&dp_netdev_mutex); - } - return error; + /* Extract flow key. */ + flow_extract(execute->packet, md->skb_priority, md->pkt_mark, &md->tunnel, + (union flow_in_port *)&md->in_port, &key); + ovs_mutex_lock(&dp_netdev_mutex); + dp_netdev_execute_actions(dp, &key, execute->packet, md, execute->actions, + execute->actions_len); + ovs_mutex_unlock(&dp_netdev_mutex); + return 0; } static int @@ -1146,23 +1138,21 @@ dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow, } static void -dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port, - struct ofpbuf *packet, uint32_t skb_priority, - uint32_t pkt_mark, const struct flow_tnl *tnl) +dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet, + struct dpif_metadata *md) { struct dp_netdev_flow *netdev_flow; struct flow key; - union flow_in_port in_port_; if (packet->size < ETH_HEADER_LEN) { return; } - in_port_.odp_port = port->port_no; - flow_extract(packet, skb_priority, pkt_mark, tnl, &in_port_, &key); + flow_extract(packet, md->skb_priority, md->pkt_mark, &md->tunnel, + (union flow_in_port *)&md->in_port, &key); netdev_flow = dp_netdev_lookup_flow(dp, &key); if (netdev_flow) { dp_netdev_flow_used(netdev_flow, packet); - dp_netdev_execute_actions(dp, &key, packet, + dp_netdev_execute_actions(dp, &key, packet, md, netdev_flow->actions, netdev_flow->actions_len); dp->n_hit++; @@ -1193,7 +1183,8 @@ dpif_netdev_run(struct dpif *dpif) error = port->rx ? netdev_rx_recv(port->rx, &packet) : EOPNOTSUPP; if (!error) { - dp_netdev_port_input(dp, port, &packet, 0, 0, NULL); + struct dpif_metadata md = DPIF_METADATA_INITIALIZER(port->port_no); + dp_netdev_port_input(dp, &packet, &md); } else if (error != EAGAIN && error != EOPNOTSUPP) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -1299,8 +1290,8 @@ struct dp_netdev_execute_aux { }; static void -dp_execute_cb(void *aux_, struct ofpbuf *packet, struct flow *flow OVS_UNUSED, - const struct nlattr *a) +dp_execute_cb(void *aux_, struct ofpbuf *packet, + struct dpif_metadata *md OVS_UNUSED, const struct nlattr *a) { struct dp_netdev_execute_aux *aux = aux_; int type = nl_attr_type(a); @@ -1332,14 +1323,12 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet, struct flow *flow OVS_UNUSED, static void dp_netdev_execute_actions(struct dp_netdev *dp, const struct flow *key, - struct ofpbuf *packet, + struct ofpbuf *packet, struct dpif_metadata *md, const struct nlattr *actions, size_t actions_len) { struct dp_netdev_execute_aux aux = {dp, key}; - struct flow md = *key; /* Packet metadata, may be modified by actions. */ - odp_execute_actions(&aux, packet, &md, actions, actions_len, - dp_execute_cb); + odp_execute_actions(&aux, packet, md, actions, actions_len, dp_execute_cb); } const struct dpif_class dpif_netdev_class = { diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index c5f8b04..0c6d8bd 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -311,11 +311,9 @@ struct dpif_class { int (*flow_dump_done)(const struct dpif *dpif, void *state); /* Performs the 'execute->actions_len' bytes of actions in - * 'execute->actions' on the Ethernet frame specified in 'execute->packet' - * taken from the flow specified in the 'execute->key_len' bytes of - * 'execute->key'. ('execute->key' is mostly redundant with - * 'execute->packet', but it contains some metadata that cannot be - * recovered from 'execute->packet', such as tunnel and in_port.) */ + * 'execute->actions' on the Ethernet frame in 'execute->packet' + * and on the packet metadata in 'execute->md'. + * May modify both packet and metadata. */ int (*execute)(struct dpif *dpif, struct dpif_execute *execute); /* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order diff --git a/lib/dpif.c b/lib/dpif.c index 6cfa4e6..21fc3e3 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1061,43 +1061,20 @@ struct dpif_execute_helper_aux { }; static void -dpif_execute_helper_execute__(void *aux_, struct ofpbuf *packet, - const struct flow *flow, - const struct nlattr *actions, size_t actions_len) +dpif_execute_helper_cb(void *aux_, struct ofpbuf *packet, + struct dpif_metadata *md, const struct nlattr *action) { struct dpif_execute_helper_aux *aux = aux_; - struct dpif_execute execute; - struct odputil_keybuf key_stub; - struct ofpbuf key; - int error; - - ofpbuf_use_stub(&key, &key_stub, sizeof key_stub); - odp_flow_key_from_flow(&key, flow, flow->in_port.odp_port); - - execute.key = key.data; - execute.key_len = key.size; - execute.actions = actions; - execute.actions_len = actions_len; - execute.packet = packet; - execute.needs_help = false; - - error = aux->dpif->dpif_class->execute(aux->dpif, &execute); - if (error) { - aux->error = error; - } -} -static void -dpif_execute_helper_cb(void *aux, struct ofpbuf *packet, struct flow *flow, - const struct nlattr *action) -{ int type = nl_attr_type(action); switch ((enum ovs_action_attr)type) { case OVS_ACTION_ATTR_OUTPUT: case OVS_ACTION_ATTR_USERSPACE: - dpif_execute_helper_execute__(aux, packet, flow, - action, NLA_ALIGN(action->nla_len)); + aux->error = dpif_execute(aux->dpif, + action, NLA_ALIGN(action->nla_len), + packet, md, false); break; + case OVS_ACTION_ATTR_PUSH_VLAN: case OVS_ACTION_ATTR_POP_VLAN: case OVS_ACTION_ATTR_PUSH_MPLS: @@ -1119,22 +1096,15 @@ static int dpif_execute_with_help(struct dpif *dpif, struct dpif_execute *execute) { struct dpif_execute_helper_aux aux; - enum odp_key_fitness fit; struct ofpbuf *packet; - struct flow flow; COVERAGE_INC(dpif_execute_with_help); - fit = odp_flow_key_to_flow(execute->key, execute->key_len, &flow); - if (fit == ODP_FIT_ERROR) { - return EINVAL; - } - aux.dpif = dpif; aux.error = 0; packet = ofpbuf_clone_with_headroom(execute->packet, VLAN_HEADER_LEN); - odp_execute_actions(&aux, packet, &flow, + odp_execute_actions(&aux, packet, execute->md, execute->actions, execute->actions_len, dpif_execute_helper_cb); ofpbuf_delete(packet); @@ -1162,10 +1132,8 @@ dpif_execute__(struct dpif *dpif, struct dpif_execute *execute) } /* Causes 'dpif' to perform the 'actions_len' bytes of actions in 'actions' on - * the Ethernet frame specified in 'packet' taken from the flow specified in - * the 'key_len' bytes of 'key'. ('key' is mostly redundant with 'packet', but - * it contains some metadata that cannot be recovered from 'packet', such as - * tunnel and in_port.) + * the Ethernet frame in 'packet' and on packet metadata in 'md'. The + * implementation is allowed to modify both the '*packet' and '*md'. * * Some dpif providers do not implement every action. The Linux kernel * datapath, in particular, does not implement ARP field modification. If @@ -1179,17 +1147,16 @@ dpif_execute__(struct dpif *dpif, struct dpif_execute *execute) * Returns 0 if successful, otherwise a positive errno value. */ int dpif_execute(struct dpif *dpif, - const struct nlattr *key, size_t key_len, const struct nlattr *actions, size_t actions_len, - struct ofpbuf *buf, bool needs_help) + struct ofpbuf *buf, struct dpif_metadata *md, + bool needs_help) { struct dpif_execute execute; - execute.key = key; - execute.key_len = key_len; execute.actions = actions; execute.actions_len = actions_len; execute.packet = buf; + execute.md = md; execute.needs_help = needs_help || nl_attr_oversized(actions_len); return dpif_execute__(dpif, &execute); } diff --git a/lib/dpif.h b/lib/dpif.h index 3bf3688..2086ec5 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -342,6 +342,7 @@ #include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include "flow.h" #include "openflow/openflow.h" #include "netdev.h" #include "util.h" @@ -352,7 +353,6 @@ extern "C" { struct dpif; struct ds; -struct flow; struct nlattr; struct ofpbuf; struct sset; @@ -492,10 +492,19 @@ int dpif_flow_dump_done(struct dpif_flow_dump *); /* Packet operations. */ +/* Datapath packet metadata */ +struct dpif_metadata { + struct flow_tnl tunnel; /* Encapsulating tunnel parameters. */ + uint32_t skb_priority; /* Packet priority for QoS. */ + uint32_t pkt_mark; /* Packet mark. */ + odp_port_t in_port; /* Input port. */ +}; + +#define DPIF_METADATA_INITIALIZER(PORT) { { 0 }, 0, 0, (PORT) } + int dpif_execute(struct dpif *, - const struct nlattr *key, size_t key_len, const struct nlattr *actions, size_t actions_len, - struct ofpbuf *, bool needs_help); + struct ofpbuf *, struct dpif_metadata *, bool needs_help); /* Operation batching interface. * @@ -534,11 +543,10 @@ struct dpif_flow_del { struct dpif_execute { /* Raw support for execute passed along to the provider. */ - const struct nlattr *key; /* Partial flow key (only for metadata). */ - size_t key_len; /* Length of 'key' in bytes. */ const struct nlattr *actions; /* Actions to execute on packet. */ size_t actions_len; /* Length of 'actions' in bytes. */ struct ofpbuf *packet; /* Packet to execute. */ + struct dpif_metadata *md; /* Packet metadata. */ /* Some dpif providers do not implement every action. The Linux kernel * datapath, in particular, does not implement ARP field modification. @@ -556,7 +564,10 @@ struct dpif_op { union { struct dpif_flow_put flow_put; struct dpif_flow_del flow_del; - struct dpif_execute execute; + struct { + struct dpif_execute execute; + struct dpif_metadata metadata; + }; } u; }; diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 8b29ddc..12f17d4 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <string.h> +#include "dpif.h" #include "netlink.h" #include "ofpbuf.h" #include "odp-util.h" @@ -61,7 +62,7 @@ set_arp(struct ofpbuf *packet, const struct ovs_key_arp *arp_key) static void odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a, - struct flow *md) + struct dpif_metadata *md) { enum ovs_key_attr type = nl_attr_type(a); const struct ovs_key_ipv4 *ipv4_key; @@ -140,7 +141,7 @@ odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a, } static void -odp_execute_sample(void *dp, struct ofpbuf *packet, struct flow *md, +odp_execute_sample(void *dp, struct ofpbuf *packet, struct dpif_metadata *md, const struct nlattr *action, odp_execute_callback callback) { const struct nlattr *subactions = NULL; @@ -173,7 +174,7 @@ odp_execute_sample(void *dp, struct ofpbuf *packet, struct flow *md, } void -odp_execute_actions(void *dp, struct ofpbuf *packet, struct flow *md, +odp_execute_actions(void *dp, struct ofpbuf *packet, struct dpif_metadata *md, const struct nlattr *actions, size_t actions_len, odp_execute_callback callback) { diff --git a/lib/odp-execute.h b/lib/odp-execute.h index 6f2376b..5ddc3d4 100644 --- a/lib/odp-execute.h +++ b/lib/odp-execute.h @@ -22,16 +22,16 @@ #include <stdint.h> #include "openvswitch/types.h" -struct flow; struct nlattr; struct ofpbuf; +struct dpif_metadata; typedef void (*odp_execute_callback)(void *dp, struct ofpbuf *packet, - struct flow *metadata, + struct dpif_metadata *, const struct nlattr *action); void -odp_execute_actions(void *dp, struct ofpbuf *packet, struct flow *metadata, +odp_execute_actions(void *dp, struct ofpbuf *packet, struct dpif_metadata *, const struct nlattr *actions, size_t actions_len, odp_execute_callback callback); #endif diff --git a/lib/odp-util.c b/lib/odp-util.c index 6ac3853..238c5e1 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -26,6 +26,7 @@ #include <string.h> #include "byte-order.h" #include "coverage.h" +#include "dpif.h" #include "dynamic-string.h" #include "flow.h" #include "netlink.h" @@ -856,7 +857,7 @@ odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun) return ODP_FIT_ERROR; } if (unknown) { - return ODP_FIT_TOO_MUCH; + return ODP_FIT_TOO_MUCH; } return ODP_FIT_PERFECT; } @@ -2676,6 +2677,74 @@ odp_flow_key_from_mask(struct ofpbuf *buf, const struct flow *mask, odp_flow_key_from_flow__(buf, mask, flow, u32_to_odp(odp_in_port_mask)); } +/* Generate ODP flow key from the given 'metadata' */ +void +odp_key_from_dpif_metadata(struct ofpbuf *buf, const struct dpif_metadata *md) +{ + nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority); + + if (md->tunnel.ip_dst) { + tun_key_to_attr(buf, &md->tunnel); + } + + nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, md->pkt_mark); + + /* Add an ingress port attribute if 'odp_in_port' is not the magical + * value "ODPP_NONE". */ + if (md->in_port != ODPP_NONE) { + nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port); + } +} + +/* Generate ODP packet metadata from the given ODP flow key. */ +void +odp_key_to_dpif_metadata(const struct nlattr *key, size_t key_len, + struct dpif_metadata *md) +{ + const struct nlattr *nla; + size_t left; + uint32_t wanted_attrs = 1u << OVS_KEY_ATTR_PRIORITY | + 1u << OVS_KEY_ATTR_SKB_MARK | 1u << OVS_KEY_ATTR_TUNNEL | + 1u << OVS_KEY_ATTR_IN_PORT; + + memset(md, 0, sizeof *md); + md->in_port = ODPP_NONE; + + NL_ATTR_FOR_EACH (nla, left, key, key_len) { + uint16_t type = nl_attr_type(nla); + size_t len = nl_attr_get_size(nla); + int expected_len = odp_flow_key_attr_len(type); + + if (len != expected_len && expected_len >= 0) { + continue; + } + + if (type == OVS_KEY_ATTR_PRIORITY) { + md->skb_priority = nl_attr_get_u32(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_PRIORITY); + } else if (type == OVS_KEY_ATTR_SKB_MARK) { + md->pkt_mark = nl_attr_get_u32(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_SKB_MARK); + } else if (type == OVS_KEY_ATTR_TUNNEL) { + enum odp_key_fitness res; + + res = odp_tun_key_from_attr(nla, &md->tunnel); + if (res == ODP_FIT_ERROR) { + memset(&md->tunnel, 0, sizeof md->tunnel); + } else if (res == ODP_FIT_PERFECT) { + wanted_attrs &= ~(1u << OVS_KEY_ATTR_TUNNEL); + } + } else if (type == OVS_KEY_ATTR_IN_PORT) { + md->in_port = nl_attr_get_odp_port(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_IN_PORT); + } + + if (!wanted_attrs) { + return; /* Have everything. */ + } + } +} + uint32_t odp_flow_key_hash(const struct nlattr *key, size_t key_len) { diff --git a/lib/odp-util.h b/lib/odp-util.h index 821b2c4..9a77c95 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -34,6 +34,7 @@ struct flow_wildcards; struct nlattr; struct ofpbuf; struct simap; +struct dpif_metadata; #define SLOW_PATH_REASONS \ /* These reasons are mutually exclusive. */ \ @@ -149,6 +150,11 @@ void odp_flow_key_from_mask(struct ofpbuf *, const struct flow *mask, uint32_t odp_flow_key_hash(const struct nlattr *, size_t); +enum { ODP_KEY_METADATA_SIZE = 9 * 8 }; /* Space to reserve for metadata. */ +void odp_key_from_dpif_metadata(struct ofpbuf *, const struct dpif_metadata *); +void odp_key_to_dpif_metadata(const struct nlattr *key, size_t key_len, + struct dpif_metadata *md); + /* How well a kernel-provided flow key (a sequence of OVS_KEY_ATTR_* * attributes) matches OVS userspace expectations. * diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index dba3d3b..b3cb8d6 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -813,9 +813,10 @@ handle_upcalls(struct udpif *udpif, struct list *upcalls) op = &ops[n_ops++]; op->type = DPIF_OP_EXECUTE; - op->u.execute.key = miss->key; - op->u.execute.key_len = miss->key_len; op->u.execute.packet = packet; + odp_key_to_dpif_metadata(miss->key, miss->key_len, + &op->u.metadata); + op->u.execute.md = &op->u.metadata; op->u.execute.actions = miss->xout.odp_actions.data; op->u.execute.actions_len = miss->xout.odp_actions.size; op->u.execute.needs_help = (miss->xout.slow & SLOW_ACTION) != 0; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index fa1dc30..d47125e 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2039,7 +2039,7 @@ execute_controller_action(struct xlate_ctx *ctx, int len, { struct ofproto_packet_in *pin; struct ofpbuf *packet; - struct flow key; + struct dpif_metadata md = DPIF_METADATA_INITIALIZER(0); ctx->xout->slow |= SLOW_CONTROLLER; if (!ctx->xin->packet) { @@ -2048,16 +2048,12 @@ execute_controller_action(struct xlate_ctx *ctx, int len, packet = ofpbuf_clone(ctx->xin->packet); - key.skb_priority = 0; - key.pkt_mark = 0; - memset(&key.tunnel, 0, sizeof key.tunnel); - ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, &ctx->mpls_depth_delta); - odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data, + odp_execute_actions(NULL, packet, &md, ctx->xout->odp_actions.data, ctx->xout->odp_actions.size, NULL); pin = xmalloc(sizeof *pin); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index da27f6a..ec6d0bc 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -3824,12 +3824,11 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, const struct ofpact *ofpacts, size_t ofpacts_len, struct ofpbuf *packet) { - struct odputil_keybuf keybuf; struct dpif_flow_stats stats; struct xlate_out xout; struct xlate_in xin; ofp_port_t in_port; - struct ofpbuf key; + struct dpif_metadata md; int error; ovs_assert((rule != NULL) != (ofpacts != NULL)); @@ -3845,15 +3844,17 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, xin.resubmit_stats = &stats; xlate_actions(&xin, &xout); - ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); in_port = flow->in_port.ofp_port; if (in_port == OFPP_NONE) { in_port = OFPP_LOCAL; } - odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(ofproto, in_port)); + md.tunnel = flow->tunnel; + md.skb_priority = flow->skb_priority; + md.pkt_mark = flow->pkt_mark; + md.in_port = ofp_port_to_odp_port(ofproto, in_port); - error = dpif_execute(ofproto->backer->dpif, key.data, key.size, - xout.odp_actions.data, xout.odp_actions.size, packet, + error = dpif_execute(ofproto->backer->dpif, xout.odp_actions.data, + xout.odp_actions.size, packet, &md, (xout.slow & SLOW_ACTION) != 0); xlate_out_uninit(&xout); -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev