Re: LTE vodafone K5150 12d1 1f16 ; 12d1 1575 mbim IPV6/ipv4

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thomas Schäfer <tschaefer@xxxxxxxxxxx> writes:

> Hi Bjørn,
>
>
> I tested your patch with the K5150 in mbim-mode
>
> with ipv6 only - ok.
> with Ipv4 only - ok.


Yes, I was pretty sure of that since I am able to test IPv4 myself and
the IPv6 solution is based on simply turning of the IFF_NOARP flag.

But I realized that we cannot do it like that after posting the patch.
What will happen if we encounter a device which doesn't respond to IPv6
ND? After all, that's the sane thing to do... Such devices will then
need a similary workaround for ND.  And then it makes more sense to just
add that for the buggy devices instead, leaving ARP entirely out of this.

So I guess we have keep the IFF_NOARP flag, and implement whatever is
necessary for dealing with the unexpected IPv6 ND.  I made a quick
attempt on that too. I won't have time to finish it any time soon, so I
am sending it to you now in an unfinished state, completely untested!  I
haven't even built this yet...

The patch requires v3.12 because of the (ab)use of the vxlan IPv6
support added there.  Not sure that was a good idea.  We could just mock
up the NA packet and fire it off ourselves.  It's not like it needs to
go through any sort of interface selection or neighbour lookup.

> I have only one mbim-device, this 5150. 
>
> Let me know, if you need further tests.

If you want to test the attached patch, then be warned:  This is likely
to crash a few times, until you have cleaned it up, *after* you have
made it build in the first place.  And then you have to make it work ;-)

Note that this should be applied instead of the first patch, not on top
of it.



Bjørn

>From dcdf1b769fb4305c92f99a4294660149f46f1a37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@xxxxxxx>
Date: Sun, 27 Oct 2013 12:09:56 +0100
Subject: [PATCH] cdc_mbim: handle IPv6 Neigbor Solicitations directly
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some buggy devices require IPv6 Neighbor Discovery support. This
is incompatible with the IFF_NOARP flag.  But ARP is impossible
on MBIM, because the protocol only supports IPv4 or IPv6 packets.

Work around this by handling Neigbor Solicitations in the driver.

Signed-off-by: Bjørn Mork <bjorn@xxxxxxx>
---
 drivers/net/usb/cdc_mbim.c |   58 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 25ba7ec..05f0a17 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -21,6 +21,8 @@
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc-wdm.h>
 #include <linux/usb/cdc_ncm.h>
+#include <net/ipv6.h>
+#include <net/addrconf.h>
 
 /* driver specific data - must match cdc_ncm usage */
 struct cdc_mbim_state {
@@ -184,6 +186,59 @@ error:
 	return NULL;
 }
 
+/* Some devices are known to send Neigbor Solicitation messages and
+ * require Neigbor Advertisement replies.  The IPv6 core will not
+ * respond since IFF_NOARP is set, so we must handle them ourselves.
+ */
+static bool do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
+{
+	struct ipv6hdr *iph = (void *)buf;
+	struct nd_msg *msg = (void *)(iph + 1);
+	struct net_device *netdev;
+	struct inet6_dev *in6_dev;
+	bool is_router;
+
+	/* we'll only respond to requests from unicast addresses to
+	 * our solicited node addresses
+	 */
+	if (!ipv6_addr_is_solict_mult(&iph->daddr) ||
+	    !(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST))
+		return false;
+
+	/* need to send the NA on the VLAN dev, if any */
+	if (tci)
+		netdev = __vlan_find_dev_deep(dev->net, htons(ETH_P_8021Q), tci);
+	else
+		netdev = dev->net;
+	if (!netdev)
+		return false;
+
+	in6_dev = in6_dev_get(netdev);
+	if (!in6_dev)
+		return false;
+	is_router = !!in6_dev->cnf.forwarding;
+	in6_dev_put(in6_dev);
+
+	/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
+	ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target,
+				 is_router, true, false, false);
+
+	/* handled - drop the original input datagram */
+	return true;
+}
+
+static bool is_neigh_solicit(u8 *buf, size_t len)
+{
+	struct ipv6hdr *iph = (void *)buf;
+	struct nd_msg *msg = (void *)(iph + 1);
+
+	return (len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) &&
+		iph->nexthdr == IPPROTO_ICMPV6 &&
+		msg->icmph.icmp6_code == 0 &&
+		msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION);
+}
+
+
 static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
 {
 	__be16 proto = htons(ETH_P_802_3);
@@ -198,6 +253,9 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
 			proto = htons(ETH_P_IP);
 			break;
 		case 0x60:
+			if (is_neigh_solicit(buf, len) &&
+			    do_neigh_solicit(dev, buf, tci))
+				goto err;
 			proto = htons(ETH_P_IPV6);
 			break;
 		default:
-- 
1.7.10.4


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux