/*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*reg = (*reg & ~(mask << ofs)) | (link << ofs);
}
-static uint32_t
-hash_symmetric_l4(const struct flow *flow, uint16_t basis)
-{
- struct {
- ovs_be32 ip_addr;
- ovs_be16 eth_type;
- ovs_be16 vlan_tci;
- ovs_be16 tp_addr;
- uint8_t eth_addr[ETH_ADDR_LEN];
- uint8_t ip_proto;
- } fields;
-
- int i;
-
- memset(&fields, 0, sizeof fields);
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- fields.eth_addr[i] = flow->dl_src[i] ^ flow->dl_dst[i];
- }
- fields.vlan_tci = flow->vlan_tci & htons(VLAN_VID_MASK);
- fields.eth_type = flow->dl_type;
- if (fields.eth_type == htons(ETH_TYPE_IP)) {
- fields.ip_addr = flow->nw_src ^ flow->nw_dst;
- fields.ip_proto = flow->nw_proto;
- if (fields.ip_proto == IP_TYPE_TCP || fields.ip_proto == IP_TYPE_UDP) {
- fields.tp_addr = flow->tp_src ^ flow->tp_dst;
- } else {
- fields.tp_addr = htons(0);
- }
- } else {
- fields.ip_addr = htonl(0);
- fields.ip_proto = 0;
- fields.tp_addr = htons(0);
- }
- return hash_bytes(&fields, sizeof fields, basis);
-}
-
static uint32_t
multipath_hash(const struct flow *flow, enum nx_mp_fields fields,
uint16_t basis)
return hash_bytes(flow->dl_src, sizeof flow->dl_src, basis);
case NX_MP_FIELDS_SYMMETRIC_L4:
- return hash_symmetric_l4(flow, basis);
+ return flow_hash_symmetric_l4(flow, basis);
}
NOT_REACHED();
return hash % n_links;
case NX_MP_ALG_HASH_THRESHOLD:
- return hash / (UINT32_MAX / n_links);
+ if (n_links == 1) {
+ return 0;
+ }
+ return hash / (UINT32_MAX / n_links + 1);
case NX_MP_ALG_HRW:
return (n_links <= 64
{
char *s = xstrdup(s_);
char *save_ptr = NULL;
- char *fields, *basis, *algorithm, *n_links, *arg, *dst;
+ char *fields, *basis, *algorithm, *n_links_str, *arg, *dst;
uint32_t header;
int ofs, n_bits;
+ int n_links;
fields = strtok_r(s, ", ", &save_ptr);
basis = strtok_r(NULL, ", ", &save_ptr);
algorithm = strtok_r(NULL, ", ", &save_ptr);
- n_links = strtok_r(NULL, ", ", &save_ptr);
+ n_links_str = strtok_r(NULL, ", ", &save_ptr);
arg = strtok_r(NULL, ", ", &save_ptr);
dst = strtok_r(NULL, ", ", &save_ptr);
if (!dst) {
- ovs_fatal(0, "%s: not enough arguments to multipath action", s);
+ ovs_fatal(0, "%s: not enough arguments to multipath action", s_);
}
memset(mp, 0, sizeof *mp);
} else if (!strcasecmp(fields, "symmetric_l4")) {
mp->fields = htons(NX_MP_FIELDS_SYMMETRIC_L4);
} else {
- ovs_fatal(0, "%s: unknown fields `%s'", s, fields);
+ ovs_fatal(0, "%s: unknown fields `%s'", s_, fields);
}
mp->basis = htons(atoi(basis));
if (!strcasecmp(algorithm, "modulo_n")) {
} else if (!strcasecmp(algorithm, "iter_hash")) {
mp->algorithm = htons(NX_MP_ALG_ITER_HASH);
} else {
- ovs_fatal(0, "%s: unknown algorithm `%s'", s, algorithm);
+ ovs_fatal(0, "%s: unknown algorithm `%s'", s_, algorithm);
}
- mp->max_link = htons(atoi(n_links) - 1);
+ 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));
nxm_parse_field_bits(dst, &header, &ofs, &n_bits);
+ if (!NXM_IS_NX_REG(header) || NXM_NX_REG_IDX(header) >= FLOW_N_REGS) {
+ ovs_fatal(0, "%s: destination field must be register", s_);
+ }
+ if (n_bits < 16 && n_links > (1u << n_bits)) {
+ ovs_fatal(0, "%s: %d-bit destination field has %u possible values, "
+ "less than specified n_links %d",
+ s_, n_bits, 1u << n_bits, n_links);
+ }
mp->ofs_nbits = nxm_encode_ofs_nbits(ofs, n_bits);
mp->dst = htonl(header);