[OpenWrt-Devel] [PATCH] comgt: add ncm proto support

Bjørn Mork bjorn at mork.no
Thu Oct 9 08:14:15 EDT 2014


"Conor O'Gorman" <i at conorogorman.net> writes:
> On 08/10/14 11:00, John Crispin wrote:
>> the e3267 that sami sent me works with this proto, but i am failing to
>> get a DHCP addr. could someone with a ncm dongle please try this patch
>> on top of latest trunk please and tell me if they are getting a dhcp addr ?
>
> I had a similar problem with a Huawei device. It worked after removing
> some zero padding in the ncm driver.
>
> In cdc_ncm.c, cdc_ncm_fill_tx_frame(), towards the end there is
> handling for Zero Length Packets (ZLP) and padding short packets. I
> removed the padding, and it worked. Are you testing 3.10 or 3.14? It's
> changed ever so slightly between them.
>
> I am somewhat confused by the comment. It won't pad out short packets,
> but does make shortish packets long.

I don't have an fix for this bug, but I can try to add some background
wrt the driver code...

The NCM protocol assumes a powerful host and a much less powerful device
(modem).  It also assumes that devices can operate more efficiently if
all (or most) packets have the same length, enabling the device DMA
engine to operate on its own without involving the device CPU. These
assumptions were true for all NCM devices and hosts implemented at the
time the protocol was finalized.  They are not necessarily true today.
But we still have to deal with those assumptions somehow.

One of the implications of this is that the device will operate more
efficiently if the host pads packets the maximum length.  On the other
hand, this padding does of course cost extra bandwidth and buffer usage, 
so there is some cutoff point for really short packets.  This is
CDC_NCM_MIN_TX_PKT (512 bytes in the current NCM linux driver).

So if a NCM packet exceeds 512 bytes then it is padded to max size.
This maximum size is decided by the device (i.e. modem), but sanitized
by the Linux driver.  Most traditional NCM devices have buffers in the
order of 4 or 8kB, which limits the overhead caused by the padding
somewhat.  But some Huawei devices have much larger buffers, causing an
insane padding overhead given the fixed 512 bytes cutoff even if the
driver sanitize the values somewhat.  This is one of the issues I tried
to fix in Linux v3.16.  Whether it was successful remains to be seen,
but at least v3.16 gives us (the users) a lot more control over the
process by adding a few tunables.  And some informational attributes as
well.

This is an example from v3.16+ (with an MBIM device, but the code and
issues are both common):

bjorn at nemi:~$ grep . /sys/class/net/wwan0/cdc_ncm/*
/sys/class/net/wwan0/cdc_ncm/bmNtbFormatsSupported:0x0001
/sys/class/net/wwan0/cdc_ncm/dwNtbInMaxSize:15360
/sys/class/net/wwan0/cdc_ncm/dwNtbOutMaxSize:15360
/sys/class/net/wwan0/cdc_ncm/min_tx_pkt:13824
/sys/class/net/wwan0/cdc_ncm/rx_max:15360
/sys/class/net/wwan0/cdc_ncm/tx_max:15360
/sys/class/net/wwan0/cdc_ncm/tx_timer_usecs:400
/sys/class/net/wwan0/cdc_ncm/wNdpInAlignment:4
/sys/class/net/wwan0/cdc_ncm/wNdpInDivisor:1
/sys/class/net/wwan0/cdc_ncm/wNdpInPayloadRemainder:0
/sys/class/net/wwan0/cdc_ncm/wNdpOutAlignment:4
/sys/class/net/wwan0/cdc_ncm/wNdpOutDivisor:32
/sys/class/net/wwan0/cdc_ncm/wNdpOutPayloadRemainder:0
/sys/class/net/wwan0/cdc_ncm/wNtbOutMaxDatagrams:32


Here you can see the device specified TX and RX buffer sizes
("dwNtb*MaxSize") and also the buffers sizes currently in use by the
driver ("rx_max"/"tx_max").  And finally the "min_tx_pkt" attribute,
which has replaced the fixed CDC_NCM_MIN_TX_PKT.  This is now
dynamically calculated based on rx_max, and, as you can see from the
values above, not causing that much overhead.

Here's an example from a Huawei device (also MBIM), where the driver has
sanitized the insane 128 kB buffer to 16 kB.

bjorn at nemi:~$ grep . /sys/class/net/wwan1/cdc_ncm/*
/sys/class/net/wwan1/cdc_ncm/bmNtbFormatsSupported:0x0003
/sys/class/net/wwan1/cdc_ncm/dwNtbInMaxSize:131072
/sys/class/net/wwan1/cdc_ncm/dwNtbOutMaxSize:32768
/sys/class/net/wwan1/cdc_ncm/min_tx_pkt:14849
/sys/class/net/wwan1/cdc_ncm/rx_max:16384
/sys/class/net/wwan1/cdc_ncm/tx_max:16385
/sys/class/net/wwan1/cdc_ncm/tx_timer_usecs:400
/sys/class/net/wwan1/cdc_ncm/wNdpInAlignment:4
/sys/class/net/wwan1/cdc_ncm/wNdpInDivisor:4
/sys/class/net/wwan1/cdc_ncm/wNdpInPayloadRemainder:0
/sys/class/net/wwan1/cdc_ncm/wNdpOutAlignment:4
/sys/class/net/wwan1/cdc_ncm/wNdpOutDivisor:4
/sys/class/net/wwan1/cdc_ncm/wNdpOutPayloadRemainder:0
/sys/class/net/wwan1/cdc_ncm/wNtbOutMaxDatagrams:0

And the last example from a device with extremely small buffers:

bjorn at nemi:~$ grep . /sys/class/net/wwan2/cdc_ncm/*
/sys/class/net/wwan2/cdc_ncm/bmNtbFormatsSupported:0x0001
/sys/class/net/wwan2/cdc_ncm/dwNtbInMaxSize:2048
/sys/class/net/wwan2/cdc_ncm/dwNtbOutMaxSize:2048
/sys/class/net/wwan2/cdc_ncm/min_tx_pkt:512
/sys/class/net/wwan2/cdc_ncm/rx_max:2048
/sys/class/net/wwan2/cdc_ncm/tx_max:2048
/sys/class/net/wwan2/cdc_ncm/tx_timer_usecs:400
/sys/class/net/wwan2/cdc_ncm/wNdpInAlignment:4
/sys/class/net/wwan2/cdc_ncm/wNdpInDivisor:4
/sys/class/net/wwan2/cdc_ncm/wNdpInPayloadRemainder:0
/sys/class/net/wwan2/cdc_ncm/wNdpOutAlignment:4
/sys/class/net/wwan2/cdc_ncm/wNdpOutDivisor:4
/sys/class/net/wwan2/cdc_ncm/wNdpOutPayloadRemainder:0
/sys/class/net/wwan2/cdc_ncm/wNtbOutMaxDatagrams:1


An interesting feature here is those 3 buffer size attributes are
writeable, along with the aggregation timeout:

bjorn at nemi:~$ ls -l /sys/class/net/wwan0/cdc_ncm/*
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/bmNtbFormatsSupported
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/dwNtbInMaxSize
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/dwNtbOutMaxSize
-rw-r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/min_tx_pkt
-rw-r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/rx_max
-rw-r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/tx_max
-rw-r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/tx_timer_usecs
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpInAlignment
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpInDivisor
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpInPayloadRemainder
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpOutAlignment
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpOutDivisor
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNdpOutPayloadRemainder
-r--r--r-- 1 root root 4096 Oct  9 10:27 /sys/class/net/wwan0/cdc_ncm/wNtbOutMaxDatagrams

I know some OpenWRT hosts have had problems using NCM modems with really
big buffers (typically Huawei modems), and am hoping that this feature
will allow those issues to be resolved.  Unfortunately not for anything
based on v3.10 or v3.14, but at least in CC...

Just one warning: I initially hoped to auto-configure the attributes to
globally perfect values, but that turned out to be impossible due to
device differences. Some buggy devices will fail if you change any of
the buffer sizes from their defaults.  So don't do that blindly, or on a
wholesale basis.  That's also one of the reasons why these settings are
per-device.

Hmm, I thought I had written some docs for this somewhere, but it
doesn't seem so.  Well, feel free to improve that now that I've posted
everything I remember :-)



Bjørn
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list