static int
type_run(const char *type)
{
+ static long long int push_timer = LLONG_MIN;
struct dpif_backer *backer;
char *devname;
int error;
dpif_run(backer->dpif);
+ /* The most natural place to push facet statistics is when they're pulled
+ * from the datapath. However, when there are many flows in the datapath,
+ * this expensive operation can occur so frequently, that it reduces our
+ * ability to quickly set up flows. To reduce the cost, we push statistics
+ * here instead. */
+ if (time_msec() > push_timer) {
+ push_timer = time_msec() + 2000;
+ push_all_stats();
+ }
+
if (backer->need_revalidate
|| !tag_set_is_empty(&backer->revalidate_set)) {
struct tag_set revalidate_set = backer->revalidate_set;
facet_account(facet);
facet->accounted_bytes = facet->byte_count;
}
- facet_push_stats(facet);
}
/* 'key' with length 'key_len' bytes is a flow in 'dpif' that we know nothing
struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto);
struct subfacet *subfacet= CONTAINER_OF(list_front(&facet->subfacets),
struct subfacet, list_node);
+ long long int now = time_msec();
struct action_xlate_ctx ctx;
- if (time_msec() < facet->learn_rl) {
+ if (!facet->has_fin_timeout && now < facet->learn_rl) {
return;
}
- facet->learn_rl = time_msec() + 500;
+ facet->learn_rl = now + 500;
if (!facet->has_learn
&& !facet->has_normal