From cf0d3c6016a5cbfdf576ee4a75eadbcaaa97b00c Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 16 Jan 2009 10:23:51 -0800 Subject: [PATCH] vswitchd: Don't reset idle timer when updating flows. When a flow was revalidated, we would use a OFPFC_ADD flow_mod message to change the flow's actions. However, this resets the idle-timer countdown. In extreme circumstances, such as when VMs are being continuously migrated, this meant that completely idle flows would never expire, because their idle timers would keep getting reset more often than every 5 seconds, and so the flow table would keep growing, never shrinking. Now, when we revalidate an existing flow and update its actions, we use an OFPFC_MODIFY_STRICT flow_mod message, which also updates actions but does not reset the idle-timer countdown. --- vswitchd/bridge.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 4934092b..fd7deb27 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1549,13 +1549,16 @@ send_packets(struct bridge *br, const struct flow *flow, if (setup_flow) { struct ft_flow *f; - bool queue; + int command; f = ft_lookup(br->ft, flow, flow_hash(flow, 0)); if (f) { if (!ftd_equal(dsts, n_dsts, f->dsts, f->n_dsts)) { + /* Update the flow. Use OFPFC_MODIFY_STRICT instead of + * OFPFC_ADD so that we don't reset the idle-timer + * countdown for this flow. */ ftf_set_dsts(f, dsts, n_dsts); - queue = true; + command = OFPFC_MODIFY_STRICT; } else { /* Correct flow is already in the flow table, nothing to do. * This should only happen on revalidate, since @@ -1563,20 +1566,24 @@ send_packets(struct bridge *br, const struct flow *flow, * no-match packet-in message. (If it could happen in other * circumstances then we'd want to arrange to send a packet-out * below, but there's no need.) */ - queue = false; + command = -1; } f->tags = tags; } else { f = ftf_create(flow, dsts, n_dsts, tags); ft_insert(br->ft, f); - queue = true; + command = OFPFC_ADD; } f->need_drop = false; - if (queue) { - struct ofpbuf *fbuf = make_add_flow(flow, pkt->buffer_id, - br->flow_idle_time, - actions_len); + if (command >= 0) { + struct ofp_flow_mod *ofm; + struct ofpbuf *fbuf; + + fbuf = make_add_flow(flow, pkt->buffer_id, br->flow_idle_time, + actions_len); + ofm = fbuf->data; + ofm->command = htons(command); put_actions(dsts, n_dsts, ntohs(flow->dl_vlan), fbuf); queue_tx(br, fbuf); -- 2.30.2