#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "packets.h"
+#include "random.h"
#include "unaligned.h"
COVERAGE_DEFINE(flow_extract);
if (tcp) {
flow->tp_src = tcp->tcp_src;
flow->tp_dst = tcp->tcp_dst;
+ flow->tcp_flags = tcp->tcp_ctl & htons(0x0fff);
packet->l7 = b->data;
}
}
void
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22);
fmd->tun_id = flow->tunnel.tun_id;
fmd->tun_src = flow->tunnel.ip_src;
memset(&wc->masks, 0, sizeof wc->masks);
}
-/* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not
- * wildcard any bits or fields. */
-void
-flow_wildcards_init_exact(struct flow_wildcards *wc)
-{
- memset(&wc->masks, 0xff, sizeof wc->masks);
-}
-
/* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or
* fields. */
bool
flow_union_with_miniflow(struct flow *dst, const struct miniflow *src)
{
uint32_t *dst_u32 = (uint32_t *) dst;
- int ofs;
- int i;
+ int ofs = 0;
+ uint64_t map;
- ofs = 0;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
-
- for (map = src->map[i]; map; map = zero_rightmost_1bit(map)) {
- dst_u32[raw_ctz(map) + i * 32] |= src->values[ofs++];
- }
+ for (map = src->map; map; map = zero_rightmost_1bit(map)) {
+ dst_u32[raw_ctz(map)] |= src->values[ofs++];
}
}
return jhash_bytes(&fields, sizeof fields, basis);
}
+/* Initialize a flow with random fields that matter for nx_hash_fields. */
+void
+flow_random_hash_fields(struct flow *flow)
+{
+ uint16_t rnd = random_uint16();
+
+ /* Initialize to all zeros. */
+ memset(flow, 0, sizeof *flow);
+
+ eth_addr_random(flow->dl_src);
+ eth_addr_random(flow->dl_dst);
+
+ flow->vlan_tci = (OVS_FORCE ovs_be16) (random_uint16() & VLAN_VID_MASK);
+
+ /* Make most of the random flows IPv4, some IPv6, and rest random. */
+ flow->dl_type = rnd < 0x8000 ? htons(ETH_TYPE_IP) :
+ rnd < 0xc000 ? htons(ETH_TYPE_IPV6) : (OVS_FORCE ovs_be16)rnd;
+
+ if (dl_type_is_ip_any(flow->dl_type)) {
+ if (flow->dl_type == htons(ETH_TYPE_IP)) {
+ flow->nw_src = (OVS_FORCE ovs_be32)random_uint32();
+ flow->nw_dst = (OVS_FORCE ovs_be32)random_uint32();
+ } else {
+ random_bytes(&flow->ipv6_src, sizeof flow->ipv6_src);
+ random_bytes(&flow->ipv6_dst, sizeof flow->ipv6_dst);
+ }
+ /* Make most of IP flows TCP, some UDP or SCTP, and rest random. */
+ rnd = random_uint16();
+ flow->nw_proto = rnd < 0x8000 ? IPPROTO_TCP :
+ rnd < 0xc000 ? IPPROTO_UDP :
+ rnd < 0xd000 ? IPPROTO_SCTP : (uint8_t)rnd;
+ if (flow->nw_proto == IPPROTO_TCP ||
+ flow->nw_proto == IPPROTO_UDP ||
+ flow->nw_proto == IPPROTO_SCTP) {
+ flow->tp_src = (OVS_FORCE ovs_be16)random_uint16();
+ flow->tp_dst = (OVS_FORCE ovs_be16)random_uint16();
+ }
+ }
+}
+
/* Masks the fields in 'wc' that are used by the flow hash 'fields'. */
void
flow_mask_hash_fields(const struct flow *flow, struct flow_wildcards *wc,
b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp);
tcp->tcp_src = flow->tp_src;
tcp->tcp_dst = flow->tp_dst;
- tcp->tcp_ctl = TCP_CTL(0, 5);
+ tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5);
} else if (flow->nw_proto == IPPROTO_UDP) {
struct udp_header *udp;
icmp->icmp_code = ntohs(flow->tp_dst);
icmp->icmp_csum = csum(icmp, ICMP_HEADER_LEN);
}
+ b->l7 = ofpbuf_tail(b);
}
ip = b->l3;
static int
miniflow_n_values(const struct miniflow *flow)
{
- int n, i;
-
- n = 0;
- for (i = 0; i < MINI_N_MAPS; i++) {
- n += popcount(flow->map[i]);
- }
- return n;
+ return popcount(flow->map);
}
static uint32_t *
{
const uint32_t *src_u32 = (const uint32_t *) src;
unsigned int ofs;
- int i;
+ uint64_t map;
dst->values = miniflow_alloc_values(dst, n);
ofs = 0;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
-
- for (map = dst->map[i]; map; map = zero_rightmost_1bit(map)) {
- dst->values[ofs++] = src_u32[raw_ctz(map) + i * 32];
- }
+ for (map = dst->map; map; map = zero_rightmost_1bit(map)) {
+ dst->values[ofs++] = src_u32[raw_ctz(map)];
}
}
/* Initialize dst->map, counting the number of nonzero elements. */
n = 0;
- memset(dst->map, 0, sizeof dst->map);
+ dst->map = 0;
+
for (i = 0; i < FLOW_U32S; i++) {
if (src_u32[i]) {
- dst->map[i / 32] |= 1u << (i % 32);
+ dst->map |= UINT64_C(1) << i;
n++;
}
}
miniflow_init_with_minimask(struct miniflow *dst, const struct flow *src,
const struct minimask *mask)
{
- memcpy(dst->map, mask->masks.map, sizeof dst->map);
+ dst->map = mask->masks.map;
miniflow_init__(dst, src, miniflow_n_values(dst));
}
miniflow_clone(struct miniflow *dst, const struct miniflow *src)
{
int n = miniflow_n_values(src);
- memcpy(dst->map, src->map, sizeof dst->map);
+ dst->map = src->map;
dst->values = miniflow_alloc_values(dst, n);
memcpy(dst->values, src->values, n * sizeof *dst->values);
}
} else {
dst->values = src->values;
}
- memcpy(dst->map, src->map, sizeof dst->map);
+ dst->map = src->map;
}
/* Frees any memory owned by 'flow'. Does not free the storage in which 'flow'
static const uint32_t *
miniflow_get__(const struct miniflow *flow, unsigned int u32_ofs)
{
- if (!(flow->map[u32_ofs / 32] & (1u << (u32_ofs % 32)))) {
+ if (!(flow->map & (UINT64_C(1) << u32_ofs))) {
static const uint32_t zero = 0;
return &zero;
- } else {
- const uint32_t *p = flow->values;
-
- BUILD_ASSERT(MINI_N_MAPS == 2);
- if (u32_ofs < 32) {
- p += popcount(flow->map[0] & ((1u << u32_ofs) - 1));
- } else {
- p += popcount(flow->map[0]);
- p += popcount(flow->map[1] & ((1u << (u32_ofs - 32)) - 1));
- }
- return p;
}
+ return flow->values + popcount(flow->map & ((UINT64_C(1) << u32_ofs) - 1));
}
/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'flow'
{
const uint32_t *ap = a->values;
const uint32_t *bp = b->values;
- int i;
+ const uint64_t a_map = a->map;
+ const uint64_t b_map = b->map;
+ uint64_t map;
- for (i = 0; i < MINI_N_MAPS; i++) {
- const uint32_t a_map = a->map[i];
- const uint32_t b_map = b->map[i];
- uint32_t map;
-
- if (a_map == b_map) {
- for (map = a_map; map; map = zero_rightmost_1bit(map)) {
- if (*ap++ != *bp++) {
- return false;
- }
+ if (a_map == b_map) {
+ for (map = a_map; map; map = zero_rightmost_1bit(map)) {
+ if (*ap++ != *bp++) {
+ return false;
}
- } else {
- for (map = a_map | b_map; map; map = zero_rightmost_1bit(map)) {
- uint32_t bit = rightmost_1bit(map);
- uint32_t a_value = a_map & bit ? *ap++ : 0;
- uint32_t b_value = b_map & bit ? *bp++ : 0;
+ }
+ } else {
+ for (map = a_map | b_map; map; map = zero_rightmost_1bit(map)) {
+ uint64_t bit = rightmost_1bit(map);
+ uint64_t a_value = a_map & bit ? *ap++ : 0;
+ uint64_t b_value = b_map & bit ? *bp++ : 0;
- if (a_value != b_value) {
- return false;
- }
+ if (a_value != b_value) {
+ return false;
}
}
}
const struct minimask *mask)
{
const uint32_t *p;
- int i;
+ uint64_t map;
p = mask->masks.values;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
- for (map = mask->masks.map[i]; map; map = zero_rightmost_1bit(map)) {
- int ofs = raw_ctz(map) + i * 32;
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
- if ((miniflow_get(a, ofs) ^ miniflow_get(b, ofs)) & *p) {
- return false;
- }
- p++;
+ if ((miniflow_get(a, ofs) ^ miniflow_get(b, ofs)) & *p) {
+ return false;
}
+ p++;
}
return true;
{
const uint32_t *b_u32 = (const uint32_t *) b;
const uint32_t *p;
- int i;
+ uint64_t map;
p = mask->masks.values;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
- for (map = mask->masks.map[i]; map; map = zero_rightmost_1bit(map)) {
- int ofs = raw_ctz(map) + i * 32;
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
- if ((miniflow_get(a, ofs) ^ b_u32[ofs]) & *p) {
- return false;
- }
- p++;
+ if ((miniflow_get(a, ofs) ^ b_u32[ofs]) & *p) {
+ return false;
}
+ p++;
}
return true;
{
const uint32_t *p = flow->values;
uint32_t hash = basis;
- int i;
-
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t hash_map = 0;
- uint32_t map;
+ uint64_t hash_map = 0;
+ uint64_t map;
- for (map = flow->map[i]; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- hash = mhash_add(hash, *p);
- hash_map |= rightmost_1bit(map);
- }
- p++;
+ for (map = flow->map; map; map = zero_rightmost_1bit(map)) {
+ if (*p) {
+ hash = mhash_add(hash, *p);
+ hash_map |= rightmost_1bit(map);
}
- hash = mhash_add(hash, hash_map);
+ p++;
}
+ hash = mhash_add(hash, hash_map);
+ hash = mhash_add(hash, hash_map >> 32);
+
return mhash_finish(hash, p - flow->values);
}
{
const uint32_t *p = mask->masks.values;
uint32_t hash;
- int i;
+ uint64_t map;
hash = basis;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
- for (map = mask->masks.map[i]; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- int ofs = raw_ctz(map) + i * 32;
- hash = mhash_add(hash, miniflow_get(flow, ofs) & *p);
- }
- p++;
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ if (*p) {
+ int ofs = raw_ctz(map);
+ hash = mhash_add(hash, miniflow_get(flow, ofs) & *p);
}
+ p++;
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
flow_hash_in_minimask(const struct flow *flow, const struct minimask *mask,
uint32_t basis)
{
- const uint32_t *flow_u32;
+ const uint32_t *flow_u32 = (const uint32_t *)flow;
const uint32_t *p = mask->masks.values;
uint32_t hash;
- int i;
+ uint64_t map;
hash = basis;
- flow_u32 = (const uint32_t *) flow;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
-
- for (map = mask->masks.map[i]; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p);
- }
- p++;
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ if (*p) {
+ hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p);
}
- flow_u32 += 32;
+ p++;
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
struct miniflow *dst = &dst_->masks;
const struct miniflow *a = &a_->masks;
const struct miniflow *b = &b_->masks;
- int i, n;
+ uint64_t map;
+ int n = 0;
- n = 0;
dst->values = storage;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
-
- dst->map[i] = 0;
- for (map = a->map[i] & b->map[i]; map;
- map = zero_rightmost_1bit(map)) {
- int ofs = raw_ctz(map) + i * 32;
- uint32_t mask = miniflow_get(a, ofs) & miniflow_get(b, ofs);
-
- if (mask) {
- dst->map[i] |= rightmost_1bit(map);
- dst->values[n++] = mask;
- }
+
+ dst->map = 0;
+ for (map = a->map & b->map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+ uint32_t mask = miniflow_get(a, ofs) & miniflow_get(b, ofs);
+
+ if (mask) {
+ dst->map |= rightmost_1bit(map);
+ dst->values[n++] = mask;
}
}
}
{
const struct miniflow *a = &a_->masks;
const struct miniflow *b = &b_->masks;
- int i;
-
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
+ uint64_t map;
- for (map = a->map[i] | b->map[i]; map;
- map = zero_rightmost_1bit(map)) {
- int ofs = raw_ctz(map) + i * 32;
- uint32_t a_u32 = miniflow_get(a, ofs);
- uint32_t b_u32 = miniflow_get(b, ofs);
+ for (map = a->map | b->map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+ uint32_t a_u32 = miniflow_get(a, ofs);
+ uint32_t b_u32 = miniflow_get(b, ofs);
- if ((a_u32 & b_u32) != b_u32) {
- return true;
- }
+ if ((a_u32 & b_u32) != b_u32) {
+ return true;
}
}
{
const struct miniflow *mask = &mask_->masks;
const uint32_t *p = mask->values;
- int i;
+ uint64_t map;
- for (i = 0; i < MINI_N_MAPS; i++) {
- uint32_t map;
-
- for (map = mask->map[i]; map; map = zero_rightmost_1bit(map)) {
- if (*p++) {
- return false;
- }
+ for (map = mask->map; map; map = zero_rightmost_1bit(map)) {
+ if (*p++) {
+ return false;
}
}
return true;