2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-17 14:28:02 +00:00

dpif: Use explicit packet metadata.

This helps reduce confusion about when a flow is a flow and when it is
just metadata.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Jarno Rajahalme
2013-12-30 15:58:58 -08:00
parent 09f9da0bca
commit 758c456df5
13 changed files with 200 additions and 171 deletions

View File

@@ -1064,46 +1064,28 @@ struct dpif_execute_helper_aux {
int error;
};
static void
dpif_execute_helper_execute__(void *aux_, struct ofpbuf *packet,
const struct flow *flow,
const struct nlattr *actions, size_t actions_len)
{
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;
}
}
/* This is called for actions that need the context of the datapath to be
* meaningful. */
static void
dpif_execute_helper_cb(void *aux, struct ofpbuf *packet, struct flow *flow,
dpif_execute_helper_cb(void *aux_, struct ofpbuf *packet,
const struct pkt_metadata *md,
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:
dpif_execute_helper_execute__(aux, packet, flow,
action, NLA_ALIGN(action->nla_len));
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);
break;
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_POP_VLAN:
case OVS_ACTION_ATTR_PUSH_MPLS:
@@ -1122,36 +1104,42 @@ dpif_execute_helper_cb(void *aux, struct ofpbuf *packet, struct flow *flow,
*
* This helps with actions that a given 'dpif' doesn't implement directly. */
static int
dpif_execute_with_help(struct dpif *dpif, const struct dpif_execute *execute)
dpif_execute_with_help(struct dpif *dpif, struct dpif_execute *execute)
{
struct dpif_execute_helper_aux aux;
enum odp_key_fitness fit;
struct flow flow;
struct dpif_execute_helper_aux aux = {dpif, 0};
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;
odp_execute_actions(&aux, execute->packet, &flow,
odp_execute_actions(&aux, execute->packet, &execute->md,
execute->actions, execute->actions_len,
dpif_execute_helper_cb);
return aux.error;
}
static int
dpif_execute__(struct dpif *dpif, const struct dpif_execute *execute)
/* Causes 'dpif' to perform the 'execute->actions_len' bytes of actions in
* 'execute->actions' on the Ethernet frame in 'execute->packet' and on packet
* metadata in 'execute->md'. The implementation is allowed to modify both the
* '*execute->packet' and 'execute->md'.
*
* Some dpif providers do not implement every action. The Linux kernel
* datapath, in particular, does not implement ARP field modification. If
* 'needs_help' is true, the dpif layer executes in userspace all of the
* actions that it can, and for OVS_ACTION_ATTR_OUTPUT and
* OVS_ACTION_ATTR_USERSPACE actions it passes the packet through to the dpif
* implementation.
*
* This works even if 'execute->actions_len' is too long for a Netlink
* attribute.
*
* Returns 0 if successful, otherwise a positive errno value. */
int
dpif_execute(struct dpif *dpif, struct dpif_execute *execute)
{
int error;
COVERAGE_INC(dpif_execute);
if (execute->actions_len > 0) {
error = (execute->needs_help
error = (execute->needs_help || nl_attr_oversized(execute->actions_len)
? dpif_execute_with_help(dpif, execute)
: dpif->dpif_class->execute(dpif, execute));
} else {
@@ -1163,39 +1151,6 @@ dpif_execute__(struct dpif *dpif, const struct dpif_execute *execute)
return error;
}
/* 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.)
*
* Some dpif providers do not implement every action. The Linux kernel
* datapath, in particular, does not implement ARP field modification. If
* 'needs_help' is true, the dpif layer executes in userspace all of the
* actions that it can, and for OVS_ACTION_ATTR_OUTPUT and
* OVS_ACTION_ATTR_USERSPACE actions it passes the packet through to the dpif
* implementation.
*
* This works even if 'actions_len' is too long for a Netlink attribute.
*
* 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 dpif_execute execute;
execute.key = key;
execute.key_len = key_len;
execute.actions = actions;
execute.actions_len = actions_len;
execute.packet = buf;
execute.needs_help = needs_help || nl_attr_oversized(actions_len);
return dpif_execute__(dpif, &execute);
}
/* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order in
* which they are specified, placing each operation's results in the "output"
* members documented in comments.
@@ -1251,7 +1206,7 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
/* Help the dpif provider to execute one op. */
struct dpif_op *op = ops[0];
op->error = dpif_execute__(dpif, &op->u.execute);
op->error = dpif_execute(dpif, &op->u.execute);
ops++;
n_ops--;
}
@@ -1272,7 +1227,7 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
break;
case DPIF_OP_EXECUTE:
op->error = dpif_execute__(dpif, &op->u.execute);
op->error = dpif_execute(dpif, &op->u.execute);
break;
default: