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:
117
lib/dpif.c
117
lib/dpif.c
@@ -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:
|
||||
|
Reference in New Issue
Block a user