Skip to content

Commit

Permalink
Replace GFSM calls with direct calls to TLS and HTTP
Browse files Browse the repository at this point in the history
Almost literaly follow ak patch from 2eae1da

Replace GFSM calls with direct calls to TLS and HTTP handlers
 on low level networking layers.

GFSM was designed to build graphs of network protocols FSMs (this
design was inspired by FreeBSD netgraph). However, during the years
neither we nor external users have any requirements to introduce
any modules which use GFSM to hook TLS or HTTP entry code. There
are only 2 users of the mechanism for TLS and HTTP for now:
1. TLS -> HTTP protocols handling
2. HTTP limits (the frang module)

This patch replaces GFSM calls with direct calls to
tfw_http_req_process(), tfw_tls_msg_process() and frang_tls_handler()
in following paths:
1. sync sockets -> TLS
2. sync sockets -> HTTP
3. TLS -> HTTP
4. TLS -> Frang

As the result the function tfw_connection_recv() was eliminated.
Now the code is simpler and has lower overhead.

We still might need GFSM for the user-space requests handling (tempesta-tech#77)
and Tempesta Language (tempesta-tech#102).

Contributes to tempesta-tech#755

Based-on-patch-by: Alexander K <[email protected]>
Signed-off-by: Aleksey Mikhaylov <[email protected]>
  • Loading branch information
ttaym committed Feb 22, 2022
1 parent abc9c21 commit 9ef4513
Show file tree
Hide file tree
Showing 15 changed files with 777 additions and 147 deletions.
705 changes: 705 additions & 0 deletions 0001-Replace-GFSM-calls-with-direct-calls-to-TLS-and-HTTP.patch

Large diffs are not rendered by default.

11 changes: 0 additions & 11 deletions fw/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,6 @@ tfw_connection_send(TfwConn *conn, TfwMsg *msg)
return TFW_CONN_HOOK_CALL(conn, conn_send, msg);
}

int
tfw_connection_recv(void *cdata, struct sk_buff *skb)
{
TfwConn *conn = cdata;
TfwFsmData fsm_data = {
.skb = skb,
};

return tfw_gfsm_dispatch(&conn->state, conn, &fsm_data);
}

void
tfw_connection_hooks_register(TfwConnHooks *hooks, int type)
{
Expand Down
4 changes: 1 addition & 3 deletions fw/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ enum {
struct sock *sk; \
void (*destructor)(void *);

typedef struct {
typedef struct TfwConn {
TFW_CONN_COMMON;
} TfwConn;

Expand Down Expand Up @@ -508,6 +508,4 @@ int tfw_connection_close(TfwConn *conn, bool sync);
void tfw_connection_drop(TfwConn *conn);
void tfw_connection_release(TfwConn *conn);

int tfw_connection_recv(void *cdata, struct sk_buff *skb);

#endif /* __TFW_CONNECTION_H__ */
3 changes: 1 addition & 2 deletions fw/gfsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. ([email protected]).
* Copyright (C) 2015-2018 Tempesta Technologies, Inc.
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -88,7 +88,6 @@ enum {
/* Security rules enforcement. */
TFW_FSM_FRANG_REQ,
TFW_FSM_FRANG_RESP,
TFW_FSM_FRANG_TLS,

TFW_FSM_NUM /* Must be <= TFW_GFSM_FSM_N */
};
Expand Down
44 changes: 15 additions & 29 deletions fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
#define RESP_BUF_LEN 128

static DEFINE_PER_CPU(char[RESP_BUF_LEN], g_buf);
int ghprio; /* GFSM hook priority. */

#define TFW_CFG_BLK_DEF (TFW_BLK_ERR_REPLY)
unsigned short tfw_blk_flags = TFW_CFG_BLK_DEF;
Expand Down Expand Up @@ -5240,12 +5239,11 @@ tfw_h1_req_process(TfwStream *stream, struct sk_buff *skb)
* TODO enter the function depending on current GFSM state.
*/
static int
tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
tfw_http_req_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb)
{
bool block;
ss_skb_actor_t *actor;
unsigned int parsed;
struct sk_buff *skb = data->skb;
TfwHttpReq *req;
TfwHttpMsg *hmsib;
TfwFsmData data_up;
Expand Down Expand Up @@ -5276,7 +5274,7 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
skb->len, skb->next, parsed, req->msg.len, req->version, r);

/*
* We have to keep @data the same to pass it as is to FSMs
* We have to keep @skb the same to pass it as is to FSMs
* registered with lower priorities after us, but we must
* feed the new data version to FSMs registered on our states.
*/
Expand Down Expand Up @@ -5455,8 +5453,7 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
* the quickest way to obtain target VHost and target backend server
* connection since it allows to avoid expensive tables lookups.
*/
switch (tfw_http_sess_obtain(req))
{
switch (tfw_http_sess_obtain(req)) {
case TFW_HTTP_SESS_SUCCESS:
break;

Expand Down Expand Up @@ -5851,11 +5848,10 @@ tfw_http_resp_terminate(TfwHttpMsg *hm)
* TODO enter the function depending on current GFSM state.
*/
static int
tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
tfw_http_resp_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb)
{
int r = TFW_BLOCK;
unsigned int chunks_unused, parsed;
struct sk_buff *skb = data->skb;
TfwHttpReq *bad_req;
TfwHttpMsg *hmresp, *hmsib;
TfwFsmData data_up;
Expand Down Expand Up @@ -5890,7 +5886,7 @@ tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
skb->len, parsed, hmresp->msg.len, hmresp->version, r);

/*
* We have to keep @data the same to pass it as is to FSMs
* We have to keep @skb the same to pass it as is to FSMs
* registered with lower priorities after us, but we must
* feed the new data version to FSMs registered on our states.
*/
Expand Down Expand Up @@ -6075,7 +6071,8 @@ tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data)
* @return status (application logic decision) of the message processing.
*/
int
tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data)
tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream,
TfwFsmData *data)
{
if (WARN_ON_ONCE(!stream))
return -EINVAL;
Expand All @@ -6095,8 +6092,8 @@ tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data)
ss_skb_queue_tail(&stream->msg->skb_head, data->skb);

return (TFW_CONN_TYPE(conn) & Conn_Clnt)
? tfw_http_req_process(conn, stream, data)
: tfw_http_resp_process(conn, stream, data);
? tfw_http_req_process(conn, stream, data->skb)
: tfw_http_resp_process(conn, stream, data->skb);
}

/**
Expand All @@ -6108,7 +6105,7 @@ tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data)
* returned an error code on. The rest of skbs are freed by us.
*/
int
tfw_http_msg_process(void *conn, TfwFsmData *data)
tfw_http_msg_process(TfwConn *conn, TfwFsmData *data)
{
int r = T_OK;
TfwStream *stream = &((TfwConn *)conn)->stream;
Expand All @@ -6117,13 +6114,14 @@ tfw_http_msg_process(void *conn, TfwFsmData *data)
if (data->skb->prev)
data->skb->prev->next = NULL;
for (next = data->skb->next; data->skb;
data->skb = next, next = next ? next->next : NULL)
data->skb = next, next = next ? next->next : NULL)
{
if (likely(r == T_OK || r == T_POSTPONE)) {
data->skb->next = data->skb->prev = NULL;
r = TFW_CONN_H2(conn)
? tfw_h2_frame_process(conn, data)
: tfw_http_msg_process_generic(conn, stream, data);
? tfw_h2_frame_process(conn, data->skb)
: tfw_http_msg_process_generic(conn, stream,
data);
} else {
__kfree_skb(data->skb);
}
Expand Down Expand Up @@ -6884,22 +6882,11 @@ tfw_http_init(void)
{
int r;

r = tfw_gfsm_register_fsm(TFW_FSM_HTTP, tfw_http_msg_process);
if (r)
if ((r = tfw_gfsm_register_fsm(TFW_FSM_HTTP, (tfw_gfsm_handler_t) tfw_http_msg_process)))
return r;

tfw_connection_hooks_register(&http_conn_hooks, TFW_FSM_HTTP);

ghprio = tfw_gfsm_register_hook(TFW_FSM_TLS,
TFW_GFSM_HOOK_PRIORITY_ANY,
TFW_TLS_FSM_DATA_READY,
TFW_FSM_HTTP, TFW_HTTP_FSM_INIT);
if (ghprio < 0) {
tfw_connection_hooks_unregister(TFW_FSM_HTTP);
tfw_gfsm_unregister_fsm(TFW_FSM_HTTP);
return ghprio;
}

tfw_mod_register(&tfw_http_mod);

return 0;
Expand All @@ -6909,7 +6896,6 @@ void
tfw_http_exit(void)
{
tfw_mod_unregister(&tfw_http_mod);
tfw_gfsm_unregister_hook(TFW_FSM_TLS, ghprio, TFW_TLS_FSM_DATA_READY);
tfw_connection_hooks_unregister(TFW_FSM_HTTP);
tfw_gfsm_unregister_fsm(TFW_FSM_HTTP);
}
2 changes: 1 addition & 1 deletion fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ tfw_h2_pseudo_index(unsigned short status)
typedef void (*tfw_http_cache_cb_t)(TfwHttpMsg *);

/* External HTTP functions. */
int tfw_http_msg_process(void *conn, TfwFsmData *data);
int tfw_http_msg_process(TfwConn *conn, TfwFsmData *data);
int tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream,
TfwFsmData *data);
unsigned long tfw_http_req_key_calc(TfwHttpReq *req);
Expand Down
6 changes: 3 additions & 3 deletions fw/http_frame.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Tempesta FW
*
* Copyright (C) 2019-2021 Tempesta Technologies, Inc.
* Copyright (C) 2019-2022 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -1698,14 +1698,14 @@ tfw_h2_context_reinit(TfwH2Ctx *ctx, bool postponed)
}

int
tfw_h2_frame_process(void *c, TfwFsmData *data)
tfw_h2_frame_process(TfwConn *c, struct sk_buff *skb)
{
int r;
bool postponed;
unsigned int parsed, unused;
TfwFsmData data_up = {};
TfwH2Ctx *h2 = tfw_h2_context(c);
struct sk_buff *nskb = NULL, *skb = data->skb;
struct sk_buff *nskb = NULL;

next_msg:
postponed = false;
Expand Down
4 changes: 3 additions & 1 deletion fw/http_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ typedef struct {
unsigned char data_off;
} TfwH2Ctx;

typedef struct TfwConn TfwConn;

int tfw_h2_init(void);
void tfw_h2_cleanup(void);
int tfw_h2_context_init(TfwH2Ctx *ctx);
void tfw_h2_context_clear(TfwH2Ctx *ctx);
int tfw_h2_frame_process(void *c, TfwFsmData *data);
int tfw_h2_frame_process(TfwConn *c, struct sk_buff *skb);
void tfw_h2_conn_streams_cleanup(TfwH2Ctx *ctx);
unsigned int tfw_h2_stream_id(TfwHttpReq *req);
unsigned int tfw_h2_stream_id_close(TfwHttpReq *req, unsigned char type,
Expand Down
40 changes: 7 additions & 33 deletions fw/http_limits.c
Original file line number Diff line number Diff line change
Expand Up @@ -855,13 +855,6 @@ enum {
TFW_FRANG_RESP_FSM_DONE = TFW_GFSM_FRANG_RESP_STATE(TFW_GFSM_STATE_LAST)
};

#define TFW_GFSM_FRANG_TLS_STATE(s) \
((TFW_FSM_FRANG_TLS << TFW_GFSM_FSM_SHIFT) | (s))
enum {
TFW_FRANG_TLS_FSM_INIT = TFW_GFSM_FRANG_TLS_STATE(0),
TFW_FRANG_TLS_FSM_DONE = TFW_GFSM_FRANG_TLS_STATE(TFW_GFSM_STATE_LAST)
};

#define __FRANG_FSM_MOVE(st) T_FSM_MOVE(st, if (r) T_FSM_EXIT(); )

#define __FRANG_FSM_JUMP_EXIT(st) \
Expand Down Expand Up @@ -1450,8 +1443,7 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state)
ra->history[i].ts = ts;
}

switch (hs_state)
{
switch (hs_state) {
case TTLS_HS_CB_FINISHED_NEW:
ra->history[i].tls_sess_new++;
break;
Expand All @@ -1472,8 +1464,7 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state)
sum_incomplete += ra->history[i].tls_sess_incomplete;
}

switch (hs_state)
{
switch (hs_state) {
case TTLS_HS_CB_FINISHED_NEW:
if (conf->tls_new_conn_rate
&& sum_new > conf->tls_new_conn_rate)
Expand Down Expand Up @@ -1510,12 +1501,11 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state)
return TFW_PASS;
}

static int
frang_tls_handler(void *obj, TfwFsmData *data)
int
frang_tls_handler(TlsCtx *tls, int state)
{
TfwCliConn *conn = (TfwCliConn *)obj;
FrangAcc *ra = conn->sk->sk_security;
int hs_state = -PTR_ERR(data->req);
TfwTlsConn *conn = container_of(tls, TfwTlsConn, tls);
FrangAcc *ra = conn->cli_conn.sk->sk_security;
TfwVhost *dflt_vh = tfw_vhost_lookup_default();
int r;

Expand All @@ -1524,7 +1514,7 @@ frang_tls_handler(void *obj, TfwFsmData *data)

spin_lock(&ra->lock);

r = frang_tls_conn_limit(ra, dflt_vh->frang_gconf, hs_state);
r = frang_tls_conn_limit(ra, dflt_vh->frang_gconf, state);
if (r == TFW_BLOCK && dflt_vh->frang_gconf->ip_block)
tfw_filter_block_ip(&FRANG_ACC2CLI(ra)->addr);

Expand Down Expand Up @@ -1595,14 +1585,6 @@ static FrangGfsmHook frang_gfsm_hooks[] = {
.st0 = TFW_FRANG_RESP_FSM_FWD,
.name = "response_fwd",
},
{
.prio = -1,
.hook_fsm = TFW_FSM_HTTPS,
.hook_state = TFW_TLS_FSM_HS_DONE,
.fsm_id = TFW_FSM_FRANG_TLS,
.st0 = TFW_FRANG_TLS_FSM_INIT,
.name = "tls_hs_done",
},
};

void
Expand Down Expand Up @@ -1663,20 +1645,13 @@ tfw_http_limits_init(void)
goto err_fsm_resp;
}

r = tfw_gfsm_register_fsm(TFW_FSM_FRANG_TLS, frang_tls_handler);
if (r) {
T_ERR_NL("frang: can't register frang tls fsm\n");
goto err_fsm_tls;
}

r = tfw_http_limits_hooks_register();
if (r)
goto err_hooks;

return 0;
err_hooks:
tfw_http_limits_hooks_remove();
tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_TLS);
err_fsm_tls:
tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_RESP);
err_fsm_resp:
Expand All @@ -1693,7 +1668,6 @@ tfw_http_limits_exit(void)
T_DBG("frang exit\n");

tfw_http_limits_hooks_remove();
tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_TLS);
tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_RESP);
tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_REQ);
tfw_classifier_unregister();
Expand Down
4 changes: 3 additions & 1 deletion fw/http_limits.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. ([email protected]).
* Copyright (C) 2015-2020 Tempesta Technologies, Inc.
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -238,4 +238,6 @@ struct frang_vhost_cfg_t {
bool http_method_override;
};

int frang_tls_handler(TlsCtx *tls, int state);

#endif /* __HTTP_LIMITS__ */
Loading

0 comments on commit 9ef4513

Please sign in to comment.