Skip to content

Commit

Permalink
ofp-actions: enforce valid range for table_id in goto_table instruction
Browse files Browse the repository at this point in the history
Found a bug that OVS allows goto_table_id to be smaller than (or equal to)
the current table id where the flow resides. It potentially creates an
infinite loop when composing actions for a packet. To fix it, we just let
OVS returns an error message to prevent such flow to be programmed.

Signed-off-by: Jing Ai <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
jingax10 authored and blp committed Jun 5, 2013
1 parent 084c3bb commit bff7eeb
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 6 deletions.
2 changes: 1 addition & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Jarno Rajahalme [email protected]
Jean Tourrilhes [email protected]
Jeremy Stribling [email protected]
Jesse Gross [email protected]
Jing Ai [email protected]
Joe Perches [email protected]
Joe Stringer [email protected]
Jun Nakajima [email protected]
Expand Down Expand Up @@ -154,7 +155,6 @@ Jari Sundell [email protected]
Jed Daniels [email protected]
Jeff Merrick [email protected]
Jeongkeun Lee [email protected]
Jing Ai [email protected]
Joan Cirer [email protected]
John Galgay [email protected]
Kevin Mancuso [email protected]
Expand Down
5 changes: 5 additions & 0 deletions lib/ofp-actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,7 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
enum ofperr
ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
unsigned int instructions_len,
uint8_t table_id,
struct ofpbuf *ofpacts)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
Expand Down Expand Up @@ -1119,6 +1120,10 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,

oigt = instruction_get_OFPIT11_GOTO_TABLE(
insts[OVSINST_OFPIT11_GOTO_TABLE]);
if (table_id >= oigt->table_id) {
error = OFPERR_OFPBRC_BAD_TABLE_ID;
goto exit;
}
ogt = ofpact_put_GOTO_TABLE(ofpacts);
ogt->table_id = oigt->table_id;
}
Expand Down
1 change: 1 addition & 0 deletions lib/ofp-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ enum ofperr ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
struct ofpbuf *ofpacts);
enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
unsigned int instructions_len,
uint8_t table_id,
struct ofpbuf *ofpacts);
enum ofperr ofpacts_check(const struct ofpact[], size_t ofpacts_len,
const struct flow *, int max_ports);
Expand Down
6 changes: 4 additions & 2 deletions lib/ofp-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,8 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
return error;
}

error = ofpacts_pull_openflow11_instructions(&b, b.size, ofpacts);
error = ofpacts_pull_openflow11_instructions(&b, b.size, ofm->table_id,
ofpacts);
if (error) {
return error;
}
Expand Down Expand Up @@ -2014,7 +2015,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
}

if (ofpacts_pull_openflow11_instructions(msg, length - sizeof *ofs -
padded_match_len, ofpacts)) {
padded_match_len,
ofs->table_id, ofpacts)) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
return EINVAL;
}
Expand Down
4 changes: 4 additions & 0 deletions tests/ofp-actions.at
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@ dnl Goto-Table 1 instruction non-zero padding
# 7: 01 -> 00
0001 0008 01 000001

dnl Goto-Table 1 instruction go back to the previous table.
# bad OF1.1 instructions: OFPBRC_BAD_TABLE_ID
2,0001 0008 01 000000

dnl Goto-Table 1
# actions=goto_table:1
0001 0008 01 000000
Expand Down
17 changes: 14 additions & 3 deletions utilities/ovs-ofctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2607,18 +2607,29 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
enum ofperr error;
size_t size;
struct ds s;
const char *table_id;
char *instructions;

/* Parse table_id separated with the follow-up instructions by ",", if
* any. */
instructions = ds_cstr(&in);
table_id = NULL;
if (strstr(instructions, ",")) {
table_id = strsep(&instructions, ",");
}

/* Parse hex bytes. */
ofpbuf_init(&of11_in, 0);
if (ofpbuf_put_hex(&of11_in, ds_cstr(&in), NULL)[0] != '\0') {
if (ofpbuf_put_hex(&of11_in, instructions, NULL)[0] != '\0') {
ovs_fatal(0, "Trailing garbage in hex data");
}

/* Convert to ofpacts. */
ofpbuf_init(&ofpacts, 0);
size = of11_in.size;
error = ofpacts_pull_openflow11_instructions(&of11_in, of11_in.size,
&ofpacts);
error = ofpacts_pull_openflow11_instructions(
&of11_in, of11_in.size, table_id ? atoi(table_id) : 0,
&ofpacts);
if (error) {
printf("bad OF1.1 instructions: %s\n\n", ofperr_get_name(error));
ofpbuf_uninit(&ofpacts);
Expand Down

0 comments on commit bff7eeb

Please sign in to comment.