Esempio n. 1
0
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;
    struct in6_addr ipv6, ipv6_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 F_ARP_SHA:
        str_to_mac(value, mac);
        cls_rule_set_arp_sha(rule, mac);
        break;

    case F_ARP_THA:
        str_to_mac(value, mac);
        cls_rule_set_arp_tha(rule, mac);
        break;

    case F_IPV6_SRC:
        str_to_ipv6(value, &ipv6, &ipv6_mask);
        cls_rule_set_ipv6_src_masked(rule, &ipv6, &ipv6_mask);
        break;

    case F_IPV6_DST:
        str_to_ipv6(value, &ipv6, &ipv6_mask);
        cls_rule_set_ipv6_dst_masked(rule, &ipv6, &ipv6_mask);
        break;

    case F_ND_TARGET:
        str_to_ipv6(value, &ipv6, NULL);
        cls_rule_set_nd_target(rule, ipv6);
        break;

    case F_ND_SLL:
        str_to_mac(value, mac);
        cls_rule_set_arp_sha(rule, mac);
        break;

    case F_ND_TLL:
        str_to_mac(value, mac);
        cls_rule_set_arp_tha(rule, mac);
        break;

    case N_FIELDS:
        NOT_REACHED();
    }
}
Esempio n. 2
0
/* 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. */
void
parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
              struct ofpbuf *actions, char *string)
{
    char *save_ptr = NULL;
    char *name;

    if (table_idx) {
        *table_idx = 0xff;
    }
    cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
    fm->cookie = htonll(0);
    fm->command = UINT16_MAX;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (actions) {
        char *act_str = strstr(string, "action");
        if (!act_str) {
            ovs_fatal(0, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ovs_fatal(0, "must specify an action");
        }

        act_str++;

        str_to_action(act_str, actions);
        fm->actions = actions->data;
        fm->n_actions = actions->size / sizeof(union ofp_action);
    } else {
        fm->actions = NULL;
        fm->n_actions = 0;
    }
    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 (parse_protocol(name, &p)) {
            cls_rule_set_dl_type(&fm->cr, htons(p->dl_type));
            if (p->nw_proto) {
                cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
            }
        } else {
            const struct field *f;
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ovs_fatal(0, "field %s missing value", name);
            }

            if (table_idx && !strcmp(name, "table")) {
                *table_idx = atoi(value);
            } else if (!strcmp(name, "out_port")) {
                fm->out_port = atoi(value);
            } else if (!strcmp(name, "priority")) {
                fm->cr.priority = atoi(value);
            } else if (!strcmp(name, "idle_timeout")) {
                fm->idle_timeout = atoi(value);
            } else if (!strcmp(name, "hard_timeout")) {
                fm->hard_timeout = atoi(value);
            } else if (!strcmp(name, "cookie")) {
                fm->cookie = htonll(str_to_u64(value));
            } else if (parse_field_name(name, &f)) {
                if (!strcmp(value, "*") || !strcmp(value, "ANY")) {
                    if (f->wildcard) {
                        fm->cr.wc.wildcards |= f->wildcard;
                        cls_rule_zero_wildcarded_fields(&fm->cr);
                    } else if (f->index == F_NW_SRC) {
                        cls_rule_set_nw_src_masked(&fm->cr, 0, 0);
                    } else if (f->index == F_NW_DST) {
                        cls_rule_set_nw_dst_masked(&fm->cr, 0, 0);
                    } else if (f->index == F_IPV6_SRC) {
                        cls_rule_set_ipv6_src_masked(&fm->cr,
                                &in6addr_any, &in6addr_any);
                    } else if (f->index == F_IPV6_DST) {
                        cls_rule_set_ipv6_dst_masked(&fm->cr,
                                &in6addr_any, &in6addr_any);
                    } else if (f->index == F_DL_VLAN) {
                        cls_rule_set_any_vid(&fm->cr);
                    } else if (f->index == F_DL_VLAN_PCP) {
                        cls_rule_set_any_pcp(&fm->cr);
                    } else {
                        NOT_REACHED();
                    }
                } else {
                    parse_field_value(&fm->cr, f->index, value);
                }
            } else if (!strncmp(name, "reg", 3)
                       && isdigit((unsigned char) name[3])) {
                unsigned int reg_idx = atoi(name + 3);
                if (reg_idx >= FLOW_N_REGS) {
                    ovs_fatal(0, "only %d registers supported", FLOW_N_REGS);
                }
                parse_reg_value(&fm->cr, reg_idx, value);
            } else {
                ovs_fatal(0, "unknown keyword %s", name);
            }
        }
    }
}
Esempio n. 3
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
 * If 'actions' is specified, an action must be in 'string' and may be expanded
 * or reallocated.
 *
 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
 * constant for 'command'.  To parse syntax for an OFPST_FLOW or
 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
void
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
              bool verbose)
{
    enum {
        F_OUT_PORT = 1 << 0,
        F_ACTIONS = 1 << 1,
        F_TIMEOUT = 1 << 3,
        F_PRIORITY = 1 << 4
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *act_str = NULL;
    char *name;

    switch (command) {
    case -1:
        fields = F_OUT_PORT;
        break;

    case OFPFC_ADD:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY;
        break;

    case OFPFC_DELETE:
        fields = F_OUT_PORT;
        break;

    case OFPFC_DELETE_STRICT:
        fields = F_OUT_PORT | F_PRIORITY;
        break;

    case OFPFC_MODIFY:
        fields = F_ACTIONS;
        break;

    case OFPFC_MODIFY_STRICT:
        fields = F_ACTIONS | F_PRIORITY;
        break;

    default:
        NOT_REACHED();
    }

    cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
        /* For modify, by default, don't update the cookie. */
        fm->new_cookie = htonll(UINT64_MAX);
    } else{
        fm->new_cookie = htonll(0);
    }
    fm->table_id = 0xff;
    fm->command = command;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (fields & F_ACTIONS) {
        act_str = strstr(string, "action");
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }

        act_str++;
    }
    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 (parse_protocol(name, &p)) {
            cls_rule_set_dl_type(&fm->cr, htons(p->dl_type));
            if (p->nw_proto) {
                cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
            }
        } else {
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ofp_fatal(str_, verbose, "field %s missing value", name);
            }

            if (!strcmp(name, "table")) {
                fm->table_id = str_to_table_id(value);
            } 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);
            } 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")) {
                fm->hard_timeout = str_to_u16(value, name);
            } else if (!strcmp(name, "cookie")) {
                char *mask = strchr(value, '/');

                if (mask) {
                    /* A mask means we're searching for a cookie. */
                    if (command == OFPFC_ADD) {
                        ofp_fatal(str_, verbose, "flow additions cannot use "
                                  "a cookie mask");
                    }
                    *mask = '\0';
                    fm->cookie = htonll(str_to_u64(value));
                    fm->cookie_mask = htonll(str_to_u64(mask+1));
                } else {
                    /* No mask means that the cookie is being set. */
                    if (command != OFPFC_ADD && command != OFPFC_MODIFY
                            && command != OFPFC_MODIFY_STRICT) {
                        ofp_fatal(str_, verbose, "cannot set cookie");
                    }
                    fm->new_cookie = htonll(str_to_u64(value));
                }
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fm->cr);
            } else if (!strcmp(name, "duration")
                       || !strcmp(name, "n_packets")
                       || !strcmp(name, "n_bytes")) {
                /* Ignore these, so that users can feed the output of
                 * "ovs-ofctl dump-flows" back into commands that parse
                 * flows. */
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
            && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
        /* On modifies without a mask, we are supposed to add a flow if
         * one does not exist.  If a cookie wasn't been specified, use a
         * default of zero. */
        fm->new_cookie = htonll(0);
    }
    if (fields & F_ACTIONS) {
        struct ofpbuf actions;

        ofpbuf_init(&actions, sizeof(union ofp_action));
        str_to_action(&fm->cr.flow, act_str, &actions);
        fm->actions = ofpbuf_steal_data(&actions);
        fm->n_actions = actions.size / sizeof(union ofp_action);
    } else {
        fm->actions = NULL;
        fm->n_actions = 0;
    }

    free(string);
}