Skip to content

Commit

Permalink
Implement ability to set stream_id to response skb
Browse files Browse the repository at this point in the history
Since we decide to move frame making into `xmit`
callback, we need to save stream id in skb private
area. In `xmit` callback we use this id to find
appropriate stream.

Part of #1394
  • Loading branch information
EvgeniiMekhanik committed Mar 22, 2023
1 parent d1cd261 commit c570b49
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 69 deletions.
18 changes: 10 additions & 8 deletions fw/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ tfw_cache_send_304(TfwHttpReq *req, TfwCacheEntry *ce)

resp->mit.start_off = FRAME_HEADER_SIZE;

r = tfw_h2_resp_status_write(resp, 304, false, true);
r = tfw_h2_resp_status_write(resp, stream_id, 304, false, true);
if (unlikely(r))
goto err_setup;
h_len++; /* account for :status field itself */
Expand Down Expand Up @@ -2385,7 +2385,8 @@ tfw_cache_build_resp_body(TDB *db, TdbVRec *trec, TfwMsgIter *it, char *p,
}

static int
tfw_cache_set_hdr_age(TfwHttpResp *resp, TfwCacheEntry *ce)
tfw_cache_set_hdr_age(TfwHttpResp *resp, unsigned int stream_id,
TfwCacheEntry *ce)
{
int r;
size_t digs;
Expand Down Expand Up @@ -2416,7 +2417,8 @@ tfw_cache_set_hdr_age(TfwHttpResp *resp, TfwCacheEntry *ce)

if (to_h2) {
h_age.hpack_idx = 21;
if ((r = tfw_hpack_encode(resp, &h_age, false, false)))
if ((r = tfw_hpack_encode(resp, stream_id, &h_age, false,
false)))
goto err;
} else {
if ((r = tfw_http_msg_expand_data(&mit->iter, skb_head,
Expand Down Expand Up @@ -2518,14 +2520,14 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long lifetime,
* Set 'set-cookie' header if needed, for HTTP/2 or HTTP/1.1
* response.
*/
if (tfw_http_sess_resp_process(resp, true))
if (tfw_http_sess_resp_process(resp, stream_id, true))
goto free;
/*
* RFC 7234 p.4 Constructing Responses from Caches:
* When a stored response is used to satisfy a request without
* validation, a cache MUST generate an Age header field.
*/
if (tfw_cache_set_hdr_age(resp, ce))
if (tfw_cache_set_hdr_age(resp, stream_id, ce))
goto free;

if (!TFW_MSG_H2(req)) {
Expand Down Expand Up @@ -2553,11 +2555,11 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long lifetime,
}

/* Set additional headers for HTTP/2 response. */
if (tfw_h2_resp_add_loc_hdrs(resp, h_mods, true)
if (tfw_h2_resp_add_loc_hdrs(resp, stream_id, h_mods, true)
|| (lifetime > ce->lifetime
&& tfw_h2_set_stale_warn(resp))
&& tfw_h2_set_stale_warn(resp, stream_id))
|| (!test_bit(TFW_HTTP_B_HDR_DATE, resp->flags)
&& tfw_h2_add_hdr_date(resp, true)))
&& tfw_h2_add_hdr_date(resp, stream_id, true)))
goto free;

h_len += mit->acc_len;
Expand Down
26 changes: 17 additions & 9 deletions fw/hpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -3748,8 +3748,9 @@ tfw_hpack_hdr_expand(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
* and @hdr must be treated as HTTP1 header with colon and uppercase.
*/
static int
__tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool use_pool, bool dyn_indexing, bool trans)
__tfw_hpack_encode(TfwHttpResp *__restrict resp, unsigned int stream_id,
TfwStr *__restrict hdr, bool use_pool, bool dyn_indexing,
bool trans)
{
TfwHPackInt idx;
bool st_full_index;
Expand Down Expand Up @@ -3820,26 +3821,33 @@ __tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,

encode:
if (use_pool)
return tfw_hpack_hdr_add(resp, hdr, &idx, name_indexed, trans);
r = tfw_hpack_hdr_add(resp, hdr, &idx, name_indexed, trans);
else
return tfw_hpack_hdr_expand(resp, hdr, &idx, name_indexed);
r = tfw_hpack_hdr_expand(resp, hdr, &idx, name_indexed);
if (likely(!r)) {
ss_skb_set_flags(resp->mit.iter.skb, SS_F_HTTT2_FRAME_HEADERS);
ss_skb_set_stream_id(resp->mit.iter.skb, stream_id);
}
return r;
}

int
tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool use_pool, bool dyn_indexing)
tfw_hpack_encode(TfwHttpResp *__restrict resp, unsigned int stream_id,
TfwStr *__restrict hdr, bool use_pool, bool dyn_indexing)
{
return __tfw_hpack_encode(resp, hdr, use_pool, dyn_indexing, false);
return __tfw_hpack_encode(resp, stream_id, hdr, use_pool,
dyn_indexing, false);
}

/*
* Trasform the header @hdr from HTTP1 field format and perform encoding of @hdr
* into the HTTP/2 HPACK format.
*/
int
tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr)
tfw_hpack_transform(TfwHttpResp *__restrict resp, unsigned int stream_id,
TfwStr *__restrict hdr)
{
return __tfw_hpack_encode(resp, hdr, true, true, true);
return __tfw_hpack_encode(resp, stream_id, hdr, true, true, true);
}

void
Expand Down
7 changes: 4 additions & 3 deletions fw/hpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,10 @@ void write_int(unsigned long index, unsigned short max, unsigned short mask,
TfwHPackInt *__restrict res_idx);
int tfw_hpack_init(TfwHPack *__restrict hp, unsigned int htbl_sz);
void tfw_hpack_clean(TfwHPack *__restrict hp);
int tfw_hpack_transform(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr);
int tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
bool use_pool, bool dyn_indexing);
int tfw_hpack_transform(TfwHttpResp *__restrict resp, unsigned int stream_id,
TfwStr *__restrict hdr);
int tfw_hpack_encode(TfwHttpResp *__restrict resp, unsigned int stream_id,
TfwStr *__restrict hdr, bool use_pool, bool dyn_indexing);
void tfw_hpack_set_rbuf_size(TfwHPackETbl *__restrict tbl,
unsigned short new_size);
int tfw_hpack_decode(TfwHPack *__restrict hp, unsigned char *__restrict src,
Expand Down
70 changes: 37 additions & 33 deletions fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ tfw_h2_prep_resp(TfwHttpResp *resp, unsigned short status, TfwStr *msg,

/* Set HTTP/2 ':status' pseudo-header. */
mit->start_off = FRAME_HEADER_SIZE;
r = tfw_h2_resp_status_write(resp, status, false, false);
r = tfw_h2_resp_status_write(resp, stream_id, status, false, false);
if (unlikely(r))
return r;

Expand All @@ -607,7 +607,8 @@ tfw_h2_prep_resp(TfwHttpResp *resp, unsigned short status, TfwStr *msg,
TfwStr s_vlen = {};

__TFW_STR_CH(&hdr, 0)->hpack_idx = name->hpack_idx;
r = tfw_hpack_encode(resp, __TFW_STR_CH(&hdr, 0),
r = tfw_hpack_encode(resp, stream_id,
__TFW_STR_CH(&hdr, 0),
false, false);
if (unlikely(r))
return r;
Expand All @@ -633,7 +634,8 @@ tfw_h2_prep_resp(TfwHttpResp *resp, unsigned short status, TfwStr *msg,
__TFW_STR_CH(&hdr, 1)->len;
hdr.hpack_idx = name->hpack_idx;

if ((r = tfw_hpack_encode(resp, &hdr, false, true)))
if ((r = tfw_hpack_encode(resp, stream_id, &hdr, false,
true)))
return r;
}
}
Expand Down Expand Up @@ -1034,8 +1036,8 @@ tfw_http_enum_resp_code(int status)
* https://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.4.
*/
int
tfw_h2_resp_status_write(TfwHttpResp *resp, unsigned short status,
bool use_pool, bool cache)
tfw_h2_resp_status_write(TfwHttpResp *resp, unsigned int stream_id,
unsigned short status, bool use_pool, bool cache)
{
int ret;
unsigned short index = tfw_h2_pseudo_index(status);
Expand All @@ -1061,7 +1063,7 @@ tfw_h2_resp_status_write(TfwHttpResp *resp, unsigned short status,
if (!tfw_ultoa(status, __TFW_STR_CH(&s_hdr, 1)->data, H2_STAT_VAL_LEN))
return -E2BIG;

if ((ret = tfw_hpack_encode(resp, &s_hdr, use_pool, !cache)))
if ((ret = tfw_hpack_encode(resp, stream_id, &s_hdr, use_pool, !cache)))
return ret;

/* set status on response for access logging */
Expand Down Expand Up @@ -4003,7 +4005,7 @@ tfw_h1_purge_resp_clean(TfwHttpResp *resp)
* Adjust the response before proxying it to real client.
*/
static int
tfw_http_adjust_resp(TfwHttpResp *resp)
tfw_http_adjust_resp(TfwHttpResp *resp, unsigned int stream_id)
{
TfwHttpReq *req = resp->req;
TfwHttpMsg *hm = (TfwHttpMsg *)resp;
Expand Down Expand Up @@ -4036,7 +4038,7 @@ tfw_http_adjust_resp(TfwHttpResp *resp)
return r;
}

r = tfw_http_sess_resp_process(resp, false);
r = tfw_http_sess_resp_process(resp, stream_id, false);
if (r < 0)
return r;

Expand Down Expand Up @@ -4256,7 +4258,7 @@ tfw_h2_hdr_map(TfwHttpResp *resp, const TfwStr *hdr, unsigned int id)
* transformation.
*/
static int
tfw_h2_add_hdr_via(TfwHttpResp *resp)
tfw_h2_add_hdr_via(TfwHttpResp *resp, unsigned int stream_id)
{
int r;
TfwGlobal *g_vhost = tfw_vhost_get_global();
Expand All @@ -4276,7 +4278,7 @@ tfw_h2_add_hdr_via(TfwHttpResp *resp)

via.hpack_idx = 60;

r = tfw_hpack_encode(resp, &via, true, true);
r = tfw_hpack_encode(resp, stream_id, &via, true, true);
if (unlikely(r))
T_ERR("HTTP/2: unable to add 'via' header (resp=[%p])\n", resp);
else
Expand All @@ -4289,7 +4291,7 @@ tfw_h2_add_hdr_via(TfwHttpResp *resp)
* transformation and for building response from cache.
*/
int
tfw_h2_add_hdr_date(TfwHttpResp *resp, bool cache)
tfw_h2_add_hdr_date(TfwHttpResp *resp, unsigned int stream_id, bool cache)
{
int r;
char *s_date = *this_cpu_ptr(&g_buf);
Expand All @@ -4306,7 +4308,7 @@ tfw_h2_add_hdr_date(TfwHttpResp *resp, bool cache)

hdr.hpack_idx = 33;

r = tfw_hpack_encode(resp, &hdr, !cache, !cache);
r = tfw_hpack_encode(resp, stream_id, &hdr, !cache, !cache);
if (unlikely(r))
T_ERR("HTTP/2: unable to add 'date' header to response"
" [%p]\n", resp);
Expand All @@ -4320,15 +4322,15 @@ tfw_h2_add_hdr_date(TfwHttpResp *resp, bool cache)
* Add 'Content-Length:' header field to an HTTP message.
*/
static int
tfw_h2_add_hdr_clen(TfwHttpResp *resp)
tfw_h2_add_hdr_clen(TfwHttpResp *resp, unsigned int stream_id)
{
int r;
char* buf = *this_cpu_ptr(&g_buf);
unsigned long body_len = TFW_HTTP_RESP_CUT_BODY_SZ(resp);
size_t cl_valsize = tfw_ultoa(body_len, buf,
TFW_ULTOA_BUF_SIZ);

r = tfw_h2_msg_hdr_add(resp, "content-length",
r = tfw_h2_msg_hdr_add(resp, stream_id, "content-length",
SLEN("content-length"), buf,
cl_valsize, 28);

Expand All @@ -4348,7 +4350,7 @@ tfw_h2_add_hdr_clen(TfwHttpResp *resp)
* from transfer encoding.
*/
static int
tfw_h2_add_hdr_cenc(TfwHttpResp *resp, TfwStr *value)
tfw_h2_add_hdr_cenc(TfwHttpResp *resp, unsigned int stream_id, TfwStr *value)
{
int r;
TfwStr name = { .data = "content-encoding",
Expand All @@ -4363,7 +4365,7 @@ tfw_h2_add_hdr_cenc(TfwHttpResp *resp, TfwStr *value)
.hpack_idx = 26
};

r = tfw_hpack_encode(resp, &hdr, true, true);
r = tfw_hpack_encode(resp, stream_id, &hdr, true, true);

if (unlikely(r))
goto err;
Expand Down Expand Up @@ -4433,7 +4435,7 @@ tfw_http_resp_copy_encodings(TfwHttpResp *resp, TfwStr* dst, size_t max_len)
* In case if response is stale, we should pass it with a warning.
*/
int
tfw_h2_set_stale_warn(TfwHttpResp *resp)
tfw_h2_set_stale_warn(TfwHttpResp *resp, unsigned int stream_id)
{
TfwStr wh = {
.chunks = (TfwStr []){
Expand All @@ -4444,7 +4446,7 @@ tfw_h2_set_stale_warn(TfwHttpResp *resp)
.nchunks = 2
};

return tfw_hpack_encode(resp, &wh, false, false);
return tfw_hpack_encode(resp, stream_id, &wh, false, false);
}

/*
Expand Down Expand Up @@ -4584,8 +4586,8 @@ tfw_h2_hdr_size(unsigned long n_len, unsigned long v_len,
}

int
tfw_h2_resp_add_loc_hdrs(TfwHttpResp *resp, const TfwHdrMods *h_mods,
bool cache)
tfw_h2_resp_add_loc_hdrs(TfwHttpResp *resp, unsigned int stream_id,
const TfwHdrMods *h_mods, bool cache)
{
unsigned int i;
TfwHttpTransIter *mit = &resp->mit;
Expand All @@ -4612,7 +4614,7 @@ tfw_h2_resp_add_loc_hdrs(TfwHttpResp *resp, const TfwHdrMods *h_mods,
continue;
}

r = tfw_hpack_encode(resp, desc->hdr, !cache, !cache);
r = tfw_hpack_encode(resp, stream_id, desc->hdr, !cache, !cache);
if (unlikely(r))
return r;
}
Expand Down Expand Up @@ -4643,7 +4645,8 @@ tfw_h2_hdr_sub(unsigned short hid, const TfwStr *hdr, const TfwHdrMods *h_mods)
}

static int
tfw_h2_hpack_encode_headers(TfwHttpResp *resp, const TfwHdrMods *h_mods)
tfw_h2_hpack_encode_headers(TfwHttpResp *resp, unsigned int stream_id,
const TfwHdrMods *h_mods)
{
int r;
unsigned int i;
Expand Down Expand Up @@ -4690,7 +4693,7 @@ tfw_h2_hpack_encode_headers(TfwHttpResp *resp, const TfwHdrMods *h_mods)
if (hid == TFW_HTTP_HDR_SERVER)
continue;

r = tfw_hpack_transform(resp, tgt);
r = tfw_hpack_transform(resp, stream_id, tgt);
if (unlikely(r))
return r;
}
Expand Down Expand Up @@ -5003,7 +5006,7 @@ tfw_h1_resp_adjust_fwd(TfwHttpResp *resp)
* requests will get responded to by the current node without
* inter-node data transfers. (see tfw_http_req_cache_cb())
*/
if (tfw_http_adjust_resp(resp)) {
if (tfw_http_adjust_resp(resp, 0)) {
tfw_http_conn_msg_free((TfwHttpMsg *)resp);
tfw_http_send_err_resp(req, 500,
"response dropped: processing error");
Expand Down Expand Up @@ -5352,11 +5355,12 @@ tfw_h2_resp_adjust_fwd(TfwHttpResp *resp)
if (unlikely(r))
goto clean;

r = tfw_h2_resp_status_write(resp, resp->status, true, false);
r = tfw_h2_resp_status_write(resp, stream_id, resp->status,
true, false);
if (unlikely(r))
goto clean;

r = tfw_h2_hpack_encode_headers(resp, h_mods);
r = tfw_h2_hpack_encode_headers(resp, stream_id, h_mods);
if (unlikely(r))
goto clean;

Expand All @@ -5366,38 +5370,38 @@ tfw_h2_resp_adjust_fwd(TfwHttpResp *resp)
* processed above and which have non-empty value (i.e. configured
* not for deletion).
*/
r = tfw_http_sess_resp_process(resp, false);
r = tfw_http_sess_resp_process(resp, stream_id, false);
if (unlikely(r))
goto clean;

r = tfw_h2_add_hdr_via(resp);
r = tfw_h2_add_hdr_via(resp, stream_id);
if (unlikely(r))
goto clean;

if (!test_bit(TFW_HTTP_B_HDR_DATE, resp->flags)) {
r = tfw_h2_add_hdr_date(resp, false);
r = tfw_h2_add_hdr_date(resp, stream_id, false);
if (unlikely(r))
goto clean;
}

if (test_bit(TFW_HTTP_B_CHUNKED, resp->flags)) {
if (unlikely(tfw_h2_add_hdr_clen(resp)))
if (unlikely(tfw_h2_add_hdr_clen(resp, stream_id)))
goto clean;
}

if (test_bit(TFW_HTTP_B_TE_EXTRA, resp->flags)) {
r = tfw_h2_add_hdr_cenc(resp, &codings);
r = tfw_h2_add_hdr_cenc(resp, stream_id, &codings);
if (unlikely(r))
goto clean;

TFW_STR_INIT(&codings);
}

r = TFW_H2_MSG_HDR_ADD(resp, "server", TFW_SERVER, 54);
r = TFW_H2_MSG_HDR_ADD(resp, stream_id, "server", TFW_SERVER, 54);
if (unlikely(r))
goto clean;

r = tfw_h2_resp_add_loc_hdrs(resp, h_mods, false);
r = tfw_h2_resp_add_loc_hdrs(resp, stream_id, h_mods, false);
if (unlikely(r))
goto clean;

Expand Down
Loading

0 comments on commit c570b49

Please sign in to comment.