2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

learn: Fix iteration over learning specs.

struct ofpact_learn_spec is variable-length.  The 'n_specs' member of
struct ofpact_learn counted the number of specs, but the iteration loops
over struct ofpact_learn_spec only iterated as far as the *minimum* length
of 'n_specs' specs.

This fixes the problem, which exhibited as consistent failures for test 431
(learning action - TCPv6 port learning), seemingly only on i386 since it
shows up for my personal development machine but appears to not happen for
anyone else.

Fixes: dfe191d5fa ("ofp-actions: Waste less memory in learn actions.")
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
This commit is contained in:
Ben Pfaff
2016-09-02 13:26:50 -07:00
parent 784bf5d4eb
commit c65a31e262
3 changed files with 28 additions and 22 deletions

View File

@@ -41,8 +41,7 @@ learn_check(const struct ofpact_learn *learn, const struct flow *flow)
struct match match;
match_init_catchall(&match);
for (spec = learn->specs; spec < &learn->specs[learn->n_specs];
spec = ofpact_learn_spec_next(spec)) {
OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) {
enum ofperr error;
/* Check the source. */
@@ -123,8 +122,7 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
oft->fin_hard_timeout = learn->fin_hard_timeout;
}
for (spec = learn->specs; spec < &learn->specs[learn->n_specs];
spec = ofpact_learn_spec_next(spec)) {
OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) {
struct ofpact_set_field *sf;
union mf_subvalue value;
@@ -179,8 +177,7 @@ learn_mask(const struct ofpact_learn *learn, struct flow_wildcards *wc)
union mf_subvalue value;
memset(&value, 0xff, sizeof value);
for (spec = learn->specs; spec < &learn->specs[learn->n_specs];
spec = ofpact_learn_spec_next(spec)) {
OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) {
if (spec->src_type == NX_LEARN_SRC_FIELD) {
mf_write_subfield_flow(&spec->src, &value, &wc->masks);
}
@@ -386,7 +383,6 @@ learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts)
return error;
}
learn = ofpacts->header;
learn->n_specs++;
}
}
ofpact_finish_LEARN(ofpacts, &learn);
@@ -459,8 +455,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s)
colors.param, colors.end, ntohll(learn->cookie));
}
for (spec = learn->specs; spec < &learn->specs[learn->n_specs];
spec = ofpact_learn_spec_next(spec)) {
OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) {
unsigned int n_bytes = DIV_ROUND_UP(spec->n_bits, 8);
ds_put_char(s, ',');