TSG-13629 tsg-service-chaining-engine解封装从SAPP收到的控制报文
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
add_library(common src/addr_tuple4.cpp src/session_table.cpp src/raw_packet.cpp src/ctrl_packet.cpp src/bfd.cpp src/utils.cpp src/g_vxlan.cpp)
|
||||
target_link_libraries(common PUBLIC cjson)
|
||||
|
||||
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ struct ctrl_pkt_parser
|
||||
char tsync[4];
|
||||
uint64_t session_id;
|
||||
enum session_state state;
|
||||
char method[32];
|
||||
int policy_ids[32];
|
||||
int policy_id_num;
|
||||
};
|
||||
@@ -29,7 +30,8 @@ void ctrl_packet_parser_init(struct ctrl_pkt_parser *handler);
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const void *data, size_t length);
|
||||
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const char *data, size_t length);
|
||||
void ctrl_packet_parser_dump(struct ctrl_pkt_parser *handler);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define MIN(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
#define LOG_TAG_POLICY "POLICY"
|
||||
#define LOG_TAG_UTILS "UTILS"
|
||||
#define LOG_TAG_RAWPKT "RAW_PACKET"
|
||||
#define LOG_TAG_CTRLPKT "CTRL_PACKET"
|
||||
#define LOG_TAG_STABLE "SESSION_TABLE"
|
||||
#define LOG_TAG_PKTIO "PACKET_IO"
|
||||
#define LOG_TAG_METRICS "METRICS"
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
#include <string.h>
|
||||
#include <cjson/cJSON.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "ctrl_packet.h"
|
||||
|
||||
static const char *session_state_to_string(enum session_state state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case SESSION_STATE_OPENING:
|
||||
return "opening";
|
||||
case SESSION_STATE_CLONING:
|
||||
return "closing";
|
||||
case SESSION_STATE_ACTIVE:
|
||||
return "active";
|
||||
case SESSION_STATE_RESETALL:
|
||||
return "resetall";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void ctrl_packet_parser_init(struct ctrl_pkt_parser *handler)
|
||||
{
|
||||
memset(handler, 0, sizeof(struct ctrl_pkt_parser));
|
||||
@@ -9,7 +29,141 @@ void ctrl_packet_parser_init(struct ctrl_pkt_parser *handler)
|
||||
|
||||
// return 0 : success
|
||||
// return -1 : error
|
||||
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const void *data, size_t length)
|
||||
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const char *data, size_t length)
|
||||
{
|
||||
int iter = 0;
|
||||
cJSON *item = NULL;
|
||||
cJSON *elem = NULL;
|
||||
cJSON *json = NULL;
|
||||
|
||||
json = cJSON_Parse(data);
|
||||
if (json == NULL)
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid json format) %s", LOG_TAG_CTRLPKT, data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// tsync
|
||||
item = cJSON_GetObjectItem(json, "tsync");
|
||||
if (!item || !cJSON_IsString(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid tsync format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
memcpy(handler->tsync, item->valuestring, MIN(sizeof(handler->tsync), strlen(item->valuestring)));
|
||||
|
||||
// session_id
|
||||
item = cJSON_GetObjectItem(json, "session_id");
|
||||
if (!item || !cJSON_IsNumber(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid session_id format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
handler->session_id = item->valueint;
|
||||
|
||||
// state
|
||||
item = cJSON_GetObjectItem(json, "state");
|
||||
if (!item || !cJSON_IsString(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid state format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (strcasecmp(item->valuestring, "opening") == 0)
|
||||
{
|
||||
handler->state = SESSION_STATE_OPENING;
|
||||
}
|
||||
else if (strcasecmp(item->valuestring, "active") == 0)
|
||||
{
|
||||
handler->state = SESSION_STATE_ACTIVE;
|
||||
}
|
||||
else if (strcasecmp(item->valuestring, "closing") == 0)
|
||||
{
|
||||
handler->state = SESSION_STATE_CLONING;
|
||||
}
|
||||
else if (strcasecmp(item->valuestring, "resetall") == 0)
|
||||
{
|
||||
handler->state = SESSION_STATE_RESETALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid state value) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (handler->state != SESSION_STATE_ACTIVE)
|
||||
{
|
||||
goto success_out;
|
||||
}
|
||||
|
||||
// method
|
||||
item = cJSON_GetObjectItem(json, "method");
|
||||
if (!item || !cJSON_IsString(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid method format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
memcpy(handler->method, item->valuestring, MIN(sizeof(handler->method), strlen(item->valuestring)));
|
||||
if (strcasecmp(item->valuestring, "policy_update") != 0)
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid method value) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
// params
|
||||
item = cJSON_GetObjectItem(json, "params");
|
||||
if (!item || !cJSON_IsObject(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid params format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
item = cJSON_GetObjectItem(item, "service_chaining");
|
||||
if (!item || !cJSON_IsArray(item) || !cJSON_GetArraySize(item))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid service_chaining format) %s", LOG_TAG_CTRLPKT, data);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
handler->policy_id_num = MIN(cJSON_GetArraySize(item), (int)(sizeof(handler->policy_ids) / sizeof(handler->policy_ids[0])));
|
||||
cJSON_ArrayForEach(elem, item)
|
||||
{
|
||||
if (!cJSON_IsNumber(elem))
|
||||
{
|
||||
LOG_ERROR("%s: unexpected control packet: (invalid service_chaining value) %s", LOG_TAG_POLICY, data);
|
||||
continue;
|
||||
}
|
||||
handler->policy_ids[iter] = elem->valueint;
|
||||
iter++;
|
||||
|
||||
if (iter == handler->policy_id_num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
success_out:
|
||||
cJSON_Delete(json);
|
||||
return 0;
|
||||
}
|
||||
|
||||
error_out:
|
||||
cJSON_Delete(json);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ctrl_packet_parser_dump(struct ctrl_pkt_parser *handler)
|
||||
{
|
||||
if (handler)
|
||||
{
|
||||
LOG_INFO("%s: tsync : %s", LOG_TAG_POLICY, handler->tsync);
|
||||
LOG_INFO("%s: session_id : %lu", LOG_TAG_POLICY, handler->session_id);
|
||||
LOG_INFO("%s: state : %s", LOG_TAG_POLICY, session_state_to_string(handler->state));
|
||||
LOG_INFO("%s: method : %s", LOG_TAG_POLICY, handler->method);
|
||||
LOG_INFO("%s: policy_id_num : %d", LOG_TAG_POLICY, handler->policy_id_num);
|
||||
|
||||
for (int i = 0; i < handler->policy_id_num; i++)
|
||||
{
|
||||
LOG_INFO("%s: policy_ids[%03d] : %i", LOG_TAG_POLICY, i, handler->policy_ids[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,14 @@ add_executable(gtest_raw_packet gtest_raw_packet.cpp)
|
||||
target_include_directories(gtest_raw_packet PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
|
||||
target_link_libraries(gtest_raw_packet common gtest)
|
||||
|
||||
###############################################################################
|
||||
# gtest_ctrl_packet
|
||||
###############################################################################
|
||||
|
||||
add_executable(gtest_ctrl_packet gtest_ctrl_packet.cpp)
|
||||
target_include_directories(gtest_ctrl_packet PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
|
||||
target_link_libraries(gtest_ctrl_packet common gtest)
|
||||
|
||||
###############################################################################
|
||||
# gtest_utils
|
||||
###############################################################################
|
||||
@@ -38,4 +46,5 @@ include(GoogleTest)
|
||||
gtest_discover_tests(gtest_addr_tuple4)
|
||||
gtest_discover_tests(gtest_session_table)
|
||||
gtest_discover_tests(gtest_raw_packet)
|
||||
gtest_discover_tests(gtest_ctrl_packet)
|
||||
gtest_discover_tests(gtest_utils)
|
||||
29
common/test/gtest_ctrl_packet.cpp
Normal file
29
common/test/gtest_ctrl_packet.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ctrl_packet.h"
|
||||
|
||||
TEST(CTRL_PACKET, PARSE)
|
||||
{
|
||||
const char *data = "{\"tsync\":\"1.0\",\"session_id\":123456789,\"state\":\"active\",\"method\":\"policy_update\",\"params\":{\"service_chaining\":[1,2,3],\"shaping\":[4,5,6]}}";
|
||||
size_t length = strlen(data);
|
||||
|
||||
struct ctrl_pkt_parser parser;
|
||||
ctrl_packet_parser_init(&parser);
|
||||
EXPECT_TRUE(ctrl_packet_parser_parse(&parser, data, length) == 0);
|
||||
ctrl_packet_parser_dump(&parser);
|
||||
|
||||
EXPECT_STREQ(parser.tsync, "1.0");
|
||||
EXPECT_TRUE(parser.session_id == 123456789);
|
||||
EXPECT_TRUE(parser.state == SESSION_STATE_ACTIVE);
|
||||
EXPECT_STREQ(parser.method, "policy_update");
|
||||
EXPECT_TRUE(parser.policy_id_num == 3);
|
||||
EXPECT_TRUE(parser.policy_ids[0] == 1);
|
||||
EXPECT_TRUE(parser.policy_ids[1] == 2);
|
||||
EXPECT_TRUE(parser.policy_ids[2] == 3);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user