X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=4995bbeca573b9b647649c01b8905dd7a124504b;hb=1b656aa878f8cd667e7700fe52e8a1ca3cb51781;hp=b49ea49f4f97b3fb29b331f457d18698d75b492b;hpb=d65349ea28bb67a0062a9b4b60ff97538206373b;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index b49ea49f4..4995bbeca 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1628,7 +1628,7 @@ rule_install(struct ofproto *p, struct rule *rule, struct rule *displaced_rule) &put)) { rule->installed = true; if (displaced_rule) { - update_stats(p, rule, &put.flow.stats); + update_stats(p, displaced_rule, &put.flow.stats); rule_post_uninstall(p, displaced_rule); } } @@ -1652,14 +1652,27 @@ rule_reinstall(struct ofproto *ofproto, struct rule *rule) static void rule_update_actions(struct ofproto *ofproto, struct rule *rule) { - bool actions_changed = rule_make_actions(ofproto, rule, NULL); + bool actions_changed; + uint16_t new_out_iface, old_out_iface; + + old_out_iface = rule->nf_flow.output_iface; + actions_changed = rule_make_actions(ofproto, rule, NULL); + if (rule->may_install) { if (rule->installed) { if (actions_changed) { - /* XXX should really do rule_post_uninstall() for the *old* set - * of actions, and distinguish the old stats from the new. */ struct odp_flow_put put; - do_put_flow(ofproto, rule, ODPPF_CREATE | ODPPF_MODIFY, &put); + do_put_flow(ofproto, rule, ODPPF_CREATE | ODPPF_MODIFY + | ODPPF_ZERO_STATS, &put); + update_stats(ofproto, rule, &put.flow.stats); + + /* Temporarily set the old output iface so that NetFlow + * messages have the correct output interface for the old + * stats. */ + new_out_iface = rule->nf_flow.output_iface; + rule->nf_flow.output_iface = old_out_iface; + rule_post_uninstall(ofproto, rule); + rule->nf_flow.output_iface = new_out_iface; } } else { rule_install(ofproto, rule, NULL); @@ -2147,11 +2160,21 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; break; + case OFPAT_SET_NW_DST: + oa = odp_actions_add(ctx->out, ODPAT_SET_NW_DST); + oa->nw_addr.nw_addr = ia->nw_addr.nw_addr; + break; + case OFPAT_SET_TP_SRC: oa = odp_actions_add(ctx->out, ODPAT_SET_TP_SRC); oa->tp_port.tp_port = ia->tp_port.tp_port; break; + case OFPAT_SET_TP_DST: + oa = odp_actions_add(ctx->out, ODPAT_SET_TP_DST); + oa->tp_port.tp_port = ia->tp_port.tp_port; + break; + case OFPAT_VENDOR: xlate_nicira_action(ctx, (const struct nx_action_header *) ia); break; @@ -2733,6 +2756,9 @@ update_time(struct ofproto *ofproto, struct rule *rule, long long int used = msec_from_nsec(stats->used_sec, stats->used_nsec); if (used > rule->used) { rule->used = used; + if (rule->super && used > rule->super->used) { + rule->super->used = used; + } netflow_flow_update_time(ofproto->netflow, &rule->nf_flow, used); } } @@ -3297,19 +3323,23 @@ expire_rule(struct cls_rule *cls_rule, void *p_) } COVERAGE_INC(ofproto_expired); + + /* Update stats. This code will be a no-op if the rule expired + * due to an idle timeout. */ if (rule->cr.wc.wildcards) { - /* Update stats. (This code will be a no-op if the rule expired - * due to an idle timeout, because in that case the rule has no - * subrules left.) */ struct rule *subrule, *next; LIST_FOR_EACH_SAFE (subrule, next, struct rule, list, &rule->list) { rule_remove(p, subrule); } + } else { + rule_uninstall(p, rule); } - send_flow_exp(p, rule, now, - (now >= hard_expire - ? OFPER_HARD_TIMEOUT : OFPER_IDLE_TIMEOUT)); + if (!rule_is_hidden(rule)) { + send_flow_exp(p, rule, now, + (now >= hard_expire + ? OFPER_HARD_TIMEOUT : OFPER_IDLE_TIMEOUT)); + } rule_remove(p, rule); }