Skip to content

Commit 996f2d3

Browse files
simonartxavieralmusil
authored andcommitted
controller: Fix mac-cache race condition causing extra ARP.
Usually mac_binding_stats_run and mac_binding_probe_stats_run are executed either both with (since_updated < threshold->cooldown_period), and sb is not updated, or both with (since_updated >= threshold->cooldown_period), and sb is updated but ARP is not sent (until stats->idle_age_ms > threshold->value). However, if mac_binding_stats_run is executed as (since_updated < threshold->cooldown_period), it does not update mac_binding, as expected. Then, if mac_binding_probe_stats_run is executed just afterwards, but with (since_updated_ms >= threshold->cooldown_period), ARP is sent. Fix this by calling time_wall_msec() once in statctrl_run() and passing it to all stats_run functions. This was identified through random failures of test "MAC binding aging - probing GW router Dynamic Neigh". Fixes: 1e4d440 ("controller: Send ARP/ND for stale mac_bindings entries.") Signed-off-by: Xavier Simonart <xsimonar@redhat.com> Acked-by: Ales Musil <amusil@redhat.com> Signed-off-by: Ales Musil <amusil@redhat.com> (cherry picked from commit a68cf33)
1 parent ded7e98 commit 996f2d3

3 files changed

Lines changed: 13 additions & 11 deletions

File tree

controller/mac-cache.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,9 @@ mac_binding_update_log(const char *action,
412412

413413
void
414414
mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay,
415-
void *data)
415+
void *data, long long timewall_now)
416416
{
417417
struct mac_cache_data *cache_data = data;
418-
long long timewall_now = time_wall_msec();
419418

420419
struct mac_cache_stats *stats;
421420
LIST_FOR_EACH_POP (stats, list_node, stats_list) {
@@ -511,10 +510,10 @@ fdb_update_log(const char *action,
511510
}
512511

513512
void
514-
fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, void *data)
513+
fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, void *data,
514+
long long timewall_now)
515515
{
516516
struct mac_cache_data *cache_data = data;
517-
long long timewall_now = time_wall_msec();
518517

519518
struct mac_cache_stats *stats;
520519
LIST_FOR_EACH_POP (stats, list_node, stats_list) {
@@ -891,9 +890,8 @@ mac_binding_probe_stats_process_flow_stats(
891890

892891
void
893892
mac_binding_probe_stats_run(struct ovs_list *stats_list, uint64_t *req_delay,
894-
void *data)
893+
void *data, long long timewall_now)
895894
{
896-
long long timewall_now = time_wall_msec();
897895
struct mac_binding_probe_data *probe_data = data;
898896
struct mac_cache_data *cache_data = probe_data->cache_data;
899897

controller/mac-cache.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,14 @@ mac_binding_stats_process_flow_stats(struct ovs_list *stats_list,
189189
struct ofputil_flow_stats *ofp_stats);
190190

191191
void mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay,
192-
void *data);
192+
void *data, long long timewall_now);
193193

194194
/* FDB stat processing. */
195195
void fdb_stats_process_flow_stats(struct ovs_list *stats_list,
196196
struct ofputil_flow_stats *ofp_stats);
197197

198198
void fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay,
199-
void *data);
199+
void *data, long long timewall_now);
200200

201201
void mac_cache_stats_destroy(struct ovs_list *stats_list);
202202

@@ -234,6 +234,7 @@ void mac_binding_probe_stats_process_flow_stats(
234234
struct ofputil_flow_stats *ofp_stats);
235235

236236
void mac_binding_probe_stats_run(struct ovs_list *stats_list,
237-
uint64_t *req_delay, void *data);
237+
uint64_t *req_delay, void *data,
238+
long long timewall_now);
238239

239240
#endif /* controller/mac-cache.h */

controller/statctrl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ struct stats_node {
6464
struct ofputil_flow_stats *ofp_stats);
6565
/* Function to process the parsed stats.
6666
* This function runs in main thread locked behind mutex. */
67-
void (*run)(struct ovs_list *stats_list, uint64_t *req_delay, void *data);
67+
void (*run)(struct ovs_list *stats_list, uint64_t *req_delay, void *data,
68+
long long timewall_now);
6869
/* Name of the stats node corresponding stopwatch. */
6970
const char *stopwatch_name;
7071
};
@@ -197,6 +198,7 @@ statctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
197198

198199
bool schedule_updated = false;
199200
long long now = time_msec();
201+
long long timewall_now = time_wall_msec();
200202

201203
ovs_mutex_lock(&mutex);
202204
statctrl_ctx.new_main_seq = seq_read(statctrl_ctx.main_seq);
@@ -205,7 +207,8 @@ statctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
205207
uint64_t prev_delay = node->request_delay;
206208

207209
stopwatch_start(node->stopwatch_name, time_msec());
208-
node->run(&node->stats_list, &node->request_delay, node_data[i]);
210+
node->run(&node->stats_list, &node->request_delay,
211+
node_data[i], timewall_now);
209212
stopwatch_stop(node->stopwatch_name, time_msec());
210213

211214
schedule_updated |=

0 commit comments

Comments
 (0)