Skip to content

Commit 3e9ec31

Browse files
committed
Reworked HTTP1 -> HTTP2 message transformation.
This patch introduce another approach to HTTP1 -> HTTP2 message transformation. We had following problems with inplace transformation: Each added header was added to new skb fragment, that caused skb fragmentation. Appending value to existing in message header was limited by size which remains after transformation. We could use mixed approach, encode headers inplace while message has room and then expand skb by new fragments, but maintain both approaches and code complexity not worth it. Now transformation consist of following steps: 1. Find skb and fragment contains body or last crlf, if body not exists. 2. Delete found data from skb. Keep skb. 3. Hpack encode headers then add to skb from previous step. Headers adds as paged fragments, now we don't use headroom. HTTP2_MAX_OFFSET not used anymore during HTTP1 -> HTTP2 transformation without cache. All paged data in skb allocates from response's TfwPool. 4. Forward message to client. 5. Cleanup all data that was deleted from skbs in first step. TfwPool was patched to statisfy new requirments. Now we use compound pages for order above zero and `put_page` insted of `free_pages`, because during free pages might be still used by skbs. Fixed CONTINUATION frame.
1 parent 7b509b2 commit 3e9ec31

File tree

11 files changed

+498
-252
lines changed

11 files changed

+498
-252
lines changed

fw/cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,8 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long lifetime,
25192519

25202520
h_len += mit->acc_len;
25212521

2522+
/* @TODO: Temporary solution */
2523+
resp->mit.frame_head = it->skb_head->data;
25222524
/*
25232525
* Split response to h2 frames. Don't write body with generic function,
25242526
* just indicate that we have body for correct framing.

fw/hpack.c

Lines changed: 44 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -3578,12 +3578,12 @@ tfw_hpack_str_expand(TfwHttpTransIter *mit, TfwMsgIter *it,
35783578
*/
35793579
static int
35803580
tfw_hpack_hdr_add(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
3581-
TfwHPackInt *__restrict idx, bool name_indexed)
3581+
TfwHPackInt *__restrict idx, bool name_indexed, bool inplace)
35823582
{
35833583
int r;
3584-
TfwStr *c, *end;
3584+
TfwHPackInt vlen;
35853585
TfwHttpTransIter *mit = &resp->mit;
3586-
TfwStr s_val;
3586+
TfwStr s_name = {}, s_val = {}, s_vlen = {};
35873587
const TfwStr s_idx = {
35883588
.data = idx->buf,
35893589
.len = idx->sz,
@@ -3592,43 +3592,53 @@ tfw_hpack_hdr_add(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
35923592
T_DBG3("%s: s_idx->len=%lu, s_idx->data='%.*s'\n",
35933593
__func__, s_idx.len, (int)s_idx.len, s_idx.data);
35943594

3595-
r = tfw_h2_msg_rewrite_data(mit, &s_idx, mit->bnd);
3595+
r = tfw_http_msg_expand_from_pool(mit, resp->pool, &s_idx);
35963596
if (unlikely(r))
35973597
return r;
35983598

35993599
if (!hdr)
36003600
return 0;
36013601

3602-
if (WARN_ON_ONCE(TFW_STR_PLAIN(hdr)))
3602+
if (WARN_ON_ONCE(TFW_STR_PLAIN(hdr) || TFW_STR_DUP(hdr)))
36033603
return -EINVAL;
36043604

3605+
tfw_http_hdr_split(hdr, &s_name, &s_val, inplace);
3606+
36053607
if (unlikely(!name_indexed)) {
3606-
r = tfw_hpack_str_add(mit, TFW_STR_CHUNK(hdr, 0), resp->pool);
3608+
TfwHPackInt nlen;
3609+
TfwStr s_nlen = {};
3610+
3611+
write_int(s_name.len, 0x7F, 0, &nlen);
3612+
s_nlen.data = nlen.buf;
3613+
s_nlen.len = nlen.sz;
3614+
3615+
r = tfw_http_msg_expand_from_pool(mit, resp->pool, &s_nlen);
3616+
if (unlikely(r))
3617+
return r;
3618+
3619+
if (inplace)
3620+
r = tfw_http_msg_expand_from_pool_lc(mit, resp->pool,
3621+
&s_name);
3622+
else
3623+
r = tfw_http_msg_expand_from_pool(mit, resp->pool,
3624+
&s_name);
36073625
if (unlikely(r))
36083626
return r;
36093627
}
36103628

3611-
/*
3612-
* During headers addition into the message the source @hdr must have
3613-
* the following chunk structure (without the OWS):
3614-
*
3615-
* { name [S_DLM] value1 [value2 [value3 ...]] }.
3616-
*
3617-
*/
3618-
c = TFW_STR_CHUNK(hdr, 1);
3619-
if (WARN_ON_ONCE(!c))
3620-
return -EINVAL;
3629+
write_int(s_val.len, 0x7F, 0, &vlen);
3630+
s_vlen.data = vlen.buf;
3631+
s_vlen.len = vlen.sz;
36213632

3622-
if (c->len == SLEN(S_DLM) && *(short *)c->data == *(short *)S_DLM) {
3623-
c = TFW_STR_CHUNK(hdr, 2);
3624-
if (WARN_ON_ONCE(!c))
3625-
return -EINVAL;
3626-
}
3633+
r = tfw_http_msg_expand_from_pool(mit, resp->pool, &s_vlen);
36273634

3628-
end = hdr->chunks + hdr->nchunks;
3629-
tfw_str_collect_cmp(c, end, &s_val, NULL);
3635+
if (unlikely(r))
3636+
return r;
3637+
if (!TFW_STR_EMPTY(&s_val)) {
3638+
r = tfw_http_msg_expand_from_pool(mit, resp->pool, &s_val);
3639+
}
36303640

3631-
return tfw_hpack_str_add(mit,&s_val, resp->pool);
3641+
return r;
36323642
}
36333643

36343644
/*
@@ -3699,88 +3709,6 @@ tfw_hpack_hdr_expand(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
36993709
return tfw_hpack_str_expand(mit, iter, skb_head, &s_val, NULL);
37003710
}
37013711

3702-
/*
3703-
* Transform the HTTP/1.1 header @hdr in-place into HTTP/2 HPACK format in the
3704-
* response @resp.
3705-
*/
3706-
static int
3707-
tfw_hpack_hdr_inplace(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
3708-
TfwHPackInt *__restrict idx, bool name_indexed,
3709-
bool indexed)
3710-
{
3711-
int r;
3712-
const char *bnd;
3713-
TfwHPackInt vlen;
3714-
TfwHttpTransIter *mit = &resp->mit;
3715-
TfwStr s_name = {}, s_val = {}, s_vlen = {};
3716-
const TfwStr s_idx = {
3717-
.data = idx->buf,
3718-
.len = idx->sz,
3719-
};
3720-
3721-
T_DBG3("%s: s_idx->len=%lu, s_idx->data='%.*s'\n",
3722-
__func__, s_idx.len, (int)s_idx.len, s_idx.data);
3723-
3724-
if (!hdr || WARN_ON_ONCE(TFW_STR_PLAIN(hdr) || TFW_STR_DUP(hdr)))
3725-
return -EINVAL;
3726-
3727-
tfw_http_hdr_split(hdr, &s_name, &s_val, true);
3728-
3729-
if (unlikely(!name_indexed)) {
3730-
TfwHPackInt nlen;
3731-
TfwStr s_nlen = {};
3732-
3733-
bnd = __TFW_STR_CH(&s_name, 0)->data;
3734-
3735-
r = tfw_h2_msg_rewrite_data(mit, &s_idx, bnd);
3736-
if (unlikely(r))
3737-
return r;
3738-
3739-
write_int(s_name.len, 0x7F, 0, &nlen);
3740-
s_nlen.data = nlen.buf;
3741-
s_nlen.len = nlen.sz;
3742-
3743-
r = tfw_h2_msg_rewrite_data(mit, &s_nlen, bnd);
3744-
if (unlikely(r))
3745-
return r;
3746-
3747-
if (!TFW_STR_EMPTY(&s_val))
3748-
bnd = __TFW_STR_CH(&s_val, 0)->data;
3749-
else
3750-
bnd = mit->bnd;
3751-
3752-
r = tfw_h2_msg_rewrite_data_lc(mit, &s_name, bnd);
3753-
if (unlikely(r))
3754-
return r;
3755-
} else {
3756-
bnd = indexed || TFW_STR_EMPTY(&s_val)
3757-
? mit->bnd
3758-
: __TFW_STR_CH(&s_val, 0)->data;
3759-
3760-
r = tfw_h2_msg_rewrite_data(mit, &s_idx, bnd);
3761-
if (unlikely(r))
3762-
return r;
3763-
3764-
if (indexed)
3765-
return 0;
3766-
}
3767-
3768-
write_int(s_val.len, 0x7F, 0, &vlen);
3769-
s_vlen.data = vlen.buf;
3770-
s_vlen.len = vlen.sz;
3771-
3772-
r = tfw_h2_msg_rewrite_data(mit, &s_vlen, bnd);
3773-
if (unlikely(r))
3774-
return r;
3775-
if (!TFW_STR_EMPTY(&s_val)) {
3776-
r = tfw_h2_msg_rewrite_data(mit, &s_val, mit->bnd);
3777-
if (unlikely(r))
3778-
return r;
3779-
}
3780-
3781-
return 0;
3782-
}
3783-
37843712
/*
37853713
* Perform encoding of the header @hdr into the HTTP/2 HPACK format. The four
37863714
* operation types can be executed here: addition, substitution, in-place
@@ -3810,7 +3738,6 @@ tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
38103738
TfwH2Ctx *ctx = tfw_h2_context(resp->req->conn);
38113739
TfwHPackETbl *tbl = &ctx->hpack.enc_tbl;
38123740
int r = HPACK_IDX_ST_NOT_FOUND;
3813-
TfwHttpTransIter mit = resp->mit;
38143741

38153742
if (WARN_ON_ONCE(!hdr || TFW_STR_EMPTY(hdr)))
38163743
return -EINVAL;
@@ -3840,26 +3767,15 @@ tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
38403767

38413768
write_int(index, 0x7F, 0x80, &idx);
38423769
switch (op) {
3843-
case TFW_H2_TRANS_SUB:
38443770
case TFW_H2_TRANS_ADD:
3845-
r = tfw_hpack_hdr_add(resp, NULL, &idx, true);
3846-
if (r != -ENOSPC)
3847-
return r;
3848-
resp->mit = mit;
3849-
break;
3771+
return tfw_hpack_hdr_add(resp, NULL, &idx, true, false);
3772+
case TFW_H2_TRANS_INPLACE:
3773+
return tfw_hpack_hdr_add(resp, NULL, &idx, true, true);
38503774
case TFW_H2_TRANS_EXPAND:
38513775
return tfw_hpack_hdr_expand(resp, NULL, &idx, true);
3852-
case TFW_H2_TRANS_INPLACE:
3853-
r = tfw_hpack_hdr_inplace(resp, hdr, &idx, true, true);
3854-
if (r != -ENOSPC)
3855-
return r;
3856-
resp->mit = mit;
3857-
break;
38583776
default:
38593777
BUG();
38603778
}
3861-
3862-
return tfw_hpack_hdr_expand(resp, NULL, &idx, true);
38633779
}
38643780

38653781
if (st_index || HPACK_IDX_RES(r) == HPACK_IDX_ST_NM_FOUND) {
@@ -3877,54 +3793,33 @@ tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
38773793
write_int(index, 0x3F, 0x40, &idx);
38783794
else
38793795
write_int(index, 0xF, 0, &idx);
3796+
38803797
switch (op) {
3881-
case TFW_H2_TRANS_SUB:
38823798
case TFW_H2_TRANS_ADD:
3883-
r = tfw_hpack_hdr_add(resp, hdr, &idx, true);
3884-
if (r != -ENOSPC)
3885-
return r;
3886-
resp->mit = mit;
3887-
break;
3799+
return tfw_hpack_hdr_add(resp, hdr, &idx, true, false);
3800+
case TFW_H2_TRANS_INPLACE:
3801+
return tfw_hpack_hdr_add(resp, hdr, &idx, true, true);
38883802
case TFW_H2_TRANS_EXPAND:
38893803
return tfw_hpack_hdr_expand(resp, hdr, &idx, true);
3890-
case TFW_H2_TRANS_INPLACE:
3891-
r = tfw_hpack_hdr_inplace(resp, hdr, &idx, true, false);
3892-
if (r != -ENOSPC)
3893-
return r;
3894-
resp->mit = mit;
3895-
break;
38963804
default:
38973805
BUG();
38983806
}
3899-
3900-
return tfw_hpack_hdr_expand(resp, hdr, &idx, true);
39013807
}
39023808

39033809
WARN_ON_ONCE(index || st_index);
39043810

39053811
idx.sz = 1;
39063812
idx.buf[0] = (r & HPACK_IDX_FLAG_ADD) ? 0x40 : 0;
39073813
switch (op) {
3908-
case TFW_H2_TRANS_SUB:
39093814
case TFW_H2_TRANS_ADD:
3910-
r = tfw_hpack_hdr_add(resp, hdr, &idx, false);
3911-
if (r != -ENOSPC)
3912-
return r;
3913-
resp->mit = mit;
3914-
break;
3815+
return tfw_hpack_hdr_add(resp, hdr, &idx, false, false);
3816+
case TFW_H2_TRANS_INPLACE:
3817+
return tfw_hpack_hdr_add(resp, hdr, &idx, false, true);
39153818
case TFW_H2_TRANS_EXPAND:
39163819
return tfw_hpack_hdr_expand(resp, hdr, &idx, false);
3917-
case TFW_H2_TRANS_INPLACE:
3918-
r = tfw_hpack_hdr_inplace(resp, hdr, &idx, false, false);
3919-
if (r != -ENOSPC)
3920-
return r;
3921-
resp->mit = mit;
3922-
break;
39233820
default:
39243821
BUG();
39253822
}
3926-
3927-
return tfw_hpack_hdr_expand(resp, hdr, &idx, false);
39283823
}
39293824

39303825
void

fw/hpack.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ typedef struct {
109109

110110
typedef enum {
111111
TFW_H2_TRANS_INPLACE = 0,
112-
TFW_H2_TRANS_SUB,
113112
TFW_H2_TRANS_ADD,
114113
TFW_H2_TRANS_EXPAND,
115114
} TfwH2TransOp;

0 commit comments

Comments
 (0)