netflow_flow_clear() asserted that no packets or bytes were included
in the statistics for the flow being cleared. Before threading Open
vSwitch, this assertion was always true because netflow_expire() was
always called before calling netflow_flow_clear(). Since Open
vSwitch was threaded, however, it was possible that a packet arrived
after netflow_expire() but before netflow_flow_clear(), since each of
these function separately took the netflow mutex.
This commit fixes the problem by merging netflow_expire() into
netflow_flow_clear(), under a single acquisition of the netflow
mutex.
Signed-off-by: Anoob Soman <anoob.soman@citrix.com>
[blp@nicira.com modified the patch to remove netflow_expire() and
rewrote the commit message]
Signed-off-by: Ben Pfaff <blp@nicira.com>
nf_flow->tcp_flags = 0;
}
nf_flow->tcp_flags = 0;
}
-void
-netflow_expire(struct netflow *nf, struct flow *flow) OVS_EXCLUDED(mutex)
-{
- struct netflow_flow *nf_flow;
-
- ovs_mutex_lock(&mutex);
- nf_flow = netflow_flow_lookup(nf, flow);
- if (nf_flow) {
- netflow_expire__(nf, nf_flow);
- }
- ovs_mutex_unlock(&mutex);
-}
-
void
netflow_flow_clear(struct netflow *nf, struct flow *flow) OVS_EXCLUDED(mutex)
{
void
netflow_flow_clear(struct netflow *nf, struct flow *flow) OVS_EXCLUDED(mutex)
{
ovs_mutex_lock(&mutex);
nf_flow = netflow_flow_lookup(nf, flow);
if (nf_flow) {
ovs_mutex_lock(&mutex);
nf_flow = netflow_flow_lookup(nf, flow);
if (nf_flow) {
- ovs_assert(!nf_flow->packet_count);
- ovs_assert(!nf_flow->byte_count);
+ netflow_expire__(nf, nf_flow);
hmap_remove(&nf->flows, &nf_flow->hmap_node);
free(nf_flow);
}
hmap_remove(&nf->flows, &nf_flow->hmap_node);
free(nf_flow);
}
- * Copyright (c) 2008, 2009, 2010, 2011, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
bool netflow_exists(void);
int netflow_set_options(struct netflow *, const struct netflow_options *);
bool netflow_exists(void);
int netflow_set_options(struct netflow *, const struct netflow_options *);
-void netflow_expire(struct netflow *, struct flow *);
void netflow_run(struct netflow *);
void netflow_wait(struct netflow *);
void netflow_run(struct netflow *);
void netflow_wait(struct netflow *);
exit:
if (netflow) {
if (!ok) {
exit:
if (netflow) {
if (!ok) {
- netflow_expire(netflow, &flow);
netflow_flow_clear(netflow, &flow);
}
netflow_unref(netflow);
netflow_flow_clear(netflow, &flow);
}
netflow_unref(netflow);
xlate_actions_for_side_effects(&xin);
if (netflow) {
xlate_actions_for_side_effects(&xin);
if (netflow) {
- netflow_expire(netflow, &flow);
netflow_flow_clear(netflow, &flow);
netflow_unref(netflow);
}
netflow_flow_clear(netflow, &flow);
netflow_unref(netflow);
}
static void
xlate_cache_clear_netflow(struct netflow *netflow, struct flow *flow)
{
static void
xlate_cache_clear_netflow(struct netflow *netflow, struct flow *flow)
{
- netflow_expire(netflow, flow);
netflow_flow_clear(netflow, flow);
netflow_unref(netflow);
free(flow);
netflow_flow_clear(netflow, flow);
netflow_unref(netflow);
free(flow);