/*
- * Copyright (c) 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define RECIRC_POOL_STATIC_IDS 1024
+static void recirc_id_node_free(struct recirc_id_node *);
+
void
recirc_init(void)
{
* finished. */
LIST_FOR_EACH_POP (node, exp_node, &expired) {
cmap_remove(&id_map, &node->id_node, node->id);
- ovsrcu_postpone(free, node);
+ ovsrcu_postpone(recirc_id_node_free, node);
}
if (!list_is_empty(&expiring)) {
}
static uint32_t
-recirc_metadata_hash(const struct recirc_state *state)
+recirc_state_hash(const struct recirc_state *state)
{
uint32_t hash;
hash = hash_pointer(state->ofproto, 0);
hash = hash_int(state->table_id, hash);
- if (state->metadata.tunnel->ip_dst) {
+ if (flow_tnl_dst_is_set(state->metadata.tunnel)) {
/* We may leave remainder bytes unhashed, but that is unlikely as
* the tunnel is not in the datapath format. */
- hash = hash_words64((const uint64_t *) state->metadata.tunnel,
- flow_tnl_size(state->metadata.tunnel)
- / sizeof(uint64_t), hash);
+ hash = hash_bytes64((const uint64_t *) state->metadata.tunnel,
+ flow_tnl_size(state->metadata.tunnel), hash);
}
hash = hash_boolean(state->conntracked, hash);
- hash = hash_words64((const uint64_t *) &state->metadata.metadata,
- (sizeof state->metadata - sizeof state->metadata.tunnel)
- / sizeof(uint64_t),
+ hash = hash_bytes64((const uint64_t *) &state->metadata.metadata,
+ sizeof state->metadata - sizeof state->metadata.tunnel,
hash);
- if (state->stack && state->stack->size != 0) {
- hash = hash_words64((const uint64_t *) state->stack->data,
- state->stack->size / sizeof(uint64_t), hash);
+ if (state->stack && state->n_stack) {
+ hash = hash_bytes64((const uint64_t *) state->stack,
+ state->n_stack * sizeof *state->stack, hash);
}
hash = hash_int(state->mirrors, hash);
hash = hash_int(state->action_set_len, hash);
+ if (state->action_set_len) {
+ hash = hash_bytes64(ALIGNED_CAST(const uint64_t *, state->action_set),
+ state->action_set_len, hash);
+ }
if (state->ofpacts_len) {
- hash = hash_words64(ALIGNED_CAST(const uint64_t *, state->ofpacts),
- state->ofpacts_len / sizeof(uint64_t),
- hash);
+ hash = hash_bytes64(ALIGNED_CAST(const uint64_t *, state->ofpacts),
+ state->ofpacts_len, hash);
}
return hash;
}
static bool
-recirc_metadata_equal(const struct recirc_state *a,
+recirc_state_equal(const struct recirc_state *a,
const struct recirc_state *b)
{
return (a->table_id == b->table_id
&& flow_tnl_equal(a->metadata.tunnel, b->metadata.tunnel)
&& !memcmp(&a->metadata.metadata, &b->metadata.metadata,
sizeof a->metadata - sizeof a->metadata.tunnel)
- && (((!a->stack || !a->stack->size) &&
- (!b->stack || !b->stack->size))
- || (a->stack && b->stack && ofpbuf_equal(a->stack, b->stack)))
+ && a->n_stack == b->n_stack
+ && !memcmp(a->stack, b->stack, a->n_stack * sizeof *a->stack)
&& a->mirrors == b->mirrors
&& a->conntracked == b->conntracked
- && a->action_set_len == b->action_set_len
&& ofpacts_equal(a->ofpacts, a->ofpacts_len,
- b->ofpacts, b->ofpacts_len));
+ b->ofpacts, b->ofpacts_len)
+ && ofpacts_equal(a->action_set, a->action_set_len,
+ b->action_set, b->action_set_len));
}
/* Lockless RCU protected lookup. If node is needed accross RCU quiescent
struct recirc_id_node *node;
CMAP_FOR_EACH_WITH_HASH (node, metadata_node, hash, &metadata_map) {
- if (recirc_metadata_equal(&node->state, target)) {
+ if (recirc_state_equal(&node->state, target)) {
return node;
}
}
flow_tnl_copy__(tunnel, old->metadata.tunnel);
new->metadata.tunnel = tunnel;
- if (new->stack) {
- new->stack = new->stack->size ? ofpbuf_clone(new->stack) : NULL;
- }
- if (new->ofpacts) {
- new->ofpacts = (new->ofpacts_len
- ? xmemdup(new->ofpacts, new->ofpacts_len)
- : NULL);
- }
+ new->stack = (new->n_stack
+ ? xmemdup(new->stack, new->n_stack * sizeof *new->stack)
+ : NULL);
+ new->ofpacts = (new->ofpacts_len
+ ? xmemdup(new->ofpacts, new->ofpacts_len)
+ : NULL);
+ new->action_set = (new->action_set_len
+ ? xmemdup(new->action_set, new->action_set_len)
+ : NULL);
+}
+
+static void
+recirc_state_free(struct recirc_state *state)
+{
+ free(state->stack);
+ free(state->ofpacts);
+ free(state->action_set);
}
/* Allocate a unique recirculation id for the given set of flow metadata.
uint32_t
recirc_find_id(const struct recirc_state *target)
{
- uint32_t hash = recirc_metadata_hash(target);
+ uint32_t hash = recirc_state_hash(target);
struct recirc_id_node *node = recirc_find_equal(target, hash);
return node ? node->id : 0;
}
uint32_t
recirc_alloc_id_ctx(const struct recirc_state *state)
{
- uint32_t hash = recirc_metadata_hash(state);
+ uint32_t hash = recirc_state_hash(state);
struct recirc_id_node *node = recirc_ref_equal(state, hash);
if (!node) {
node = recirc_alloc_id__(state, hash);
{
struct flow_tnl tunnel;
tunnel.ip_dst = htonl(0);
+ tunnel.ipv6_dst = in6addr_any;
struct recirc_state state = {
.table_id = TBL_INTERNAL,
.ofproto = ofproto,
.metadata = { .tunnel = &tunnel, .in_port = OFPP_NONE },
};
- return recirc_alloc_id__(&state, recirc_metadata_hash(&state))->id;
+ return recirc_alloc_id__(&state, recirc_state_hash(&state))->id;
+}
+
+static void
+recirc_id_node_free(struct recirc_id_node *node)
+{
+ recirc_state_free(CONST_CAST(struct recirc_state *, &node->state));
+ free(node);
}
void