Skip to content

Commit

Permalink
feat: save flow statistical information into hash table
Browse files Browse the repository at this point in the history
  • Loading branch information
chen622 committed Nov 10, 2021
1 parent 9da119f commit 06d637a
Show file tree
Hide file tree
Showing 10 changed files with 406 additions and 79 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ set_target_properties(
)
configure_file(conf/zlog-debug.conf ${CMAKE_CURRENT_BINARY_DIR}/conf/zlog.conf COPYONLY)

include_directories(include)
include_directories(${CMAKE_SOURCE_DIR}/include)

SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})

Expand Down
48 changes: 48 additions & 0 deletions include/flow_meta.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* MIT License
*
* Copyright (c) 2021 Chenming C (ccm@ccm.ink)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef SMART_OFFLOAD_FLOW_META_H
#define SMART_OFFLOAD_FLOW_META_H

#include <rte_flow.h>

/**
* The data structure to save statistical information of flow.
*/
struct flow_meta {
/* Use the number of cycles of CPU as the time*/
uint64_t create_at;
/* Total size of flow */
uint32_t flow_size;
/* Total amount of packets in a flow */
uint32_t packet_amount;
/* Has created rte_flow to offload flow or not */
bool is_offload;
/* The rte_flow to handle this flow */
struct rte_flow *flow;
};

struct flow_meta *create_flow_meta(uint32_t pkt_len);

#endif //SMART_OFFLOAD_FLOW_META_H
117 changes: 117 additions & 0 deletions include/hash_key.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* MIT License
*
* Copyright (c) 2021 Chenming C (ccm@ccm.ink)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef SMART_OFFLOAD_HASH_KEY_H
#define SMART_OFFLOAD_HASH_KEY_H

/* check the instruction support for hash function */
#if defined(RTE_ARCH_X86) || defined(__ARM_FEATURE_CRC32)
#define EM_HASH_CRC 1
#endif

#ifdef EM_HASH_CRC
#include <rte_hash_crc.h>
#define DEFAULT_HASH_FUNC rte_hash_crc
#else
#include <rte_jhash.h>
#define DEFAULT_HASH_FUNC rte_jhash
#endif

/**
* The width of wide instruction for load data.
*/
typedef __m128i xmm_t;

#define IPV6_ADDR_LEN 16

struct ipv4_5tuple {
uint32_t ip_dst;
uint32_t ip_src;
uint16_t port_dst;
uint16_t port_src;
uint8_t proto;
} __rte_packed;

/**
* The key of the flow hash table.
*/
union ipv4_5tuple_host {
struct {
uint8_t pad0;
uint8_t proto;
uint16_t pad1;
uint32_t ip_src;
uint32_t ip_dst;
uint16_t port_src;
uint16_t port_dst;
};
xmm_t xmm;
};


/**
* The hash function to generate the real hash key.
*
* @param data The key used as the key of flow table.
* @param data_len The length of key.
* @param init_val
* @return The real hash key.
*/
static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len,
uint32_t init_val) {
const union ipv4_5tuple_host *k;
uint32_t t;
const uint32_t *p;

k = data;
t = k->proto;
p = (const uint32_t *) &k->port_src;

#ifdef EM_HASH_CRC
init_val = rte_hash_crc_4byte(t, init_val);
init_val = rte_hash_crc_4byte(k->ip_src, init_val);
init_val = rte_hash_crc_4byte(k->ip_dst, init_val);
init_val = rte_hash_crc_4byte(*p, init_val);
#else
init_val = rte_jhash_1word(t, init_val);
init_val = rte_jhash_1word(k->ip_src, init_val);
init_val = rte_jhash_1word(k->ip_dst, init_val);
init_val = rte_jhash_1word(*p, init_val);
#endif

return init_val;
}

static void convert_ipv4_5tuple(struct ipv4_5tuple *key1,
union ipv4_5tuple_host *key2) {
key2->ip_dst = rte_cpu_to_be_32(key1->ip_dst);
key2->ip_src = rte_cpu_to_be_32(key1->ip_src);
key2->port_dst = rte_cpu_to_be_16(key1->port_dst);
key2->port_src = rte_cpu_to_be_16(key1->port_src);
key2->proto = key1->proto;
key2->pad0 = 0;
key2->pad1 = 0;
}

#endif //SMART_OFFLOAD_HASH_KEY_H
21 changes: 19 additions & 2 deletions include/smart_offload.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,33 @@
#include <signal.h>
#include <zlog.h>
#include <rte_ethdev.h>
#include <rte_hash.h>

/**
* Used to check the link status
*/
#define CHECK_INTERVAL 1000 /* 100ms */
#define MAX_REPEAT_TIMES 90 /* 9s (90 * 100ms) in total */

/**
* default to 4k hash entries (approx)
*/
#define MAX_HASH_ENTRIES (1024*4)

#define MAX_ERROR_MESSAGE_LENGTH 512

/**
* The quantity of different queues.
*/
#define GENERAL_QUEUES_QUANTITY 8
#define HAIRPIN_QUEUES_QUANTITY 1

/**
* Used to mask useless bits when extract packet info.
*/
#define ALL_32_BITS 0xffffffff
#define BIT_8_TO_15 0x0000ff00

/**
* Shutdown flag
*/
Expand Down Expand Up @@ -90,9 +107,9 @@ int destroy_hairpin();
void assert_link_status(uint16_t port_id);

/**
* Run on the worker core to process packets from rx queues.
* Run on the worker core to pull packets from rx queues.
*
*/
int packet_processing(void *args);
int process_loop(void *args);

#endif //SMART_OFFLOAD_SMART_OFFLOAD_H
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(SRC main.c packet_processing.c setup.c hairpin.c)
set(SRC main.c flow_meta.c packet_processing.c setup.c hairpin.c)

add_executable(smart_offload ${SRC})

Expand Down
36 changes: 36 additions & 0 deletions src/flow_meta.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* MIT License
*
* Copyright (c) 2021 Chenming C (ccm@ccm.ink)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <rte_malloc.h>
#include "flow_meta.h"

struct flow_meta * create_flow_meta(uint32_t pkt_len){
struct flow_meta *data = rte_zmalloc("flow_table_data", sizeof(struct flow_meta), 0);
data->create_at = rte_rdtsc(); // The number of cycles of CPU. One cycle is 1/rte_get_tsc_hz() second.
data->flow_size = pkt_len;
data->packet_amount = 1;
data->flow = NULL;
data->is_offload = false;
return data;
}
20 changes: 10 additions & 10 deletions src/hairpin.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static int setup_hairpin_queues(uint16_t port_id, uint16_t prev_port_id, uint16_
/* The id of peer port */
uint16_t peer_port_id = RTE_MAX_ETHPORTS;
int ret;
char *err_msg;
char err_msg[MAX_ERROR_MESSAGE_LENGTH];

struct rte_eth_hairpin_conf hairpin_conf = {
.peer_count = 1,
Expand All @@ -54,7 +54,7 @@ static int setup_hairpin_queues(uint16_t port_id, uint16_t prev_port_id, uint16_
/* get the information of port */
ret = rte_eth_dev_info_get(port_id, &dev_info);
if (ret) {
sprintf(err_msg, "can not get device info, port id: %u\n", port_id);
snprintf(err_msg,MAX_ERROR_MESSAGE_LENGTH,"can not get device info, port id: %u\n", port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
general_rxq_quantity = dev_info.nb_rx_queues - HAIRPIN_QUEUES_QUANTITY;
Expand All @@ -74,7 +74,7 @@ static int setup_hairpin_queues(uint16_t port_id, uint16_t prev_port_id, uint16_
/* get the information of peer port */
ret = rte_eth_dev_info_get(peer_port_id, &peer_dev_info);
if (ret) {
sprintf(err_msg, "can not get peer device info, port id: %u\n", port_id);
snprintf(err_msg,MAX_ERROR_MESSAGE_LENGTH,"can not get peer device info, port id: %u\n", port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
peer_general_rxq_quantity = peer_dev_info.nb_rx_queues - HAIRPIN_QUEUES_QUANTITY;
Expand Down Expand Up @@ -137,16 +137,16 @@ static int hairpin_port_bind(uint16_t port_id, int direction) {
void setup_hairpin() {
int ret;
uint16_t port_id;
char *err_msg;
char err_msg[MAX_ERROR_MESSAGE_LENGTH];

/* setup hairpin queues */
uint16_t prev_port_id = RTE_MAX_ETHPORTS;
uint16_t port_num = 0;
RTE_ETH_FOREACH_DEV(port_id) {
ret = setup_hairpin_queues(port_id, prev_port_id, port_num);
if (ret) {
sprintf(err_msg, "failed to setup hairpin queues"
" on port: %u", port_id);
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "failed to setup hairpin queues"
" on port: %u", port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
port_num++;
Expand All @@ -157,8 +157,8 @@ void setup_hairpin() {
RTE_ETH_FOREACH_DEV(port_id) {
ret = rte_eth_dev_start(port_id);
if (ret < 0) {
sprintf(err_msg, "failed to start network device: err=%d, port=%u",
ret, port_id);
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "failed to start network device: err=%d, port=%u",
ret, port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
/* check the port status */
Expand All @@ -170,13 +170,13 @@ void setup_hairpin() {
/* Let's find our peer RX ports, TXQ -> RXQ. */
ret = hairpin_port_bind(port_id, 1);
if (ret) {
sprintf(err_msg, "failed to bind port#%u.tx with peer's rx", port_id);
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "failed to bind port#%u.tx with peer's rx", port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
/* Let's find our peer TX ports, RXQ -> TXQ. */
ret = hairpin_port_bind(port_id, 0);
if (ret) {
sprintf(err_msg, "failed to bind port#%u.rx with peer's tx", port_id);
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "failed to bind port#%u.rx with peer's tx", port_id);
smto_exit(EXIT_FAILURE, err_msg);
}
}
Expand Down
Loading

0 comments on commit 06d637a

Please sign in to comment.