Skip to content

Commit

Permalink
add server
Browse files Browse the repository at this point in the history
  • Loading branch information
yunwei37 committed Apr 29, 2024
1 parent a13320b commit 4c3c634
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 3 deletions.
75 changes: 73 additions & 2 deletions src/test_udp_pkt.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static __be16 __calc_udp_cksum(const struct test_udp_packet *pkt)
return bpf_htons(~chksum);
}

static struct test_udp_packet create_test_udp_packet(void)
static struct test_udp_packet create_test_udp_packet_v6(void)
{
struct test_udp_packet pkt = {0};

Expand All @@ -49,7 +49,7 @@ static struct test_udp_packet create_test_udp_packet(void)
// b8:3f:d2:2a:e5:11
memcpy(pkt.eth.h_dest, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe5, 0x11}, sizeof(pkt.eth.h_dest));
// b8:3f:d2:2a:e7:69
// memcpy(pkt.eth.h_source, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe7, 0x69}, sizeof(pkt.eth.h_source));
memcpy(pkt.eth.h_source, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe7, 0x69}, sizeof(pkt.eth.h_source));

// IPv6 header
pkt.iph.version = 6;
Expand All @@ -74,4 +74,75 @@ static struct test_udp_packet create_test_udp_packet(void)
return pkt;
}


// Packed attribute to prevent padding
struct __attribute__((__packed__)) test_udp_packet_v4
{
struct ethhdr eth;
struct iphdr iph;
struct udphdr udp;
uint8_t payload[64 - sizeof(struct udphdr) - sizeof(struct ethhdr) - sizeof(struct iphdr)];
};

// Helper function to calculate IP checksum
static uint16_t ip_checksum(void *vdata, size_t length) {
char *data = vdata;
uint64_t acc = 0xffff;

for (size_t i = 0; i + 1 < length; i += 2) {
uint16_t word;
memcpy(&word, data + i, 2);
acc += ntohs(word);
if (acc > 0xffff) {
acc -= 0xffff;
}
}

if (length & 1) {
uint16_t word = 0;
memcpy(&word, data + length - 1, 1);
acc += ntohs(word);
if (acc > 0xffff) {
acc -= 0xffff;
}
}

return htons(~acc);
}

#define PORT 9876
#define SERVER_IP "127.0.0.1"

static struct test_udp_packet_v4 create_test_udp_packet_v4(void) {
struct test_udp_packet_v4 pkt = {0};

// Ethernet header
pkt.eth.h_proto = htons(ETH_P_IP);
memcpy(pkt.eth.h_dest, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe5, 0x11}, sizeof(pkt.eth.h_dest));
memcpy(pkt.eth.h_source, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe7, 0x69}, sizeof(pkt.eth.h_source));

// IPv4 header
pkt.iph.version = 4;
pkt.iph.ihl = 5;
pkt.iph.tot_len = htons(sizeof(struct test_udp_packet_v4));
pkt.iph.ttl = 64; // default TTL
pkt.iph.protocol = IPPROTO_UDP;
pkt.iph.saddr = inet_addr(SERVER_IP);
pkt.iph.daddr = inet_addr(SERVER_IP);
pkt.iph.check = ip_checksum(&pkt.iph, sizeof(struct iphdr)); // Calculate IPv4 header checksum

// UDP header
pkt.udp.source = htons(12345);
pkt.udp.dest = htons(PORT); // Use the PORT macro if you want to match the listening server
pkt.udp.len = htons(sizeof(struct udphdr) + sizeof(pkt.payload)); // UDP length field

// No need for UDP checksum for IPv4 in this controlled test environment unless required
pkt.udp.check = 0;

// Payload
memset(pkt.payload, 0x42, sizeof(pkt.payload)); // Fill payload with character 'B' (0x42)

return pkt;
}

#endif // TEST_UDP_PKT_H
8 changes: 7 additions & 1 deletion src/xdp-pktgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,17 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va

static int run_prog(int run_prog_fd, int count)
{
struct test_udp_packet pkt_udp = create_test_udp_packet();
// struct test_udp_packet pkt_udp = create_test_udp_packet_v6();
struct test_udp_packet_v4 pkt_udp = create_test_udp_packet_v4();
struct xdp_md ctx_in = {
.data_end = sizeof(pkt_udp),
.ingress_ifindex = cfg.ifindex
};
// struct xdp_md ctx_in_array[64];
// for (int i = 0; i < 64; i++) {
// ctx_in_array[i].data_end = sizeof(pkt_udp);
// ctx_in_array[i].ingress_ifindex = cfg.ifindex;
// }

printf("pkt size: %ld\n", sizeof(pkt_udp));
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
Expand Down
2 changes: 2 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
udp_server
udp_client
18 changes: 18 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CC=gcc
CFLAGS=-Wall
LDFLAGS=-pthread
TARGET_SERVER=udp_server
TARGET_CLIENT=udp_client

all: $(TARGET_SERVER) $(TARGET_CLIENT)

$(TARGET_SERVER): udp_server.c
$(CC) $(CFLAGS) -o $(TARGET_SERVER) udp_server.c $(LDFLAGS)

$(TARGET_CLIENT): udp_client.c
$(CC) $(CFLAGS) -o $(TARGET_CLIENT) udp_client.c $(LDFLAGS)

clean:
rm -f $(TARGET_SERVER) $(TARGET_CLIENT)

.PHONY: all clean
21 changes: 21 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# test udp server and client

## build

```sh
make
```

## run

```sh
./udp_server
UDP Server listening on port 9876
...
Packets received in the last second: 560500
Packets received in the last second: 563273
Packets received in the last second: 575896
Packets received in the last second: 574643
Packets received in the last second: 564236
Packets received in the last second: 564961
```
41 changes: 41 additions & 0 deletions test/udp_client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9876
#define SERVER_IP "127.0.0.1"
#define NUM_PACKETS 100000000

int main() {
int sockfd;
struct sockaddr_in serverAddr;
char message[] = "Hello Server!";

// Create socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}

// Set server address
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);

// Send packets
for (int i = 0; i < NUM_PACKETS; i++) {
// printf("Sending packet %d\n", i + 1);
if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
perror("Send failed");
break;
}
}

close(sockfd);
return 0;
}
69 changes: 69 additions & 0 deletions test/udp_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

#define PORT 9876
#define BUFFER_SIZE 1024

volatile int num_packets = 0; // Global variable to track the number of packets

// Function to monitor packets per second
void *monitor_packets(void *arg) {
while (1) {
int current_count = num_packets;
sleep(1);
int new_count = num_packets;
printf("Packets received in the last second: %d\n", new_count - current_count);
}
return NULL;
}

int main() {
int sockfd;
struct sockaddr_in serverAddr, clientAddr;
char buffer[BUFFER_SIZE];
socklen_t addr_size;
pthread_t thread_id;

// Create socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}

// Set server address
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(PORT);

// Bind socket
if (bind(sockfd, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}

printf("UDP Server listening on port %d\n", PORT);

// Start monitoring thread
if (pthread_create(&thread_id, NULL, monitor_packets, NULL) != 0) {
perror("Failed to create thread");
exit(EXIT_FAILURE);
}

while (1) {
addr_size = sizeof(clientAddr);
// Receive packets
if (recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *) &clientAddr, &addr_size) < 0) {
perror("Receive failed");
} else {
num_packets++;
}
}

return 0;
}

0 comments on commit 4c3c634

Please sign in to comment.