ds_destroy(&flow);
free(packet);
+ } else if (error && error != EAGAIN) {
+ log_operation(dpif, "recv", error);
}
return error;
}
}
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)) {
error = dpif_recv(ofproto->dpif, upcall);
if (error) {
- if (error == ENODEV && n_misses == 0) {
- return -ENODEV;
- }
break;
}
destruct,
dealloc,
run,
+ run_fast,
wait,
flush,
get_features,
* - Call ofproto_rule_expire() for each OpenFlow flow that has reached
* its hard_timeout or idle_timeout, to expire the flow.
*
- * Returns 0 if successful, otherwise a positive errno value. The ENODEV
- * return value specifically means that the datapath underlying 'ofproto'
- * has been destroyed (externally, e.g. by an admin running ovs-dpctl).
- */
+ * Returns 0 if successful, otherwise a positive errno value. */
int (*run)(struct ofproto *ofproto);
+ /* Performs periodic activity required by 'ofproto' that needs to be done
+ * with the least possible latency.
+ *
+ * This is run multiple times per main loop. An ofproto provider may
+ * implement it or not, according to whether it provides a performance
+ * boost for that ofproto implementation. */
+ int (*run_fast)(struct ofproto *ofproto);
+
/* Causes the poll loop to wake up when 'ofproto''s 'run' function needs to
* be called, e.g. by calling the timer or fd waiting functions in
* poll-loop.h. */
int error;
error = p->ofproto_class->run(p);
- if (error == ENODEV) {
- /* Someone destroyed the datapath behind our back. The caller
- * better destroy us and give up, because we're just going to
- * spin from here on out. */
- static struct vlog_rate_limit rl2 = VLOG_RATE_LIMIT_INIT(1, 5);
- VLOG_ERR_RL(&rl2, "%s: datapath was destroyed externally",
- p->name);
- return ENODEV;
+ if (error && error != EAGAIN) {
+ VLOG_ERR_RL(&rl, "%s: run failed (%s)", p->name, strerror(error));
}
if (p->ofproto_class->port_poll) {
NOT_REACHED();
}
- return 0;
+ return error;
+}
+
+/* Performs periodic activity required by 'ofproto' that needs to be done
+ * with the least possible latency.
+ *
+ * It makes sense to call this function a couple of times per poll loop, to
+ * provide a significant performance boost on some benchmarks with the
+ * ofproto-dpif implementation. */
+int
+ofproto_run_fast(struct ofproto *p)
+{
+ int error;
+
+ error = p->ofproto_class->run_fast ? p->ofproto_class->run_fast(p) : 0;
+ if (error && error != EAGAIN) {
+ VLOG_ERR_RL(&rl, "%s: fastpath run failed (%s)",
+ p->name, strerror(error));
+ }
+ return error;
}
void
int ofproto_delete(const char *name, const char *type);
int ofproto_run(struct ofproto *);
+int ofproto_run_fast(struct ofproto *);
void ofproto_wait(struct ofproto *);
bool ofproto_is_alive(const struct ofproto *);
}
}
+/* Performs periodic activity required by bridges that needs to be done with
+ * the least possible latency.
+ *
+ * It makes sense to call this function a couple of times per poll loop, to
+ * provide a significant performance boost on some benchmarks with ofprotos
+ * that use the ofproto-dpif implementation. */
+void
+bridge_run_fast(void)
+{
+ struct bridge *br;
+
+ HMAP_FOR_EACH (br, node, &all_bridges) {
+ ofproto_run_fast(br->ofproto);
+ }
+}
+
void
bridge_run(void)
{
const struct ovsrec_open_vswitch *cfg;
bool vlan_splinters_changed;
- bool datapath_destroyed;
bool database_changed;
struct bridge *br;
cfg = ovsrec_open_vswitch_first(idl);
/* Let each bridge do the work that it needs to do. */
- datapath_destroyed = false;
HMAP_FOR_EACH (br, node, &all_bridges) {
- int error = ofproto_run(br->ofproto);
- if (error) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- VLOG_ERR_RL(&rl, "bridge %s: datapath was destroyed externally, "
- "forcing reconfiguration", br->name);
- datapath_destroyed = true;
- }
+ ofproto_run(br->ofproto);
}
/* Re-configure SSL. We do this on every trip through the main loop,
}
}
- if (database_changed || datapath_destroyed || vlan_splinters_changed) {
+ if (database_changed || vlan_splinters_changed) {
if (cfg) {
struct ovsdb_idl_txn *txn = ovsdb_idl_txn_create(idl);
-/* Copyright (c) 2008, 2009, 2010 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void bridge_exit(void);
void bridge_run(void);
+void bridge_run_fast(void);
void bridge_wait(void);
#endif /* bridge.h */
if (signal_poll(sighup)) {
vlog_reopen_log_file();
}
+ bridge_run_fast();
bridge_run();
+ bridge_run_fast();
unixctl_server_run(unixctl);
netdev_run();