diff options
author | Ben Pfaff <blp@ovn.org> | 2018-08-29 13:16:36 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-12-03 12:50:05 -0800 |
commit | c332ed151a78c0c05d6d655e19f1d72f69c5b1a6 (patch) | |
tree | af7a46bf129cbe73e42e42b64f51228257497f0f /lib | |
parent | 5f223e92327501f939f5777d900782177d445219 (diff) | |
download | openvswitch-c332ed151a78c0c05d6d655e19f1d72f69c5b1a6.tar.gz |
ofp-table: Parse table features messages more carefully.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Justin Pettit <jpettit@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ofp-table.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/ofp-table.c b/lib/ofp-table.c index 8a070af3f..126b5060a 100644 --- a/lib/ofp-table.c +++ b/lib/ofp-table.c @@ -74,6 +74,33 @@ ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy) default: return "***error***"; } } + +static bool +ofp15_table_features_command_is_valid(enum ofp15_table_features_command cmd) +{ + switch (cmd) { + case OFPTFC15_REPLACE: + case OFPTFC15_MODIFY: + case OFPTFC15_ENABLE: + case OFPTFC15_DISABLE: + return true; + + default: + return false; + } +} + +static const char * +ofp15_table_features_command_to_string(enum ofp15_table_features_command cmd) +{ + switch (cmd) { + case OFPTFC15_REPLACE: return "replace"; + case OFPTFC15_MODIFY: return "modify"; + case OFPTFC15_ENABLE: return "enable"; + case OFPTFC15_DISABLE: return "disable"; + default: return "***bad command***"; + } +} /* ofputil_table_map. */ @@ -361,6 +388,15 @@ ofputil_decode_table_features(struct ofpbuf *msg, return OFPERR_OFPBPC_BAD_LEN; } + if (oh->version >= OFP15_VERSION) { + if (!ofp15_table_features_command_is_valid(otf->command)) { + return OFPERR_OFPTFFC_BAD_COMMAND; + } + tf->command = otf->command; + } else { + tf->command = OFPTFC15_REPLACE; + } + tf->table_id = otf->table_id; if (tf->table_id == OFPTT_ALL) { return OFPERR_OFPTFFC_BAD_TABLE; @@ -382,7 +418,9 @@ ofputil_decode_table_features(struct ofpbuf *msg, struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len), len); + tf->any_properties = properties.size > 0; ofpbuf_pull(&properties, sizeof *otf); + uint32_t seen = 0; while (properties.size > 0) { struct ofpbuf payload; enum ofperr error; @@ -393,6 +431,14 @@ ofputil_decode_table_features(struct ofpbuf *msg, return error; } + if (type < 32) { + uint32_t bit = 1u << type; + if (seen & bit) { + return OFPERR_OFPTFFC_BAD_FEATURES; + } + seen |= bit; + } + switch ((enum ofp13_table_feature_prop_type) type) { case OFPTFPT13_INSTRUCTIONS: error = parse_instruction_ids(&payload, loose, @@ -464,6 +510,36 @@ ofputil_decode_table_features(struct ofpbuf *msg, } } + /* OpenFlow 1.3 and 1.4 always require all of the required properties. + * OpenFlow 1.5 requires all of them if any property is present. */ + if ((seen & OFPTFPT13_REQUIRED) != OFPTFPT13_REQUIRED + && (tf->any_properties || oh->version < OFP15_VERSION)) { + VLOG_WARN_RL(&rl, "table features message missing required property"); + return OFPERR_OFPTFFC_BAD_FEATURES; + } + + /* Copy nonmiss to miss when appropriate. */ + if (tf->any_properties) { + if (!(seen & (1u << OFPTFPT13_INSTRUCTIONS_MISS))) { + tf->miss.instructions = tf->nonmiss.instructions; + } + if (!(seen & (1u << OFPTFPT13_NEXT_TABLES_MISS))) { + memcpy(tf->miss.next, tf->nonmiss.next, sizeof tf->miss.next); + } + if (!(seen & (1u << OFPTFPT13_WRITE_ACTIONS_MISS))) { + tf->miss.write.ofpacts = tf->nonmiss.write.ofpacts; + } + if (!(seen & (1u << OFPTFPT13_APPLY_ACTIONS_MISS))) { + tf->miss.apply.ofpacts = tf->nonmiss.apply.ofpacts; + } + if (!(seen & (1u << OFPTFPT13_WRITE_SETFIELD_MISS))) { + tf->miss.write.set_fields = tf->nonmiss.write.set_fields; + } + if (!(seen & (1u << OFPTFPT13_APPLY_SETFIELD_MISS))) { + tf->miss.apply.set_fields = tf->nonmiss.apply.set_fields; + } + } + /* Fix inconsistencies: * * - Turn on 'match' bits that are set in 'mask', because maskable @@ -577,6 +653,7 @@ ofputil_append_table_features_reply(const struct ofputil_table_features *tf, otf = ofpbuf_put_zeros(reply, sizeof *otf); otf->table_id = tf->table_id; + otf->command = version >= OFP15_VERSION ? tf->command : 0; ovs_strlcpy_arrays(otf->name, tf->name); otf->metadata_match = tf->metadata_match; otf->metadata_write = tf->metadata_write; @@ -1434,6 +1511,12 @@ ofputil_table_features_format( const struct ofputil_table_stats *prev_stats, int *first_ditto, int *last_ditto) { + if (!prev_features && features->command != OFPTFC15_REPLACE) { + ds_put_format(s, "\n command: %s", + ofp15_table_features_command_to_string( + features->command)); + } + int table = features->table_id; int prev_table = prev_features ? prev_features->table_id : 0; |