X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-actions.c;h=db603b6e5e06fe5ef59d1d43a68cddaedb044e28;hb=c2d967a562aaa57b679c302a5041d5a941154143;hp=5681fba8a94ff33d48339d721d99e263aef8684f;hpb=1ec3db6fd8cff83555ba496c32324ab78731b6c1;p=openvswitch diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 5681fba8..db603b6e 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -148,6 +148,58 @@ note_from_openflow(const struct nx_action_note *nan, struct ofpbuf *out) memcpy(note->data, nan->note, length); } +static enum ofperr +dec_ttl_from_openflow(struct ofpbuf *out) +{ + uint16_t id = 0; + struct ofpact_cnt_ids *ids; + enum ofperr error = 0; + + ids = ofpact_put_DEC_TTL(out); + ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL; + ids->n_controllers = 1; + ofpbuf_put(out, &id, sizeof id); + ids = out->l2; + ofpact_update_len(out, &ids->ofpact); + return error; +} + +static enum ofperr +dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids, + struct ofpbuf *out) +{ + struct ofpact_cnt_ids *ids; + size_t ids_size; + int i; + + ids = ofpact_put_DEC_TTL(out); + ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS; + ids->n_controllers = ntohs(nac_ids->n_controllers); + ids_size = ntohs(nac_ids->len) - sizeof *nac_ids; + + if (!is_all_zeros(nac_ids->zeros, sizeof nac_ids->zeros)) { + return OFPERR_NXBRC_MUST_BE_ZERO; + } + + if (ids_size < ids->n_controllers * sizeof(ovs_be16)) { + VLOG_WARN_RL(&rl, "Nicira action dec_ttl_cnt_ids only has %zu bytes " + "allocated for controller ids. %zu bytes are required for " + "%"PRIu16" controllers.", ids_size, + ids->n_controllers * sizeof(ovs_be16), ids->n_controllers); + return OFPERR_OFPBAC_BAD_LEN; + } + + for (i = 0; i < ids->n_controllers; i++) { + uint16_t id = ntohs(((ovs_be16 *)(nac_ids + 1))[i]); + ofpbuf_put(out, &id, sizeof id); + } + + ids = out->l2; + ofpact_update_len(out, &ids->ofpact); + + return 0; +} + static enum ofperr decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code) { @@ -310,7 +362,12 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, break; case OFPUTIL_NXAST_DEC_TTL: - ofpact_put_DEC_TTL(out); + error = dec_ttl_from_openflow(out); + break; + + case OFPUTIL_NXAST_DEC_TTL_CNT_IDS: + error = dec_ttl_cnt_ids_from_openflow( + (const struct nx_action_cnt_ids *) a, out); break; case OFPUTIL_NXAST_FIN_TIMEOUT: @@ -434,38 +491,54 @@ action_is_valid(const union ofp_action *a, size_t n_actions) ((LEFT) -= ntohs((ITER)->header.len) / sizeof(union ofp_action), \ (ITER) = action_next(ITER))) +static void +log_bad_action(const union ofp_action *actions, size_t n_actions, size_t ofs, + enum ofperr error) +{ + if (!VLOG_DROP_WARN(&rl)) { + struct ds s; + + ds_init(&s); + ds_put_hex_dump(&s, actions, n_actions * sizeof *actions, 0, false); + VLOG_WARN("bad action at offset %#zx (%s):\n%s", + ofs * sizeof *actions, ofperr_get_name(error), ds_cstr(&s)); + ds_destroy(&s); + } +} + static enum ofperr -ofpacts_from_openflow10(const union ofp_action *in, size_t n_in, - struct ofpbuf *out) +ofpacts_from_openflow(const union ofp_action *in, size_t n_in, + struct ofpbuf *out, + enum ofperr (*ofpact_from_openflow)( + const union ofp_action *a, struct ofpbuf *out)) { const union ofp_action *a; size_t left; ACTION_FOR_EACH (a, left, in, n_in) { - enum ofperr error = ofpact_from_openflow10(a, out); + enum ofperr error = ofpact_from_openflow(a, out); if (error) { - VLOG_WARN_RL(&rl, "bad action at offset %td (%s)", - (a - in) * sizeof *a, ofperr_get_name(error)); + log_bad_action(in, n_in, a - in, error); return error; } } if (left) { - if (!VLOG_DROP_WARN(&rl)) { - struct ds s; - - ds_init(&s); - ds_put_hex_dump(&s, in, n_in * sizeof *a, 0, false); - VLOG_WARN("bad action format at offset %#zx:\n%s", - (n_in - left) * sizeof *a, ds_cstr(&s)); - ds_destroy(&s); - } - return OFPERR_OFPBAC_BAD_LEN; + enum ofperr error = OFPERR_OFPBAC_BAD_LEN; + log_bad_action(in, n_in, n_in - left, error); + return error; } ofpact_pad(out); return 0; } +static enum ofperr +ofpacts_from_openflow10(const union ofp_action *in, size_t n_in, + struct ofpbuf *out) +{ + return ofpacts_from_openflow(in, n_in, out, ofpact_from_openflow10); +} + static enum ofperr ofpacts_pull_actions(struct ofpbuf *openflow, unsigned int actions_len, struct ofpbuf *ofpacts, @@ -652,62 +725,19 @@ static enum ofperr ofpacts_from_openflow11(const union ofp_action *in, size_t n_in, struct ofpbuf *out) { - const union ofp_action *a; - size_t left; - - ACTION_FOR_EACH (a, left, in, n_in) { - enum ofperr error = ofpact_from_openflow11(a, out); - if (error) { - VLOG_WARN_RL(&rl, "bad action at offset %td (%s)", - (a - in) * sizeof *a, ofperr_get_name(error)); - return error; - } - } - if (left) { - VLOG_WARN_RL(&rl, "bad action format at offset %zu", - (n_in - left) * sizeof *a); - return OFPERR_OFPBAC_BAD_LEN; - } - - return 0; + return ofpacts_from_openflow(in, n_in, out, ofpact_from_openflow11); } /* OpenFlow 1.1 instructions. */ -#define OVS_INSTRUCTIONS \ - DEFINE_INST(OFPIT11_GOTO_TABLE, \ - ofp11_instruction_goto_table, false, \ - "goto_table") \ - \ - DEFINE_INST(OFPIT11_WRITE_METADATA, \ - ofp11_instruction_write_metadata, false, \ - "write_metadata") \ - \ - DEFINE_INST(OFPIT11_WRITE_ACTIONS, \ - ofp11_instruction_actions, true, \ - "write_actions") \ - \ - DEFINE_INST(OFPIT11_APPLY_ACTIONS, \ - ofp11_instruction_actions, true, \ - "apply_actions") \ - \ - DEFINE_INST(OFPIT11_CLEAR_ACTIONS, \ - ofp11_instruction, false, \ - "clear_actions") - -enum ovs_instruction_type { -#define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME) OVSINST_##ENUM, - OVS_INSTRUCTIONS -#undef DEFINE_INST -}; - -enum { -#define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME) + 1 - N_OVS_INSTRUCTIONS = OVS_INSTRUCTIONS -#undef DEFINE_INST -}; - #define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME) \ + static inline const struct STRUCT * \ + instruction_get_##ENUM(const struct ofp11_instruction *inst)\ + { \ + assert(inst->type == htons(ENUM)); \ + return (struct STRUCT *)inst; \ + } \ + \ static inline void \ instruction_init_##ENUM(struct STRUCT *s) \ { \ @@ -726,6 +756,41 @@ enum { OVS_INSTRUCTIONS #undef DEFINE_INST +struct instruction_type_info { + enum ovs_instruction_type type; + const char *name; +}; + +static const struct instruction_type_info inst_info[] = { +#define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME) {OVSINST_##ENUM, NAME}, +OVS_INSTRUCTIONS +#undef DEFINE_INST +}; + +const char * +ofpact_instruction_name_from_type(enum ovs_instruction_type type) +{ + const struct instruction_type_info *p; + for (p = inst_info; p < &inst_info[ARRAY_SIZE(inst_info)]; p++) { + if (p->type == type) { + return p->name; + } + } + return NULL; +} + +int +ofpact_instruction_type_from_name(const char *name) +{ + const struct instruction_type_info *p; + for (p = inst_info; p < &inst_info[ARRAY_SIZE(inst_info)]; p++) { + if (!strcasecmp(name, p->name)) { + return p->type; + } + } + return -1; +} + static inline struct ofp11_instruction * instruction_next(const struct ofp11_instruction *inst) { @@ -839,14 +904,8 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow, unsigned int actions_len, struct ofpbuf *ofpacts) { - enum ofperr error; - - error = ofpacts_pull_actions(openflow, actions_len, ofpacts, - ofpacts_from_openflow11); - if (!error) { - ofpact_pad(ofpacts); - } - return error; + return ofpacts_pull_actions(openflow, actions_len, ofpacts, + ofpacts_from_openflow11); } enum ofperr @@ -897,8 +956,6 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, } } - ofpact_pad(ofpacts); - if (insts[OVSINST_OFPIT11_GOTO_TABLE] || insts[OVSINST_OFPIT11_WRITE_METADATA] || insts[OVSINST_OFPIT11_WRITE_ACTIONS] || @@ -1082,6 +1139,29 @@ ofpact_controller_to_nxast(const struct ofpact_controller *oc, nac->reason = oc->reason; } +static void +ofpact_dec_ttl_to_nxast(const struct ofpact_cnt_ids *oc_ids, + struct ofpbuf *out) +{ + if (oc_ids->ofpact.compat == OFPUTIL_NXAST_DEC_TTL) { + ofputil_put_NXAST_DEC_TTL(out); + } else { + struct nx_action_cnt_ids *nac_ids = + ofputil_put_NXAST_DEC_TTL_CNT_IDS(out); + int ids_len = ROUND_UP(2 * oc_ids->n_controllers, OFP_ACTION_ALIGN); + ovs_be16 *ids; + size_t i; + + nac_ids->len = htons(ntohs(nac_ids->len) + ids_len); + nac_ids->n_controllers = htons(oc_ids->n_controllers); + + ids = ofpbuf_put_zeros(out, ids_len); + for (i = 0; i < oc_ids->n_controllers; i++) { + ids[i] = htons(oc_ids->cnt_ids[i]); + } + } +} + static void ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout, struct ofpbuf *out) @@ -1116,7 +1196,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) break; case OFPACT_DEC_TTL: - ofputil_put_NXAST_DEC_TTL(out); + ofpact_dec_ttl_to_nxast(ofpact_get_DEC_TTL(a), out); break; case OFPACT_SET_TUNNEL: @@ -1393,15 +1473,18 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) /* Converts the ofpacts in 'ofpacts' (terminated by OFPACT_END) into OpenFlow * 1.1 actions in 'openflow', appending the actions to any existing data in * 'openflow'. */ -void +size_t ofpacts_put_openflow11_actions(const struct ofpact ofpacts[], size_t ofpacts_len, struct ofpbuf *openflow) { const struct ofpact *a; + size_t start_size = openflow->size; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { ofpact_to_openflow11(a, openflow); } + + return openflow->size - start_size; } void @@ -1508,6 +1591,25 @@ print_note(const struct ofpact_note *note, struct ds *string) } } +static void +print_dec_ttl(const struct ofpact_cnt_ids *ids, + struct ds *s) +{ + size_t i; + + ds_put_cstr(s, "dec_ttl"); + if (ids->ofpact.compat == OFPUTIL_NXAST_DEC_TTL_CNT_IDS) { + ds_put_cstr(s, "("); + for (i = 0; i < ids->n_controllers; i++) { + if (i) { + ds_put_cstr(s, ","); + } + ds_put_format(s, "%"PRIu16, ids->cnt_ids[i]); + } + ds_put_cstr(s, ")"); + } +} + static void print_fin_timeout(const struct ofpact_fin_timeout *fin_timeout, struct ds *s) @@ -1644,7 +1746,7 @@ ofpact_format(const struct ofpact *a, struct ds *s) break; case OFPACT_DEC_TTL: - ds_put_cstr(s, "dec_ttl"); + print_dec_ttl(ofpact_get_DEC_TTL(a), s); break; case OFPACT_SET_TUNNEL: