Commit 2ae40ee9 authored by Mark Kamichoff's avatar Mark Kamichoff Committed by David S. Miller

net/usb: Add IPv6 support to the LG-VL600 LTE USB modem driver

The LG-VL600 LTE USB modem supports IPv6, but uses and expects an IPv4
ethertype (0x800) for these packets instead of the standard 0x86dd.
This patch peeks at the IP version in the L3 header and sets the
ethertype appropriately for IPv6 packets.
Signed-off-by: default avatarMark Kamichoff <prox@prolixium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8a4cadc7
...@@ -89,6 +89,8 @@ static int vl600_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -89,6 +89,8 @@ static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
* addresses have no meaning, the destination and the source of every * addresses have no meaning, the destination and the source of every
* packet depend only on whether it is on the IN or OUT endpoint. */ * packet depend only on whether it is on the IN or OUT endpoint. */
dev->net->flags |= IFF_NOARP; dev->net->flags |= IFF_NOARP;
/* IPv6 NDP relies on multicast. Enable it by default. */
dev->net->flags |= IFF_MULTICAST;
return ret; return ret;
} }
...@@ -200,6 +202,14 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ...@@ -200,6 +202,14 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
} else { } else {
memset(ethhdr->h_source, 0, ETH_ALEN); memset(ethhdr->h_source, 0, ETH_ALEN);
memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN); memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
/* Inbound IPv6 packets have an IPv4 ethertype (0x800)
* for some reason. Peek at the L3 header to check
* for IPv6 packets, and set the ethertype to IPv6
* (0x86dd) so Linux can understand it.
*/
if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
ethhdr->h_proto = __constant_htons(ETH_P_IPV6);
} }
if (count) { if (count) {
...@@ -297,6 +307,15 @@ static struct sk_buff *vl600_tx_fixup(struct usbnet *dev, ...@@ -297,6 +307,15 @@ static struct sk_buff *vl600_tx_fixup(struct usbnet *dev,
if (skb->len < full_len) /* Pad */ if (skb->len < full_len) /* Pad */
skb_put(skb, full_len - skb->len); skb_put(skb, full_len - skb->len);
/* The VL600 wants IPv6 packets to have an IPv4 ethertype
* Check if this is an IPv6 packet, and set the ethertype
* to 0x800
*/
if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
}
return skb; return skb;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment