/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const struct flow *,
const struct nlattr *odp_actions,
size_t actions_len,
- struct ofpbuf *packet);
+ struct ofpbuf *packet, bool clone);
static void facet_execute(struct ofproto_dpif *, struct facet *,
struct ofpbuf *packet);
}
static int
-run(struct ofproto *ofproto_)
+run_fast(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofport_dpif *ofport;
- struct ofbundle *bundle;
unsigned int work;
- if (!clogged) {
- complete_operations(ofproto);
- }
- dpif_run(ofproto->dpif);
-
/* Handle one or more batches of upcalls, until there's nothing left to do
* or until we do a fixed total amount of work.
*
work = 0;
while (work < FLOW_MISS_MAX_BATCH) {
int retval = handle_upcalls(ofproto, FLOW_MISS_MAX_BATCH - work);
- if (retval < 0) {
+ if (retval <= 0) {
return -retval;
- } else if (!retval) {
- break;
- } else {
- work += retval;
}
+ work += retval;
+ }
+ return 0;
+}
+
+static int
+run(struct ofproto *ofproto_)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+ struct ofport_dpif *ofport;
+ struct ofbundle *bundle;
+ int error;
+
+ if (!clogged) {
+ complete_operations(ofproto);
+ }
+ dpif_run(ofproto->dpif);
+
+ error = run_fast(ofproto_);
+ if (error) {
+ return error;
}
if (timer_expired(&ofproto->next_expiration)) {
}
if (!execute_controller_action(ofproto, &facet->flow,
facet->actions, facet->actions_len,
- packet)) {
+ packet, true)) {
struct flow_miss_op *op = &ops[(*n_ops)++];
struct dpif_execute *execute = &op->dpif_op.execute;
error = dpif_recv(ofproto->dpif, upcall);
if (error) {
- if (error == ENODEV && n_misses == 0) {
- return -ENODEV;
- }
break;
}
free(facet);
}
+/* If the 'actions_len' bytes of actions in 'odp_actions' are just a single
+ * OVS_ACTION_ATTR_USERSPACE action, executes it internally and returns true.
+ * Otherwise, returns false without doing anything.
+ *
+ * If 'clone' is true, the caller always retains ownership of 'packet'.
+ * Otherwise, ownership is transferred to this function if it returns true. */
static bool
execute_controller_action(struct ofproto_dpif *ofproto,
const struct flow *flow,
const struct nlattr *odp_actions, size_t actions_len,
- struct ofpbuf *packet)
+ struct ofpbuf *packet, bool clone)
{
if (actions_len
&& odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE
nla = nl_attr_find_nested(odp_actions, OVS_USERSPACE_ATTR_USERDATA);
send_packet_in_action(ofproto, packet, nl_attr_get_u64(nla), flow,
- false);
+ clone);
return true;
} else {
return false;
int error;
if (execute_controller_action(ofproto, flow, odp_actions, actions_len,
- packet)) {
+ packet, false)) {
return true;
}
commit_odp_actions(ctx);
compose_controller_action(ctx, max_len);
break;
- case OFPP_LOCAL:
- add_output_action(ctx, OFPP_LOCAL);
- break;
case OFPP_NONE:
break;
+ case OFPP_LOCAL:
default:
if (port != ctx->flow.in_port) {
add_output_action(ctx, port);
destruct,
dealloc,
run,
+ run_fast,
wait,
flush,
get_features,