ofpacts_parse__(char *str, const struct ofpact_parse_params *pp,
                bool allow_instructions, enum ofpact_type outer_action)
{
    char *key, *value;
    bool drop = false;
    char *pos;

    pos = str;
    while (ofputil_parse_key_value(&pos, &key, &value)) {
        enum ofpact_type type;
        char *error = NULL;
        ofp_port_t port;
        if (ofpact_type_from_name(key, &type)) {
            error = ofpact_parse(type, value, pp);

            if (type == OFPACT_METER && !allow_instructions) {
                /* Meter is an action in OF1.5 and it's being used in a
                 * context where instructions aren't allowed.  Therefore,
                 * this must be OF1.5+. */
                *pp->usable_protocols &= OFPUTIL_P_OF15_UP;
            }
        } else if (!strcasecmp(key, "mod_vlan_vid")) {
            error = parse_set_vlan_vid(value, true, pp);
        } else if (!strcasecmp(key, "mod_vlan_pcp")) {
            error = parse_set_vlan_pcp(value, true, pp);
        } else if (!strcasecmp(key, "set_nw_ttl")) {
            error = parse_SET_IP_TTL(value, pp);
        } else if (!strcasecmp(key, "pop_vlan")) {
            error = parse_pop_vlan(pp);
        } else if (!strcasecmp(key, "set_tunnel64")) {
            error = parse_set_tunnel(value, NXAST_RAW_SET_TUNNEL64, pp);
        } else if (!strcasecmp(key, "load")) {
            error = parse_reg_load(value, pp);
        } else if (!strcasecmp(key, "bundle_load")) {
            error = parse_bundle_load(value, pp);
        } else if (!strcasecmp(key, "drop")) {
            drop = true;
        } else if (!strcasecmp(key, "apply_actions")) {
            return xstrdup("apply_actions is the default instruction");
        } else if (ofputil_port_from_string(key, pp->port_map, &port)) {
            ofpact_put_OUTPUT(pp->ofpacts)->port = port;
        } else {
            return xasprintf("unknown action %s", key);
        }
        if (error) {
            return error;
        }
    }

    if (drop && pp->ofpacts->size) {
        return xstrdup("\"drop\" must not be accompanied by any other action "
                       "or instruction");
    }

    char *error = NULL;
    ofpacts_verify(pp->ofpacts->data, pp->ofpacts->size, OFP11_VERSION,
                   (allow_instructions
                    ? (1u << N_OVS_INSTRUCTIONS) - 1
                    : ((1u << OVSINST_OFPIT11_APPLY_ACTIONS)
                       | (1u << OVSINST_OFPIT13_METER))),
                   outer_action, &error);
    if (error) {
        return error;
    }

    return NULL;
}
ofpacts_parse__(char *str, const struct ofpact_parse_params *pp,
                bool allow_instructions, enum ofpact_type outer_action)
{
    char *key, *value;
    bool drop = false;
    char *pos;

    pos = str;
    while (ofputil_parse_key_value(&pos, &key, &value)) {
        enum ofpact_type type;
        char *error = NULL;
        ofp_port_t port;
        if (ofpact_type_from_name(key, &type)) {
            error = ofpact_parse(type, value, pp);

            if (type == OFPACT_METER && !allow_instructions) {
                 
                *pp->usable_protocols &= OFPUTIL_P_OF15_UP;
            }
        } else if (!strcasecmp(key, "mod_vlan_vid")) {
            error = parse_set_vlan_vid(value, true, pp);
        } else if (!strcasecmp(key, "mod_vlan_pcp")) {
            error = parse_set_vlan_pcp(value, true, pp);
        } else if (!strcasecmp(key, "set_nw_ttl")) {
            error = parse_SET_IP_TTL(value, pp);
        } else if (!strcasecmp(key, "pop_vlan")) {
            error = parse_pop_vlan(pp);
        } else if (!strcasecmp(key, "set_tunnel64")) {
            error = parse_set_tunnel(value, NXAST_RAW_SET_TUNNEL64, pp);
        } else if (!strcasecmp(key, "load")) {
            error = parse_reg_load(value, pp);
        } else if (!strcasecmp(key, "bundle_load")) {
            error = parse_bundle_load(value, pp);
        } else if (!strcasecmp(key, "drop")) {
            drop = true;
        } else if (!strcasecmp(key, "apply_actions")) {
            return xstrdup("apply_actions is the default instruction");
        } else if (ofputil_port_from_string(key, pp->port_map, &port)) {
            ofpact_put_OUTPUT(pp->ofpacts)->port = port;
        } else {
            return xasprintf("unknown action %s", key);
        }
        if (error) {
            return error;
        }
    }

    if (drop && pp->ofpacts->size) {
        return xstrdup("\"drop\" must not be accompanied by any other action "
                       "or instruction");
    }

    char *error = NULL;
    ofpacts_verify(pp->ofpacts->data, pp->ofpacts->size, OFP11_VERSION,
                   (allow_instructions
                    ? (1u << N_OVS_INSTRUCTIONS) - 1
                    : ((1u << OVSINST_OFPIT11_APPLY_ACTIONS)
                       | (1u << OVSINST_OFPIT13_METER))),
                   outer_action, &error);
    if (error) {
        return error;
    }

    return NULL;
}