Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tls: encrypting in new sk_buff pages, if sendfile() is used or response from cache #1264

Merged
merged 1 commit into from
Jul 1, 2019

Conversation

avbelov23
Copy link
Contributor

@avbelov23 avbelov23 commented May 29, 2019

#1217

Transfer the tx_flags to the new skb_buff and encrypt in the new sk_buff pages if SKBTX_SHARED_FRAG is set or response from cache when send response via https.

@avbelov23 avbelov23 changed the title copy sk_buff pages, if sendfile () is used tls: copy sk_buff pages, if sendfile () is used May 29, 2019
@avbelov23 avbelov23 changed the title tls: copy sk_buff pages, if sendfile () is used tls: copy sk_buff pages, if sendfile() is used May 29, 2019
Copy link
Contributor

@i-rinat i-rinat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current version of PR introduces redundant data copying, which could be avoided.

tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several issues with the code. Also @i-rinat proposed much better design - this is the right way to go.

__copy_ip_header(*skb_head, skb);
skb_shinfo(*skb_head)->tx_flags = skb_shinfo(skb)->tx_flags;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Socket buffer unrolling is supposed to receive list of skbs on GRO and unroll it to separate skbs, which will be processed separately in Tempesta and the TCP/IP stack aftewards. The sense of GROed lists of skbs is that the only head skb is processed in control flow and the rest of skbs are processed only when some data is needed, so all the control information is kept in head skb only.

It seems this is a wrong place for the flags copying - you set the flags only for the first skb, bu all the skbs must have the flag. You should do very similar things as we propagate skb->mark: the first newly allocated skb gets mark from the original skb at the first ss_skb_queue_coalesce_tail() call in ss_skb_unroll_slow(). Next, we copy the mark to all frags f_skb and they pass the mark to any newly allocated skb if necessary.

int r;
TlsCtx *tls = tfw_tls_context(c);
TlsIOCtx *io = &tls->io_out;

while ((skb = ss_skb_dequeue(&msg->skb_head))) {
if (skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, lovely to see that splice() sets the flag. Please also investigate MSG_ZEROCOPY usage in modern kernels (see comment #1217 (comment)) . Please explore the latest kernel for the flag and at least write a comment what should we do if a application server uses it for sending us the data. The comment will be very helpful for further migration to newer kernel and we won't forget about the problem.

BTW @ikoveshnikov is right in #1217 (comment) : we should copy only response body for cached responses, headers are copied anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, SKBTX_DEV_ZEROCOPY is set when MSG_ZEROCOPY is used:

static inline struct ubuf_info *skb_zcopy(struct sk_buff *skb)
{
        bool is_zcopy = skb && skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY;
        
        return is_zcopy ? skb_uarg(skb) : NULL;
}
#define SKBTX_ZEROCOPY_FRAG     (SKBTX_DEV_ZEROCOPY | SKBTX_SHARED_FRAG)

So, maybe we should check for SKBTX_ZEROCOPY_FRAG rather than only for SKBTX_SHARED_FRAG?

{
int i;
struct sk_buff *frag_iter;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a comment why don't we need to copy skb head.


p = skb_frag_page(f);
order = get_order(frag_size);
p2 = alloc_pages(__GFP_MEMALLOC, order);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're in softirq, so GFP_ATOMIC must be used instead

goto err;
vaddr = kmap_atomic(p);
vaddr2 = kmap_atomic(p2);
memcpy(vaddr2, vaddr + f->page_offset, frag_size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memcpy() sucks, we can and should use memcpy_fast()

vaddr2 = kmap_atomic(p2);
memcpy(vaddr2, vaddr + f->page_offset, frag_size);
kunmap_atomic(vaddr2);
kunmap_atomic(vaddr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're in softirq, so there is no preemtion or page faults, so it's safe just to use page_address().

tempesta_fw/tls.c Outdated Show resolved Hide resolved
@avbelov23 avbelov23 force-pushed the avb-sendfile2 branch 7 times, most recently from 491f99c to 7b8806e Compare June 17, 2019 12:00
@avbelov23 avbelov23 changed the title tls: copy sk_buff pages, if sendfile() is used tls: encrypt in new sk_buff pages, if sendfile() is used or response from cache Jun 17, 2019
@avbelov23 avbelov23 changed the title tls: encrypt in new sk_buff pages, if sendfile() is used or response from cache tls: encrypting in new sk_buff pages, if sendfile() is used or response from cache Jun 17, 2019
Copy link
Contributor

@i-rinat i-rinat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some comments about the code. See below.

tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
tls/ttls.c Outdated Show resolved Hide resolved
tls/ttls.c Outdated Show resolved Hide resolved
GFP_ATOMIC);
if (!pages) {
T_WARN("cannot alloc memory.\n");
return -ENOMEM;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak happens here. In case of the error, the out_sgt.sgl wouldn't be freed.

tempesta_fw/tls.c Outdated Show resolved Hide resolved
@avbelov23 avbelov23 force-pushed the avb-sendfile2 branch 3 times, most recently from 33089bf to 3de5b27 Compare June 20, 2019 14:53
@avbelov23 avbelov23 changed the title tls: encrypting in new sk_buff pages, if sendfile() is used or response from cache tls: encrypting in new sk_buff pages, if sendfile() or MSG_ZEROCOPY is used or response from cache Jun 20, 2019
@avbelov23
Copy link
Contributor Author

DONE

@@ -1579,6 +1579,9 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce)
if (tfw_cache_build_resp_body(db, resp, trec, &it, p))
goto err;

if (TFW_CONN_TLS(req->conn))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should happen right after the response object is allocated in tfw_cache_build_resp() function, i.e. after tfw_http_msg_setup(). Please add a comment here, why the flag is added and which problem it solves.

And we have problem here, only very first skb is marked with the flag, all the following skbs in the message won't have the flag. Bit in the same time huge responses may require more than one skb. Seems like we should care of this case in tfw_msg_iter_append_skb() function.

@avbelov23 avbelov23 force-pushed the avb-sendfile2 branch 2 times, most recently from 7fa1ce8 to 284a8d0 Compare June 21, 2019 11:17
Copy link
Contributor

@vankoven vankoven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

Copy link
Contributor

@i-rinat i-rinat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to revert to SKBTX_SHARED_FRAG, since we don't handle working with user pages yet.

tempesta_fw/cache.c Outdated Show resolved Hide resolved
tempesta_fw/cache.c Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
tempesta_fw/tls.c Outdated Show resolved Hide resolved
Copy link
Contributor

@i-rinat i-rinat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@i-rinat i-rinat dismissed krizhanovsky’s stale review June 24, 2019 19:51

All comments from the review were addressed.

@avbelov23 avbelov23 changed the title tls: encrypting in new sk_buff pages, if sendfile() or MSG_ZEROCOPY is used or response from cache tls: encrypting in new sk_buff pages, if sendfile() is used or response from cache Jun 25, 2019
@avbelov23 avbelov23 force-pushed the avb-sendfile2 branch 2 times, most recently from d55621e to 2ce2672 Compare June 28, 2019 13:44
Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! I tested #1217 and #1275 cases against the code and can confirm that the issues are gone, so close them on the merge. However, there are couple notes, and one of them relatively crucial, which must be fixed before merge.

if (!pages) {
T_WARN("cannot alloc memory.\n");
r = -ENOMEM;
goto err_pages_alloc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic allocation is relatively heavy operation and I see no reason to call kmalloc() 3 times - you free all the allocations at the same time.

if (r <= 0)
goto out;
out_frags += r;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tfw_tls_encrypt() is already overloaded function and the code just prepares memory for encrypted data, so it could make sense to move it to separate function in ss_skb. However, I'm not sure how many local variables are used - if the function must accept more than standard 6 arguments, them let's leave with the current code.

ttls_aad2hdriv(xfrm, skb->data);

spin_unlock(&tls->lock);

for (i = 0; i < elt; ++i) {
put_page(pages[i]);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not need braces for single line code blocks

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@avbelov23 avbelov23 merged commit 1d7f538 into master Jul 1, 2019
@avbelov23 avbelov23 deleted the avb-sendfile2 branch July 1, 2019 16:02
avbelov23 added a commit that referenced this pull request Jul 2, 2019
backport tls encrypting in new sk_buff pages, if `sendfile()` is used or response from cache, from #1264 to release 0.6 branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants