}
opp->name[sizeof opp->name - 1] = '\0';
}
+
+/* Returns the idle time that the bridge is currently using. We reduce the
+ * idle time as the flow table grows, so as to act as a brake on further flow
+ * table growth. */
+static int
+bridge_idle_time(const struct bridge *br)
+{
+ int idle_time = br->flow_idle_time;
+ if (idle_time) {
+ size_t n_flows = hmap_count(&br->ft->flows);
+ int step = MAX(1, br->flow_idle_time / 5);
+ while (n_flows > 1000 && idle_time > 0) {
+ idle_time -= step;
+ n_flows /= 2;
+ }
+ if (idle_time < 1) {
+ idle_time = 1;
+ }
+ }
+ return idle_time;
+}
\f
/* Bridge packet processing functions. */
struct ofp_flow_mod *ofm;
struct ofpbuf *fbuf;
- fbuf = make_add_flow(flow, pkt->buffer_id, br->flow_idle_time,
+ fbuf = make_add_flow(flow, pkt->buffer_id, bridge_idle_time(br),
actions_len);
ofm = fbuf->data;
ofm->command = htons(command);
"interface %"PRIu16, br->name, in_ifidx);
queue_tx(br, make_add_flow(flow, pkt->buffer_id,
- br->flow_idle_time, 0));
+ bridge_idle_time(br), 0));
if (f) {
ftf_set_dsts(f, NULL, 0);
f->tags = tags;