Add packet injector test frame
This commit is contained in:
@@ -120,16 +120,25 @@ struct packet *packet_dup(const struct packet *pkt)
|
|||||||
{
|
{
|
||||||
return NULL;
|
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++)
|
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].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].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
|
// update frag_layer
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ struct dumpfile_io
|
|||||||
struct io_stat stat[MAX_THREAD_NUM];
|
struct io_stat stat[MAX_THREAD_NUM];
|
||||||
uint64_t io_thread_need_exit;
|
uint64_t io_thread_need_exit;
|
||||||
uint64_t io_thread_is_runing;
|
uint64_t io_thread_is_runing;
|
||||||
|
uint64_t io_thread_wait_exit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcap_pkt
|
struct pcap_pkt
|
||||||
@@ -34,10 +35,90 @@ struct pcap_pkt
|
|||||||
int len;
|
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
|
* 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);
|
typedef int file_handle(const char *file, void *arg);
|
||||||
|
|
||||||
static int scan_directory(const char *dir, file_handle *handler, 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;
|
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)
|
static void *dumpfile_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct dumpfile_io *handle = (struct dumpfile_io *)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)
|
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");
|
PACKET_IO_LOG_STATE("dumpfile io thread waiting");
|
||||||
sleep(1);
|
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)
|
int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx)
|
||||||
{
|
{
|
||||||
return 0;
|
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_pkts++;
|
||||||
stat->dev_tx_bytes += len;
|
stat->dev_tx_bytes += len;
|
||||||
|
|
||||||
|
save_packet(pkt, stat->inject_pkts);
|
||||||
|
|
||||||
packet_free(pkt);
|
packet_free(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ extern "C"
|
|||||||
struct dumpfile_io;
|
struct dumpfile_io;
|
||||||
struct dumpfile_io *dumpfile_io_new(const char *directory, uint16_t nr_threads);
|
struct dumpfile_io *dumpfile_io_new(const char *directory, uint16_t nr_threads);
|
||||||
void dumpfile_io_free(struct dumpfile_io *handle);
|
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_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);
|
int dumpfile_io_ingress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
|
||||||
|
|||||||
@@ -78,3 +78,9 @@ void lock_free_queue_pop(struct lock_free_queue *queue, void **data)
|
|||||||
*data = (void *)read;
|
*data = (void *)read;
|
||||||
queue->head = (queue->head + 1) % queue->size;
|
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;
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ struct lock_free_queue;
|
|||||||
|
|
||||||
struct lock_free_queue *lock_free_queue_new(uint32_t size);
|
struct lock_free_queue *lock_free_queue_new(uint32_t size);
|
||||||
void lock_free_queue_free(struct lock_free_queue *queue);
|
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);
|
int lock_free_queue_push(struct lock_free_queue *queue, void *data);
|
||||||
void lock_free_queue_pop(struct lock_free_queue *queue, void **data);
|
void lock_free_queue_pop(struct lock_free_queue *queue, void **data);
|
||||||
|
|||||||
@@ -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)
|
int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx)
|
||||||
{
|
{
|
||||||
if (likely(packet_io->mode == PACKET_IO_MARSIO))
|
if (likely(packet_io->mode == PACKET_IO_MARSIO))
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ struct inject_packet_meta
|
|||||||
struct packet_io;
|
struct packet_io;
|
||||||
struct packet_io *packet_io_new(struct packet_io_options *opts);
|
struct packet_io *packet_io_new(struct packet_io_options *opts);
|
||||||
void packet_io_free(struct packet_io *packet_io);
|
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_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);
|
int packet_io_ingress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
|
||||||
|
|||||||
@@ -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)
|
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)
|
const struct packet *session_get_first_packet(const struct session *sess, enum flow_direction dir)
|
||||||
|
|||||||
@@ -571,7 +571,7 @@ static void session_update(struct session *sess, enum session_state next_state,
|
|||||||
packet_get_route_ctx(pkt, &ctx);
|
packet_get_route_ctx(pkt, &ctx);
|
||||||
packet_get_sid_list(pkt, &list);
|
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_route_ctx(sess, dir, &ctx);
|
||||||
session_set_sid_list(sess, dir, &list);
|
session_set_sid_list(sess, dir, &list);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ int main(int argc, char **argv)
|
|||||||
stellar_stat_output(runtime->stat);
|
stellar_stat_output(runtime->stat);
|
||||||
}
|
}
|
||||||
usleep(1000); // 1ms
|
usleep(1000); // 1ms
|
||||||
|
|
||||||
|
if (packet_io_wait_exit(runtime->packet_io))
|
||||||
|
{
|
||||||
|
ATOMIC_SET(&runtime->need_exit, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_out:
|
error_out:
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ static void *work_thread(void *arg)
|
|||||||
while (ATOMIC_READ(&runtime->need_exit) == 0)
|
while (ATOMIC_READ(&runtime->need_exit) == 0)
|
||||||
{
|
{
|
||||||
now = timestamp_get_msec();
|
now = timestamp_get_msec();
|
||||||
|
memset(packets, 0, sizeof(packets));
|
||||||
nr_recv = packet_io_ingress(packet_io, thr_idx, packets, RX_BURST_MAX);
|
nr_recv = packet_io_ingress(packet_io, thr_idx, packets, RX_BURST_MAX);
|
||||||
if (nr_recv == 0)
|
if (nr_recv == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
add_executable(gtest_build_tcp_packet gtest_build_tcp_packet.cpp)
|
add_executable(gtest_inject_tcp_rst gtest_inject_tcp_rst.cpp packet_injector_test_frame.cpp)
|
||||||
target_link_libraries(gtest_build_tcp_packet core gtest)
|
target_link_libraries(gtest_inject_tcp_rst core gtest)
|
||||||
|
|
||||||
add_executable(gtest_build_udp_packet gtest_build_udp_packet.cpp)
|
|
||||||
target_link_libraries(gtest_build_udp_packet core gtest)
|
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_discover_tests(gtest_build_tcp_packet)
|
gtest_discover_tests(gtest_inject_tcp_rst)
|
||||||
gtest_discover_tests(gtest_build_udp_packet)
|
|
||||||
|
|
||||||
add_executable(packet_injector packet_injector.cpp)
|
add_executable(packet_injector packet_injector.cpp)
|
||||||
target_link_libraries(packet_injector core gtest)
|
target_link_libraries(packet_injector core gtest)
|
||||||
|
|
||||||
file(COPY ./conf/log.toml DESTINATION ./conf/)
|
file(COPY ./conf/ DESTINATION ./conf/)
|
||||||
file(COPY ./conf/stellar.toml DESTINATION ./conf/)
|
file(COPY ./pcap/ DESTINATION ./pcap/)
|
||||||
@@ -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
|
``` shell
|
||||||
kubectl -n tsg-os-system exec -it dign-client-9h8rm -c dign-client sh
|
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"
|
curl -v http://http.badssl.selftest.gdnt-cloud.website --resolve "http.badssl.selftest.gdnt-cloud.website:80:192.0.2.110"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 结果
|
||||||
|
|
||||||
|
| -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 |
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
39
test/gtest_inject_tcp_rst.cpp
Normal file
39
test/gtest_inject_tcp_rst.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
@@ -339,12 +339,12 @@ static int parse_cmdline(int argc, char **argv, struct inject_rule *rule)
|
|||||||
printf("invalid count\n");
|
printf("invalid count\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("load inject rule:\n");
|
printf("%s load inject rule:\n", argv[0]);
|
||||||
printf(" host : %s\n", host);
|
printf(" host : %s\n", host);
|
||||||
printf(" port : %d\n", ntohs(rule->port));
|
printf(" port : %d\n", ntohs(rule->port));
|
||||||
printf(" type : %s\n", type);
|
printf(" type : %s\n", type);
|
||||||
printf(" condition : %s\n", condition);
|
printf(" condition : %s\n", condition);
|
||||||
printf(" count : %lu\n\n", rule->count_num);
|
printf(" count : %lu\n\n", rule->count_num);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,6 @@ int main(int argc, char **argv)
|
|||||||
STELLAR_LOG_ERROR("unable to init log");
|
STELLAR_LOG_ERROR("unable to init log");
|
||||||
goto error_out;
|
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)
|
if (stellar_load_config(stellar_config_file, config) != 0)
|
||||||
{
|
{
|
||||||
@@ -427,6 +426,11 @@ int main(int argc, char **argv)
|
|||||||
stellar_stat_output(runtime->stat);
|
stellar_stat_output(runtime->stat);
|
||||||
}
|
}
|
||||||
usleep(1000); // 1ms
|
usleep(1000); // 1ms
|
||||||
|
|
||||||
|
if (packet_io_wait_exit(runtime->packet_io))
|
||||||
|
{
|
||||||
|
ATOMIC_SET(&runtime->need_exit, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_out:
|
error_out:
|
||||||
|
|||||||
205
test/packet_injector_test_frame.cpp
Normal file
205
test/packet_injector_test_frame.cpp
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
test/packet_injector_test_frame.h
Normal file
41
test/packet_injector_test_frame.h
Normal file
@@ -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
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/fw.pcap
Normal file
BIN
test/pcap/inject_ipv4_based_tcp_rst_after_recv_syn/raw/fw.pcap
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user