Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion fw/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include <linux/tcp.h>
#include <linux/topology.h>
#include <linux/nodemask.h>
#include <linux/skbuff_ref.h>

#undef DEBUG
#if DBG_CACHE > 0
Expand Down
89 changes: 34 additions & 55 deletions fw/hpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ tfw_hpack_set_entry(TfwPool *__restrict h_pool, TfwMsgParseIter *__restrict it,
}

T_DBG3("%s: entry created, d_hdr->nchunks=%u, d_hdr->len=%lu,"
" d_hdr->flags=%hu, it->nm_len=%lu, it->nm_num=%u, it->tag=%u\n",
" d_hdr->flags=%hu, it->nm_len=%u, it->nm_num=%u, it->tag=%u\n",
__func__, d_hdr->nchunks, d_hdr->len, d_hdr->flags, it->nm_len,
it->nm_num, it->tag);

Expand Down Expand Up @@ -1176,6 +1176,7 @@ tfw_hpack_init(TfwHPack *__restrict hp, TfwClientMem *owner,
goto err_dt;

et->window = htbl_sz;
et->min_window = HPACK_ENC_TABLE_MAX_SIZE;
et->rb_size = HPACK_ENC_TABLE_MAX_SIZE;
if (!(et->pool = __tfw_pool_new(HPACK_ENC_TABLE_MAX_SIZE, owner)))
goto err_et;
Expand Down Expand Up @@ -3718,71 +3719,49 @@ tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
* into the HTTP/2 HPACK format.
*/
int
tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr)
tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool dyn_indexing)
{
return __tfw_hpack_encode(resp, hdr, true, true, true);
return __tfw_hpack_encode(resp, hdr, true, dyn_indexing, true);
}

void
tfw_hpack_set_rbuf_size(TfwHPackETbl *__restrict tbl, unsigned short new_size)
tfw_hpack_set_rbuf_size(TfwHPackETbl *__restrict tbl,
unsigned int requested_size)
{
if (new_size > HPACK_ENC_TABLE_MAX_SIZE) {
T_WARN("Client requests hpack table size (%hu), which is "
"greater than HPACK_ENC_TABLE_MAX_SIZE.", new_size);
new_size = HPACK_ENC_TABLE_MAX_SIZE;
}

T_DBG3("%s: tbl->rb_len=%hu, tbl->size=%hu, tbl->window=%hu,"
" new_size=%hu\n", __func__, tbl->rb_len, tbl->size,
tbl->window, new_size);
" requested_size=%u\n", __func__, tbl->rb_len, tbl->size,
tbl->window, requested_size);

/*
* RFC7541#section-4.2:
* Multiple updates to the maximum table size can occur between the
* transmission of two header blocks. In the case that this size is
* changed more than once in this interval, the smallest maximum table
* size that occurs in that interval MUST be signaled in a dynamic
* table size update.
*/
if (tbl->window != new_size && (likely(!tbl->wnd_changed)
|| unlikely(!tbl->window) || new_size < tbl->window))
{
if (tbl->size > new_size)
tfw_hpack_rbuf_calc(tbl, new_size, NULL,
(TfwHPackETblIter *)tbl);
WARN_ON_ONCE(tbl->rb_len > tbl->size);
if (requested_size == tbl->window)
return;

tbl->window = new_size;
tbl->wnd_changed = true;
}
}
unsigned short new_size = min_t(unsigned int, requested_size,
HPACK_ENC_TABLE_MAX_SIZE);
BUILD_BUG_ON(HPACK_ENC_TABLE_MAX_SIZE > USHRT_MAX ||
sizeof(new_size) != sizeof(tbl->window));

int
tfw_hpack_enc_tbl_write_sz(TfwHPackETbl *__restrict tbl, TfwStream *stream)
{
TfwHPackInt tmp = {};
TfwStr dst = {};
char *data;
unsigned int _;
int r = 0;

WARN_ON_ONCE(!tbl->wnd_changed);
write_int(tbl->window, 0x1F, 0x20, &tmp);

data = ss_skb_data_ptr_by_offset(stream->xmit.skb_head,
FRAME_HEADER_SIZE);
BUG_ON(!data);
/**
* RFC7541#section-4.2:
*
* The smallest maximum table size that occurs in that interval MUST be
* signaled in a dynamic table size update. The final maximum size is
* always signaled, resulting in at most two dynamic table size updates.
* This ensures that the decoder is able to perform eviction based on
* reductions in dynamic table size.
*/
if (new_size < tbl->min_window)
tbl->min_window = new_size;

r = ss_skb_get_room_w_frag(stream->xmit.skb_head,
stream->xmit.skb_head,
data, tmp.sz, &dst, &_);
if (unlikely(r))
return r;
if (tbl->size > new_size)
tfw_hpack_rbuf_calc(tbl, new_size, NULL,
(TfwHPackETblIter *)tbl);

memcpy_fast(dst.data, tmp.buf, tmp.sz);
stream->xmit.h_len += tmp.sz;
tbl->wnd_changed = false;
tbl->window = new_size;
tbl->wnd_changed = true;
WARN_ON_ONCE(tbl->rb_len > tbl->size);

return 0;
T_DBG3("%s: New hpack encoder table size has been changed min=%u "
"new=%u\n", __func__, tbl->min_window, tbl->window);
}

8 changes: 5 additions & 3 deletions fw/hpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef struct {
*
* @window - maximum pseudo-length of the dynamic table (in bytes); this
* value used as threshold to flushing old entries;
* @min_window - minimum applied @window before sending dynamic table update;
* @wnd_changed - flag indicates, that window was changed by settings update;
* @rbuf - pointer to the ring buffer;
* @root - pointer to the root node of binary tree;
Expand All @@ -100,6 +101,7 @@ typedef struct {
typedef struct {
TFW_HPACK_ETBL_COMMON;
unsigned short window;
unsigned short min_window;
bool wnd_changed;
char *rbuf;
TfwHPackNode *root;
Expand Down Expand Up @@ -302,19 +304,19 @@ void write_int(unsigned long index, unsigned short max, unsigned short mask,
int tfw_hpack_init(TfwHPack *__restrict hp, TfwClientMem *owner,
unsigned int htbl_sz);
void tfw_hpack_clean(TfwHPack *__restrict hp);
int tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr);
int tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool dyn_indexing);
int tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool use_pool, bool dyn_indexing);
void tfw_hpack_set_rbuf_size(TfwHPackETbl *__restrict tbl,
unsigned short new_size);
unsigned int new_size);
int tfw_hpack_decode(TfwHPack *__restrict hp, unsigned char *__restrict src,
unsigned long n, TfwHttpReq *__restrict req,
unsigned int *__restrict parsed);
int tfw_hpack_cache_decode_expand(TfwHPack *__restrict hp,
TfwHttpResp *__restrict resp,
unsigned char *__restrict src, unsigned long n,
TfwDecodeCacheIter *__restrict cd_iter);
int tfw_hpack_enc_tbl_write_sz(TfwHPackETbl *__restrict tbl, TfwStream *stream);

static inline unsigned int
tfw_hpack_int_size(unsigned long index, unsigned short max)
Expand Down
42 changes: 11 additions & 31 deletions fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
#include <linux/string.h>
#include <linux/sort.h>
#include <linux/bsearch.h>
#include <linux/skbuff_ref.h>

#undef DEBUG
#if DBG_HTTP > 0
Expand Down Expand Up @@ -1818,31 +1817,12 @@ do { \
}
}

static void
__tfw_http_free_cleanup(TfwHttpMsgCleanup *cleanup)
{
int i;
struct sk_buff *skb;

while ((skb = ss_skb_dequeue(&cleanup->skb_head)))
__ss_kfree_skb(skb);

for (i = 0; i < cleanup->pages_sz; i++)
/*
* Pass "true" even for non recyclable pages, relying on check
* pp_magic == PP_SIGNATURE in napi_pp_put_page(), which avoid
* recycling of non page_pool pages. Overhead seems the same
* as to have/maintain flag for each fragment.
*/
skb_page_unref(cleanup->pages[i], true);
}

static void
__tfw_http_req_cleanup(TfwHttpReq *req)
{
if (!req->cleanup)
return;
__tfw_http_free_cleanup(req->cleanup);
ss_skb_free_cleanup(req->cleanup);
req->cleanup = NULL;
}

Expand Down Expand Up @@ -3927,7 +3907,7 @@ tfw_h1_adjust_req(TfwHttpReq *req)
req->vhost,
TFW_VHOST_HDRMOD_REQ);

req->cleanup = tfw_pool_alloc(hm->pool, sizeof(TfwHttpMsgCleanup));
req->cleanup = tfw_pool_alloc(hm->pool, sizeof(TfwSkbCleanup));
if (unlikely(!req->cleanup))
return -ENOMEM;
req->cleanup->pages_sz = 0;
Expand Down Expand Up @@ -4281,10 +4261,10 @@ tfw_h2_adjust_req(TfwHttpReq *req)
bool need_cl = req->body.len &&
TFW_STR_EMPTY(&ht->tbl[TFW_HTTP_HDR_CONTENT_LENGTH]);

req->cleanup = tfw_pool_alloc(req->pool, sizeof(TfwHttpMsgCleanup));
req->cleanup = tfw_pool_alloc(req->pool, sizeof(TfwSkbCleanup));
if (unlikely(!req->cleanup))
return -ENOMEM;
memset(req->cleanup, 0, sizeof(TfwHttpMsgCleanup));
memset(req->cleanup, 0, sizeof(TfwSkbCleanup));

if (need_cl) {
cl_data_len = tfw_ultoa(req->body.len, cl_data, TFW_ULTOA_BUF_SIZ);
Expand Down Expand Up @@ -4624,7 +4604,7 @@ tfw_http_resp_get_conn_flags(TfwHttpResp *resp)
* headers will be avoided.
*/
static int
tfw_http_resp_set_empty_skb_head(TfwHttpResp *resp, TfwHttpMsgCleanup *cleanup)
tfw_http_resp_set_empty_skb_head(TfwHttpResp *resp, TfwSkbCleanup *cleanup)
{
void *opaque_data = TFW_SKB_CB(resp->msg.skb_head)->opaque_data;
TfwMsgIter *iter = &resp->iter;
Expand All @@ -4650,7 +4630,7 @@ tfw_http_resp_set_empty_skb_head(TfwHttpResp *resp, TfwHttpMsgCleanup *cleanup)
}

static int
tfw_h1_resp_cutoff_headers(TfwHttpResp *resp, TfwHttpMsgCleanup *cleanup)
tfw_h1_resp_cutoff_headers(TfwHttpResp *resp, TfwSkbCleanup *cleanup)
{
TfwHttpMsg *hm = (TfwHttpMsg *)resp;
TfwHttpReq *req = resp->req;
Expand Down Expand Up @@ -4748,7 +4728,7 @@ tfw_http_adjust_resp(TfwHttpResp *resp)
TfwHttpReq *req = resp->req;
TfwHttpMsg *hm = (TfwHttpMsg *)resp;
TfwMsgIter *iter = &resp->iter;
TfwHttpMsgCleanup cleanup = {};
TfwSkbCleanup cleanup = {};
const TfwHdrMods *h_mods = tfw_vhost_get_hdr_mods(req->location,
req->vhost,
TFW_VHOST_HDRMOD_RESP);
Expand Down Expand Up @@ -4801,7 +4781,7 @@ tfw_http_adjust_resp(TfwHttpResp *resp)
r = tfw_http_msg_expand_from_pool(hm, &STR_CRLF);

clean:
__tfw_http_free_cleanup(&cleanup);
ss_skb_free_cleanup(&cleanup);

return r;
}
Expand Down Expand Up @@ -5397,7 +5377,7 @@ tfw_h2_hpack_encode_headers(TfwHttpResp *resp, const TfwHdrMods *h_mods)
|| tgt->flags & TFW_STR_TRAILER_HDR)
continue;

r = tfw_hpack_transform(resp, tgt);
r = tfw_hpack_transform(resp, tgt, true);
if (unlikely(r))
return r;
}
Expand Down Expand Up @@ -5905,7 +5885,7 @@ tfw_h2_resp_encode_headers(TfwHttpResp *resp)
TfwHttpReq *req = resp->req;
TfwHttpMsg *hm = (TfwHttpMsg *)resp;
TfwHttpTransIter *mit = &resp->mit;
TfwHttpMsgCleanup cleanup = {};
TfwSkbCleanup cleanup = {};
TfwStr codings = {};
const TfwHdrMods *h_mods = tfw_vhost_get_hdr_mods(req->location,
req->vhost,
Expand Down Expand Up @@ -6007,7 +5987,7 @@ tfw_h2_resp_encode_headers(TfwHttpResp *resp)
req, resp);
SS_SKB_QUEUE_DUMP(&resp->msg.skb_head);

__tfw_http_free_cleanup(&cleanup);
ss_skb_free_cleanup(&cleanup);
return r;
}

Expand Down
16 changes: 1 addition & 15 deletions fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,19 +343,6 @@ typedef struct {
long m_date;
} TfwHttpCond;

/**
* Represents the data that should be cleaned up after message transformation.
*
* @skb_head - head of skb list that must be freed;
* @pages - pages that must be freed;
* @pages_sz - current number of @pages;
*/
typedef struct {
struct sk_buff *skb_head;
netmem_ref pages[MAX_SKB_FRAGS];
unsigned char pages_sz;
} TfwHttpMsgCleanup;

/**
* HTTP Request.
*
Expand Down Expand Up @@ -404,7 +391,7 @@ struct tfw_http_req_t {
TfwHttpSess *sess;
TfwClient *peer;
void *stale_ce;
TfwHttpMsgCleanup *cleanup;
TfwSkbCleanup *cleanup;
TfwHttpCond cond;
TfwMsgParseIter pit;
HttpTfh tfh;
Expand Down Expand Up @@ -815,5 +802,4 @@ void tfw_http_extract_request_authority(TfwHttpReq *req);
bool tfw_http_mark_is_in_whitlist(unsigned int mark);
char *tfw_http_resp_status_line(int status, size_t *len);
int tfw_h2_on_send_resp(void *conn, struct sk_buff **skb_head);

#endif /* __TFW_HTTP_H__ */
7 changes: 3 additions & 4 deletions fw/http2.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,8 @@ tfw_h2_apply_settings_entry(TfwH2Ctx *ctx, unsigned short id,

switch (id) {
case HTTP2_SETTINGS_TABLE_SIZE:
dest->hdr_tbl_sz = min_t(unsigned int,
val, HPACK_ENC_TABLE_MAX_SIZE);
tfw_hpack_set_rbuf_size(&ctx->hpack.enc_tbl, dest->hdr_tbl_sz);
tfw_hpack_set_rbuf_size(&ctx->hpack.enc_tbl, val);
dest->hdr_tbl_sz = ctx->hpack.enc_tbl.window;
break;

case HTTP2_SETTINGS_ENABLE_PUSH:
Expand Down Expand Up @@ -627,7 +626,7 @@ tfw_h2_hpack_encode_trailer_headers(TfwHttpResp *resp)
T_DBG3("%s: hid=%hu, d_num=%hu, nchunks=%u\n",
__func__, hid, d_num, ht->tbl[hid].nchunks);

r = tfw_hpack_transform(resp, tgt);
r = tfw_hpack_transform(resp, tgt, false);
if (unlikely(r))
goto finish;
}
Expand Down
Loading