All of lore.kernel.org
 help / color / mirror / Atom feed
* PROBLEM: rtlwifi drops most IPv6 packets
@ 2015-02-16  7:35 Alan Fisher
  2015-02-16 16:57 ` Larry Finger
  2015-02-16 18:26 ` Larry Finger
  0 siblings, 2 replies; 6+ messages in thread
From: Alan Fisher @ 2015-02-16  7:35 UTC (permalink / raw)
  To: linux-wireless, Larry.Finger, linville

Hello!

I have a machine with a Realtek RTL8188 wireless card. This card is 
handled by the rtl8192 driver. The driver in kernel 3.16.0-4 causes most 
sent ARP packets to be dropped. ARP packets appear to get through with 
the driver in kernel 3.19, but IPv6 packets suffer instead. I have 
reproduced this when connected to multiple access points.

I think I have traced this issue to some code in the rtlwifi driver that 
does special handling on "special" packets. The function 
rtl_is_special_data() in base.c determines whether a packet is 
considered special. In the 3.16 kernel, this includes ARP packets, 
wireless encryption packets, and DHCP/BOOTP packets. IPv6 appears to 
have been added to this list as of kernel 3.19.

It seems the idea is that certain important packets should be 
transmitted at the lowest possible 802.11 rate. The 
rtl_is_special_data() function is used to determine which packets to 
handle this way. Not treating any packets as special, by adding a 
"return false;" at the beginning of rtl_is_special_data(), seems to fix 
the problems with lost packets with both kernels.

I would guess that some good reason exists for this special handling, 
but I can't determine what it is. I couldn't find anything similar in 
iwlwifi. Either way, it seems like a bug to send all IPv6 traffic at the 
lowest possible rate, successful or not.

-Alan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PROBLEM: rtlwifi drops most IPv6 packets
  2015-02-16  7:35 PROBLEM: rtlwifi drops most IPv6 packets Alan Fisher
@ 2015-02-16 16:57 ` Larry Finger
  2015-02-16 18:26 ` Larry Finger
  1 sibling, 0 replies; 6+ messages in thread
From: Larry Finger @ 2015-02-16 16:57 UTC (permalink / raw)
  To: Alan Fisher, linux-wireless

On 02/16/2015 01:35 AM, Alan Fisher wrote:
> Hello!
>
> I have a machine with a Realtek RTL8188 wireless card. This card is handled by
> the rtl8192 driver. The driver in kernel 3.16.0-4 causes most sent ARP packets
> to be dropped. ARP packets appear to get through with the driver in kernel 3.19,
> but IPv6 packets suffer instead. I have reproduced this when connected to
> multiple access points.
>
> I think I have traced this issue to some code in the rtlwifi driver that does
> special handling on "special" packets. The function rtl_is_special_data() in
> base.c determines whether a packet is considered special. In the 3.16 kernel,
> this includes ARP packets, wireless encryption packets, and DHCP/BOOTP packets.
> IPv6 appears to have been added to this list as of kernel 3.19.
>
> It seems the idea is that certain important packets should be transmitted at the
> lowest possible 802.11 rate. The rtl_is_special_data() function is used to
> determine which packets to handle this way. Not treating any packets as special,
> by adding a "return false;" at the beginning of rtl_is_special_data(), seems to
> fix the problems with lost packets with both kernels.
>
> I would guess that some good reason exists for this special handling, but I
> can't determine what it is. I couldn't find anything similar in iwlwifi. Either
> way, it seems like a bug to send all IPv6 traffic at the lowest possible rate,
> successful or not.

When you specify a card number, please include the letters after the numbers. 
You say you have an RTL8188, but there are RTL8188EE, RTL8188CU, and RTL8188CE 
devices. There are drivers rtl8192cu, and rtl8192ce, as well as rtl8192de, 
rtl8192ee, and rtl8192se. I am guessing that you have an RTL8188CE, which uses 
rtl8192ce. If this is wrong, please let me know.

The purpose of rtl_is_special_data() is to ensure that management packets have 
the highest probability of being successfully transmitted by sending them at a 
low rate. This routine should never cause any packets to be dropped, only force 
them to be transmitted slowly. Obviously, there is a problem with the current 
implementation, and I will need to consult with the Realtek engineers. It also 
occurs to me that mac80211 probably handles this function, and that it may be 
possible to remove this routine, which is essentially what your workaround does.


Larry


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PROBLEM: rtlwifi drops most IPv6 packets
  2015-02-16  7:35 PROBLEM: rtlwifi drops most IPv6 packets Alan Fisher
  2015-02-16 16:57 ` Larry Finger
@ 2015-02-16 18:26 ` Larry Finger
  2015-02-17  8:29   ` Alan Fisher
  1 sibling, 1 reply; 6+ messages in thread
From: Larry Finger @ 2015-02-16 18:26 UTC (permalink / raw)
  To: Alan Fisher, linux-wireless, linville

[-- Attachment #1: Type: text/plain, Size: 179 bytes --]

On 02/16/2015 01:35 AM, Alan Fisher wrote:

Alan,

I looked at the routine, and it is returning true for all IPv6 packets.

Does the attached patch for 3.18 or 3.19 help?

Larry


[-- Attachment #2: modify_is_special_data --]
[-- Type: text/plain, Size: 805 bytes --]

Index: wireless-drivers-next/drivers/net/wireless/rtlwifi/base.c
===================================================================
--- wireless-drivers-next.orig/drivers/net/wireless/rtlwifi/base.c
+++ wireless-drivers-next/drivers/net/wireless/rtlwifi/base.c
@@ -1347,7 +1347,7 @@ u8 rtl_is_special_data(struct ieee80211_
 	offset = mac_hdr_len + SNAP_SIZE + encrypt_header_len;
 	ether_type = be16_to_cpup((__be16 *)(skb->data + offset));
 
-	if (ETH_P_IP == ether_type) {
+	if (ETH_P_IP == ether_type || ETH_P_IPV6 == ether_type) {
 		ip = (struct iphdr *)((u8 *)skb->data + offset +
 		     PROTOC_TYPE_SIZE);
 		if (IPPROTO_UDP == ip->protocol) {
@@ -1386,8 +1386,6 @@ u8 rtl_is_special_data(struct ieee80211_
 		}
 
 		return true;
-	} else if (0x86DD == ether_type) {
-		return true;
 	}
 
 end:

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PROBLEM: rtlwifi drops most IPv6 packets
  2015-02-16 18:26 ` Larry Finger
@ 2015-02-17  8:29   ` Alan Fisher
  2015-02-17 16:43     ` Larry Finger
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Fisher @ 2015-02-17  8:29 UTC (permalink / raw)
  To: Larry Finger, linux-wireless, linville

Larry,

> I am guessing that you have an RTL8188CE, which uses rtl8192ce.

Yep, my wireless card is an RTL8188CE

> The purpose of rtl_is_special_data() is to ensure that management packets have the highest probability of being successfully transmitted by sending them at a low rate.
...
> It also occurs to me that mac80211 probably handles this function, and that it may be possible to remove this routine, which is essentially what your workaround does.
I couldn't find any information on mac80211 treating certain packets (ARP, DHCP, etc...) as special. It does seem to handle automatic rate selection, though. I would think that would be enough to handle packet loss reasonably well. I believe the protocols tested for here all have mechanisms for handling lost packets. I also can't find any other 802.11 drivers which try to handle DHCP packets in a special way. I think it would be safe to remove this routine. I have a patch to do that, if you're okay with that change.

Regarding the patch, this change:

-	} else if (0x86DD == ether_type) {
-		return true;
  	}

successfully prevents IPv6 packets from being treated as special (and thus dropped).

However, this:
+	if (ETH_P_IP == ether_type || ETH_P_IPV6 == ether_type) {
  		ip = (struct iphdr *)((u8 *)skb->data + offset +

seems to be reading an IPv4 header (struct iphdr) from an IPv6 packet. I believe a struct ipv6hdr should be used here.

If we are to continue handling certain types of packets differently, IPv6 neighbor solicitation messages (like ARP in IPv4) and IPv6 router discovery messages (stateless IPv6 autoconfig, similar to DHCP in IPv4 networks) should probably be added to the list to maintain consistency with what is being handled for IPv4. These are both variants of ICMPv6 packets, although generally transmitting all ICMPv6 packets at the lowest rate is probably a bad idea, as ICMP echo is commonly used to measure network performance and should be treated the same as normal traffic.

Thanks,
Alan

On 02/16/2015 10:26 AM, Larry Finger wrote:
> On 02/16/2015 01:35 AM, Alan Fisher wrote:
>
> Alan,
>
> I looked at the routine, and it is returning true for all IPv6 packets.
>
> Does the attached patch for 3.18 or 3.19 help?
>
> Larry
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PROBLEM: rtlwifi drops most IPv6 packets
  2015-02-17  8:29   ` Alan Fisher
@ 2015-02-17 16:43     ` Larry Finger
  2015-02-22 22:49       ` Alan Fisher
  0 siblings, 1 reply; 6+ messages in thread
From: Larry Finger @ 2015-02-17 16:43 UTC (permalink / raw)
  To: Alan Fisher, linux-wireless, linville

[-- Attachment #1: Type: text/plain, Size: 2616 bytes --]

On 02/17/2015 02:29 AM, Alan Fisher wrote:
> Larry,
>
>> I am guessing that you have an RTL8188CE, which uses rtl8192ce.
>
> Yep, my wireless card is an RTL8188CE
>
>> The purpose of rtl_is_special_data() is to ensure that management packets have
>> the highest probability of being successfully transmitted by sending them at a
>> low rate.
> ...
>> It also occurs to me that mac80211 probably handles this function, and that it
>> may be possible to remove this routine, which is essentially what your
>> workaround does.
> I couldn't find any information on mac80211 treating certain packets (ARP, DHCP,
> etc...) as special. It does seem to handle automatic rate selection, though. I
> would think that would be enough to handle packet loss reasonably well. I
> believe the protocols tested for here all have mechanisms for handling lost
> packets. I also can't find any other 802.11 drivers which try to handle DHCP
> packets in a special way. I think it would be safe to remove this routine. I
> have a patch to do that, if you're okay with that change.

The story is a bit more complicated. These drivers use firmware rate selection, 
not the ones in mac80211. At this point, I would not be comfortable with 
removing the entire routine.
>
> Regarding the patch, this change:
>
> -    } else if (0x86DD == ether_type) {
> -        return true;
>       }
>
> successfully prevents IPv6 packets from being treated as special (and thus
> dropped).
>
> However, this:
> +    if (ETH_P_IP == ether_type || ETH_P_IPV6 == ether_type) {
>           ip = (struct iphdr *)((u8 *)skb->data + offset +
>
> seems to be reading an IPv4 header (struct iphdr) from an IPv6 packet. I believe
> a struct ipv6hdr should be used here.

You are correct. My patch was prepared too hastily.

> If we are to continue handling certain types of packets differently, IPv6
> neighbor solicitation messages (like ARP in IPv4) and IPv6 router discovery
> messages (stateless IPv6 autoconfig, similar to DHCP in IPv4 networks) should
> probably be added to the list to maintain consistency with what is being handled
> for IPv4. These are both variants of ICMPv6 packets, although generally
> transmitting all ICMPv6 packets at the lowest rate is probably a bad idea, as
> ICMP echo is commonly used to measure network performance and should be treated
> the same as normal traffic.

For the moment, I think we need to return false, not true, for all IPv6 packets 
until a more complete solution is found. Does the attached patch fix the problem 
you are seeing? I do not have an IPv6 compliant ISP, thus I cannot do much testing.

Larry



[-- Attachment #2: modify_is_special_data --]
[-- Type: text/plain, Size: 572 bytes --]

Index: wireless-drivers-next/drivers/net/wireless/rtlwifi/base.c
===================================================================
--- wireless-drivers-next.orig/drivers/net/wireless/rtlwifi/base.c
+++ wireless-drivers-next/drivers/net/wireless/rtlwifi/base.c
@@ -1386,8 +1386,11 @@ u8 rtl_is_special_data(struct ieee80211_
 		}
 
 		return true;
-	} else if (0x86DD == ether_type) {
-		return true;
+	} else if (ETH_P_IPV6 == ether_type) {
+		/* TODO: Handle any IPv6 cases that need special handling.
+		 * For now, always return false
+		 */
+		goto end;
 	}
 
 end:

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PROBLEM: rtlwifi drops most IPv6 packets
  2015-02-17 16:43     ` Larry Finger
@ 2015-02-22 22:49       ` Alan Fisher
  0 siblings, 0 replies; 6+ messages in thread
From: Alan Fisher @ 2015-02-22 22:49 UTC (permalink / raw)
  To: Larry Finger, linux-wireless, linville


On 02/17/2015 08:43 AM, Larry Finger wrote:
> On 02/17/2015 02:29 AM, Alan Fisher wrote:
>> Larry,
>>
>>> I am guessing that you have an RTL8188CE, which uses rtl8192ce.
>>
>> Yep, my wireless card is an RTL8188CE
>>
>>> The purpose of rtl_is_special_data() is to ensure that management 
>>> packets have
>>> the highest probability of being successfully transmitted by sending 
>>> them at a
>>> low rate.
>> ...
>>> It also occurs to me that mac80211 probably handles this function, 
>>> and that it
>>> may be possible to remove this routine, which is essentially what your
>>> workaround does.
>> I couldn't find any information on mac80211 treating certain packets 
>> (ARP, DHCP,
>> etc...) as special. It does seem to handle automatic rate selection, 
>> though. I
>> would think that would be enough to handle packet loss reasonably 
>> well. I
>> believe the protocols tested for here all have mechanisms for 
>> handling lost
>> packets. I also can't find any other 802.11 drivers which try to 
>> handle DHCP
>> packets in a special way. I think it would be safe to remove this 
>> routine. I
>> have a patch to do that, if you're okay with that change.
>
> The story is a bit more complicated. These drivers use firmware rate 
> selection, not the ones in mac80211. At this point, I would not be 
> comfortable with removing the entire routine.
Ok, makes sense.

>> Regarding the patch, this change:
>>
>> -    } else if (0x86DD == ether_type) {
>> -        return true;
>>       }
>>
>> successfully prevents IPv6 packets from being treated as special (and 
>> thus
>> dropped).
>>
>> However, this:
>> +    if (ETH_P_IP == ether_type || ETH_P_IPV6 == ether_type) {
>>           ip = (struct iphdr *)((u8 *)skb->data + offset +
>>
>> seems to be reading an IPv4 header (struct iphdr) from an IPv6 
>> packet. I believe
>> a struct ipv6hdr should be used here.
>
> You are correct. My patch was prepared too hastily.
>
>> If we are to continue handling certain types of packets differently, 
>> IPv6
>> neighbor solicitation messages (like ARP in IPv4) and IPv6 router 
>> discovery
>> messages (stateless IPv6 autoconfig, similar to DHCP in IPv4 
>> networks) should
>> probably be added to the list to maintain consistency with what is 
>> being handled
>> for IPv4. These are both variants of ICMPv6 packets, although generally
>> transmitting all ICMPv6 packets at the lowest rate is probably a bad 
>> idea, as
>> ICMP echo is commonly used to measure network performance and should 
>> be treated
>> the same as normal traffic.
>
> For the moment, I think we need to return false, not true, for all 
> IPv6 packets until a more complete solution is found. Does the 
> attached patch fix the problem you are seeing? I do not have an IPv6 
> compliant ISP, thus I cannot do much testing.
Yes, IPv6 appears to work normally with that patch applied. I recently 
spoke with someone who uses RTL8188 under Linux 3.18, and doesn't see 
any packet loss with special packets. I would guess this is because he 
has a slightly different hardware configuration (different processor, 
etc..).

>
> Larry
>

Thanks,
Alan

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-02-22 22:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-16  7:35 PROBLEM: rtlwifi drops most IPv6 packets Alan Fisher
2015-02-16 16:57 ` Larry Finger
2015-02-16 18:26 ` Larry Finger
2015-02-17  8:29   ` Alan Fisher
2015-02-17 16:43     ` Larry Finger
2015-02-22 22:49       ` Alan Fisher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.