Skip to content

Commit 79901d9

Browse files
Protobuf send (#10)
* feat: modify osd mapping util for handoff conn * feat: add handoff_in accept in main * feat: multiplex for handoff_in/out and s3_http on epoll.event.data.u32 * docs(handoff): more implementation details about handoff requests * fix compile * fix: delete tlse related macros * factor handoff code to own source file * implement socket sock and client serialization - fix control plane loop to use epoll event data ptr - use first element of structures to indicate event type * link libforward-tc * feat: handoff out * feat: handoff in * fix compile * switch to use val for rados ctx * remove aio * set first read to 512 * refactor * bugfix * fix to_migrate * add more prints * fetch client MAC address and add to migration info * implement soruce IP modification on fake server * temp use async for GET * modify aio * fake server reply HTTP OK and data * handoff out reconnect max try * build options to build for async io and migration * ktls serialize and deserialize * incoming traffic block with before deserialize * add redirection rule * fix missing http reset after migration * implement migration option switch * handoff back * handoff back and back-forward working --------- Co-authored-by: steven <steven.chien@ed.ac.uk>
1 parent de51077 commit 79901d9

File tree

15 files changed

+2005
-526
lines changed

15 files changed

+2005
-526
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,6 @@ core.*
5454
vgcore.*
5555

5656
build
57+
58+
proto/socket_serialize.pb-c.h
59+
proto/socket_serialize.pb-c.c

CMakeLists.txt

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,40 @@ cmake_minimum_required(VERSION 3.22)
22
project(xo-server)
33
enable_language(C)
44

5+
include(ExternalProject)
56
include(FetchContent)
67

78
include(${CMAKE_SOURCE_DIR}/cmake/modules/Findlibrados2.cmake)
89
include(${CMAKE_SOURCE_DIR}/cmake/modules/FindProtobufC.cmake)
910
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
1011

11-
#option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
12+
option(USE_ASYNC_WRITE "Build using rados aio for write" OFF)
13+
option(USE_ASYNC_READ "Build using rados aio for read" OFF)
14+
option(USE_MIGRATION "Build migration support" OFF)
15+
1216
FetchContent_Declare(llhttp
13-
URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz")
17+
URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz")
1418

1519
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
1620
set(BUILD_STATIC_LIBS ON CACHE INTERNAL "")
1721
FetchContent_MakeAvailable(llhttp)
1822

23+
# add libforward source
24+
ExternalProject_Add(libforward-tc
25+
GIT_REPOSITORY https://github.com/uoenoplab/libforward-tc.git
26+
SOURCE_DIR libs/libforward-tc
27+
UPDATE_DISCONNECTED true
28+
GIT_TAG main
29+
#BUILD_IN_SOURCE ON
30+
#CONFIGURE_COMMAND ./configure
31+
#BUILD_COMMAND make -j 32
32+
INSTALL_COMMAND "")
33+
1934
## Link with the llhttp_static target
2035
#target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_static ${PROJECT_NAME})
2136

2237
if (NOT CMAKE_BUILD_TYPE)
23-
set(CMAKE_BUILD_TYPE "Debug")
38+
set(CMAKE_BUILD_TYPE "Debug")
2439
endif()
2540

2641
if (POLICY CMP0074)
@@ -30,7 +45,7 @@ endif()
3045
set(C_SRC
3146
src/http_client.c
3247
src/object_store.c
33-
src/conn_migration.c
48+
src/handoff.c
3449
src/md5.c
3550
src/util.c
3651
)
@@ -55,48 +70,81 @@ find_program(Protobuf_PROTOC-C_EXECUTABLE
5570
mark_as_advanced(Protobuf_PROTOC-C_EXECUTABLE)
5671
PROTOBUF_GENERATE_C(PROTO_SRC PROTO_HEAD proto/socket_serialize.proto)
5772

58-
# build benchmark library
73+
# build http server library
5974
add_library(http_server STATIC
6075
${PROTO_SRC}
6176
${C_SRC})
77+
78+
add_dependencies(http_server libforward-tc)
79+
80+
ExternalProject_Get_property(libforward-tc SOURCE_DIR)
6281
target_include_directories(http_server PRIVATE
6382
include
6483
${CMAKE_CURRENT_BINARY_DIR} # for proto
84+
${SOURCE_DIR}/include
6585
${URIPARSER_INCLUDE_DIR}
6686
${llhttp_SOURCE_DIR}/include
6787
${LIBXML2_INCLUDE_DIR}
6888
${LIBRADOS2_INCLUDE_DIRS})
69-
target_link_libraries(http_server PRIVATE
89+
90+
ExternalProject_Get_property(libforward-tc BINARY_DIR)
91+
target_link_directories(http_server PUBLIC
92+
${BINARY_DIR})
93+
94+
target_link_libraries(http_server PUBLIC
7095
llhttp_static
7196
uriparser::uriparser
7297
LibXml2::LibXml2
7398
OpenSSL::Crypto
99+
forward-tc
100+
${PROTOBUF-C_LIBRARIES}
74101
${LIBRADOS2_LIBRARIES})
102+
75103
set_target_properties(http_server PROPERTIES
76-
POSITION_INDEPENDENT_CODE ON
77-
C_STANDARD 11)
104+
POSITION_INDEPENDENT_CODE ON
105+
C_STANDARD 11)
106+
107+
if (USE_ASYNC_WRITE)
108+
list(APPEND HTTP_SERVER_DEF -DASYNC_WRITE)
109+
endif()
110+
if (USE_ASYNC_READ)
111+
list(APPEND HTTP_SERVER_DEF -DASYNC_READ)
112+
endif()
113+
if (USE_MIGRATION)
114+
list(APPEND HTTP_SERVER_DEF -DUSE_MIGRATION)
115+
endif()
116+
117+
target_compile_definitions(http_server PUBLIC ${HTTP_SERVER_DEF})
78118
target_compile_options(http_server PRIVATE
79-
-fstack-protector-all -Wall -Wextra -ggdb -O3 -g)
119+
-fstack-protector-all -Wall -Wextra -ggdb -O3 -g)
80120
#-fsanitize=undefined,address -fno-omit-frame-pointer -fstack-protector -Wall -Wextra -ggdb -O3 -g)
81121
target_link_options(http_server PRIVATE
82-
-fstack-protector-all -Wall -Wextra -ggdb -O3 -g)
122+
-fstack-protector-all -Wall -Wextra -ggdb -O3 -g)
83123
#-fsanitize=undefined,address -fno-omit-frame-pointer -fstack-protector -Wall -Wextra -ggdb -O3 -g)
84124

85125
# build driver application
86126
add_executable(server.out src/server.c src/tls.c)
127+
128+
add_dependencies(server.out libforward-tc http_server)
129+
87130
target_include_directories(server.out PUBLIC
131+
${SOURCE_DIR}/include
88132
${llhttp_SOURCE_DIR}/include
89133
${INIH_INCLUDE_DIRS}
90134
${LIBXML2_INCLUDE_DIR}
91135
include)
136+
92137
target_link_libraries(server.out PUBLIC
138+
llhttp_static
93139
http_server
94140
${INIH_LIBRARIES}
95-
${PROTOBUF-C_LIBRARIES}
141+
#efence
96142
OpenSSL::Crypto
97143
OpenSSL::SSL)
144+
98145
set_target_properties(server.out PROPERTIES
99146
C_STANDARD 11)
147+
100148
target_compile_options(server.out PRIVATE
101149
${INIH_CFLAGS_OTHER}
102150
-fstack-protector-all -O3 -Wall -Wextra -g)
@@ -113,6 +161,9 @@ target_link_options(server.out PRIVATE
113161
file(COPY ${CMAKE_SOURCE_DIR}/assets DESTINATION ${CMAKE_BINARY_DIR})
114162

115163
message(STATUS "Building xo server binary")
164+
message(STATUS "Build with rados aio for write: " ${USE_ASYNC_WRITE})
165+
message(STATUS "Build with rados aio for read: " ${USE_ASYNC_READ})
166+
message(STATUS "Build with connection migration support: " ${USE_MIGRATION})
116167

117168
# uninstall target
118169
#if(NOT TARGET uninstall)

include/conn_migration.h

Lines changed: 0 additions & 8 deletions
This file was deleted.

include/handoff.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#ifndef __HANDOFF_H__
2+
#define __HANDOFF_H__
3+
4+
#include "forward.h"
5+
#include "ebpf_forward.h"
6+
7+
#include "http_client.h"
8+
9+
#ifndef TCPOPT_MSS
10+
#define TCPOPT_MSS 2
11+
#endif
12+
13+
#ifndef TCPOPT_WINDOW
14+
#define TCPOPT_WINDOW 3
15+
#endif
16+
17+
#ifndef TCPOPT_SACK_PERM
18+
#define TCPOPT_SACK_PERM 4
19+
#endif
20+
21+
#ifndef TCPOPT_TIMESTAMP
22+
#define TCPOPT_TIMESTAMP 8
23+
#endif
24+
25+
enum {
26+
HANDOFF_REQUEST,
27+
HANDOFF_BACK_REQUEST,
28+
HANDOFF_DONE
29+
};
30+
31+
struct handoff_in {
32+
uint32_t epoll_data_u32;
33+
int epoll_fd;
34+
int fd;
35+
int osd_arr_index;
36+
int thread_id; // just for print stuff
37+
uint8_t *recv_protobuf;
38+
uint32_t recv_protobuf_len;
39+
uint32_t recv_protobuf_received;
40+
uint8_t *send_protobuf;
41+
uint32_t send_protobuf_len; // include header uint32 size
42+
uint32_t send_protobuf_sent;
43+
rados_ioctx_t data_io_ctx;
44+
rados_ioctx_t bucket_io_ctx;
45+
struct http_client *client_to_handoff_again;
46+
};
47+
48+
struct handoff_out_req;
49+
50+
struct handoff_out_queue {
51+
struct handoff_out_req* front;
52+
struct handoff_out_req* rear;
53+
};
54+
55+
#define MAX_HANDOFF_OUT_RECONNECT 10
56+
57+
struct handoff_out {
58+
uint32_t epoll_data_u32;
59+
int epoll_fd;
60+
int fd;
61+
bool is_fd_in_epoll;
62+
int reconnect_count;
63+
int osd_arr_index;
64+
int thread_id; // just for print stuff
65+
struct handoff_out_queue *queue;
66+
// handoff out request currently sending out, deququed from queue
67+
struct http_client *client;
68+
uint8_t *recv_protobuf;
69+
uint32_t recv_protobuf_len;
70+
uint32_t recv_protobuf_received;
71+
};
72+
73+
void handoff_out_connect(struct handoff_out *out_ctx);
74+
void handoff_out_reconnect(struct handoff_out *out_ctx);
75+
void handoff_out_issue(int epoll_fd, uint32_t epoll_data_u32, struct http_client *client,
76+
struct handoff_out *out_ctx, int osd_arr_index, int thread_id, bool serialize, bool urgent);
77+
void handoff_out_send(struct handoff_out *out_ctx);
78+
void handoff_out_recv(struct handoff_out *out_ctx);
79+
80+
void handoff_in_disconnect(struct handoff_in *in_ctx);
81+
void handoff_in_recv(struct handoff_in *in_ctx);
82+
void handoff_in_send(struct handoff_in *in_ctx, struct http_client **client_to_handoff_again);
83+
84+
#endif

include/http_client.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424

2525
enum http_expect { CONTINUE, NONE };
2626

27-
extern size_t BUF_SIZE;
27+
extern const size_t BUF_SIZE;
28+
#ifdef USE_MIGRATION
29+
extern bool enable_migration;
30+
#endif
2831

2932
typedef struct ssl_st SSL;
3033
typedef struct bio_st BIO;
@@ -42,17 +45,16 @@ static char *HTTP_CONTINUE_HDR = (char *)"HTTP/1.1 100 CONTINUE\r\n\r\n";
4245
static char *AMZ_REQUEST_ID = (char*)"tx000009a75d393f1564ec2-0065202454-3771-default";
4346

4447
struct http_client {
45-
int epoll_fd;
48+
uint32_t epoll_data_u32;
49+
// always set epoll.data.u32 to this value
4650
int fd;
51+
int epoll_fd;
4752

4853
int prval;
4954
rados_xattrs_iter_t iter;
50-
51-
rados_write_op_t write_op;
55+
rados_completion_t comp;
5256
rados_read_op_t read_op;
53-
54-
rados_completion_t aio_completion;
55-
rados_completion_t aio_head_read_completion;
57+
rados_read_op_t write_op;
5658

5759
ssize_t data_payload_sent;
5860
ssize_t data_payload_size;
@@ -86,8 +88,11 @@ struct http_client {
8688
//char **header_values;
8789
size_t num_fields;
8890

91+
pthread_mutex_t mutex;
8992
rados_ioctx_t *bucket_io_ctx;
9093
rados_ioctx_t *data_io_ctx;
94+
rados_completion_t aio_completion;
95+
rados_completion_t aio_head_read_completion;
9196

9297
size_t object_size;
9398
size_t object_offset;
@@ -123,6 +128,16 @@ struct http_client {
123128
unsigned char client_traffic_secret[48];
124129
unsigned char server_traffic_secret[48];
125130
} tls;
131+
132+
// handoff
133+
int to_migrate;
134+
int from_migrate;
135+
int acting_primary_osd_id;
136+
uint8_t client_mac[6];
137+
138+
uint8_t *proto_buf;
139+
uint32_t proto_buf_len; // include the uint32 header size
140+
uint32_t proto_buf_sent;
126141
};
127142

128143
struct http_client *create_http_client(int epoll_fd, int fd);
@@ -139,9 +154,9 @@ void free_http_client(struct http_client *client);
139154
//static int on_message_complete_cb(llhttp_t* parser);
140155
//static int on_reset_cb(llhttp_t *parser);
141156

142-
void send_client_data(struct http_client *client);
143-
void send_response(struct http_client *client);
144157
void aio_ack_callback(rados_completion_t comp, void *arg);
145158
void aio_commit_callback(rados_completion_t comp, void *arg);
159+
void send_client_data(struct http_client *client);
160+
void send_response(struct http_client *client);
146161

147162
#endif

include/osd_mapping.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
#ifndef __OSD_MAPPING_H__
22
#define __OSD_MAPPING_H__
33

4-
extern char *osd_ips[65536];
5-
extern long my_osd_id;
6-
extern char *my_ip_address;
4+
#define MAX_OSDS 64
5+
6+
extern char *osd_addr_strs[MAX_OSDS];
7+
extern struct sockaddr_in osd_addrs[MAX_OSDS];
8+
extern int osd_ids[MAX_OSDS];
9+
extern int osd_id_to_arr_index[];
10+
extern int num_osds;
11+
extern int num_peers;
12+
13+
extern uint8_t my_mac[6];
14+
15+
// FUTURE TODO: add a data structure to optimize this linear search?
16+
static inline int get_arr_index_from_osd_id(int osd_id)
17+
{
18+
for (int i = 0; i < num_osds; i++)
19+
{
20+
if (osd_ids[i] == osd_id)
21+
return i;
22+
}
23+
fprintf(stderr, "%s: cant find osd_id %d in array\n",
24+
__func__, osd_id);
25+
return -1;
26+
}
27+
28+
static inline struct sockaddr_in get_my_osd_addr()
29+
{
30+
return osd_addrs[num_osds - 1];
31+
}
32+
33+
static inline char *get_my_osd_addr_str()
34+
{
35+
return osd_addr_strs[num_osds - 1];
36+
}
37+
38+
static inline int get_my_osd_id()
39+
{
40+
return osd_ids[num_osds - 1];
41+
}
742

843
#endif

include/util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef __UTIL_H__
22
#define __UTIL_H__
33

4+
void print_mac_address(unsigned char *mac);
5+
void hexdump(const char *title, void *buf, size_t len);
46
double elapsed_time(struct timespec a, struct timespec b);
57
void get_datetime_str(char *buf, size_t length);
68
void convertToISODateTime(const char* inputDateTime, char* outputISODateTime);

0 commit comments

Comments
 (0)