Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Sep 2017 10:57:23 -0700
From:      Stephen Hurd <shurd@sasktel.net>
To:        Hans Petter Selasky <hps@selasky.org>
Cc:        Stephen Hurd <shurd@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r323942 - head/sys/net
Message-ID:  <311ab67b-7d37-69aa-8a7b-cbd5350e51c0@sasktel.net>
In-Reply-To: <3601ee57-2bf5-036a-a3d1-a4795847d0ec@selasky.org>
References:  <201709230135.v8N1ZE6S063264@repo.freebsd.org> <B28D9879-4ECF-43E4-9A58-51F616CEC4BE@lists.zabbadoz.net> <283397c7-a01e-3776-7ed3-b64d68003d0b@sasktel.net> <6F5DC92C-2CF6-4A33-9663-BFECB7DB65F2@lists.zabbadoz.net> <89d68ff8-84ed-83a6-4e77-9a321babe2fe@sasktel.net> <3601ee57-2bf5-036a-a3d1-a4795847d0ec@selasky.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Hans Petter Selasky wrote:
> On 09/24/17 01:46, Stephen Hurd wrote:
>> Basically, it changed from this:
>>
>> foreach (mbuf in rx) {
>>    if (lro && tcp_lro_rx(mbuf) == 0)
>>      continue;
>>    if_input(mbuf)
>> }
>>
>> To this:
>>
>> prev_mbuf = first_mbuf = NULL;
>> foreach (mbuf in rx) {
>>    if (lro && tcp_lro_rx(mbuf) == 0)
>>      continue;
>>    if (prev_mbuf) {
>>      prev_mbuf->m_nextpkt = mbuf;
>>      prev_mbuf = mbuf;
>>    }
>>    else {
>>      first_mbuf = prev_mbuf = mbuf;
>>    }
>> }
>>
>> if (first_mbuf)
>>    if_input(first_mbuf);
>>
>> So while before it called if_input() for each separate mbuf that was 
>> not LROed, it now builds a chain of mbufs that were not LROed, and 
>> makes a single call to if_input() with the whole chain.  For cases 
>> like packet forwarding where no packets are LROed, performance is 
>> better.
>>
>
> Can such a similar logic be applied inside TCP LRO aswell?

It looks like it would be more complex to do a similar thing in 
tcp_lro.c, and I'm not certain it would help much except in cases with a 
large number of streams that mostly end up not being coalesced.  Taking 
a quick look, tcp_lro_flush() would need to be modified to return an 
mbuf head and tail, then the caller would need to be responsible for 
combining them into a single mbuf chain and calling if_input().

Either that, or an mbuf tail could be passed into tcp_lro_flush(), the 
tail modified in there, and an mbuf head returned... that way it would 
work something like this:

The caller would be something like this:

m_head = m_tail = NULL;
LIST_FOREACH(le, bucket, hash_next) {
   head = tcp_lro_flush(lc, le, &m_tail);
   if (m_head == NULL)
     m_head = head;
}
if (m_head)
   if_input(m_head);

And tcp_lro_flush() would be something like this:

struct mbuf *tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le, 
struct mbuf **tail)
{
   ...
   if (*tail)
     *tail->m_next = le->m_head;
   *tail = le->m_tail;
   ...
   return le->m_head;
}

Hrm, maybe it wouldn't be all that difficult after all.  :-)

I'll be driving across the country later this week, so I don't want to 
start poking into LRO then disappear, so if nobody else tries it out 
before then, I should take a look in a couple weeks.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?311ab67b-7d37-69aa-8a7b-cbd5350e51c0>