bool mark; /* Used by mark and sweep GC algorithm. */
struct odputil_keybuf key_buf; /* Memory for 'key'. */
+ struct xlate_cache *xcache; /* Cache for xlate entries that
+ * are affected by this ukey.
+ * Used for stats and learning.*/
};
/* 'udpif_flow_dump's hold the state associated with one iteration in a flow
ukey->mark = false;
ukey->created = used ? used : time_msec();
memset(&ukey->stats, 0, sizeof ukey->stats);
+ ukey->xcache = NULL;
return ukey;
}
ukey_delete(struct revalidator *revalidator, struct udpif_key *ukey)
{
hmap_remove(&revalidator->ukeys, &ukey->hmap_node);
+ xlate_cache_delete(ukey->xcache);
free(ukey);
}
struct xlate_in xin;
int error;
size_t i;
- bool ok;
+ bool may_learn, ok;
ok = false;
xoutp = NULL;
actions = NULL;
netflow = NULL;
+ may_learn = push.n_packets > 0;
/* If we don't need to revalidate, we can simply push the stats contained
* in the udump, otherwise we'll have to get the actions so we can check
goto exit;
}
+ if (ukey->xcache && !udump->need_revalidate) {
+ xlate_push_stats(ukey->xcache, may_learn, &push);
+ ok = true;
+ goto exit;
+ }
+
error = xlate_receive(udpif->backer, NULL, ukey->key, ukey->key_len, &flow,
&ofproto, NULL, NULL, &netflow, &odp_in_port);
if (error) {
goto exit;
}
+ if (udump->need_revalidate) {
+ xlate_cache_clear(ukey->xcache);
+ }
+ if (!ukey->xcache) {
+ ukey->xcache = xlate_cache_new();
+ }
+
xlate_in_init(&xin, ofproto, &flow, NULL, push.tcp_flags, NULL);
xin.resubmit_stats = push.n_packets ? &push : NULL;
- xin.may_learn = push.n_packets > 0;
+ xin.xcache = ukey->xcache;
+ xin.may_learn = may_learn;
xin.skip_wildcards = !udump->need_revalidate;
xlate_actions(&xin, &xout);
xoutp = &xout;
struct ofproto_dpif *ofproto;
struct netflow *netflow;
struct flow flow;
+ bool may_learn;
+
+ may_learn = push->n_packets > 0;
+ if (op->ukey && op->ukey->xcache) {
+ xlate_push_stats(op->ukey->xcache, may_learn, push);
+ continue;
+ }
if (!xlate_receive(udpif->backer, NULL, op->op.u.flow_del.key,
op->op.u.flow_del.key_len, &flow, &ofproto,
xlate_in_init(&xin, ofproto, &flow, NULL, push->tcp_flags,
NULL);
xin.resubmit_stats = push->n_packets ? push : NULL;
- xin.may_learn = push->n_packets > 0;
+ xin.may_learn = may_learn;
xin.skip_wildcards = true;
xlate_actions_for_side_effects(&xin);