ofp-group: Don't assert-fail decoding bad OF1.5 group mod type or command.

When decoding a group mod, the current code validates the group type and
command after the whole group mod has been decoded.  The OF1.5 decoder,
however, tries to use the type and command earlier, when it might still be
invalid.  This caused an assertion failure (via OVS_NOT_REACHED).  This
commit fixes the problem.

ovs-vswitchd does not enable support for OpenFlow 1.5 by default.

Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9249
Signed-off-by: Ben Pfaff <blp@ovn.org>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
parse_table_mod_vacancy_property(struct ofpbuf *property,
                                 struct ofputil_table_mod *tm)
{
    struct ofp14_table_mod_prop_vacancy *otv = property->data;

    if (property->size != sizeof *otv) {
        return OFPERR_OFPBPC_BAD_LEN;
    }
    tm->table_vacancy.vacancy_down = otv->vacancy_down;
    tm->table_vacancy.vacancy_up = otv->vacancy_up;
    if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Value of vacancy_down is greater than vacancy_up");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    if (tm->table_vacancy.vacancy_down > 100 ||
        tm->table_vacancy.vacancy_up > 100) {
        OFPPROP_LOG(&bad_ofmsg_rl, false, "Vacancy threshold percentage "
                    "should not be greater than 100");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    tm->table_vacancy.vacancy = otv->vacancy;
    if (tm->table_vacancy.vacancy) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Vacancy value should be zero for table-mod messages");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    return 0;
}

parse_table_mod_vacancy_property(struct ofpbuf *property,
                                 struct ofputil_table_mod *tm)
{
    struct ofp14_table_mod_prop_vacancy *otv = property->data;

    if (property->size != sizeof *otv) {
        return OFPERR_OFPBPC_BAD_LEN;
    }
    tm->table_vacancy.vacancy_down = otv->vacancy_down;
    tm->table_vacancy.vacancy_up = otv->vacancy_up;
    if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Value of vacancy_down is greater than vacancy_up");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    if (tm->table_vacancy.vacancy_down > 100 ||
        tm->table_vacancy.vacancy_up > 100) {
        OFPPROP_LOG(&bad_ofmsg_rl, false, "Vacancy threshold percentage "
                    "should not be greater than 100");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    tm->table_vacancy.vacancy = otv->vacancy;
    if (tm->table_vacancy.vacancy) {
        OFPPROP_LOG(&bad_ofmsg_rl, false,
                    "Vacancy value should be zero for table-mod messages");
        return OFPERR_OFPBPC_BAD_VALUE;
    }
    return 0;
}
