Skip to content

Commit 4815fa3

Browse files
Fix moving body during adding headers
- Check that body is moved using return code of `__tfw_http_msg_move_body`. - If body was moved use current skb and it's last fragment. - If body was not moved use new skb
1 parent e26a9b8 commit 4815fa3

File tree

2 files changed

+83
-17
lines changed

2 files changed

+83
-17
lines changed

fw/http_msg.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,14 +1172,16 @@ tfw_http_msg_setup_transform_pool(TfwHttpTransIter *mit, TfwMsgIter *it,
11721172

11731173
/*
11741174
* Move body to @nskb if body located in current skb.
1175+
* Return -errno in case of error, 0 if body was not
1176+
* moved and 1 if body was moved.
11751177
*/
11761178
static inline int
1177-
__tfw_http_msg_move_body(TfwHttpResp *resp, struct sk_buff *nskb)
1179+
__tfw_http_msg_move_body(TfwHttpResp *resp, struct sk_buff *nskb, int *frag)
11781180
{
11791181
TfwMsgIter *it = &resp->iter;
11801182
struct sk_buff **body;
1181-
int r, frag;
11821183
char *p;
1184+
int r;
11831185

11841186
if (test_bit(TFW_HTTP_B_CHUNKED, resp->flags)) {
11851187
p = resp->body_start_data;
@@ -1192,15 +1194,15 @@ __tfw_http_msg_move_body(TfwHttpResp *resp, struct sk_buff *nskb)
11921194
if (*body != it->skb)
11931195
return 0;
11941196

1195-
if ((r = ss_skb_find_frag_by_offset(*body, p, &frag)))
1197+
if ((r = ss_skb_find_frag_by_offset(*body, p, frag)))
11961198
return r;
11971199

11981200
/* Move body to the next skb. */
1199-
ss_skb_move_frags(it->skb, nskb, frag,
1200-
skb_shinfo(it->skb)->nr_frags - frag);
1201+
ss_skb_move_frags(it->skb, nskb, *frag,
1202+
skb_shinfo(it->skb)->nr_frags - *frag);
12011203
*body = nskb;
12021204

1203-
return 0;
1205+
return 1;
12041206
}
12051207

12061208
/*
@@ -1215,12 +1217,12 @@ __tfw_http_msg_expand_from_pool(TfwHttpMsg *hm, const TfwStr *str,
12151217
unsigned int *copied,
12161218
void cpy(void *dest, const void *src, size_t n))
12171219
{
1218-
int r;
1219-
void *addr;
12201220
const TfwStr *c, *end;
12211221
unsigned int room, skb_room, n_copy, rlen, off, acc = 0;
12221222
TfwMsgIter *it = &hm->iter;
12231223
TfwPool* pool = hm->pool;
1224+
void *addr;
1225+
int r;
12241226

12251227
BUG_ON(it->skb->len > SS_SKB_MAX_DATA_LEN);
12261228

@@ -1246,32 +1248,36 @@ __tfw_http_msg_expand_from_pool(TfwHttpMsg *hm, const TfwStr *str,
12461248
{
12471249
struct sk_buff *nskb = ss_skb_alloc(0);
12481250
TfwHttpResp *resp = (TfwHttpResp *)hm;
1251+
bool body_was_moved = false;
1252+
int frag;
12491253

12501254
if (!nskb)
12511255
return -ENOMEM;
12521256

12531257
if (hm->body.len > 0) {
1254-
r = __tfw_http_msg_move_body(resp,
1255-
nskb);
1256-
if (unlikely(r)) {
1258+
r = __tfw_http_msg_move_body(resp, nskb,
1259+
&frag);
1260+
if (unlikely(r < 0)) {
12571261
T_WARN("Error during moving body");
12581262
return r;
12591263
}
1264+
body_was_moved = !!r;
12601265
}
12611266

12621267
skb_shinfo(nskb)->tx_flags =
12631268
skb_shinfo(it->skb)->tx_flags;
12641269
ss_skb_insert_after(it->skb, nskb);
12651270
/*
1266-
* If body is located in the zero fragment and
1267-
* takes all SS_SKB_MAX_DATA_LEN bytes, we move
1268-
* it to the next skb and continue use current
1269-
* skb.
1271+
* If body was moved to the new allocated skb
1272+
* we should use current skb.
12701273
*/
1271-
if (likely(nskb->len < SS_SKB_MAX_DATA_LEN))
1274+
if (likely(!body_was_moved)) {
12721275
it->skb = nskb;
1276+
it->frag = -1;
1277+
} else {
1278+
it->frag = frag - 1;
1279+
}
12731280

1274-
it->frag = -1;
12751281
skb_room = SS_SKB_MAX_DATA_LEN - it->skb->len;
12761282
}
12771283

fw/t/unit/test_http_msg.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,69 @@ TEST(http_msg, cutoff_linear_headers_and_linear_body)
212212
tfw_http_msg_free((TfwHttpMsg *)resp);
213213
}
214214

215+
TEST(http_msg, expand_from_pool_for_headers)
216+
{
217+
static TfwStr frags[] = {
218+
TFW_STR_STRING("headers"),
219+
TFW_STR_STRING("paged_body")
220+
};
221+
TfwStr *hdr = &frags[0], *head = &frags[0], *pgd = &frags[1];
222+
TfwHttpResp *resp = __test_resp_alloc(head, pgd, MAX_SKB_FRAGS - 1);
223+
TfwHttpMsg *msg = (TfwHttpMsg *)resp;
224+
TfwHttpMsgCleanup cleanup = {};
225+
TfwMsgIter *it;
226+
int i;
227+
228+
EXPECT_NOT_NULL(resp);
229+
if (!resp)
230+
return;
231+
232+
it = &resp->iter;
233+
set_bit(TFW_HTTP_B_CHUNKED, resp->flags);
234+
resp->body.data = skb_frag_address(&skb_shinfo(it->skb)->frags[0]);
235+
resp->body_start_data = skb_frag_address(&skb_shinfo(it->skb)->frags[0]);
236+
resp->body_start_skb = it->skb;
237+
resp->body.len = (MAX_SKB_FRAGS - 1) * SLEN("paged_body");
238+
239+
tfw_http_msg_setup_transform_pool(&resp->mit, it, resp->pool);
240+
241+
EXPECT_EQ(tfw_http_msg_cutoff_headers(msg, &cleanup), 0);
242+
243+
/* Linear part MUST be moved to paged fragments */
244+
EXPECT_TRUE(!skb_headlen(it->skb));
245+
EXPECT_NULL(cleanup.skb_head);
246+
247+
EXPECT_EQ(tfw_http_msg_expand_from_pool(msg, hdr), 0);
248+
EXPECT_EQ(tfw_http_msg_expand_from_pool(msg, hdr), 0);
249+
EXPECT_EQ(tfw_http_msg_expand_from_pool(msg, hdr), 0);
250+
EXPECT_EQ(tfw_http_msg_expand_from_pool(msg, hdr), 0);
251+
252+
EXPECT_TRUE(resp->msg.skb_head != resp->msg.skb_head->next);
253+
EXPECT_TRUE(resp->msg.skb_head->next->next == resp->msg.skb_head);
254+
255+
{
256+
skb_frag_t *frag = &skb_shinfo(resp->msg.skb_head)->frags[0];
257+
char* addr = skb_frag_address(frag);
258+
unsigned int fragsz = skb_frag_size(frag);
259+
260+
EXPECT_ZERO(memcmp(addr, "headersheadersheadersheaders", fragsz));
261+
}
262+
263+
for (i = 0; i < MAX_SKB_FRAGS - 1; i++) {
264+
skb_frag_t *frag = &skb_shinfo(resp->msg.skb_head->next)->frags[i];
265+
char* addr = skb_frag_address(frag);
266+
unsigned int fragsz = skb_frag_size(frag);
267+
268+
EXPECT_ZERO(memcmp(addr, pgd->data, fragsz));
269+
}
270+
271+
tfw_http_msg_free((TfwHttpMsg *)resp);
272+
}
273+
215274
TEST_SUITE(http_msg)
216275
{
217276
TEST_RUN(http_msg, hdr_in_array);
218277
TEST_RUN(http_msg, cutoff_linear_headers_paged_body);
219278
TEST_RUN(http_msg, cutoff_linear_headers_and_linear_body);
279+
TEST_RUN(http_msg, expand_from_pool_for_headers);
220280
}

0 commit comments

Comments
 (0)