summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <[email protected]>2023-11-09 07:27:03 +0000
committerroot <[email protected]>2023-11-09 07:27:03 +0000
commit0e780765553bbcf62fa604add488cca48d49ea03 (patch)
tree171877fc2579b26edd28535b0497aae1bae6fc6d
parentd5c95aaa048120ddc4b72a7d08cb70638172b3ac (diff)
modify test case
-rw-r--r--shaping/include/shaper.h1
-rw-r--r--shaping/src/shaper.cpp5
-rw-r--r--shaping/src/shaper_swarmkv.cpp4
-rw-r--r--shaping/test/gtest_shaper.cpp50
-rw-r--r--shaping/test/stub.cpp22
-rw-r--r--shaping/test/stub.h5
-rw-r--r--shaping/test/test_conf/shaping.conf1
7 files changed, 51 insertions, 37 deletions
diff --git a/shaping/include/shaper.h b/shaping/include/shaper.h
index aacd15e..d130222 100644
--- a/shaping/include/shaper.h
+++ b/shaping/include/shaper.h
@@ -33,6 +33,7 @@ extern "C" {
struct shaping_system_conf {
unsigned int session_queue_len_max;
unsigned int priority_queue_len_max;
+ unsigned int pkt_max_delay_time_us;
int polling_node_num_max[SHAPING_PRIORITY_NUM_MAX];
int work_thread_num;
int cpu_affinity_enable;
diff --git a/shaping/src/shaper.cpp b/shaping/src/shaper.cpp
index 8853197..1013d0f 100644
--- a/shaping/src/shaper.cpp
+++ b/shaping/src/shaper.cpp
@@ -30,8 +30,6 @@ extern "C" {
#define NANO_SECONDS_PER_MILLI_SEC 1000000
#define MILLI_SECONDS_PER_SEC 1000
-#define SHAPING_LATENCY_THRESHOLD 2000000 //2s
-
#define TOKEN_ENLARGE_TIMES 10
#define TOKEN_GET_FAILED_INTERVAL_MS 1
#define HMGET_REQUEST_INTERVAL_MS 1000
@@ -718,7 +716,7 @@ static enum shaping_packet_action shaper_pkt_action_decide_queueing(struct shapi
if (pf_container[0].pf_type == PROFILE_IN_RULE_TYPE_PRIMARY) {
clock_gettime(CLOCK_MONOTONIC, &curr_time);
- if (shaper_pkt_latency_us_calculate(pf_container[0].pf_info, &curr_time) > SHAPING_LATENCY_THRESHOLD) {
+ if (shaper_pkt_latency_us_calculate(pf_container[0].pf_info, &curr_time) > ctx->conf.pkt_max_delay_time_us) {
shaper_flow_pop(ctx, sf);
goto DROP;
}
@@ -1215,6 +1213,7 @@ int shaper_global_conf_init(struct shaping_system_conf *conf)
MESA_load_profile_uint_def(SHAPING_GLOBAL_CONF_FILE, "CONFIG", "PRIORITY_QUEUE_LEN_MAX", &conf->priority_queue_len_max, 1024);
MESA_load_profile_int_def(SHAPING_GLOBAL_CONF_FILE, "CONFIG", "CHECK_RULE_ENABLE_INTERVAL_SEC", &conf->check_rule_enable_interval_sec, 120);
+ MESA_load_profile_uint_def(SHAPING_GLOBAL_CONF_FILE, "CONFIG", "PKT_MAX_DELAY_TIME_US", &conf->pkt_max_delay_time_us, 2000000);
return 0;
diff --git a/shaping/src/shaper_swarmkv.cpp b/shaping/src/shaper_swarmkv.cpp
index 5e66361..1fea20c 100644
--- a/shaping/src/shaper_swarmkv.cpp
+++ b/shaping/src/shaper_swarmkv.cpp
@@ -119,12 +119,12 @@ int shaper_swarmkv_pending_queue_aqm_drop(struct shaping_thread_ctx *ctx)
if (ctx->swarmkv_aqm_prob < PROBABILITY_MAX) {
ctx->swarmkv_aqm_prob += INCREMENT;
}
- LOG_DEBUG("%s: shaping pending queue len %lu, aqm prob %d", LOG_TAG_SWARMKV, pending_queue_len, ctx->swarmkv_aqm_prob);
+ LOG_DEBUG("%s: shaping pending queue len %lld, aqm prob %d", LOG_TAG_SWARMKV, pending_queue_len, ctx->swarmkv_aqm_prob);
} else {
if (ctx->swarmkv_aqm_prob >= DECREMENT) {
ctx->swarmkv_aqm_prob -= DECREMENT;
}
- LOG_DEBUG("%s: shaping pending queue len %lu, aqm prob %d", LOG_TAG_SWARMKV, pending_queue_len, ctx->swarmkv_aqm_prob);
+ LOG_DEBUG("%s: shaping pending queue len %lld, aqm prob %d", LOG_TAG_SWARMKV, pending_queue_len, ctx->swarmkv_aqm_prob);
}
ctx->swarmkv_aqm_update_time = now;
diff --git a/shaping/test/gtest_shaper.cpp b/shaping/test/gtest_shaper.cpp
index 41520aa..a625068 100644
--- a/shaping/test/gtest_shaper.cpp
+++ b/shaping/test/gtest_shaper.cpp
@@ -56,7 +56,7 @@ static void send_packets(struct shaping_thread_ctx *ctx, struct shaping_flow *sf
for (int i = 0; i < pkt_num; i++) {
memset(&meta, 0, sizeof(meta));
- time = stub_curr_time_get();
+ time = stub_curr_time_ns_get();
packet = packet_new(time, pkt_len, dir);
if (expec_tx_queue) {
pkt_node = packet_node_new(packet);
@@ -75,7 +75,7 @@ static void send_packets(struct shaping_thread_ctx *ctx, struct shaping_flow *sf
polling_entry(ctx->sp, ctx->stat, ctx);
}
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
return;
@@ -261,7 +261,7 @@ TEST(single_session, udp_tx_in_order)
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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -348,7 +348,7 @@ TEST(single_session, tcp_tx_in_order)
stub_refresh_token_bucket(0);
for (int i = 0; i < 10; i++) {//10 pkts which is not pure control
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 10));
@@ -422,7 +422,7 @@ TEST(single_session, udp_diff_direction)
stub_refresh_token_bucket(0);
for (int i = 0; i < 20; i++) {
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
//10 out packets
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 10));
@@ -503,7 +503,7 @@ TEST(single_session, udp_multi_rules)
//there are 3 rules, send one packet need 3 polling process, so 10 packets need 30 polling
//even though invoke polling more than 30 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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -577,7 +577,7 @@ TEST(single_session, udp_borrow)
stub_refresh_token_bucket(2);
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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -651,7 +651,7 @@ TEST(single_session, udp_borrow_same_priority_9)
stub_refresh_token_bucket(3);
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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -747,7 +747,7 @@ TEST(two_session_diff_priority, udp_in_order)
stub_refresh_token_bucket(1);
for (int i = 0; i < 10; i++) {
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue2, actual_tx_queue, 10));//stream2 priority 1, first
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -758,7 +758,7 @@ TEST(two_session_diff_priority, udp_in_order)
stub_refresh_token_bucket(1);
for (int i = 0; i < 10; i++) {
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue1, actual_tx_queue, 10));//stream1 priority 2
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -864,7 +864,7 @@ TEST(two_session_diff_priority, udp_in_order_multi_rule)
stub_refresh_token_bucket(4);
for (int i = 0; i < 30; i++) {
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue1, actual_tx_queue, 10));
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -877,7 +877,7 @@ TEST(two_session_diff_priority, udp_in_order_multi_rule)
stub_refresh_token_bucket(4);
for (int i = 0; i < 10; i++) {
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue2, actual_tx_queue, 10));//stream2 priority 3
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -965,7 +965,7 @@ TEST(single_session_async, udp_tx_in_order)
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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -1103,7 +1103,7 @@ TEST(two_session_diff_priority_same_profile, udp_borrow_in_order)
stub_refresh_token_bucket(2);
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_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue2, actual_tx_queue, 10));
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -1114,7 +1114,7 @@ TEST(two_session_diff_priority_same_profile, udp_borrow_in_order)
stub_refresh_token_bucket(2);
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_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
}
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue1, actual_tx_queue, 10));
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
@@ -1200,7 +1200,7 @@ TEST(two_session_same_rule, udp_tx_in_order)
stub_refresh_token_bucket(1);
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_inc(STUB_TIME_INC_FOR_PACKET);
+ 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));
@@ -1280,6 +1280,7 @@ TEST(two_session_diff_priority_same_profile, two_thread_udp_tx_in_order)
ASSERT_TRUE(TAILQ_EMPTY(actual_tx_queue));
shaper_stat_refresh(&ctx->thread_ctx[0], sf1, 0, 1);//刷新线程0中的优先级队列长度到swarmkv中
+ stub_curr_time_s_inc(1);//inc time to refresh hmget interval
for (int i = 0; i < 10; i++) {//线程1中的session优先级为2,被线程0中优先级为1的session阻断
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
@@ -1294,6 +1295,7 @@ TEST(two_session_diff_priority_same_profile, two_thread_udp_tx_in_order)
}
shaper_stat_refresh(&ctx->thread_ctx[0], sf1, 0, 1);//刷新线程0中的优先级队列长度到swarmkv中
+ stub_curr_time_s_inc(1);//inc time to refresh hmget interval
while (!TAILQ_EMPTY(&expec_tx_queue2)) {
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
@@ -1362,15 +1364,16 @@ TEST(two_session_diff_priority_same_profile, session_timer_test)
sleep(3);//wait session timer to expire, to refresh priority queue_len to swarmkv
for (int i = 0; i < 500; i++) {
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);//inc time to refresh stat in timer
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);//inc time to refresh stat in timer
}
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);//timer triggered in polling
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
+ stub_curr_time_s_inc(1);//inc time to refresh hmget interval
for (int i = 0; i < 10; i++) {//线程1中的session优先级为2,被线程0中优先级为1的session阻断
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
ASSERT_EQ(-1, judge_packet_eq(&expec_tx_queue2, actual_tx_queue, 1));//优先级低,不能发出报文
}
@@ -1378,22 +1381,23 @@ TEST(two_session_diff_priority_same_profile, session_timer_test)
while (!TAILQ_EMPTY(&expec_tx_queue1)) {
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue1, actual_tx_queue, 1));//sf1 priority 1
}
sleep(3);//wait session timer to expire, to refresh priority queue_len to swarmkv
for (int i = 0; i < 500; i++) {
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);//inc time to refresh stat in timer
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);//inc time to refresh stat in timer
}
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);//timer triggered in polling
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
+ stub_curr_time_s_inc(1);//inc time to refresh hmget interval
while (!TAILQ_EMPTY(&expec_tx_queue2)) {
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[1].sp, ctx->thread_ctx[1].stat, &ctx->thread_ctx[1]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue2, actual_tx_queue, 1));//sf2 priority 2
}
@@ -1444,7 +1448,7 @@ TEST(statistics, udp_drop_pkt)
while (!TAILQ_EMPTY(&expec_tx_queue)) {
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 1));
}
@@ -1531,7 +1535,7 @@ TEST(statistics, udp_queueing_pkt)
while (!TAILQ_EMPTY(&expec_tx_queue)) {//last 90 delay packets
stub_refresh_token_bucket(0);
polling_entry(ctx->thread_ctx[0].sp, ctx->thread_ctx[0].stat, &ctx->thread_ctx[0]);
- stub_curr_time_inc(STUB_TIME_INC_FOR_PACKET);
+ stub_curr_time_ns_inc(STUB_TIME_INC_FOR_PACKET);
ASSERT_EQ(0, judge_packet_eq(&expec_tx_queue, actual_tx_queue, 1));
}
diff --git a/shaping/test/stub.cpp b/shaping/test/stub.cpp
index 24b390a..db7ce23 100644
--- a/shaping/test/stub.cpp
+++ b/shaping/test/stub.cpp
@@ -50,7 +50,8 @@ struct stub_matched_rules matched_rules;
struct shaping_profile pf_array[MAX_STUB_PROFILE_NUM];
static int profile_priority_len[MAX_STUB_PROFILE_NUM][10] = {{0}};
-static unsigned long long curr_time = 2000000000;//2s
+static unsigned long long curr_time_ns = 2000000000;//2s
+static unsigned int curr_time_s = 0;
void * stub_get_token_thread_func(void *data)
{
@@ -151,16 +152,23 @@ struct stub_pkt_queue* stub_get_tx_queue()
return &tx_queue;
}
-void stub_curr_time_inc(unsigned long long time_ns)
+void stub_curr_time_ns_inc(unsigned long long time_ns)
{
- curr_time += time_ns;
+ curr_time_ns += time_ns;
return;
}
-unsigned long long stub_curr_time_get()
+void stub_curr_time_s_inc(int time_s)
{
- return curr_time;
+ curr_time_s += time_s;
+
+ return;
+}
+
+unsigned long long stub_curr_time_ns_get()
+{
+ return curr_time_ns;
}
void stub_init()
@@ -193,8 +201,8 @@ void stub_init()
int clock_gettime (clockid_t __clock_id, struct timespec *__tp)
{
- __tp->tv_sec = 0;
- __tp->tv_nsec = curr_time;
+ __tp->tv_sec = curr_time_s;
+ __tp->tv_nsec = curr_time_ns;
return 0;
}
diff --git a/shaping/test/stub.h b/shaping/test/stub.h
index 80e099b..48b9b0b 100644
--- a/shaping/test/stub.h
+++ b/shaping/test/stub.h
@@ -41,8 +41,9 @@ struct stub_pkt_queue* stub_get_tx_queue();
int stub_AQM_drop_packet(int queue_len, unsigned long long income_time);
-void stub_curr_time_inc(unsigned long long time_ns);
-unsigned long long stub_curr_time_get();
+void stub_curr_time_ns_inc(unsigned long long time_ns);
+void stub_curr_time_s_inc(int time_s);
+unsigned long long stub_curr_time_ns_get();
void stub_init();
diff --git a/shaping/test/test_conf/shaping.conf b/shaping/test/test_conf/shaping.conf
index bcba85c..015ab3c 100644
--- a/shaping/test/test_conf/shaping.conf
+++ b/shaping/test/test_conf/shaping.conf
@@ -40,5 +40,6 @@ LINE_PROTOCOL_SERVER_PORT=6667
#PROFILE_QUEUE_LEN_PER_PRIORITY_MAX=128
SESSION_QUEUE_LEN_MAX=128
QUEUEING_SESSIONS_PER_PRIORITY_PER_THREAD_MAX=1024
+PKT_MAX_DELAY_TIME_US=999999999
POLLING_NODE_NUM_MAX={"polling_node_num_max":[ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]}