summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <[email protected]>2023-12-06 08:36:47 +0000
committerroot <[email protected]>2023-12-06 08:36:47 +0000
commit29cd6942c133fad7c38a75e22e1cadea726ec89f (patch)
tree6ef77e9a4b8c54a515928bc7f5c19fd5527e775f
parenta5923348e98e0a312826d12c92beef20f702a0ca (diff)
1.fix bug fairness profile can't limit rate
2.add corresponding test case
-rw-r--r--shaping/src/shaper.cpp39
-rw-r--r--shaping/test/gtest_shaper.cpp81
-rw-r--r--shaping/test/stub.cpp7
-rw-r--r--shaping/test/stub.h1
4 files changed, 119 insertions, 9 deletions
diff --git a/shaping/src/shaper.cpp b/shaping/src/shaper.cpp
index 170a235..55f32fb 100644
--- a/shaping/src/shaper.cpp
+++ b/shaping/src/shaper.cpp
@@ -465,13 +465,36 @@ END:
return;
}
-static void shaper_deposit_token_sub(struct shaping_profile_hash_node *pf_hash_node, int req_token_bits, unsigned char direction, int priority)
+static void shaper_deposit_token_sub(struct shaping_profile_info *profile, int req_token_bits, unsigned char direction, int priority)
{
- if (direction == SHAPING_DIR_IN) {
- pf_hash_node->in_deposit_token_bits[priority] -= req_token_bits;
- } else {
- pf_hash_node->out_deposit_token_bits[priority] -= req_token_bits;
+ int *deposit_token;
+ struct shaping_profile_hash_node *pf_hash_node = profile->hash_node;
+
+ switch (profile->type) {
+ case PROFILE_TYPE_GENERIC:
+ if (direction == SHAPING_DIR_IN) {
+ deposit_token = &pf_hash_node->in_deposit_token_bits[priority];
+ } else {
+ deposit_token = &pf_hash_node->out_deposit_token_bits[priority];
+ }
+ break;
+ case PROFILE_TYPE_HOST_FARINESS:
+ case PROFILE_TYPE_MAX_MIN_HOST_FAIRNESS:
+ case PROFILE_TYPE_SPLIT_BY_LOCAL_HOST:
+ if (direction == SHAPING_DIR_IN) {
+ deposit_token = &profile->in_deposit_token_bits;
+ } else {
+ deposit_token = &profile->out_deposit_token_bits;
+ }
+ break;
+ default:
+ LOG_ERROR("%s: invalid profile type %d, profile id %d", LOG_TAG_SHAPING, profile->type, profile->id);
+ return;
}
+
+ *deposit_token -= req_token_bits;
+
+ return;
}
static int shaper_deposit_token_is_enough(struct shaping_profile_info *profile, int req_token_bits, unsigned char direction, int priority)
@@ -551,7 +574,7 @@ static int shaper_token_get_from_profile(struct shaping_thread_ctx *ctx, struct
}
if (shaper_deposit_token_is_enough(pf_info, req_token_bits, direction, pf_info->priority)) {
- shaper_deposit_token_sub(pf_info->hash_node, req_token_bits, direction, pf_info->priority);
+ shaper_deposit_token_sub(pf_info, req_token_bits, direction, pf_info->priority);
return SHAPER_TOKEN_GET_SUCCESS;
}
@@ -695,7 +718,7 @@ static int shaper_token_consume(struct shaping_thread_ctx *ctx, struct shaping_f
shaper_profile_hash_node_update(profile);
if (shaper_deposit_token_is_enough(profile, req_token_bytes * 8, direction, profile->priority)) {
- shaper_deposit_token_sub(profile->hash_node, req_token_bytes * 8, direction, profile->priority);
+ shaper_deposit_token_sub(profile, req_token_bytes * 8, direction, profile->priority);
return SHAPER_TOKEN_GET_SUCCESS;
}
@@ -962,7 +985,7 @@ static void shaper_token_consume_force(struct shaping_flow *sf, struct metadata
for (int i = 0; i < sf->rule_num; i++) {
rule = &sf->matched_rule_infos[i];
shaper_profile_hash_node_update(&rule->primary);
- shaper_deposit_token_sub(rule->primary.hash_node, meta->raw_len * 8, meta->dir, rule->primary.priority);
+ shaper_deposit_token_sub(&rule->primary, meta->raw_len * 8, meta->dir, rule->primary.priority);
}
return;
diff --git a/shaping/test/gtest_shaper.cpp b/shaping/test/gtest_shaper.cpp
index 8196ed2..8c120d9 100644
--- a/shaping/test/gtest_shaper.cpp
+++ b/shaping/test/gtest_shaper.cpp
@@ -303,6 +303,85 @@ TEST(single_session, udp_tx_in_order)
/*session1 match rule1
rule1:
profile: limit 1000*/
+TEST(max_min_host_fairness_profile, udp_tx_in_order)
+{
+ struct stub_pkt_queue expec_tx_queue;
+ struct stub_pkt_queue *actual_tx_queue;
+ struct shaping_ctx *ctx = NULL;
+ struct shaping_flow *sf = NULL;
+ long long rule_id[] = {0};
+ int priority[] = {1};
+ int profile_num[] = {1};
+ int profile_id[][MAX_REF_PROFILE] = {{0}};
+
+ TAILQ_INIT(&expec_tx_queue);
+ stub_init();
+ ctx = shaping_engine_init();
+ ASSERT_TRUE(ctx != NULL);
+ sf = shaping_flow_new(&ctx->thread_ctx[0]);
+ ASSERT_TRUE(sf != NULL);
+
+ stub_set_matched_shaping_rules(1, rule_id, priority, profile_num, profile_id);
+ stub_set_token_bucket_avl_per_sec(0, 1000, SHAPING_DIR_OUT);
+ stub_set_profile_type(0, PROFILE_TYPE_MAX_MIN_HOST_FAIRNESS);
+ actual_tx_queue = stub_get_tx_queue();
+ shaper_rules_update(&ctx->thread_ctx[0], sf, rule_id, 1);
+
+
+ /**********send packets*********************/
+ send_packets(&ctx->thread_ctx[0], sf, 100, 100, SHAPING_DIR_OUT, &expec_tx_queue, 1, 0);
+ /*******************************************/
+
+ //first 10 packets
+ ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 10));
+ ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
+
+ while (!TAILQ_EMPTY(&expec_tx_queue)) {//last 90 delay packets
+ stub_refresh_token_bucket(0);
+ for (int i = 0; i < 20; i++) {//even though invoke polling more than 10 times, there should be only 10 pkts be sent
+ polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
+ }
+ ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 10));
+ ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
+ }
+
+ shaping_flow_free(&ctx->thread_ctx[0], sf);
+ fieldstat_global_disable_prometheus_endpoint();
+
+ /***********send stat data here********************/
+ fieldstat_dynamic_passive_output(ctx->stat->instance);//send metric manualy
+ shaper_global_stat_refresh(ctx->global_stat);
+
+ shaper_thread_resource_clear();
+ shaping_engine_destroy(ctx);
+
+ stub_clear_matched_shaping_rules();
+
+ /*******test statistics***********/
+ sleep(2);//wait telegraf to output
+ FILE *stat_file;
+
+ //judge shaping metric
+ stat_file = fopen(SHAPING_STAT_FILE_NAME, "r");
+ memset(line, 0, sizeof(line));
+ ASSERT_TRUE(NULL != fgets(line, sizeof(line), stat_file));
+ shaping_stat_judge(line, 0, 0, 1, 100, 10000, 0, 0, 170000, SHAPING_DIR_OUT, profile_type_primary);//max latency is last 10 pkts
+ fclose(stat_file);
+ stat_file = fopen(SHAPING_STAT_FILE_NAME, "w");//clear stat file
+ fclose(stat_file);
+
+ //judge shaping global metric
+ stat_file = fopen(SHAPING_GLOBAL_STAT_FILE_NAME, "r");
+ memset(line, 0, sizeof(line));
+ ASSERT_TRUE(NULL != fgets(line, sizeof(line), stat_file));
+ shaping_global_stat_judge(line, 100, 10000, 0, 0, 0, 0);
+ fclose(stat_file);
+}
+
+/*session1 match rule1
+ rule1:
+ profile: limit 1000*/
TEST(single_session, tcp_tx_in_order)
{
struct stub_pkt_queue expec_tx_queue;
@@ -1595,6 +1674,6 @@ TEST(statistics, udp_queueing_pkt)
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
- //testing::GTEST_FLAG(filter) = "single_session.tcp_tx_in_order";
+ //testing::GTEST_FLAG(filter) = "max_min_host_fairness_profile.udp_tx_in_order";
return RUN_ALL_TESTS();
} \ No newline at end of file
diff --git a/shaping/test/stub.cpp b/shaping/test/stub.cpp
index 293ef3c..f3c89e5 100644
--- a/shaping/test/stub.cpp
+++ b/shaping/test/stub.cpp
@@ -84,6 +84,12 @@ void stub_refresh_token_bucket(int profile_id)
return;
}
+void stub_set_profile_type(int profile_id, enum shaping_profile_type type)
+{
+ pf_array[profile_id].type = type;
+ return;
+}
+
void stub_set_async_token_get_times(int profile_id, int times)
{
pf_async_times[profile_id] = times;
@@ -419,6 +425,7 @@ void swarmkv_tconsume(struct swarmkv * db, const char * key, size_t keylen, long
void swarmkv_ftconsume(struct swarmkv * db, const char * key, size_t keylen, const char * member, size_t member_len, long long weight, long long tokens, swarmkv_on_reply_callback_t *cb, void *cb_arg)
{
+ swarmkv_tconsume(db, key, keylen, tokens, cb, cb_arg);
return;
}
diff --git a/shaping/test/stub.h b/shaping/test/stub.h
index 48b9b0b..f7119d2 100644
--- a/shaping/test/stub.h
+++ b/shaping/test/stub.h
@@ -31,6 +31,7 @@ TAILQ_HEAD(stub_pkt_queue, stub_packet_node);
void stub_set_token_bucket_avl_per_sec(int profile_id, unsigned int tokens, unsigned char direction);
void stub_refresh_token_bucket(int profile_id);
+void stub_set_profile_type(int profile_id, enum shaping_profile_type type);
void stub_set_async_token_get_times(int profile_id, int times);
void stub_set_matched_shaping_rules(int rule_num, long long *rule_id, const int *priority, const int *profile_num, int profile_id[][MAX_REF_PROFILE]);