static int
timed_adds(unsigned with_hash, unsigned with_data, unsigned table_index)
{
	unsigned i;
	const uint64_t start_tsc = rte_rdtsc();
	void *data;
	int32_t ret;

	for (i = 0; i < KEYS_TO_ADD; i++) {
		data = (void *) ((uintptr_t) signatures[i]);
		if (with_hash && with_data) {
			ret = rte_hash_add_key_with_hash_data(h[table_index],
						(const void *) keys[i],
						signatures[i], data);
			if (ret < 0) {
				printf("Failed to add key number %u\n", ret);
				return -1;
			}
		} else if (with_hash && !with_data) {
			ret = rte_hash_add_key_with_hash(h[table_index],
						(const void *) keys[i],
						signatures[i]);
			if (ret >= 0)
				positions[i] = ret;
			else {
				printf("Failed to add key number %u\n", ret);
				return -1;
			}
		} else if (!with_hash && with_data) {
			ret = rte_hash_add_key_data(h[table_index],
						(const void *) keys[i],
						data);
			if (ret < 0) {
				printf("Failed to add key number %u\n", ret);
				return -1;
			}
		} else {
			ret = rte_hash_add_key(h[table_index], keys[i]);
			if (ret >= 0)
				positions[i] = ret;
			else {
				printf("Failed to add key number %u\n", ret);
				return -1;
			}
		}
	}

	const uint64_t end_tsc = rte_rdtsc();
	const uint64_t time_taken = end_tsc - start_tsc;

	cycles[table_index][ADD][with_hash][with_data] = time_taken/KEYS_TO_ADD;

	return 0;
}
Esempio n. 2
0
int
onvm_ft_add_key(struct onvm_ft* table, struct onvm_ft_ipv4_5tuple *key, char** data) {
        int32_t tbl_index;
	uint32_t softrss;

	softrss = onvm_softrss(key);

        tbl_index = rte_hash_add_key_with_hash(table->hash, (const void *)key, softrss);
        if (tbl_index >= 0) {
		*data = onvm_ft_get_data(table, tbl_index);
        }

        return tbl_index;
}
Esempio n. 3
0
/* Create a new flow table made of an rte_hash table and a fixed size
 * data array for storing values. Only supports IPv4 5-tuple lookups. */
struct onvm_ft*
onvm_ft_create(int cnt, int entry_size) {
        struct rte_hash* hash;
        struct onvm_ft* ft;
        struct rte_hash_parameters ipv4_hash_params = {
            .name = NULL,
            .entries = cnt,
            .key_len = sizeof(struct onvm_ft_ipv4_5tuple),
            .hash_func = NULL,
            .hash_func_init_val = 0,
        };

        char s[64];
        /* create ipv4 hash table. use core number and cycle counter to get a unique name. */
        ipv4_hash_params.name = s;
        ipv4_hash_params.socket_id = rte_socket_id();
        snprintf(s, sizeof(s), "onvm_ft_%d-%"PRIu64, rte_lcore_id(), rte_get_tsc_cycles());
        hash = rte_hash_create(&ipv4_hash_params);
        if (hash == NULL) {
                return NULL;
        }
	ft = (struct onvm_ft*)rte_calloc("table", 1, sizeof(struct onvm_ft), 0);
        if (ft == NULL) {
                rte_hash_free(hash);
                return NULL;
        }
        ft->hash = hash;
        ft->cnt = cnt;
        ft->entry_size = entry_size;
        /* Create data array for storing values */
        ft->data = rte_calloc("entry", cnt, entry_size, 0);
        if (ft->data == NULL) {
                rte_hash_free(hash);
                rte_free(ft);
                return NULL;
        }
        return ft;
}

/* Add an entry in flow table and set data to point to the new value.
Returns:
 index in the array on success
 -EPROTONOSUPPORT if packet is not ipv4.
 -EINVAL if the parameters are invalid.
 -ENOSPC if there is no space in the hash for this key.
*/
int
onvm_ft_add_pkt(struct onvm_ft* table, struct rte_mbuf *pkt, char** data) {
        int32_t tbl_index;
        struct onvm_ft_ipv4_5tuple key;
        int err;

        err = onvm_ft_fill_key(&key, pkt);
        if (err < 0) {
                return err;
        }
        tbl_index = rte_hash_add_key_with_hash(table->hash, (const void *)&key, pkt->hash.rss);
        if (tbl_index >= 0) {
        	*data = &table->data[tbl_index*table->entry_size];
        }
        return tbl_index;
}
/*
 * Looks for random keys which
 * ALL can fit in hash table (no errors)
 */
static int
get_input_keys(unsigned with_pushes, unsigned table_index)
{
	unsigned i, j;
	unsigned bucket_idx, incr, success = 1;
	uint8_t k = 0;
	int32_t ret;
	const uint32_t bucket_bitmask = NUM_BUCKETS - 1;

	/* Reset all arrays */
	for (i = 0; i < MAX_ENTRIES; i++)
		slot_taken[i] = 0;

	for (i = 0; i < NUM_BUCKETS; i++)
		buckets[i] = 0;

	for (j = 0; j < hashtest_key_lens[table_index]; j++)
		keys[0][j] = 0;

	/*
	 * Add only entries that are not duplicated and that fits in the table
	 * (cannot store more than BUCKET_SIZE entries in a bucket).
	 * Regardless a key has been added correctly or not (success),
	 * the next one to try will be increased by 1.
	 */
	for (i = 0; i < KEYS_TO_ADD;) {
		incr = 0;
		if (i != 0) {
			keys[i][0] = ++k;
			/* Overflow, need to increment the next byte */
			if (keys[i][0] == 0)
				incr = 1;
			for (j = 1; j < hashtest_key_lens[table_index]; j++) {
				/* Do not increase next byte */
				if (incr == 0)
					if (success == 1)
						keys[i][j] = keys[i - 1][j];
					else
						keys[i][j] = keys[i][j];
				/* Increase next byte by one */
				else {
					if (success == 1)
						keys[i][j] = keys[i-1][j] + 1;
					else
						keys[i][j] = keys[i][j] + 1;
					if (keys[i][j] == 0)
						incr = 1;
					else
						incr = 0;
				}
			}
		}
		success = 0;
		signatures[i] = rte_hash_hash(h[table_index], keys[i]);
		bucket_idx = signatures[i] & bucket_bitmask;
		/*
		 * If we are not inserting keys in secondary location,
		 * when bucket is full, do not try to insert the key
		 */
		if (with_pushes == 0)
			if (buckets[bucket_idx] == BUCKET_SIZE)
				continue;

		/* If key can be added, leave in successful key arrays "keys" */
		ret = rte_hash_add_key_with_hash(h[table_index], keys[i],
						signatures[i]);
		if (ret >= 0) {
			/* If key is already added, ignore the entry and do not store */
			if (slot_taken[ret])
				continue;
			else {
				/* Store the returned position and mark slot as taken */
				slot_taken[ret] = 1;
				positions[i] = ret;
				buckets[bucket_idx]++;
				success = 1;
				i++;
			}
		}
	}

	/* Reset the table, so we can measure the time to add all the entries */
	rte_hash_free(h[table_index]);
	h[table_index] = rte_hash_create(&ut_params);

	return 0;
}