-/* Convert 'string' (as described in the Flow Syntax section of the
- * ovs-ofctl man page) into 'match'. The other arguments are optional
- * and may be NULL if their value is not needed. If 'actions' is
- * specified, an action must be in 'string' and may be expanded or
- * reallocated. */
-void
-parse_ofp_str(char *string, struct ofp_match *match, struct ofpbuf *actions,
- uint8_t *table_idx, uint16_t *out_port, uint16_t *priority,
- uint16_t *idle_timeout, uint16_t *hard_timeout,
- uint64_t *cookie)
+static void
+parse_field_value(struct cls_rule *rule, enum field_index index,
+ const char *value)
+{
+ uint8_t mac[ETH_ADDR_LEN];
+ ovs_be64 tun_id, tun_mask;
+ ovs_be32 ip, mask;
+ uint16_t port_no;
+
+ switch (index) {
+ case F_TUN_ID:
+ str_to_tun_id(value, &tun_id, &tun_mask);
+ cls_rule_set_tun_id_masked(rule, tun_id, tun_mask);
+ break;
+
+ case F_IN_PORT:
+ if (!parse_port_name(value, &port_no)) {
+ port_no = atoi(value);
+ }
+ if (port_no == OFPP_LOCAL) {
+ port_no = ODPP_LOCAL;
+ }
+ cls_rule_set_in_port(rule, port_no);
+ break;
+
+ case F_DL_VLAN:
+ cls_rule_set_dl_vlan(rule, htons(str_to_u32(value)));
+ break;
+
+ case F_DL_VLAN_PCP:
+ cls_rule_set_dl_vlan_pcp(rule, str_to_u32(value));
+ break;
+
+ case F_DL_SRC:
+ str_to_mac(value, mac);
+ cls_rule_set_dl_src(rule, mac);
+ break;
+
+ case F_DL_DST:
+ str_to_mac(value, mac);
+ cls_rule_set_dl_dst(rule, mac);
+ break;
+
+ case F_DL_TYPE:
+ cls_rule_set_dl_type(rule, htons(str_to_u32(value)));
+ break;
+
+ case F_NW_SRC:
+ str_to_ip(value, &ip, &mask);
+ cls_rule_set_nw_src_masked(rule, ip, mask);
+ break;
+
+ case F_NW_DST:
+ str_to_ip(value, &ip, &mask);
+ cls_rule_set_nw_dst_masked(rule, ip, mask);
+ break;
+
+ case F_NW_PROTO:
+ cls_rule_set_nw_proto(rule, str_to_u32(value));
+ break;
+
+ case F_NW_TOS:
+ cls_rule_set_nw_tos(rule, str_to_u32(value));
+ break;
+
+ case F_TP_SRC:
+ cls_rule_set_tp_src(rule, htons(str_to_u32(value)));
+ break;
+
+ case F_TP_DST:
+ cls_rule_set_tp_dst(rule, htons(str_to_u32(value)));
+ break;
+
+ case F_ICMP_TYPE:
+ cls_rule_set_icmp_type(rule, str_to_u32(value));
+ break;
+
+ case F_ICMP_CODE:
+ cls_rule_set_icmp_code(rule, str_to_u32(value));
+ break;
+
+ case N_FIELDS:
+ NOT_REACHED();
+ }
+}
+
+static void
+parse_reg_value(struct cls_rule *rule, int reg_idx, const char *value)
+{
+ uint32_t reg_value, reg_mask;
+
+ if (!strcmp(value, "ANY") || !strcmp(value, "*")) {
+ cls_rule_set_reg_masked(rule, reg_idx, 0, 0);
+ } else if (sscanf(value, "%"SCNi32"/%"SCNi32,
+ ®_value, ®_mask) == 2) {
+ cls_rule_set_reg_masked(rule, reg_idx, reg_value, reg_mask);
+ } else if (sscanf(value, "%"SCNi32, ®_value)) {
+ cls_rule_set_reg(rule, reg_idx, reg_value);
+ } else {
+ ovs_fatal(0, "register fields must take the form <value> "
+ "or <value>/<mask>");
+ }
+}
+
+/* Convert 'string' (as described in the Flow Syntax section of the ovs-ofctl
+ * man page) into 'pf'. If 'actions' is specified, an action must be in
+ * 'string' and may be expanded or reallocated. */
+static void
+parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
+ struct ofpbuf *actions, char *string)