Skip to content

Commit c35c14a

Browse files
committed
feat(cpufreq): add a definition to disable lock cpu frequency feature
1 parent 7c1fcff commit c35c14a

File tree

4 files changed

+169
-157
lines changed

4 files changed

+169
-157
lines changed

README-ZH.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# smart_offload
22

3+
[![Build](https://github.com/chen622/smart_offload/actions/workflows/build.yml/badge.svg)](https://github.com/chen622/smart_offload/actions/workflows/build.yml)
4+
35
## 一、主要功能
46

57
- 将流经的数据包上送到处理线程中,并在第 n 个包后下发对应的流表进行卸载
@@ -24,7 +26,7 @@
2426
## 四、快速上手
2527

2628
### 配置要求:
27-
- DPDK 20.11.3.0.4
29+
- DPDK 20.11.5
2830
- 配备 Mellanox/Nvidia 智能网卡的 x86 服务器
2931

3032
### 运行指令
@@ -34,4 +36,10 @@ cmake ..
3436
make
3537
# -l 用于指定核心 -a 用于指定网口
3638
./smart_offload -l 1-9 -a 82:00.0
37-
```
39+
```
40+
41+
## 五、问题
42+
43+
### Unable to set Power Management Environment
44+
45+
无法锁定 CPU 的运行频率,可能是由于缺乏相关权限。可以通过增加一个定义`-DVM=true`来关闭此功能

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ The diagram is written with Chinese, you can see the English comment of function
1818
## 3. Quick Start
1919

2020
### Requirements:
21-
- DPDK 20.11.3.0.4
22-
- x86 server with Mellanox/Nvidia smart-nic.
21+
- DPDK 20.11.5
22+
- x86 server with Mellanox/Nvidia SmartNic.
2323

2424
### Run
2525
```bash
@@ -29,3 +29,9 @@ make
2929
# -l Specify the core; -a Specify the port
3030
./smart_offload -l 1-9 -a 82:00.0
3131
```
32+
33+
## 4. Questions
34+
35+
### Unable to set Power Management Environment
36+
37+
Can not set frequency of CPU cores, you can a definition `-DVM=true` to disable this feature.

src/main.c

Lines changed: 149 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -35,168 +35,165 @@ char *zlog_conf = "conf/zlog.conf";
3535
#endif
3636

3737
static void signal_handler(int signum) {
38-
if (signum == SIGINT || signum == SIGTERM) {
39-
dzlog_info("Signal %d received, preparing to exit...",
40-
signum);
41-
force_quit = true;
42-
}
38+
if (signum == SIGINT || signum == SIGTERM) {
39+
dzlog_info("Signal %d received, preparing to exit...",
40+
signum);
41+
force_quit = true;
42+
}
4343
}
4444

45-
4645
int main(int argc, char **argv) {
47-
48-
49-
/* General return value */
50-
int ret;
51-
char err_msg[MAX_ERROR_MESSAGE_LENGTH];
52-
/* Quantity of ports */
53-
uint16_t port_quantity;
54-
/* Quantity of slave works */
55-
uint16_t worker_quantity;
56-
uint16_t port_id = 0;
57-
58-
/* Setup environment of DPDK */
59-
ret = rte_eal_init(argc, argv);
60-
if (ret < 0) {
61-
smto_exit(EXIT_FAILURE, "invalid EAL arguments");
62-
}
63-
64-
/* Setup zlog */
65-
ret = dzlog_init(zlog_conf, "main");
66-
if (ret) {
67-
smto_exit(EXIT_FAILURE, "zlog init failed");
68-
}
69-
70-
/* Check the instruction */
46+
/* General return value */
47+
int ret;
48+
char err_msg[MAX_ERROR_MESSAGE_LENGTH];
49+
/* Quantity of ports */
50+
uint16_t port_quantity;
51+
/* Quantity of slave works */
52+
uint16_t worker_quantity;
53+
uint16_t port_id = 0;
54+
55+
/* Setup environment of DPDK */
56+
ret = rte_eal_init(argc, argv);
57+
if (ret < 0) {
58+
smto_exit(EXIT_FAILURE, "invalid EAL arguments");
59+
}
60+
61+
/* Setup zlog */
62+
ret = dzlog_init(zlog_conf, "main");
63+
if (ret) {
64+
smto_exit(EXIT_FAILURE, "zlog init failed");
65+
}
66+
67+
/* Check the instruction */
7168
#if defined(__SSE2__)
72-
dzlog_debug("Find SSE2 support");
69+
dzlog_debug("Find SSE2 support");
7370
#else
7471
#error No vector engine (SSE, NEON, ALTIVEC) available, check your toolchain
7572
#endif
7673

77-
/* Listen to the shutdown event */
78-
force_quit = false;
79-
signal(SIGINT, signal_handler);
80-
signal(SIGTERM, signal_handler);
81-
82-
dzlog_debug("Running on socket #%d", rte_socket_id());
83-
84-
/* Check the quantity of network ports */
85-
port_quantity = rte_eth_dev_count_avail();
86-
if (port_quantity < 1) {
87-
smto_exit(EXIT_FAILURE, "no enough Ethernet ports found");
88-
} else if (port_quantity > 2) {
89-
dzlog_warn("%d ports detected, but we only use two", port_quantity);
90-
}
91-
92-
/* Check the quantity of workers */
93-
worker_quantity = rte_lcore_count();
94-
if (worker_quantity != GENERAL_QUEUES_QUANTITY + 1) {
95-
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
96-
"worker quantity does not match the queue quantity, it should be %u rather than %u",
97-
GENERAL_QUEUES_QUANTITY + 1, worker_quantity);
98-
smto_exit(EXIT_FAILURE, err_msg);
99-
}
100-
101-
/* Initialize the memory pool of dpdk */
102-
struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NUM_MBUFS, CACHE_SIZE, 0,
103-
RTE_MBUF_DEFAULT_BUF_SIZE,
104-
rte_socket_id());
105-
if (mbuf_pool == NULL) {
106-
smto_exit(EXIT_FAILURE, "cannot init mbuf pool");
74+
/* Listen to the shutdown event */
75+
force_quit = false;
76+
signal(SIGINT, signal_handler);
77+
signal(SIGTERM, signal_handler);
78+
79+
dzlog_debug("Running on socket #%d", rte_socket_id());
80+
81+
/* Check the quantity of network ports */
82+
port_quantity = rte_eth_dev_count_avail();
83+
if (port_quantity < 1) {
84+
smto_exit(EXIT_FAILURE, "no enough Ethernet ports found");
85+
} else if (port_quantity > 2) {
86+
dzlog_warn("%d ports detected, but we only use two", port_quantity);
87+
}
88+
89+
/* Check the quantity of workers */
90+
worker_quantity = rte_lcore_count();
91+
if (worker_quantity != GENERAL_QUEUES_QUANTITY + 1) {
92+
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
93+
"worker quantity does not match the queue quantity, it should be %u rather than %u",
94+
GENERAL_QUEUES_QUANTITY + 1, worker_quantity);
95+
smto_exit(EXIT_FAILURE, err_msg);
96+
}
97+
98+
/* Initialize the memory pool of dpdk */
99+
struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NUM_MBUFS, CACHE_SIZE, 0,
100+
RTE_MBUF_DEFAULT_BUF_SIZE,
101+
rte_socket_id());
102+
if (mbuf_pool == NULL) {
103+
smto_exit(EXIT_FAILURE, "cannot init mbuf pool");
104+
}
105+
106+
/* Config port and setup hairpin mode */
107+
if (port_quantity == 1) {
108+
dzlog_debug("ONE port hairpin mode");
109+
port_id = rte_eth_find_next_owned_by(0, RTE_ETH_DEV_NO_OWNER);
110+
init_port(port_id, mbuf_pool);
111+
setup_one_port_hairpin(port_id);
112+
} else {
113+
dzlog_debug("TWO port hairpin mode unsupported");
114+
smto_exit(EXIT_FAILURE, "WO port hairpin mode unsupported");
115+
/* Initialize the network port and do some configure */
116+
RTE_ETH_FOREACH_DEV(port_id) {
117+
init_port(port_id, mbuf_pool);
107118
}
108-
109-
/* Config port and setup hairpin mode */
110-
if (port_quantity == 1) {
111-
dzlog_debug("ONE port hairpin mode");
112-
port_id = rte_eth_find_next_owned_by(0, RTE_ETH_DEV_NO_OWNER);
113-
init_port(port_id, mbuf_pool);
114-
setup_one_port_hairpin(port_id);
115-
} else {
116-
dzlog_debug("TWO port hairpin mode unsupported");
117-
smto_exit(EXIT_FAILURE, "WO port hairpin mode unsupported");
118-
/* Initialize the network port and do some configure */
119-
RTE_ETH_FOREACH_DEV(port_id) {
120-
init_port(port_id, mbuf_pool);
121-
}
122-
setup_two_port_hairpin();
123-
}
124-
125-
126-
struct rte_flow *flow = 0;
127-
struct rte_flow_error flow_error = {0};
128-
flow = create_default_jump_flow(port_id, &flow_error);
129-
if (flow == NULL) {
130-
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
131-
"the default jump flow create failed: %s", flow_error.message);
132-
smto_exit(EXIT_FAILURE, err_msg);
133-
}
134-
flow = create_default_rss_flow(port_id, GENERAL_QUEUES_QUANTITY, &flow_error);
135-
if (flow == NULL) {
136-
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
137-
"the default rss flow create failed: %s", flow_error.message);
138-
smto_exit(EXIT_FAILURE, err_msg);
139-
}
140-
141-
/* Create flow hash map */
142-
struct rte_hash_parameters flow_hash_map_parameter = {
143-
.name = "flow_hash_table",
144-
.entries = MAX_HASH_ENTRIES,
145-
.key_len = sizeof(union ipv4_5tuple_host),
146-
.hash_func = ipv4_hash_crc,
147-
.hash_func_init_val = 0,
148-
.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
149-
};
150-
struct rte_hash *flow_hash_map = rte_hash_create(&flow_hash_map_parameter);
151-
if (flow_hash_map == NULL) {
152-
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "unable to create flow hash table");
153-
smto_exit(EXIT_FAILURE, err_msg);
154-
}
155-
156-
if (register_aged_event(port_id, flow_hash_map)) {
157-
smto_exit(EXIT_FAILURE, "cannot register from age timeout event");
158-
}
159-
160-
uint16_t lcore_id = 0;
161-
uint16_t index = 0;
162-
struct worker_parameter worker_params[GENERAL_QUEUES_QUANTITY];
163-
RTE_LCORE_FOREACH_WORKER(lcore_id) {
164-
worker_params[index].port_id = port_id;
165-
worker_params[index].queue_id = index;
166-
worker_params[index].flow_hash_map = flow_hash_map;
167-
rte_power_init(lcore_id);
168-
ret = rte_power_set_freq(lcore_id, 2);
169-
if (ret < 0) {
170-
dzlog_warn("worker #%u does not running at the fixed frequency", lcore_id);
171-
}
172-
rte_eal_remote_launch(process_loop, &worker_params[index], lcore_id);
173-
index++;
119+
setup_two_port_hairpin();
120+
}
121+
122+
struct rte_flow *flow = 0;
123+
struct rte_flow_error flow_error = {0};
124+
flow = create_default_jump_flow(port_id, &flow_error);
125+
if (flow == NULL) {
126+
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
127+
"the default jump flow create failed: %s", flow_error.message);
128+
smto_exit(EXIT_FAILURE, err_msg);
129+
}
130+
flow = create_default_rss_flow(port_id, GENERAL_QUEUES_QUANTITY, &flow_error);
131+
if (flow == NULL) {
132+
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH,
133+
"the default rss flow create failed: %s", flow_error.message);
134+
smto_exit(EXIT_FAILURE, err_msg);
135+
}
136+
137+
/* Create flow hash map */
138+
struct rte_hash_parameters flow_hash_map_parameter = {
139+
.name = "flow_hash_table",
140+
.entries = MAX_HASH_ENTRIES,
141+
.key_len = sizeof(union ipv4_5tuple_host),
142+
.hash_func = ipv4_hash_crc,
143+
.hash_func_init_val = 0,
144+
.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
145+
};
146+
struct rte_hash *flow_hash_map = rte_hash_create(&flow_hash_map_parameter);
147+
if (flow_hash_map == NULL) {
148+
snprintf(err_msg, MAX_ERROR_MESSAGE_LENGTH, "unable to create flow hash table");
149+
smto_exit(EXIT_FAILURE, err_msg);
150+
}
151+
152+
if (register_aged_event(port_id, flow_hash_map)) {
153+
smto_exit(EXIT_FAILURE, "cannot register from age timeout event");
154+
}
155+
156+
uint16_t lcore_id = 0;
157+
uint16_t index = 0;
158+
struct worker_parameter worker_params[GENERAL_QUEUES_QUANTITY];
159+
RTE_LCORE_FOREACH_WORKER(lcore_id) {
160+
worker_params[index].port_id = port_id;
161+
worker_params[index].queue_id = index;
162+
worker_params[index].flow_hash_map = flow_hash_map;
163+
#ifndef VM
164+
rte_power_init(lcore_id);
165+
ret = rte_power_set_freq(lcore_id, 2);
166+
#endif
167+
if (ret < 0) {
168+
dzlog_warn("worker #%u does not running at the fixed frequency", lcore_id);
174169
}
175-
176-
177-
rte_eal_mp_wait_lcore();
178-
179-
180-
/* free the memory of flow metadata and the flow hash map*/
181-
int32_t key_count = rte_hash_count(flow_hash_map);
182-
dzlog_debug("%d flow keys has been added into flow hash map", key_count);
183-
if (key_count > 0) {
184-
char format_key[MAX_ERROR_MESSAGE_LENGTH];
185-
const void *key = 0;
186-
void *data = 0;
187-
uint32_t *next = 0;
188-
uint32_t current = rte_hash_iterate(flow_hash_map, &key, &data, next);
189-
for (; current != -ENOENT; current = rte_hash_iterate(flow_hash_map, &key, &data, next)) {
190-
int32_t del_key = rte_hash_del_key(flow_hash_map, key);
191-
ret = rte_hash_free_key_with_position(flow_hash_map, del_key);
192-
if (ret) {
193-
dump_pkt_info((union ipv4_5tuple_host *) key, -1, format_key, MAX_ERROR_MESSAGE_LENGTH);
194-
dzlog_error("cannot free hash key(%s)", format_key);
195-
}
196-
rte_free(data);
197-
}
170+
rte_eal_remote_launch(process_loop, &worker_params[index], lcore_id);
171+
index++;
172+
}
173+
174+
rte_eal_mp_wait_lcore();
175+
176+
177+
/* free the memory of flow metadata and the flow hash map*/
178+
int32_t key_count = rte_hash_count(flow_hash_map);
179+
dzlog_debug("%d flow keys has been added into flow hash map", key_count);
180+
if (key_count > 0) {
181+
char format_key[MAX_ERROR_MESSAGE_LENGTH];
182+
const void *key = 0;
183+
void *data = 0;
184+
uint32_t *next = 0;
185+
uint32_t current = rte_hash_iterate(flow_hash_map, &key, &data, next);
186+
for (; current != -ENOENT; current = rte_hash_iterate(flow_hash_map, &key, &data, next)) {
187+
int32_t del_key = rte_hash_del_key(flow_hash_map, key);
188+
ret = rte_hash_free_key_with_position(flow_hash_map, del_key);
189+
if (ret) {
190+
dump_pkt_info((union ipv4_5tuple_host *) key, -1, format_key, MAX_ERROR_MESSAGE_LENGTH);
191+
dzlog_error("cannot free hash key(%s)", format_key);
192+
}
193+
rte_free(data);
198194
}
199-
rte_hash_free(flow_hash_map);
195+
}
196+
rte_hash_free(flow_hash_map);
200197

201-
smto_exit(EXIT_SUCCESS, "SUCCESS! All core stop running!");
198+
smto_exit(EXIT_SUCCESS, "SUCCESS! All core stop running!");
202199
}

src/setup.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,12 @@ void smto_exit(int exit_code, const char *format) {
142142
rte_eth_dev_stop(port_id);
143143
rte_eth_dev_close(port_id);
144144
}
145-
145+
#ifndef VM
146146
uint16_t lcore_id = 0;
147147
RTE_LCORE_FOREACH_WORKER(lcore_id) {
148148
rte_power_exit(lcore_id);
149149
}
150+
#endif
150151

151152
/* clean up the EAL */
152153
rte_eal_cleanup();

0 commit comments

Comments
 (0)