Ejemplo n.º 1
0
void
bundle_to_nxast(const struct ofpact_bundle *bundle, struct ofpbuf *openflow)
{
    int slaves_len = ROUND_UP(2 * bundle->n_slaves, OFP_ACTION_ALIGN);
    struct nx_action_bundle *nab;
    ovs_be16 *slaves;
    size_t i;

    nab = (bundle->dst.field
           ? ofputil_put_NXAST_BUNDLE_LOAD(openflow)
           : ofputil_put_NXAST_BUNDLE(openflow));
    nab->len = htons(ntohs(nab->len) + slaves_len);
    nab->algorithm = htons(bundle->algorithm);
    nab->fields = htons(bundle->fields);
    nab->basis = htons(bundle->basis);
    nab->slave_type = htonl(NXM_OF_IN_PORT);
    nab->n_slaves = htons(bundle->n_slaves);
    if (bundle->dst.field) {
        nab->ofs_nbits = nxm_encode_ofs_nbits(bundle->dst.ofs,
                                              bundle->dst.n_bits);
        nab->dst = htonl(bundle->dst.field->nxm_header);
    }

    slaves = ofpbuf_put_zeros(openflow, slaves_len);
    for (i = 0; i < bundle->n_slaves; i++) {
        slaves[i] = htons(ofp_to_u16(bundle->slaves[i]));
    }
}
Ejemplo n.º 2
0
void
multipath_parse(struct nx_action_multipath *mp, const char *s_)
{
    char *s = xstrdup(s_);
    char *save_ptr = NULL;
    char *fields, *basis, *algorithm, *n_links_str, *arg, *dst_s;
    struct mf_subfield dst;
    int n_links;

    fields = strtok_r(s, ", ", &save_ptr);
    basis = strtok_r(NULL, ", ", &save_ptr);
    algorithm = strtok_r(NULL, ", ", &save_ptr);
    n_links_str = strtok_r(NULL, ", ", &save_ptr);
    arg = strtok_r(NULL, ", ", &save_ptr);
    dst_s = strtok_r(NULL, ", ", &save_ptr);
    if (!dst_s) {
        ovs_fatal(0, "%s: not enough arguments to multipath action", s_);
    }

    ofputil_init_NXAST_MULTIPATH(mp);
    if (!strcasecmp(fields, "eth_src")) {
        mp->fields = htons(NX_HASH_FIELDS_ETH_SRC);
    } else if (!strcasecmp(fields, "symmetric_l4")) {
        mp->fields = htons(NX_HASH_FIELDS_SYMMETRIC_L4);
    } else {
        ovs_fatal(0, "%s: unknown fields `%s'", s_, fields);
    }
    mp->basis = htons(atoi(basis));
    if (!strcasecmp(algorithm, "modulo_n")) {
        mp->algorithm = htons(NX_MP_ALG_MODULO_N);
    } else if (!strcasecmp(algorithm, "hash_threshold")) {
        mp->algorithm = htons(NX_MP_ALG_HASH_THRESHOLD);
    } else if (!strcasecmp(algorithm, "hrw")) {
        mp->algorithm = htons(NX_MP_ALG_HRW);
    } else if (!strcasecmp(algorithm, "iter_hash")) {
        mp->algorithm = htons(NX_MP_ALG_ITER_HASH);
    } else {
        ovs_fatal(0, "%s: unknown algorithm `%s'", s_, algorithm);
    }
    n_links = atoi(n_links_str);
    if (n_links < 1 || n_links > 65536) {
        ovs_fatal(0, "%s: n_links %d is not in valid range 1 to 65536",
                  s_, n_links);
    }
    mp->max_link = htons(n_links - 1);
    mp->arg = htonl(atoi(arg));

    mf_parse_subfield(&dst, dst_s);
    if (dst.n_bits < 16 && n_links > (1u << dst.n_bits)) {
        ovs_fatal(0, "%s: %d-bit destination field has %u possible values, "
                  "less than specified n_links %d",
                  s_, dst.n_bits, 1u << dst.n_bits, n_links);
    }
    mp->ofs_nbits = nxm_encode_ofs_nbits(dst.ofs, dst.n_bits);
    mp->dst = htonl(dst.field->nxm_header);

    free(s);
}
Ejemplo n.º 3
0
/* Converts 'mp' into an OpenFlow NXAST_MULTIPATH action, which it appends to
 * 'openflow'. */
void
multipath_to_nxast(const struct ofpact_multipath *mp, struct ofpbuf *openflow)
{
    struct nx_action_multipath *nam = ofputil_put_NXAST_MULTIPATH(openflow);

    nam->fields = htons(mp->fields);
    nam->basis = htons(mp->basis);
    nam->algorithm = htons(mp->algorithm);
    nam->max_link = htons(mp->max_link);
    nam->arg = htonl(mp->arg);
    nam->ofs_nbits = nxm_encode_ofs_nbits(mp->dst.ofs, mp->dst.n_bits);
    nam->dst = htonl(mp->dst.field->nxm_header);
}
Ejemplo n.º 4
0
static void
parse_output(struct ofpbuf *b, char *arg)
{
    if (strchr(arg, '[')) {
        struct nx_action_output_reg *naor;
        int ofs, n_bits;
        uint32_t src;

        nxm_parse_field_bits(arg, &src, &ofs, &n_bits);

        naor = ofputil_put_NXAST_OUTPUT_REG(b);
        naor->ofs_nbits = nxm_encode_ofs_nbits(ofs, n_bits);
        naor->src = htonl(src);
        naor->max_len = htons(UINT16_MAX);
    } else {
        put_output_action(b, str_to_u32(arg));
    }
}
Ejemplo n.º 5
0
void
learn_execute(const struct nx_action_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm)
{
    const void *p, *end;
    struct ofpbuf actions;

    cls_rule_init_catchall(&fm->cr, ntohs(learn->priority));
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    fm->new_cookie = learn->cookie;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = ntohs(learn->idle_timeout);
    fm->hard_timeout = ntohs(learn->hard_timeout);
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = ntohs(learn->flags) & OFPFF_SEND_FLOW_REM;
    fm->actions = NULL;
    fm->n_actions = 0;

    ofpbuf_init(&actions, 64);

    if (learn->fin_idle_timeout || learn->fin_hard_timeout) {
        struct nx_action_fin_timeout *naft;

        naft = ofputil_put_NXAST_FIN_TIMEOUT(&actions);
        naft->fin_idle_timeout = learn->fin_idle_timeout;
        naft->fin_hard_timeout = learn->fin_hard_timeout;
    }

    for (p = learn + 1, end = (char *) learn + ntohs(learn->len); p != end; ) {
        uint16_t header = ntohs(get_be16(&p));
        int n_bits = header & NX_LEARN_N_BITS_MASK;
        int src_type = header & NX_LEARN_SRC_MASK;
        int dst_type = header & NX_LEARN_DST_MASK;
        union mf_subvalue value;

        struct mf_subfield dst;
        int chunk, ofs;

        if (!header) {
            break;
        }

        if (src_type == NX_LEARN_SRC_FIELD) {
            struct mf_subfield src;

            get_subfield(n_bits, &p, &src);
            mf_read_subfield(&src, flow, &value);
        } else {
            int p_bytes = 2 * DIV_ROUND_UP(n_bits, 16);

            memset(&value, 0, sizeof value);
            bitwise_copy(p, p_bytes, 0,
                         &value, sizeof value, 0,
                         n_bits);
            p = (const uint8_t *) p + p_bytes;
        }

        switch (dst_type) {
        case NX_LEARN_DST_MATCH:
            get_subfield(n_bits, &p, &dst);
            mf_write_subfield(&dst, &value, &fm->cr);
            break;

        case NX_LEARN_DST_LOAD:
            get_subfield(n_bits, &p, &dst);
            for (ofs = 0; ofs < n_bits; ofs += chunk) {
                struct nx_action_reg_load *load;

                chunk = MIN(n_bits - ofs, 64);

                load = ofputil_put_NXAST_REG_LOAD(&actions);
                load->ofs_nbits = nxm_encode_ofs_nbits(dst.ofs + ofs, chunk);
                load->dst = htonl(dst.field->nxm_header);
                bitwise_copy(&value, sizeof value, ofs,
                             &load->value, sizeof load->value, 0,
                             chunk);
            }
            break;

        case NX_LEARN_DST_OUTPUT:
            if (n_bits <= 16 || is_all_zeros(value.u8, sizeof value - 2)) {
                ofputil_put_OFPAT10_OUTPUT(&actions)->port = value.be16[7];
            }
            break;
        }
    }

    fm->actions = ofpbuf_steal_data(&actions);
    fm->n_actions = actions.size / sizeof(struct ofp_action_header);
}
Ejemplo n.º 6
0
/* Helper for bundle_parse and bundle_parse_load. */
static void
bundle_parse__(struct ofpbuf *b, const char *s, char **save_ptr,
               const char *fields, const char *basis, const char *algorithm,
               const char *slave_type, const char *dst,
               const char *slave_delim)
{
    enum ofputil_action_code code;
    struct nx_action_bundle *nab;
    uint16_t n_slaves;

    if (!slave_delim) {
        ovs_fatal(0, "%s: not enough arguments to bundle action", s);
    }

    if (strcasecmp(slave_delim, "slaves")) {
        ovs_fatal(0, "%s: missing slave delimiter, expected `slaves' got `%s'",
                   s, slave_delim);
    }

    code = dst ? OFPUTIL_NXAST_BUNDLE_LOAD : OFPUTIL_NXAST_BUNDLE;
    b->l2 = ofputil_put_action(code, b);

    n_slaves = 0;
    for (;;) {
        ovs_be16 slave_be;
        char *slave;

        slave = strtok_r(NULL, ", ", save_ptr);
        if (!slave || n_slaves >= BUNDLE_MAX_SLAVES) {
            break;
        }

        slave_be = htons(atoi(slave));
        ofpbuf_put(b, &slave_be, sizeof slave_be);

        n_slaves++;
    }

    /* Slaves array must be multiple of 8 bytes long. */
    if (b->size % 8) {
        ofpbuf_put_zeros(b, 8 - (b->size % 8));
    }

    nab = b->l2;
    nab->len = htons(b->size - ((char *) b->l2 - (char *) b->data));
    nab->n_slaves = htons(n_slaves);
    nab->basis = htons(atoi(basis));

    if (!strcasecmp(fields, "eth_src")) {
        nab->fields = htons(NX_HASH_FIELDS_ETH_SRC);
    } else if (!strcasecmp(fields, "symmetric_l4")) {
        nab->fields = htons(NX_HASH_FIELDS_SYMMETRIC_L4);
    } else {
        ovs_fatal(0, "%s: unknown fields `%s'", s, fields);
    }

    if (!strcasecmp(algorithm, "active_backup")) {
        nab->algorithm = htons(NX_BD_ALG_ACTIVE_BACKUP);
    } else if (!strcasecmp(algorithm, "hrw")) {
        nab->algorithm = htons(NX_BD_ALG_HRW);
    } else {
        ovs_fatal(0, "%s: unknown algorithm `%s'", s, algorithm);
    }

    if (!strcasecmp(slave_type, "ofport")) {
        nab->slave_type = htonl(NXM_OF_IN_PORT);
    } else {
        ovs_fatal(0, "%s: unknown slave_type `%s'", s, slave_type);
    }

    if (dst) {
        uint32_t reg;
        int ofs, n_bits;

        nxm_parse_field_bits(dst, &reg, &ofs, &n_bits);

        nab->dst = htonl(reg);
        nab->ofs_nbits = nxm_encode_ofs_nbits(ofs, n_bits);
    }

    b->l2 = NULL;
}
void
learn_execute(const struct nx_action_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm)
{
    const void *p, *end;
    struct ofpbuf actions;

    cls_rule_init_catchall(&fm->cr, ntohs(learn->priority));
    fm->cookie = learn->cookie;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = ntohs(learn->idle_timeout);
    fm->hard_timeout = ntohs(learn->hard_timeout);
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = ntohs(learn->flags) & OFPFF_SEND_FLOW_REM;
    fm->actions = NULL;
    fm->n_actions = 0;

    ofpbuf_init(&actions, 64);

    for (p = learn + 1, end = (char *) learn + ntohs(learn->len); p != end; ) {
        uint16_t header = ntohs(get_be16(&p));
        int n_bits = header & NX_LEARN_N_BITS_MASK;
        int src_type = header & NX_LEARN_SRC_MASK;
        int dst_type = header & NX_LEARN_DST_MASK;
        uint64_t value;

        struct nx_action_reg_load *load;
        ovs_be32 dst_field;
        int dst_ofs;

        if (!header) {
            break;
        }

        if (src_type == NX_LEARN_SRC_FIELD) {
            ovs_be32 src_field = get_be32(&p);
            int src_ofs = ntohs(get_be16(&p));

            value = nxm_read_field_bits(src_field,
                                        nxm_encode_ofs_nbits(src_ofs, n_bits),
                                        flow);
        } else {
            value = get_bits(n_bits, &p);
        }

        switch (dst_type) {
        case NX_LEARN_DST_MATCH:
            dst_field = get_be32(&p);
            dst_ofs = ntohs(get_be16(&p));
            mf_set_subfield(mf_from_nxm_header(ntohl(dst_field)), value,
                            dst_ofs, n_bits, &fm->cr);
            break;

        case NX_LEARN_DST_LOAD:
            dst_field = get_be32(&p);
            dst_ofs = ntohs(get_be16(&p));
            load = ofputil_put_NXAST_REG_LOAD(&actions);
            load->ofs_nbits = nxm_encode_ofs_nbits(dst_ofs, n_bits);
            load->dst = dst_field;
            load->value = htonll(value);
            break;

        case NX_LEARN_DST_OUTPUT:
            ofputil_put_OFPAT_OUTPUT(&actions)->port = htons(value);
            break;
        }
    }

    fm->actions = ofpbuf_steal_data(&actions);
    fm->n_actions = actions.size / sizeof(struct ofp_action_header);
}