stats.n_missed += local_stats.n_missed;
stats.n_lost += local_stats.n_lost;
}
- stats.max_miss_queue = DP_MAX_QUEUE_LEN;
- stats.max_action_queue = DP_MAX_QUEUE_LEN;
return copy_to_user(statsp, &stats, sizeof(stats)) ? -EFAULT : 0;
}
uint64_t n_hit; /* Number of flow table matches. */
uint64_t n_missed; /* Number of flow table misses. */
uint64_t n_lost; /* Number of misses not sent to userspace. */
-
- /* Queues. */
- uint16_t max_miss_queue; /* Max length of ODPL_MISS queue. */
- uint16_t max_action_queue; /* Max length of ODPL_ACTION queue. */
- uint16_t max_sflow_queue; /* Max length of ODPL_SFLOW queue. */
};
/* Logical ports. */
poll_fd_wait(dpif->fd, POLLIN);
}
+static void
+dpif_linux_recv_purge(struct dpif *dpif_)
+{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+ int i;
+
+ /* This is somewhat bogus because it assumes that the following macros have
+ * fixed values, but it's going to go away later. */
+#define DP_N_QUEUES 3
+#define DP_MAX_QUEUE_LEN 100
+ for (i = 0; i < DP_N_QUEUES * DP_MAX_QUEUE_LEN; i++) {
+ /* Reading even 1 byte discards a whole datagram and saves time. */
+ char buffer;
+
+ if (read(dpif->fd, &buffer, 1) != 1) {
+ break;
+ }
+ }
+}
+
const struct dpif_class dpif_linux_class = {
"system",
NULL,
dpif_linux_queue_to_priority,
dpif_linux_recv,
dpif_linux_recv_wait,
+ dpif_linux_recv_purge,
};
\f
static int get_openvswitch_major(void);
}
static void
-dp_netdev_free(struct dp_netdev *dp)
+dp_netdev_purge_queues(struct dp_netdev *dp)
{
int i;
- dp_netdev_flow_flush(dp);
- while (dp->n_ports > 0) {
- struct dp_netdev_port *port = CONTAINER_OF(
- dp->port_list.next, struct dp_netdev_port, node);
- do_del_port(dp, port->port_no);
- }
for (i = 0; i < N_QUEUES; i++) {
struct dp_netdev_queue *q = &dp->queues[i];
- unsigned int j;
- for (j = q->tail; j != q->head; j++) {
- struct dpif_upcall *upcall = q->upcalls[j & QUEUE_MASK];
+ while (q->tail != q->head) {
+ struct dpif_upcall *upcall = q->upcalls[q->tail++ & QUEUE_MASK];
ofpbuf_delete(upcall->packet);
free(upcall);
}
}
+}
+
+static void
+dp_netdev_free(struct dp_netdev *dp)
+{
+ dp_netdev_flow_flush(dp);
+ while (dp->n_ports > 0) {
+ struct dp_netdev_port *port = CONTAINER_OF(
+ dp->port_list.next, struct dp_netdev_port, node);
+ do_del_port(dp, port->port_no);
+ }
+ dp_netdev_purge_queues(dp);
hmap_destroy(&dp->flow_table);
free(dp->name);
free(dp);
stats->n_hit = dp->n_hit;
stats->n_missed = dp->n_missed;
stats->n_lost = dp->n_lost;
- stats->max_miss_queue = MAX_QUEUE_LEN;
- stats->max_action_queue = MAX_QUEUE_LEN;
return 0;
}
* wake up to queue new messages, so there is nothing to do. */
}
}
+
+static void
+dpif_netdev_recv_purge(struct dpif *dpif)
+{
+ struct dpif_netdev *dpif_netdev = dpif_netdev_cast(dpif);
+ dp_netdev_purge_queues(dpif_netdev->dp);
+}
\f
static void
dp_netdev_flow_used(struct dp_netdev_flow *flow, struct flow *key,
NULL, /* queue_to_priority */
dpif_netdev_recv,
dpif_netdev_recv_wait,
+ dpif_netdev_recv_purge,
};
void
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
/* Arranges for the poll loop to wake up when 'dpif' has a message queued
* to be received with the recv member function. */
void (*recv_wait)(struct dpif *dpif);
+
+ /* Throws away any queued upcalls that 'dpif' currently has ready to
+ * return. */
+ void (*recv_purge)(struct dpif *dpif);
};
extern const struct dpif_class dpif_linux_class;
}
/* Discards all messages that would otherwise be received by dpif_recv() on
- * 'dpif'. Returns 0 if successful, otherwise a positive errno value. */
-int
+ * 'dpif'. */
+void
dpif_recv_purge(struct dpif *dpif)
{
- struct odp_stats stats;
- unsigned int i;
- int error;
-
COVERAGE_INC(dpif_purge);
-
- error = dpif_get_dp_stats(dpif, &stats);
- if (error) {
- return error;
- }
-
- for (i = 0; i < stats.max_miss_queue + stats.max_action_queue + stats.max_sflow_queue; i++) {
- struct dpif_upcall upcall;
- error = dpif_recv(dpif, &upcall);
- if (error) {
- return error == EAGAIN ? 0 : error;
- }
- ofpbuf_delete(upcall.packet);
+ if (dpif->dpif_class->recv_purge) {
+ dpif->dpif_class->recv_purge(dpif);
}
- return 0;
}
/* Arranges for the poll loop to wake up when 'dpif' has a message queued to be
int dpif_get_sflow_probability(const struct dpif *, uint32_t *probability);
int dpif_set_sflow_probability(struct dpif *, uint32_t probability);
int dpif_recv(struct dpif *, struct dpif_upcall *);
-int dpif_recv_purge(struct dpif *);
+void dpif_recv_purge(struct dpif *);
void dpif_recv_wait(struct dpif *);
void dpif_get_netflow_ids(const struct dpif *,
/*
- * 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.
(unsigned long long int) stats.n_hit,
(unsigned long long int) stats.n_missed,
(unsigned long long int) stats.n_lost);
- printf("\tqueues: max-miss:%"PRIu16", max-action:%"PRIu16"\n",
- stats.max_miss_queue, stats.max_action_queue);
}
DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
printf("\tport %u: %s", dpif_port.port_no, dpif_port.name);