X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=518bbdd39f5bef3114a1f0907beba54a6232711b;hb=81a76618be9ea195a1e4a881ba9591728891d10b;hp=6236e5006a4f561678da890c944bb18eb4469ac6;hpb=f25d0cf3c366d92042269a4f787f19c741c2530c;p=sliver-openvswitch.git diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 6236e5006..518bbdd39 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -278,6 +278,41 @@ parse_controller(struct ofpbuf *b, char *arg) } } +static void +parse_dec_ttl(struct ofpbuf *b, char *arg) +{ + struct ofpact_cnt_ids *ids; + + ids = ofpact_put_DEC_TTL(b); + + if (*arg == '\0') { + uint16_t id = 0; + + ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL; + ofpbuf_put(b, &id, sizeof id); + ids = b->l2; + ids->n_controllers++; + } else { + char *cntr; + + ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS; + for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL; + cntr = strtok_r(NULL, ", ", &arg)) { + uint16_t id = atoi(cntr); + + ofpbuf_put(b, &id, sizeof id); + ids = b->l2; + ids->n_controllers++; + } + if (!ids->n_controllers) { + ovs_fatal(0, "dec_ttl_cnt_ids: expected at least one controller " + "id."); + } + + } + ofpact_update_len(b, &ids->ofpact); +} + static void parse_named_action(enum ofputil_action_code code, const struct flow *flow, char *arg, struct ofpbuf *ofpacts) @@ -293,10 +328,12 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, NOT_REACHED(); case OFPUTIL_OFPAT10_OUTPUT: + case OFPUTIL_OFPAT11_OUTPUT: parse_output(arg, ofpacts); break; case OFPUTIL_OFPAT10_SET_VLAN_VID: + case OFPUTIL_OFPAT11_SET_VLAN_VID: vid = str_to_u32(arg); if (vid & ~VLAN_VID_MASK) { ovs_fatal(0, "%s: not a valid VLAN VID", arg); @@ -305,6 +342,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_OFPAT10_SET_VLAN_PCP: + case OFPUTIL_OFPAT11_SET_VLAN_PCP: pcp = str_to_u32(arg); if (pcp & ~7) { ovs_fatal(0, "%s: not a valid VLAN PCP", arg); @@ -317,24 +355,29 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_OFPAT10_SET_DL_SRC: + case OFPUTIL_OFPAT11_SET_DL_SRC: str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac); break; case OFPUTIL_OFPAT10_SET_DL_DST: + case OFPUTIL_OFPAT11_SET_DL_DST: str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac); break; case OFPUTIL_OFPAT10_SET_NW_SRC: + case OFPUTIL_OFPAT11_SET_NW_SRC: str_to_ip(arg, &ip); ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip; break; case OFPUTIL_OFPAT10_SET_NW_DST: + case OFPUTIL_OFPAT11_SET_NW_DST: str_to_ip(arg, &ip); ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip; break; case OFPUTIL_OFPAT10_SET_NW_TOS: + case OFPUTIL_OFPAT11_SET_NW_TOS: tos = str_to_u32(arg); if (tos & ~IP_DSCP_MASK) { ovs_fatal(0, "%s: not a valid TOS", arg); @@ -343,10 +386,12 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_OFPAT10_SET_TP_SRC: + case OFPUTIL_OFPAT11_SET_TP_SRC: ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg); break; case OFPUTIL_OFPAT10_SET_TP_DST: + case OFPUTIL_OFPAT11_SET_TP_DST: ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg); break; @@ -389,7 +434,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg); break; - case OFPUTIL_NXAST_AUTOPATH: + case OFPUTIL_NXAST_AUTOPATH__DEPRECATED: autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg); break; @@ -403,6 +448,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, case OFPUTIL_NXAST_RESUBMIT_TABLE: case OFPUTIL_NXAST_OUTPUT_REG: + case OFPUTIL_NXAST_DEC_TTL_CNT_IDS: NOT_REACHED(); case OFPUTIL_NXAST_LEARN: @@ -414,7 +460,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_NXAST_DEC_TTL: - ofpact_put_DEC_TTL(ofpacts); + parse_dec_ttl(ofpacts, arg); break; case OFPUTIL_NXAST_FIN_TIMEOUT: @@ -508,7 +554,7 @@ ofp_fatal(const char *flow, bool verbose, const char *format, ...) } static void -parse_field(const struct mf_field *mf, const char *s, struct cls_rule *rule) +parse_field(const struct mf_field *mf, const char *s, struct match *match) { union mf_value value, mask; char *error; @@ -518,7 +564,7 @@ parse_field(const struct mf_field *mf, const char *s, struct cls_rule *rule) ovs_fatal(0, "%s", error); } - mf_set(mf, &value, &mask, rule); + mf_set(mf, &value, &mask, match); } /* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man @@ -574,7 +620,8 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, NOT_REACHED(); } - cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY); + match_init_catchall(&fm->match); + fm->priority = OFP_DEFAULT_PRIORITY; fm->cookie = htonll(0); fm->cookie_mask = htonll(0); if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) { @@ -609,9 +656,9 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, const struct protocol *p; if (parse_protocol(name, &p)) { - cls_rule_set_dl_type(&fm->cr, htons(p->dl_type)); + match_set_dl_type(&fm->match, htons(p->dl_type)); if (p->nw_proto) { - cls_rule_set_nw_proto(&fm->cr, p->nw_proto); + match_set_nw_proto(&fm->match, p->nw_proto); } } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) { fm->flags |= OFPFF_SEND_FLOW_REM; @@ -630,7 +677,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, } else if (!strcmp(name, "out_port")) { fm->out_port = atoi(value); } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { - fm->cr.priority = str_to_u16(value, name); + fm->priority = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { fm->idle_timeout = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { @@ -656,7 +703,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, fm->new_cookie = htonll(str_to_u64(value)); } } else if (mf_from_name(name)) { - parse_field(mf_from_name(name), value, &fm->cr); + parse_field(mf_from_name(name), value, &fm->match); } else if (!strcmp(name, "duration") || !strcmp(name, "n_packets") || !strcmp(name, "n_bytes")) { @@ -679,7 +726,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, struct ofpbuf ofpacts; ofpbuf_init(&ofpacts, 32); - str_to_ofpacts(&fm->cr.flow, act_str, &ofpacts); + str_to_ofpacts(&fm->match.flow, act_str, &ofpacts); fm->ofpacts_len = ofpacts.size; fm->ofpacts = ofpbuf_steal_data(&ofpacts); } else { @@ -690,6 +737,68 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, free(string); } +/* Convert 'str_' (as described in the documentation for the "monitor" command + * in the ovs-ofctl man page) into 'fmr'. */ +void +parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, + const char *str_) +{ + static uint32_t id; + + char *string = xstrdup(str_); + char *save_ptr = NULL; + char *name; + + fmr->id = id++; + fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY + | NXFMF_OWN | NXFMF_ACTIONS); + fmr->out_port = OFPP_NONE; + fmr->table_id = 0xff; + match_init_catchall(&fmr->match); + + for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; + name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { + const struct protocol *p; + + if (!strcmp(name, "!initial")) { + fmr->flags &= ~NXFMF_INITIAL; + } else if (!strcmp(name, "!add")) { + fmr->flags &= ~NXFMF_ADD; + } else if (!strcmp(name, "!delete")) { + fmr->flags &= ~NXFMF_DELETE; + } else if (!strcmp(name, "!modify")) { + fmr->flags &= ~NXFMF_MODIFY; + } else if (!strcmp(name, "!actions")) { + fmr->flags &= ~NXFMF_ACTIONS; + } else if (!strcmp(name, "!own")) { + fmr->flags &= ~NXFMF_OWN; + } else if (parse_protocol(name, &p)) { + match_set_dl_type(&fmr->match, htons(p->dl_type)); + if (p->nw_proto) { + match_set_nw_proto(&fmr->match, p->nw_proto); + } + } else { + char *value; + + value = strtok_r(NULL, ", \t\r\n", &save_ptr); + if (!value) { + ovs_fatal(0, "%s: field %s missing value", str_, name); + } + + if (!strcmp(name, "table")) { + fmr->table_id = str_to_table_id(value); + } else if (!strcmp(name, "out_port")) { + fmr->out_port = atoi(value); + } else if (mf_from_name(name)) { + parse_field(mf_from_name(name), value, &fmr->match); + } else { + ovs_fatal(0, "%s: unknown keyword %s", str_, name); + } + } + } + free(string); +} + /* Parses 's' as a set of OpenFlow actions and appends the actions to * 'actions'. * @@ -709,15 +818,15 @@ void parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string, uint16_t command, bool verbose) { - struct cls_rule rule_copy; + struct match match_copy; parse_ofp_str(fm, command, string, verbose); - /* Normalize a copy of the rule. This ensures that non-normalized flows + /* Normalize a copy of the match. This ensures that non-normalized flows * get logged but doesn't affect what gets sent to the switch, so that the * switch can do whatever it likes with the flow. */ - rule_copy = fm->cr; - ofputil_normalize_rule(&rule_copy); + match_copy = fm->match; + ofputil_normalize_match(&match_copy); } void @@ -759,7 +868,7 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, fsr->aggregate = aggregate; fsr->cookie = fm.cookie; fsr->cookie_mask = fm.cookie_mask; - fsr->match = fm.cr; + fsr->match = fm.match; fsr->out_port = fm.out_port; fsr->table_id = fm.table_id; }