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

@@ -744,21 +744,34 @@ ofpact_learn_spec_next(const struct ofpact_learn_spec *spec)
*
* Used for NXAST_LEARN. */
struct ofpact_learn {
struct ofpact ofpact;
OFPACT_PADDED_MEMBERS(
struct ofpact ofpact;
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Max time before discarding (seconds). */
uint16_t priority; /* Priority level of flow entry. */
uint8_t table_id; /* Table to insert flow entry. */
enum nx_learn_flags flags; /* NX_LEARN_F_*. */
ovs_be64 cookie; /* Cookie for new flow. */
uint16_t fin_idle_timeout; /* Idle timeout after FIN, if nonzero. */
uint16_t fin_hard_timeout; /* Hard timeout after FIN, if nonzero. */
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Max time before discarding (seconds). */
uint16_t priority; /* Priority level of flow entry. */
uint8_t table_id; /* Table to insert flow entry. */
enum nx_learn_flags flags; /* NX_LEARN_F_*. */
ovs_be64 cookie; /* Cookie for new flow. */
uint16_t fin_idle_timeout; /* Idle timeout after FIN, if nonzero. */
uint16_t fin_hard_timeout; /* Hard timeout after FIN, if nonzero. */
);
unsigned int n_specs;
struct ofpact_learn_spec specs[];
};
static inline const struct ofpact_learn_spec *
ofpact_learn_spec_end(const struct ofpact_learn *learn)
{
return ALIGNED_CAST(const struct ofpact_learn_spec *,
ofpact_next(&learn->ofpact));
}
#define OFPACT_LEARN_SPEC_FOR_EACH(SPEC, LEARN) \
for ((SPEC) = (LEARN)->specs; \
(SPEC) < ofpact_learn_spec_end(LEARN); \
(SPEC) = ofpact_learn_spec_next(SPEC))
/* Multipath link choice algorithm to apply.
*
* In the descriptions below, 'n_links' is max_link + 1. */