From b33dafff5353c5727f97d5fa9719ec7b6c50da5a Mon Sep 17 00:00:00 2001 From: luwenpeng Date: Wed, 15 May 2024 11:40:00 +0800 Subject: [PATCH] Add packet injector test frame --- src/packet/packet_utils.cpp | 19 +- src/packet_io/dumpfile_io.cpp | 105 +++++++++ src/packet_io/dumpfile_io.h | 1 + src/packet_io/lock_free_queue.cpp | 6 + src/packet_io/lock_free_queue.h | 1 + src/packet_io/packet_io.cpp | 12 + src/packet_io/packet_io.h | 1 + src/session/session.cpp | 2 +- src/session/session_manager.cpp | 2 +- src/stellar/main.cpp | 5 + src/stellar/stellar.cpp | 1 + test/CMakeLists.txt | 14 +- test/README.md | 10 +- test/gtest_build_tcp_packet.cpp | 63 ------ test/gtest_build_udp_packet.cpp | 53 ----- test/gtest_inject_tcp_rst.cpp | 39 ++++ test/packet_injector.cpp | 18 +- test/packet_injector_test_frame.cpp | 205 ++++++++++++++++++ test/packet_injector_test_frame.h | 41 ++++ .../raw/fw.pcap | Bin 0 -> 6048 bytes .../raw/virtio_dign_c.pcap | Bin 0 -> 611 bytes .../raw/virtio_dign_s.pcap | Bin 0 -> 529 bytes .../raw/fw.pcap | Bin 0 -> 13020 bytes .../raw/virtio_dign_c.pcap | Bin 0 -> 1856 bytes .../raw/virtio_dign_s.pcap | Bin 0 -> 1836 bytes .../raw/fw.pcap | Bin 0 -> 2952 bytes .../raw/virtio_dign_c.pcap | Bin 0 -> 184 bytes .../raw/virtio_dign_s.pcap | Bin 0 -> 274 bytes ...ct-192.0.2.110:80-192.0.2.211:59942-2.pcap | Bin 0 -> 94 bytes ...ct-192.0.2.211:59942-192.0.2.110:80-1.pcap | Bin 0 -> 94 bytes .../test/input.pcap | Bin 0 -> 1428 bytes 31 files changed, 458 insertions(+), 140 deletions(-) delete mode 100644 test/gtest_build_tcp_packet.cpp delete mode 100644 test/gtest_build_udp_packet.cpp create mode 100644 test/gtest_inject_tcp_rst.cpp create mode 100644 test/packet_injector_test_frame.cpp create mode 100644 test/packet_injector_test_frame.h create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/fw.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_c.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_s.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/fw.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/virtio_dign_c.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/virtio_dign_s.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/fw.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/virtio_dign_c.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/virtio_dign_s.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.110:80-192.0.2.211:59942-2.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.211:59942-192.0.2.110:80-1.pcap create mode 100644 test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/input.pcap diff --git a/src/packet/packet_utils.cpp b/src/packet/packet_utils.cpp index 8ffc0da..6318b35 100644 --- a/src/packet/packet_utils.cpp +++ b/src/packet/packet_utils.cpp @@ -120,16 +120,25 @@ struct packet *packet_dup(const struct packet *pkt) { return NULL; } - memcpy(dup_pkt, pkt, sizeof(struct packet)); - memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len); - dup_pkt->origin = PACKET_ORIGIN_USERHEAP; - dup_pkt->origin_ctx = NULL; - // update layers + dup_pkt->layers_used = pkt->layers_used; + dup_pkt->layers_size = pkt->layers_size; + + memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len); + dup_pkt->data_len = pkt->data_len; + + dup_pkt->origin_ctx = NULL; + dup_pkt->origin = PACKET_ORIGIN_USERHEAP; + dup_pkt->action = PACKET_ACTION_DROP; + for (int8_t i = 0; i < pkt->layers_used; i++) { + dup_pkt->layers[i].type = pkt->layers[i].type; dup_pkt->layers[i].hdr_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset; dup_pkt->layers[i].pld_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len; + dup_pkt->layers[i].hdr_offset = pkt->layers[i].hdr_offset; + dup_pkt->layers[i].hdr_len = pkt->layers[i].hdr_len; + dup_pkt->layers[i].pld_len = pkt->layers[i].pld_len; } // update frag_layer diff --git a/src/packet_io/dumpfile_io.cpp b/src/packet_io/dumpfile_io.cpp index 127d3e5..f10d798 100644 --- a/src/packet_io/dumpfile_io.cpp +++ b/src/packet_io/dumpfile_io.cpp @@ -26,6 +26,7 @@ struct dumpfile_io struct io_stat stat[MAX_THREAD_NUM]; uint64_t io_thread_need_exit; uint64_t io_thread_is_runing; + uint64_t io_thread_wait_exit; }; struct pcap_pkt @@ -34,10 +35,90 @@ struct pcap_pkt int len; }; +struct pcap_file_hdr +{ + unsigned int magic; + unsigned short version_major; + unsigned short version_minor; + unsigned int thiszone; // gmt to local correction + unsigned int sigfigs; // accuracy of timestamps + unsigned int snaplen; // max length saved portion of each pkt + unsigned int linktype; // data link type (LINKTYPE_*) +}; + +struct pcap_pkt_hdr +{ + unsigned int tv_sec; // time stamp + unsigned int tv_usec; // time stamp + unsigned int caplen; // length of portion present + unsigned int len; // length this packet (off wire) +}; + +struct pcap_file_hdr DEFAULT_PCAP_FILE_HDR = + { + .magic = 0xA1B2C3D4, + .version_major = 0x0002, + .version_minor = 0x0004, + .thiszone = 0, + .sigfigs = 0, + .snaplen = 0xFFFF, + .linktype = 1}; + /****************************************************************************** * Private API ******************************************************************************/ +static void save_packet(struct packet *pkt, uint64_t idx) +{ + int len = 0; + FILE *fp = NULL; + struct tuple6 tuple; + struct timeval ts = {0}; + struct pcap_pkt_hdr pcap_hdr = {0}; + + char file[256] = {0}; + char src_addr[INET6_ADDRSTRLEN] = {0}; + char dst_addr[INET6_ADDRSTRLEN] = {0}; + + len = packet_get_len(pkt); + memset(&tuple, 0, sizeof(struct tuple6)); + packet_get_innermost_tuple6(pkt, &tuple); + + if (tuple.ip_type == IP_TYPE_V4) + { + inet_ntop(AF_INET, &tuple.src_addr.v4, src_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET, &tuple.dst_addr.v4, dst_addr, INET6_ADDRSTRLEN); + } + else + { + inet_ntop(AF_INET6, &tuple.src_addr.v6, src_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &tuple.dst_addr.v6, dst_addr, INET6_ADDRSTRLEN); + } + snprintf(file, sizeof(file), "/tmp/inject-%s:%u-%s:%u-%lu.pcap", src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), idx); + + fp = fopen(file, "w+"); + if (fp) + { + gettimeofday(&ts, NULL); + pcap_hdr.tv_sec = ts.tv_sec; + pcap_hdr.tv_usec = ts.tv_usec; + + pcap_hdr.caplen = len; + pcap_hdr.len = len; + + fwrite(&DEFAULT_PCAP_FILE_HDR, sizeof(DEFAULT_PCAP_FILE_HDR), 1, fp); + fwrite(&pcap_hdr, sizeof(struct pcap_pkt_hdr), 1, fp); + fwrite(packet_get_data(pkt), 1, len, fp); + fflush(fp); + fclose(fp); + PACKET_IO_LOG_DEBUG("save packet to %s", file); + } + else + { + PACKET_IO_LOG_ERROR("unable to write pcap file: %s, %s", file, strerror(errno)); + } +} + typedef int file_handle(const char *file, void *arg); static int scan_directory(const char *dir, file_handle *handler, void *arg) @@ -165,6 +246,18 @@ static int dumpfile_handler(const char *file, void *arg) return 0; } +static int all_packet_processed(struct dumpfile_io *handle) +{ + for (uint16_t i = 0; i < handle->nr_threads; i++) + { + if (!lock_free_queue_empty(handle->queue[i])) + { + return 0; + } + } + return 1; +} + static void *dumpfile_thread(void *arg) { struct dumpfile_io *handle = (struct dumpfile_io *)arg; @@ -176,6 +269,11 @@ static void *dumpfile_thread(void *arg) while (ATOMIC_READ(&handle->io_thread_need_exit) == 0) { + if (all_packet_processed(handle)) + { + ATOMIC_SET(&handle->io_thread_wait_exit, 1); + } + PACKET_IO_LOG_STATE("dumpfile io thread waiting"); sleep(1); } @@ -259,6 +357,11 @@ void dumpfile_io_free(struct dumpfile_io *handle) } } +int dumpfile_io_wait_exit(struct dumpfile_io *handle) +{ + return ATOMIC_READ(&handle->io_thread_wait_exit); +} + int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx) { return 0; @@ -365,6 +468,8 @@ int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct pack stat->dev_tx_pkts++; stat->dev_tx_bytes += len; + save_packet(pkt, stat->inject_pkts); + packet_free(pkt); } diff --git a/src/packet_io/dumpfile_io.h b/src/packet_io/dumpfile_io.h index 0951882..fb9c7a8 100644 --- a/src/packet_io/dumpfile_io.h +++ b/src/packet_io/dumpfile_io.h @@ -11,6 +11,7 @@ extern "C" struct dumpfile_io; struct dumpfile_io *dumpfile_io_new(const char *directory, uint16_t nr_threads); void dumpfile_io_free(struct dumpfile_io *handle); +int dumpfile_io_wait_exit(struct dumpfile_io *handle); int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx); int dumpfile_io_ingress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts); diff --git a/src/packet_io/lock_free_queue.cpp b/src/packet_io/lock_free_queue.cpp index 0fd036a..a8d03e2 100644 --- a/src/packet_io/lock_free_queue.cpp +++ b/src/packet_io/lock_free_queue.cpp @@ -78,3 +78,9 @@ void lock_free_queue_pop(struct lock_free_queue *queue, void **data) *data = (void *)read; queue->head = (queue->head + 1) % queue->size; } + +int lock_free_queue_empty(struct lock_free_queue *queue) +{ + uint64_t read = ATOMIC_READ(&queue->queue[queue->head]); + return read == 0; +} \ No newline at end of file diff --git a/src/packet_io/lock_free_queue.h b/src/packet_io/lock_free_queue.h index 1dab21d..e6e0978 100644 --- a/src/packet_io/lock_free_queue.h +++ b/src/packet_io/lock_free_queue.h @@ -15,6 +15,7 @@ struct lock_free_queue; struct lock_free_queue *lock_free_queue_new(uint32_t size); void lock_free_queue_free(struct lock_free_queue *queue); +int lock_free_queue_empty(struct lock_free_queue *queue); int lock_free_queue_push(struct lock_free_queue *queue, void *data); void lock_free_queue_pop(struct lock_free_queue *queue, void **data); diff --git a/src/packet_io/packet_io.cpp b/src/packet_io/packet_io.cpp index 3b545d2..822c35d 100644 --- a/src/packet_io/packet_io.cpp +++ b/src/packet_io/packet_io.cpp @@ -58,6 +58,18 @@ void packet_io_free(struct packet_io *packet_io) } } +int packet_io_wait_exit(struct packet_io *packet_io) // used for dumpfile mode +{ + if (likely(packet_io->mode == PACKET_IO_MARSIO)) + { + return 0; + } + else + { + return dumpfile_io_wait_exit(packet_io->dumpfile); + } +} + int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx) { if (likely(packet_io->mode == PACKET_IO_MARSIO)) diff --git a/src/packet_io/packet_io.h b/src/packet_io/packet_io.h index 7415b2d..59bf049 100644 --- a/src/packet_io/packet_io.h +++ b/src/packet_io/packet_io.h @@ -83,6 +83,7 @@ struct inject_packet_meta struct packet_io; struct packet_io *packet_io_new(struct packet_io_options *opts); void packet_io_free(struct packet_io *packet_io); +int packet_io_wait_exit(struct packet_io *packet_io); // used for dumpfile mode int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx); int packet_io_ingress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts); diff --git a/src/session/session.cpp b/src/session/session.cpp index a72ae87..5b6f127 100644 --- a/src/session/session.cpp +++ b/src/session/session.cpp @@ -177,7 +177,7 @@ void session_get_route_ctx(const struct session *sess, enum flow_direction dir, void session_set_first_packet(struct session *sess, enum flow_direction dir, const struct packet *pkt) { - sess->first_pkt[dir] = packet_dup(pkt); + sess->first_pkt[dir] = pkt; } const struct packet *session_get_first_packet(const struct session *sess, enum flow_direction dir) diff --git a/src/session/session_manager.cpp b/src/session/session_manager.cpp index 034790c..d63f4b9 100644 --- a/src/session/session_manager.cpp +++ b/src/session/session_manager.cpp @@ -571,7 +571,7 @@ static void session_update(struct session *sess, enum session_state next_state, packet_get_route_ctx(pkt, &ctx); packet_get_sid_list(pkt, &list); - session_set_first_packet(sess, dir, pkt); + session_set_first_packet(sess, dir, packet_dup(pkt)); session_set_route_ctx(sess, dir, &ctx); session_set_sid_list(sess, dir, &list); } diff --git a/src/stellar/main.cpp b/src/stellar/main.cpp index 51fbd2f..aba22be 100644 --- a/src/stellar/main.cpp +++ b/src/stellar/main.cpp @@ -115,6 +115,11 @@ int main(int argc, char **argv) stellar_stat_output(runtime->stat); } usleep(1000); // 1ms + + if (packet_io_wait_exit(runtime->packet_io)) + { + ATOMIC_SET(&runtime->need_exit, 1); + } } error_out: diff --git a/src/stellar/stellar.cpp b/src/stellar/stellar.cpp index ee33fc6..61c49d8 100644 --- a/src/stellar/stellar.cpp +++ b/src/stellar/stellar.cpp @@ -123,6 +123,7 @@ static void *work_thread(void *arg) while (ATOMIC_READ(&runtime->need_exit) == 0) { now = timestamp_get_msec(); + memset(packets, 0, sizeof(packets)); nr_recv = packet_io_ingress(packet_io, thr_idx, packets, RX_BURST_MAX); if (nr_recv == 0) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f65ebdf..e7e3f36 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,15 +1,11 @@ -add_executable(gtest_build_tcp_packet gtest_build_tcp_packet.cpp) -target_link_libraries(gtest_build_tcp_packet core gtest) - -add_executable(gtest_build_udp_packet gtest_build_udp_packet.cpp) -target_link_libraries(gtest_build_udp_packet core gtest) +add_executable(gtest_inject_tcp_rst gtest_inject_tcp_rst.cpp packet_injector_test_frame.cpp) +target_link_libraries(gtest_inject_tcp_rst core gtest) include(GoogleTest) -gtest_discover_tests(gtest_build_tcp_packet) -gtest_discover_tests(gtest_build_udp_packet) +gtest_discover_tests(gtest_inject_tcp_rst) add_executable(packet_injector packet_injector.cpp) target_link_libraries(packet_injector core gtest) -file(COPY ./conf/log.toml DESTINATION ./conf/) -file(COPY ./conf/stellar.toml DESTINATION ./conf/) \ No newline at end of file +file(COPY ./conf/ DESTINATION ./conf/) +file(COPY ./pcap/ DESTINATION ./pcap/) \ No newline at end of file diff --git a/test/README.md b/test/README.md index d1ad5e6..258c239 100644 --- a/test/README.md +++ b/test/README.md @@ -29,4 +29,12 @@ tcpdump -i virtio_dign_s host 192.0.2.110 and port 80 -n -v -w virtio_dign_s.pca ``` shell kubectl -n tsg-os-system exec -it dign-client-9h8rm -c dign-client sh curl -v http://http.badssl.selftest.gdnt-cloud.website --resolve "http.badssl.selftest.gdnt-cloud.website:80:192.0.2.110" -``` \ No newline at end of file +``` + +## 结果 + +| -t | -c | -n | Note | result | +| ----------- | ----------- | ----------- | ---------------------------- | ----------- | +| tcp-rst | c2s-packet | 1 | After recv SYN | Failed | +| tcp-rst | s2c-packet | 1 | After recv SYN-ACK | Success | +| tcp-rst | c2s-packet | 2 | After recv Sub-ACK | Success | \ No newline at end of file diff --git a/test/gtest_build_tcp_packet.cpp b/test/gtest_build_tcp_packet.cpp deleted file mode 100644 index 8166b75..0000000 --- a/test/gtest_build_tcp_packet.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include - -#include "inject_priv.h" - -/****************************************************************************** - * BUILD_TCP_PACKET - ******************************************************************************/ - -// IPv4 -TEST(BUILD_IPV4_BASED_TCP_PACKET, WITH_RST) -{ - // TODO -} - -TEST(BUILD_IPV4_BASED_TCP_PACKET, WITH_FIN) -{ - // TODO -} - -TEST(BUILD_IPV4_BASED_TCP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// IPv6 -TEST(BUILD_IPV6_BASED_TCP_PACKET, WITH_RST) -{ - // TODO -} - -TEST(BUILD_IPV6_BASED_TCP_PACKET, WITH_FIN) -{ - // TODO -} - -TEST(BUILD_IPV6_BASED_TCP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// IPv4 + IPv6 -TEST(BUILD_IPV4_IPV6_BASED_TCP_PACKET, WITH_RST) -{ - // TODO -} - -// IPv6 + IPv4 -TEST(BUILD_IPV6_IPV4_BASED_TCP_PACKET, WITH_RST) -{ - // TODO -} - -// GRE -TEST(BUILD_GRE_BASED_TCP_PACKET, WITH_RST) -{ - // TODO -} - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/gtest_build_udp_packet.cpp b/test/gtest_build_udp_packet.cpp deleted file mode 100644 index eee7ebb..0000000 --- a/test/gtest_build_udp_packet.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include "inject_priv.h" - -/****************************************************************************** - * BUILD_UDP_PACKET - ******************************************************************************/ - -// IPv4 -TEST(BUILD_IPV4_BASED_UDP_PACKET, NO_PAYLOD) -{ - // TODO -} - -TEST(BUILD_IPV4_BASED_UDP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// IPv6 -TEST(BUILD_IPV6_BASED_UDP_PACKET, NO_PAYLOD) -{ - // TODO -} - -TEST(BUILD_IPV6_BASED_UDP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// IPv4 + IPv6 -TEST(BUILD_IPV4_IPV6_BASED_UDP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// IPv6 + IPv4 -TEST(BUILD_IPV6_IPV4_BASED_UDP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -// GRE -TEST(BUILD_GRE_BASED_UDP_PACKET, WITH_PAYLOD) -{ - // TODO -} - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/gtest_inject_tcp_rst.cpp b/test/gtest_inject_tcp_rst.cpp new file mode 100644 index 0000000..79e6e47 --- /dev/null +++ b/test/gtest_inject_tcp_rst.cpp @@ -0,0 +1,39 @@ +#include + +#include "packet_injector_test_frame.h" + +TEST(INJECT_IPV4_BASED_TCP_RST, AFTER_RECV_SYN_ACK) +{ + struct packet_injector_case test = { + // descriptor + .finish_clean_work_dir = 1, + .descriptor = "Inject IPv4 based TCP RST after receiving SYN-ACK packet.", + .work_dir = "/tmp/inject_ipv4_based_tcp_rst_after_recv_syn_ack/", // user defined work directory + + // prefix + .input_prefix = "pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/", + .output_prefix = "/tmp/", + + // input pcap + .input_pcap = "input.pcap", + + // compare + .c2s_expect_pcap = "expect-192.0.2.211:59942-192.0.2.110:80-1.pcap", + .c2s_output_pcap = "inject-192.0.2.211:59942-192.0.2.110:80-1.pcap", + + .s2c_expect_pcap = "expect-192.0.2.110:80-192.0.2.211:59942-2.pcap", + .s2c_output_pcap = "inject-192.0.2.110:80-192.0.2.211:59942-2.pcap", + + // packet injector command + .packet_injector_cmd = "./packet_injector -t tcp-rst -c s2c-packet -n 1", + .diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size", + }; + + packet_injector_test_frame_run(&test); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/packet_injector.cpp b/test/packet_injector.cpp index 9bc5abc..f21b084 100644 --- a/test/packet_injector.cpp +++ b/test/packet_injector.cpp @@ -339,12 +339,12 @@ static int parse_cmdline(int argc, char **argv, struct inject_rule *rule) printf("invalid count\n"); return -1; } - printf("load inject rule:\n"); - printf(" host : %s\n", host); - printf(" port : %d\n", ntohs(rule->port)); - printf(" type : %s\n", type); - printf(" condition : %s\n", condition); - printf(" count : %lu\n\n", rule->count_num); + printf("%s load inject rule:\n", argv[0]); + printf(" host : %s\n", host); + printf(" port : %d\n", ntohs(rule->port)); + printf(" type : %s\n", type); + printf(" condition : %s\n", condition); + printf(" count : %lu\n\n", rule->count_num); return 0; } @@ -368,7 +368,6 @@ int main(int argc, char **argv) STELLAR_LOG_ERROR("unable to init log"); goto error_out; } - STELLAR_LOG_STATE("start stellar (version: %s)\n %s", __stellar_version, logo_str); if (stellar_load_config(stellar_config_file, config) != 0) { @@ -427,6 +426,11 @@ int main(int argc, char **argv) stellar_stat_output(runtime->stat); } usleep(1000); // 1ms + + if (packet_io_wait_exit(runtime->packet_io)) + { + ATOMIC_SET(&runtime->need_exit, 1); + } } error_out: diff --git a/test/packet_injector_test_frame.cpp b/test/packet_injector_test_frame.cpp new file mode 100644 index 0000000..d049eb6 --- /dev/null +++ b/test/packet_injector_test_frame.cpp @@ -0,0 +1,205 @@ +#include + +#include +#include +#include +#include "packet_injector_test_frame.h" + +static void system_cmd(const char *cmd, ...) +{ + char buf[1024] = {0}; + va_list args; + + va_start(args, cmd); + vsnprintf(buf, sizeof(buf), cmd, args); + va_end(args); + + system(buf); +} + +static int replace_file_string(const char *file, const char *old_str, const char *new_str) +{ +#define BUFFER_SIZE 1024 + + FILE *in_fp = fopen(file, "r"); + if (in_fp == NULL) + { + printf("Open file %s failed, %s\n", file, strerror(errno)); + return -1; + } + + FILE *tmp_fp = tmpfile(); + if (tmp_fp == NULL) + { + printf("Create temporary file failed, %s\n", strerror(errno)); + fclose(in_fp); + return -1; + } + + size_t old_len = strlen(old_str); + size_t new_len = strlen(new_str); + char buff[BUFFER_SIZE]; + + while (fgets(buff, BUFFER_SIZE, in_fp)) + { + char *pos = buff; + if ((pos = strstr(pos, old_str))) + { + fwrite(buff, 1, pos - buff, tmp_fp); // Write characters before the old_str + fwrite(new_str, 1, new_len, tmp_fp); // Write the new_str + pos += old_len; // Move past the old_str + fwrite(pos, 1, strlen(pos), tmp_fp); // Write characters after the old_str + } + else + { + fputs(buff, tmp_fp); // Write the remaining part of the line + } + } + + fclose(in_fp); + fseek(tmp_fp, 0, SEEK_SET); + + FILE *out_fp = fopen(file, "w"); + if (out_fp == NULL) + { + printf("Open file %s for writing failed, %s\n", file, strerror(errno)); + fclose(tmp_fp); + return -1; + } + + while (fgets(buff, BUFFER_SIZE, tmp_fp)) + { + fputs(buff, out_fp); // Write the contents of the temporary file to the original file + } + + fclose(tmp_fp); + fclose(out_fp); + + return 0; +} + +static void expect_cmp_inject(const char *work_dir, + const char *expect_dir_abs_path, const char *expect_pcap_file, + const char *output_dir_abs_path, const char *output_pcap_file, + const char *diff_skip_pattern, const char *flow_dir) +{ + printf("\033[32m ============================================= \033[0m\n"); + printf("\033[32m Compare [%s] expect pcap and output pcap \033[0m\n", flow_dir); + printf("\033[32m ============================================= \033[0m\n"); + + struct stat s; + char expect_pcap_file_abs_path[1024] = {0}; + char output_pcap_file_abs_path[1024] = {0}; + char expect_json_file_abs_path[1024] = {0}; + char output_json_file_abs_path[1024] = {0}; + char diff_txt_file_abs_path[1024] = {0}; + + // absulute path + snprintf(expect_pcap_file_abs_path, sizeof(expect_pcap_file_abs_path), "%s/%s", expect_dir_abs_path, expect_pcap_file); + snprintf(output_pcap_file_abs_path, sizeof(output_pcap_file_abs_path), "%s/%s", output_dir_abs_path, output_pcap_file); + snprintf(expect_json_file_abs_path, sizeof(expect_json_file_abs_path), "%s/expect_%s.json", work_dir, flow_dir); + snprintf(output_json_file_abs_path, sizeof(output_json_file_abs_path), "%s/output_%s.json", work_dir, flow_dir); + snprintf(diff_txt_file_abs_path, sizeof(diff_txt_file_abs_path), "%s/diff_%s.txt", work_dir, flow_dir); + + // check pcap file size + stat(expect_pcap_file_abs_path, &s); + EXPECT_TRUE(s.st_size > 0); + + stat(output_pcap_file_abs_path, &s); + EXPECT_TRUE(s.st_size > 0); + + // tcpdump + printf("\033[32m tcpdump read [%s] expect pcap (%s) \033[0m\n", flow_dir, expect_pcap_file); + system_cmd("tcpdump -r %s", expect_pcap_file_abs_path); + + printf("\033[32m tcpdump read [%s] output pcap (%s) \033[0m\n", flow_dir, output_pcap_file); + system_cmd("tcpdump -r %s", output_pcap_file_abs_path); + + // tshark + system_cmd("tshark -r %s -T json | jq >> %s", expect_pcap_file_abs_path, expect_json_file_abs_path); + system_cmd("tshark -r %s -T json | jq >> %s", output_pcap_file_abs_path, output_json_file_abs_path); + + // check json file size + stat(expect_json_file_abs_path, &s); + EXPECT_TRUE(s.st_size > 0); + + stat(output_json_file_abs_path, &s); + EXPECT_TRUE(s.st_size > 0); + + // diff + system_cmd("diff %s %s %s >> %s", diff_skip_pattern, expect_json_file_abs_path, output_json_file_abs_path, diff_txt_file_abs_path); + + // check diff file size + stat(diff_txt_file_abs_path, &s); + EXPECT_TRUE(s.st_size == 0); +} + +void packet_injector_test_frame_run(struct packet_injector_case *test) +{ + printf("\033[32mTest: %s\033[0m\n", test->descriptor); + + char config_file_abs_path[1024] = {0}; + char input_dir_abs_path[1024] = {0}; + char output_dir_abs_path[1024] = {0}; + char expect_dir_abs_path[1024] = {0}; + + // absulute path + snprintf(config_file_abs_path, sizeof(config_file_abs_path), "%s/conf/stellar.toml", test->work_dir); + snprintf(input_dir_abs_path, sizeof(input_dir_abs_path), "%s/input/", test->work_dir); + snprintf(output_dir_abs_path, sizeof(output_dir_abs_path), "%s/output/", test->work_dir); + snprintf(expect_dir_abs_path, sizeof(expect_dir_abs_path), "%s/expect/", test->work_dir); + + // create directory + system_cmd("rm -rf %s", test->work_dir); + system_cmd("mkdir -p %s", input_dir_abs_path); + system_cmd("mkdir -p %s", output_dir_abs_path); + system_cmd("mkdir -p %s", expect_dir_abs_path); + + // copy file to work directory + if (test->c2s_expect_pcap) + { + system_cmd("cp %s/%s %s", test->input_prefix, test->c2s_expect_pcap, expect_dir_abs_path); + } + if (test->s2c_expect_pcap) + { + system_cmd("cp %s/%s %s", test->input_prefix, test->s2c_expect_pcap, expect_dir_abs_path); + } + system_cmd("cp %s/%s %s", test->input_prefix, test->input_pcap, input_dir_abs_path); + system_cmd("cp -r conf %s/", test->work_dir); + system_cmd("cp packet_injector %s/", test->work_dir); + + // replace config file + char temp[2048] = {0}; + snprintf(temp, sizeof(temp), "dumpfile_dir = \"%s\"", input_dir_abs_path); + EXPECT_TRUE(replace_file_string(config_file_abs_path, "mode = marsio", "mode = dumpfile") == 0); + EXPECT_TRUE(replace_file_string(config_file_abs_path, "dumpfile_dir = \"/tmp/dumpfile/\"", temp) == 0); + + // run packet injector + chdir(test->work_dir); + system_cmd(test->packet_injector_cmd); + chdir("../"); + + // compare pcap + if (test->c2s_output_pcap && test->c2s_expect_pcap) + { + system_cmd("mv %s/%s %s", test->output_prefix, test->c2s_output_pcap, output_dir_abs_path); + expect_cmp_inject(test->work_dir, + expect_dir_abs_path, test->c2s_expect_pcap, + output_dir_abs_path, test->c2s_output_pcap, + test->diff_skip_pattern, "C2S"); + } + if (test->s2c_output_pcap && test->s2c_expect_pcap) + { + system_cmd("mv %s/%s %s", test->output_prefix, test->s2c_output_pcap, output_dir_abs_path); + expect_cmp_inject(test->work_dir, + expect_dir_abs_path, test->s2c_expect_pcap, + output_dir_abs_path, test->s2c_output_pcap, + test->diff_skip_pattern, "S2C"); + } + + // clean work directory + if (test->finish_clean_work_dir) + { + system_cmd("rm -rf %s", test->work_dir); + } +} diff --git a/test/packet_injector_test_frame.h b/test/packet_injector_test_frame.h new file mode 100644 index 0000000..ade3f30 --- /dev/null +++ b/test/packet_injector_test_frame.h @@ -0,0 +1,41 @@ +#ifndef _PACKET_INJECTOR_TEST_FRAME_H +#define _PACKET_INJECTOR_TEST_FRAME_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct packet_injector_case +{ + // descriptor + int finish_clean_work_dir; + const char *descriptor; + const char *work_dir; + + // prefix + const char *input_prefix; + const char *output_prefix; + + // input pcap + const char *input_pcap; + + // compare + const char *c2s_expect_pcap; + const char *c2s_output_pcap; + + const char *s2c_expect_pcap; + const char *s2c_output_pcap; + + // packet injector command + const char *packet_injector_cmd; + const char *diff_skip_pattern; +}; + +void packet_injector_test_frame_run(struct packet_injector_case *test); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/fw.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/fw.pcap new file mode 100644 index 0000000000000000000000000000000000000000..9a643327cfda9a1950916294c274f1c1b9fe6556 GIT binary patch literal 6048 zcmds5U1%It6h6DzZkvsZH3%(vah}@JCX<={&k#sblP1_k7fkdamSM6plbv=lJIu@` zn<7-~OCh1+?}J5KEEV;sLMxJ|3OImTdkIK~o9dJxDiX|q=@@bY&cJZvDXV_9EC8iPp zA$SO;EmJN|o6HQ)a`-BcAM)Yd$<~UNR?aYk*i#HUrDC53hw<;lD{r*!YXx{1c7vJI zx;VUq#H7G+Yxv`R{;iVN0)wqsfpW>v;jnDNL2HBKP3bAr*=UzUN zU+h@rt0zOTxxPFfHETT$5X7~)zT%a2zP|sCah-fU0yDBQ(>0@6j#dzhwqkKOo-WUi zcPE=0o8KSqJMEh=-hTA_{`&s-RsJ&QXT@6aIS4z!P(@BuX9vmO_b>If%@5Oz05m>~ z?I(O`2j1^5f3YWV_B-VX>{I*s)UWg7CF9$VFFd)h3x)uCmjnIKAHGq#4#8X4jLSjD z-uv*E$8a!Q4E}!iol%@IwBu?hxGOUH+R;zR9%yNaP#hs_G+)S#@p<|MUIC}n$(RMp z5jA7VQfym@SDuy1W2}?WY!R1`vlPiu1g?{rRwTPc7%yI z#~o)T{-%im+(}up$e*H$x@MfLcy}yGRkd8zlu9P!Nq3N`D3&`Y0MEH|S<)<%S0q_T zcQTHo=|ZZL$w{V^)0{c7<%*VwF$p~K1{a~pwoo@F`W?fq22I!!#=rS6o>&@CHw$Ar ze}pk%UB>tlSpOl$v7T5uo=)&dE|y5gGjR_0vJU84gP1eTj5%Swn%5(r9Ij$sW^|d| zWnKgHBd@QWB2Htw1=-8N6IY#ij#+E;dNsB@|xc! zyneOx_@-gJE?#dT#+%LSX2jg%^^z}_cP9tc!9vM!ZIr`|33D*}>MFb(%Z=f6Cc}Ddp@z+;mTiUAa4`zK=F)HQ1hC zZgH{QQy1I4(D&vCE3q9O8e_Vdk+HFCH_!6X$VdUz4U=~qlbw`g+tyiI(N#yW9d=4K zoUWW+D9Y@tGHGj$5{-iK5i2IYUcm zYtA!dp>}IX>)|?@SL@N)p)=&q50`chsVTHkt2sjlE)4alw zPk;W;qb&d%&~=zpYqUG6S=9FpYxi~Lf4xC`&3}gPGb^<`uGiJ_xW;-~zAEIaYQ3(c zM?G)rUViXn+r~b?wnoz(`0-3X^o4In5L>^dTOdt`*k%{MZV218YWvn>JGoJ8H&)v> z3)`aXVLRr_{bz0tZQI=M&lTm|zkytV2)ml)SF91kSTsyZqUr?6Fh5+7e^YR6{M&IRc{BkX5#_zp`^Q>F4WT*7mjX|JL($wn4sDYkM=|OSt|CSLmre literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_c.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_c.pcap new file mode 100644 index 0000000000000000000000000000000000000000..9d69b1c5127af339646c907f4cb6d595fba1ab66 GIT binary patch literal 611 zcmca|c+)~A1{MYcU}0bcayZ%?(->CqF?a#lApETAb9ZP(-mM+;{dzbUTp1W_-ZDBc zIIx|lIKaSk8Hn?iGBE`F*!WH!WYPkrUmq6vGB7Z)ux?>t;^6X~;(Y`p&dAKn1v2^L z5roMQGa=?fOlDvJnY^_MWGcvXhJd9^SzAiFfu<`g5c=0K7ic}q5?`aTVus;SH0-&Ilz7{VRFF256fDShUIvRvA0$Jl>vjc-Y+f^=5Fn}Bn4dfnBAP0!B1njy2 aNd$NBngWfgK6F!nRx$(tQ`ItV1_l6FkGkam literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_s.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/raw/virtio_dign_s.pcap new file mode 100644 index 0000000000000000000000000000000000000000..06833e662aff2b8c3b5970786732dc8692e302f7 GIT binary patch literal 529 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 VU5PZFctYa}M*US3_0e99{{ghGS+D>A literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/virtio_dign_s.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/virtio_dign_s.pcap new file mode 100644 index 0000000000000000000000000000000000000000..cdf92ba62bdbf22c45eea1ebacd5f48b5afc2b4d GIT binary patch literal 1836 zcma)+Pi)&%9LHbNFm0C7trLiffq3{drrJ)LH0|8{D_gY*78bx&$I-EWiLJVJWWS_M z5z;Q3K&!;PNMnctDyOXiZCuc#oEQ=UvD1)tQ z{?lC&`vsf3t&z$-cJmKTsyrV*`lLn3KS;U%XpFpxW4sMeavi-yN{1dz45QqL{k!u; zijY|Rxv%4~!$SF;tpcZyjE)MN{QEv~q%7ix`f`MD@;B>T8>f@Xwsu7R^$Kd-xpDlz zkLIrQ$Uk;&UgPv#^2d+I$Q!s4Zv&b$oocB0RZivfZst2kzk2x?DO%T2<4B~JleyNP zk+_94-Uf)Db_`DZ^Y&2U1S!t$>=BEccy2+X3O%oB6(uF762f^eU@Em3YsgjI3<5_E zz^O3^m|QnqCK-;`H04#O1~!9)uo!?Z&DX)jNk-Fmlo>gjm6Hi!-Y}qngQt{J2_X@h z{9vCI114uSZ*$=<{lIPD;=3kay~l1Xp%o=76A4Gr8)$HmTT%XNjKC-f+d<;!(&imb zeDTYn#0gSLoaiU+nn0(LNqX_Egzz5tE$~(9)@^r<+mn>j^yFf->9XeQ3E`~HK&55R zousKWE$eNZIF+HvDK(i^(=+s3SxX3KJeQ$6lGbiuFoQLwSZu}V{kQ;bomncKPNVx5 z^ngia&$Mecm@3tpFiDd$eeCIJHIvz6yI?Teb5*(w(2#V;ZsDdZXnI|xVm6yTeR?*X zl%`T?5f{`A3nZ?`_Z&>hlLF@X7#?kv^sesKAy8?xjl0eFEce>ki)Xa=D+_oWR-A&6 z+kJs<76eLjE5LMWSh^no%Zp7`lV-)<4_9A-yx6i~wc+_pq(H$(YQrJf2!bfN zuv@5lW}ALMtGcmV_r0czn~r(R(GPP<6d>djEA%_ZLva&KyG3m?FLv#WU{;ET;d!x! zE=z&Ej)!fwwK^C6rq6nxc@Bz|!c`PprXb+EyJ~o73*j~1#!L5V6vmj8Y#5klh2Ly6-^93LbW_Yn^k29nwQHY_#Y_ZNnTTUcr?T^=VT iINDzrxW?=IhyztO)2W3TPaM#A3A6qx%=%cr#{U5pKvzrv literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/fw.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/fw.pcap new file mode 100644 index 0000000000000000000000000000000000000000..81a8b702591b67f5816d3dee9414d6ab817f2228 GIT binary patch literal 2952 zcmdT_PiPcp6o0$ftR^*DB~Zy}PDvn}WoBpgPlg=!(h8cCy{rdg8OEJ&vLD&Z4l}dK zCKL)iwWLHUtrww9Nn1RqDA*cW3s${&NejV?NTDhoG>3v7#Dn_Y?4PXJ#h4V^_$`m` z``*0yeeZq0{k`ez>gvn@!07NmPXOoV)zJn$Fv6`;S%^oaWK@a|N>NrwMa!v#mQVmf zunQ&~+bB)i!ju#h@l_xk!l=#U>p)M3XxTwrG0RPuxTfGR{ysf_vZJ>HU=O?tc8(8< zI8^1BDvBH6Ney_oma2HMo2S2d@^ec(3aRHcf@{i?hM%907Y4&NCe&CZxA`wW$p6x_ z4r?eyx%pT%jHX&Y0SIDkK9*dq^XtA<>k47*g(-tg4Nh^#<3+9HGDpOC8a15SOg=xi zMm)TCx;Hhu@6f5f)_Br7ycFWRR4eX-umdbp6E$=CH^Tet`0zV(2k1lqiVvgR!Iu&%J++nV( z%GEuqZetOFyBd~|bC~WiRg4IeOm|BTn`D-!c{4UsQ+`a&a|*{wCPmo#OrfY7TG2FJ z=8?z0e_FVB2rpV1H)xmF-8^#RsB$8fj3;GzNKr7a0dTn?6u9fDW3niIB#gbnv;f|u z!5zY5rdHtAL>1k0bkpRyx+@Wn%W*%*X3X(}0&vtn%h9KWJkt#|84*047t};V$mzD8 zF^=i~M;sH^6^<9d`5!rs z4aJgjQjwIQL`qR&sZ?vy`6f9Rwln9%^?F_N`5)?>R}@`QcSY9#Y1H*kv!rRX705j3 zeRyR2Z`AhXg?-OHJG*;L*UPK>?~=Bgb-l)U3tcO3udbzStn1qix}GclC?`;NWKF%h z|9U75vGDWHiC^Nm+Pg0!&v!E2?b$4S0#LUh{~J=%a2|aD*n)=f(wh1-Y7cw)ru+13 zYIu5+8n*wPh7Z5ox3ONoZ)1(E`gXl(*E@5|_Km%}P$W)Czm42pxUt4`#Lc n{+$u8#BZa1Gu@%3?Bb@l-AJqdJ-6|#a=SI{zA0`UmpFX^h8`g< literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/virtio_dign_c.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/raw/virtio_dign_c.pcap new file mode 100644 index 0000000000000000000000000000000000000000..a826169fe27f275622812ab9044c3eaed14f3828 GIT binary patch literal 184 zcmca|c+)~A1{MYcU}0bca)Rm|)A|^h7`%XN5PnwmxjVEX@79j_emxuvt_%z|>;?`D z4s7eZ4lpoX2I9O|Y77B~4xir*GHC(RuMe*eGcYi*ux?>t;^6YF5}XDSXJlsP0-3DJ z%*0>@Ey-H2qP42y194D+2=nk&jXH literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.110:80-192.0.2.211:59942-2.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.110:80-192.0.2.211:59942-2.pcap new file mode 100644 index 0000000000000000000000000000000000000000..66a6ee3c78ebb2dd298cb21e5cb73bc4a462baae GIT binary patch literal 94 zcmca|c+)~A1{MYcU}0bca)Rm|(^Q$67|eid5YD@`W4>R{v#QVCp%okqt_%zs7c?9g kQrHfr9$;X~1LDgJ0k70vN2NbJbol(901=iQp^F(901k5-KL7v# literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.211:59942-192.0.2.110:80-1.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/expect-192.0.2.211:59942-192.0.2.110:80-1.pcap new file mode 100644 index 0000000000000000000000000000000000000000..bca10d5b4078b7217567f57f546b1235db9c126f GIT binary patch literal 94 zcmca|c+)~A1{MYcU}0bca)Rm|)0CN+7|eid5PnwmxjVEX@79j_emxuvt_%zsM_3#f kjM)Bn9$;X)48(b_)EEK|9X`M3byWJJ01?*EP*w&801o{cJ^%m! literal 0 HcmV?d00001 diff --git a/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/input.pcap b/test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/input.pcap new file mode 100644 index 0000000000000000000000000000000000000000..01e5164123f5b451d657919f0033881b4d503275 GIT binary patch literal 1428 zcmdT?zi-n(6n^>9w2dfG7EmWoU7AF896PDiAp61 zF#jB`3@pG^?#Eq8D=F2Iq7{`A^J=ATO*i!lKo-tGO9W2b3Z#xwlCc$thd3?|GbWhD z$}HwI{xUz*UD*!^d=Ab-VDqAk%cyJ^vOM4z^^WpH4#f|Y$sAN3-(SZ)>7jM3BL`04 zY#HSf8kTFMA?dFp{?G3i_N&xC4;_bfiXAQ@-ZtZqiDVGiKhi(SSURl%=QxQY5%C*G z0r#ihF%7J(RI_7Yq9#MZ?;an)ozR%5iT+2qW6?By^7f?1{N9tX#{+i