Skip to content

Commit ce05810

Browse files
committed
ofp-actions: Make ofpact_finish() harder to misuse.
It's pretty easy to forget to update the pointer to an ofpact when finishing it. This commit forces the caller to pass a pointer-to-pointer instead, and uses that to automatically update the pointer. There still could be cases that retain other pointers into the ofpbuf, but I imagine that this is harder to misuse. Suggested-by: Joe Stringer <[email protected]> Signed-off-by: Ben Pfaff <[email protected]> Acked-by: Joe Stringer <[email protected]>
1 parent 6e3a764 commit ce05810

File tree

6 files changed

+42
-22
lines changed

6 files changed

+42
-22
lines changed

lib/bundle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ bundle_parse__(const char *s, char **save_ptr,
179179
bundle = ofpacts->header;
180180
bundle->n_slaves++;
181181
}
182-
bundle = ofpact_finish(ofpacts, &bundle->ofpact);
182+
ofpact_finish_BUNDLE(ofpacts, &bundle);
183183
bundle->basis = atoi(basis);
184184

185185
if (!strcasecmp(fields, "eth_src")) {

lib/learn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts)
380380
}
381381
}
382382
}
383-
ofpact_finish(ofpacts, &learn->ofpact);
383+
ofpact_finish_LEARN(ofpacts, &learn);
384384

385385
return NULL;
386386
}

lib/ofp-actions.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ decode_NXAST_RAW_CONTROLLER(const struct nx_action_controller *nac,
668668
oc->max_len = ntohs(nac->max_len);
669669
oc->controller_id = ntohs(nac->controller_id);
670670
oc->reason = nac->reason;
671-
ofpact_finish(out, &oc->ofpact);
671+
ofpact_finish_CONTROLLER(out, &oc);
672672

673673
return 0;
674674
}
@@ -737,7 +737,7 @@ decode_NXAST_RAW_CONTROLLER2(const struct nx_action_controller2 *nac2,
737737
}
738738
}
739739

740-
ofpact_finish(out, &oc->ofpact);
740+
ofpact_finish_CONTROLLER(out, &oc);
741741

742742
return 0;
743743
}
@@ -852,7 +852,7 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
852852
controller = ofpacts->header;
853853
controller->userdata_len = userdata_len;
854854
}
855-
ofpact_finish(ofpacts, &controller->ofpact);
855+
ofpact_finish_CONTROLLER(ofpacts, &controller);
856856
}
857857

858858
return NULL;
@@ -1262,7 +1262,7 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
12621262
bundle = ofpacts->header;
12631263
}
12641264

1265-
bundle = ofpact_finish(ofpacts, &bundle->ofpact);
1265+
ofpact_finish_BUNDLE(ofpacts, &bundle);
12661266
if (!error) {
12671267
error = bundle_check(bundle, OFPP_MAX, NULL);
12681268
}
@@ -3096,7 +3096,7 @@ decode_OFPAT_RAW_DEC_NW_TTL(struct ofpbuf *out)
30963096
ids->n_controllers = 1;
30973097
ofpbuf_put(out, &id, sizeof id);
30983098
ids = out->header;
3099-
ofpact_finish(out, &ids->ofpact);
3099+
ofpact_finish_DEC_TTL(out, &ids);
31003100
return error;
31013101
}
31023102

@@ -3133,7 +3133,7 @@ decode_NXAST_RAW_DEC_TTL_CNT_IDS(const struct nx_action_cnt_ids *nac_ids,
31333133
ids = out->header;
31343134
}
31353135

3136-
ofpact_finish(out, &ids->ofpact);
3136+
ofpact_finish_DEC_TTL(out, &ids);
31373137

31383138
return 0;
31393139
}
@@ -3172,7 +3172,7 @@ parse_noargs_dec_ttl(struct ofpbuf *ofpacts)
31723172
ofpbuf_put(ofpacts, &id, sizeof id);
31733173
ids = ofpacts->header;
31743174
ids->n_controllers++;
3175-
ofpact_finish(ofpacts, &ids->ofpact);
3175+
ofpact_finish_DEC_TTL(ofpacts, &ids);
31763176
}
31773177

31783178
static char * OVS_WARN_UNUSED_RESULT
@@ -3199,7 +3199,7 @@ parse_DEC_TTL(char *arg, struct ofpbuf *ofpacts,
31993199
return xstrdup("dec_ttl_cnt_ids: expected at least one controller "
32003200
"id.");
32013201
}
3202-
ofpact_finish(ofpacts, &ids->ofpact);
3202+
ofpact_finish_DEC_TTL(ofpacts, &ids);
32033203
}
32043204
return NULL;
32053205
}
@@ -4228,7 +4228,7 @@ decode_NXAST_RAW_LEARN(const struct nx_action_learn *nal,
42284228
get_subfield(spec->n_bits, &p, &spec->dst);
42294229
}
42304230
}
4231-
ofpact_finish(ofpacts, &learn->ofpact);
4231+
ofpact_finish_LEARN(ofpacts, &learn);
42324232

42334233
if (!is_all_zeros(p, (char *) end - (char *) p)) {
42344234
return OFPERR_OFPBAC_BAD_ARGUMENT;
@@ -4554,7 +4554,7 @@ decode_NXAST_RAW_NOTE(const struct nx_action_note *nan,
45544554
note = ofpact_put_NOTE(out);
45554555
note->length = length;
45564556
ofpbuf_put(out, nan->note, length);
4557-
ofpact_finish(out, out->header);
4557+
ofpact_finish_NOTE(out, &note);
45584558

45594559
return 0;
45604560
}
@@ -4586,7 +4586,7 @@ parse_NOTE(const char *arg, struct ofpbuf *ofpacts,
45864586
struct ofpact_note *note = ofpbuf_at_assert(ofpacts, start_ofs,
45874587
sizeof *note);
45884588
note->length = ofpacts->size - (start_ofs + sizeof *note);
4589-
ofpact_finish(ofpacts, &note->ofpact);
4589+
ofpact_finish_NOTE(ofpacts, &note);
45904590
return NULL;
45914591
}
45924592

@@ -4994,7 +4994,7 @@ decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
49944994

49954995
conntrack = ofpbuf_push_uninit(out, sizeof(*conntrack));
49964996
out->header = &conntrack->ofpact;
4997-
conntrack = ofpact_finish(out, &conntrack->ofpact);
4997+
ofpact_finish_CT(out, &conntrack);
49984998

49994999
if (conntrack->ofpact.len > sizeof(*conntrack)
50005000
&& !(conntrack->flags & NX_CT_F_COMMIT)) {
@@ -5115,7 +5115,7 @@ parse_CT(char *arg, struct ofpbuf *ofpacts,
51155115
}
51165116
}
51175117

5118-
ofpact_finish(ofpacts, &oc->ofpact);
5118+
ofpact_finish_CT(ofpacts, &oc);
51195119
ofpbuf_push_uninit(ofpacts, ct_offset);
51205120
return error;
51215121
}
@@ -7419,6 +7419,7 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len,
74197419

74207420
/* Internal use by helpers. */
74217421

7422+
/* Implementation of ofpact_put_<ENUM>(). */
74227423
void *
74237424
ofpact_put(struct ofpbuf *ofpacts, enum ofpact_type type, size_t len)
74247425
{
@@ -7430,6 +7431,7 @@ ofpact_put(struct ofpbuf *ofpacts, enum ofpact_type type, size_t len)
74307431
return ofpact;
74317432
}
74327433

7434+
/* Implementation of ofpact_init_<ENUM>(). */
74337435
void
74347436
ofpact_init(struct ofpact *ofpact, enum ofpact_type type, size_t len)
74357437
{
@@ -7438,8 +7440,10 @@ ofpact_init(struct ofpact *ofpact, enum ofpact_type type, size_t len)
74387440
ofpact->raw = -1;
74397441
ofpact->len = len;
74407442
}
7441-
7442-
/* Finishes composing a variable-length action (begun using
7443+
7444+
/* Implementation of ofpact_finish_<ENUM>().
7445+
*
7446+
* Finishes composing a variable-length action (begun using
74437447
* ofpact_put_<NAME>()), by padding the action to a multiple of OFPACT_ALIGNTO
74447448
* bytes and updating its embedded length field. See the large comment near
74457449
* the end of ofp-actions.h for more information.

lib/ofp-actions.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ const char *ofpact_name(enum ofpact_type);
903903
/* Internal use by the helpers below. */
904904
void ofpact_init(struct ofpact *, enum ofpact_type, size_t len);
905905
void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len);
906+
void *ofpact_finish(struct ofpbuf *, struct ofpact *);
906907

907908
/* For each OFPACT_<ENUM> with a corresponding struct <STRUCT>, this defines
908909
* the following commonly useful functions:
@@ -924,6 +925,16 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len);
924925
* Returns 'ofpact' cast to "struct <STRUCT> *". 'ofpact->type' must be
925926
* OFPACT_<ENUM>.
926927
*
928+
* void ofpact_finish_<ENUM>(struct ofpbuf *ofpacts, struct <STRUCT> **ap);
929+
*
930+
* Finishes composing variable-length action '*ap' (begun using
931+
* ofpact_put_<NAME>() on 'ofpacts'), by padding the action to a multiple
932+
* of OFPACT_ALIGNTO bytes and updating its embedded length field.
933+
*
934+
* May reallocate 'ofpacts', and so as a convenience automatically updates
935+
* '*ap' to point to the new location. If the caller has other pointers
936+
* within 'ap' or 'ofpacts', it needs to update them manually.
937+
*
927938
* as well as the following more rarely useful definitions:
928939
*
929940
* void ofpact_init_<ENUM>(struct <STRUCT> *ofpact);
@@ -965,13 +976,18 @@ void *ofpact_put(struct ofpbuf *, enum ofpact_type, size_t len);
965976
{ \
966977
ofpact_init(&ofpact->ofpact, OFPACT_##ENUM, \
967978
OFPACT_##ENUM##_SIZE); \
979+
} \
980+
\
981+
static inline void \
982+
ofpact_finish_##ENUM(struct ofpbuf *ofpbuf, struct STRUCT **ofpactp) \
983+
{ \
984+
struct ofpact *ofpact = &(*ofpactp)->ofpact; \
985+
ovs_assert(ofpact->type == OFPACT_##ENUM); \
986+
*ofpactp = ofpact_finish(ofpbuf, ofpact); \
968987
}
969988
OFPACTS
970989
#undef OFPACT
971990

972-
/* Call after adding the variable-length part to a variable-length action. */
973-
void *ofpact_finish(struct ofpbuf *, struct ofpact *);
974-
975991
/* Additional functions for composing ofpacts. */
976992
struct ofpact_set_field *ofpact_put_reg_load(struct ofpbuf *ofpacts);
977993

ofproto/ofproto-dpif.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ add_internal_flows(struct ofproto_dpif *ofproto)
14111411
controller->max_len = UINT16_MAX;
14121412
controller->controller_id = 0;
14131413
controller->reason = OFPR_IMPLICIT_MISS;
1414-
controller = ofpact_finish(&ofpacts, &controller->ofpact);
1414+
ofpact_finish_CONTROLLER(&ofpacts, &controller);
14151415

14161416
error = add_internal_miss_flow(ofproto, id++, &ofpacts,
14171417
&ofproto->miss_rule);

ovn/lib/actions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ finish_controller_op(struct ofpbuf *ofpacts, size_t ofs)
205205
struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc);
206206
ofpacts->header = oc;
207207
oc->userdata_len = ofpacts->size - (ofs + sizeof *oc);
208-
ofpact_finish(ofpacts, &oc->ofpact);
208+
ofpact_finish_CONTROLLER(ofpacts, &oc);
209209
}
210210

211211
static void

0 commit comments

Comments
 (0)