On Wed, Sep 12, 2012 at 05:44:29PM +0900, Simon Horman wrote: > +enum ofperr > +nxm_reg_load_from_openflow12_set_field( > + const struct ofp12_action_set_field * oasf, struct ofpbuf *ofpacts) > +{ > + uint16_t oasf_len = ntohs(oasf->len); > + ovs_be32 *p = (ovs_be32*)oasf->field; > + uint32_t oxm_header = ntohl(*p); > + uint8_t oxm_length = NXM_LENGTH(oxm_header); > + struct ofpact_reg_load *load; > + const struct mf_field *mf; > + int i; > + > + /* ofp12_action_set_field is padded to 64 bits by zero */ > + if (oasf_len != ROUND_UP(sizeof(*oasf) + oxm_length, 8)) { > + return OFPERR_OFPBAC_BAD_ARGUMENT;
This seems to be just coincidentally correct, simply because oasf->field[] happens to be the right length. I think that we should change struct ofp12_action_set_field so that it ends with "ovs_be32 dst;" instead of "uint8_t field[4];" (and update the comments). Then it would make more sense to do the arithmetic here, and we could skip the silliness with the cast to ovs_be32 above. > + } > + for (i = sizeof(*oasf) + oxm_length; i < oasf_len; i++) { > + if (((const char*)oasf)[i]) { > + return OFPERR_OFPBAC_BAD_ARGUMENT; > + } > + } Please use is_all_zeros() instead of the loop above. > + if (NXM_HASMASK(oxm_header)) { > + return OFPERR_OFPBAC_BAD_ARGUMENT; > + } > + mf = mf_from_nxm_header(oxm_header); > + if (!mf || mf->oxm_header == 0) { I guess mf->oxm_header == 0 is meant to rule out non-OXM fields. But I don't think that's a good idea. Extensibility is an OXM/NXM design goal and I don't know why we'd rule out non-official OXM fields. > + return OFPERR_OFPBAC_BAD_ARGUMENT; > + } > enum ofperr > nxm_reg_load_check(const struct ofpact_reg_load *load, const struct flow > *flow) > { > + const struct mf_field *mf; > + union mf_value value; > + > + if (load->ofpact.compat != OFPUTIL_OFPAT12_SET_FIELD) { > + return mf_check_dst(&load->dst, flow); I think it would be good to do the same checks for set-field as we do for reg-load. Do you know a good reason why not? The kinds of checks we do are pretty minimal, just to rule out values that don't make sense at all for a given field. If there's really some reason why we can't do those checks for set-field, then I'd prefer to do the mf_check_dst() check up front here, in one place, for both set-field and reg-load. > { > struct nx_action_reg_load *narl; > > + if (load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD) { > + const struct mf_field *mf = load->dst.field; > + struct ofp12_action_set_field *oasf; > + > + oasf = ofputil_put_OFPAT12_SET_FIELD(openflow); > + *(uint32_t *)oasf->field = mf->oxm_header; > + memset(oasf + 1, 0, mf->n_bytes); > + bitwise_copy(&load->subvalue, sizeof load->subvalue, load->dst.ofs, > + oasf + 1, mf->n_bytes, load->dst.ofs, load->dst.n_bits); Hmm. This looks like it blindly puts an OFPAT12_SET_FIELD action into other versions of OpenFlow. I think we have a few options: * Don't worry about it. That might be OK because OFPAT12_SET_FIELD doesn't collide with any assigned OpenFlow 1.0 action (accidentally) or 1.1 action (by design). * Translate into a series of NXAST_REG_LOAD actions. * Any other ideas? Thanks, Ben. _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev