unable to get ipv6 working using MC7304

I am working on my own embedded Linux device with MC7304 for IPv6 support. However, I am unable to get ipv6 working. (Everything for IPv4 works.)
I could get the cell modem registered, and get a valid ipv6 data session. However, dhcp client get no response. Therefore it is not assigned any dhcp ipv6 address.
I also tried using ipv4+v6. In this case, it get data session for both ipv4 and ipv6. However, it only gets ipv4 dhcp ip address. It still cannot get ipv6 ip address(dhcp client still get no reply).

I can guarantee that these is no issue in Linux kernel ipv6 configuration, or dhcp client in my embedded Linux device. I can configure the ethernet interface (e.g. eth0) of my embedded device to get a dhcp ipv6 address and ping6 to the dhcp6 server I setted up or ping6 to Google Public DNS IPv6 addresses.

The development tools and version I used are:
Linux Qualcomm USB Network device driver(GobiNet): 2013-11-28/SWI_2.23
Linux Qualcomm Serial USB driver (GobiSerial): 2014-01-06/SWI_2.17
Sierra Linux QMI SDK (SLQS): 03.02.03

The cell modem firmware versions are:
Firmware and bootloader version are both: SWI9X15C_05.05.67.00
PRI version: SWI9X15C_05.05.67.00_Generic_005.028_000
(These two are the latest ones that I can find.)

I guess it may caused by any of the issues below:

  1. cell firmware has issue in supporting ipv6, or it has ipv6 disabled by default (I can’t find any AT command to enable ipv6)
  2. Sierra Linux QMI SDK (SLQS) version is old, and it has bug in supporting ipv6
  3. Linux Qualcomm USB Network device driver(GobiNet) version is old, and it has issue in supporting ipv6

I could be wrong (this is memory filtered empirical data…) but I don’t think the MC73xx supports DHCPv6. Did you try SLAAC? Or configuring the IPv6 addresses manually?

IIRC, the modem will send RAs immediately after connect, so make sure the network interface is up before you initiate a connect. Otherwise you might miss them. And I don’t think it necessarily responds to RS later (unsure about this - you should test for yourself…)

Thanks for your reply.

I am quite confident that the network interface is up before it initiates a connect. I haven’t try SLAAC yet. But I tried assigning IPv6 address manually.
Using one of the SDK function (SLQSGetRuntimeSettings), I can query the run time IPv6 address, IPv6 gateway address, and IP family preference(4 or 6 or 7). Therefore, I manually assigned the network interface with the IPv6 address returned by this SDK function. However, it still does not work. I cannot ping6 to the IPv6 gateway address, nor ping6 to Google Public DNS IPv6 addresses.

There is something weird that I realized returned by this SDK function (SLQSGetRuntimeSettings). The IPv6 address is different each time when I call this function. Then, after several times (couple minutes after), SLQSGetRuntimeSettings returns error about IPv6 link is down, and no IPv6 address is returned. Also, if I use IP family = 6, the IP family preference returned by this function is 255 which is invalid. But, if I use IP family = 7, the IP family preference returned by this function is 7 which is correct.

OK, then there is something odd going on. Maybe related to neigbour discovery? I don’t know how the GobiNet driver handles this, but you could try something like

ifconfig wwan0 -arp
ip addr add wwan0 <assigned ipv6 address>
ip -6 route add default dev wwan0

I.e. try dropping all layer2 address resolving and see if that helps.

It’s normal that the firmware returns a new address for every query. The nework assigns a /64, and the firmware just generates an arbitrary address in this prefix. It doesn’t matter which one you use, as long as it is within the assigned prefix. I guess it stops working after a few minutes due to missing traffic. This is just a symptom of the problem, and not the cause.

Don’t know about the IP family thing. Sounds like a minor unrelated issue. But I could be wrong.

Assume I have:
Gateway IPv6 address = fcb1:abab:cdcd:efe0:cc3f:3547:fcf6:f248
IPv6 Address assigned by Gateway = fcb1:abab:cdcd:efe0:e428:8a24:2a95:8f5e
IPv6 Prefix = 64
cell modem network interface is usb0

The commands I did:
(Remove any stale addresses from aborted clients.)
ip -f inet6 addr flush dev usb0 scope global

(assign ipv6 address to cell network interface)
ifconfig usb0 add fcb1:abab:cdcd:efe0:e428:8a24:2a95:8f5e/64

(remove all previous default gw)
ip -6 route flush default

(Set default gw)
ip -6 route add default via fcb1:abab:cdcd:efe0:cc3f:3547:fcf6:f248 dev usb0

However, this still doesn’t work. I cannot ping6 to gateway even
ping6 -I usb0 fcb1:abab:cdcd:efe0:cc3f:3547:fcf6:f248 fails

If configure ipv6 address statically does not work. I may need to try SLAAC. Honestly, I am not quite familiar with SLAAC. It seems that I need to install some package to support SLAAC (e.g. odhcp6c)

Note that there is no real gateway. The gateway address is just a dummy place holder to help you set up routing. But using it will only work if the modem responds to ND for that address, which might be the problem. That’s why I recommend turning off ARP (which strangely enough also turns off IPv6 ND), and set the route to point out the device without specifying any gateway.

The Linux kernel has SLAAC support. It should work by default. If it doesn’t, then you are probably not receiving any RAs. Watch the RX packet counter.

I tried turn off arp by: ifconfig usb0 -arp, and set default route using: ip -6 route add default dev usb0.
But it still does not work.

After researching SLAAC in LInux, I found that if my device is IPv6 client, I should set /proc/sys/net/ipv6/conf/eth0/forwarding to 0 and /proc/sys/net/ipv6/conf/all/forwarding to 0. Alternatively, this can be set statically by put ipv6 forwarding = 0 in /etc/sysctl.conf. Setting ipv6 forwarding = 1 will cause Linux to NOT accept Router Advertisements.
However, this still not work.

I also tried not using static way to get ipv6 address, so I comment out most of the command in my script which configures ipv6 address. I monitored network traffic using tcpdump. When cell modem established an ipv6 data session, there is no Router Solicitation (RS) message sent out by my device(cell modem). And usb0 does not get any ipv6 address. During this time SLQSGetRuntimeSettings returns IPv6 address (each time it gets a different address which is correct). And ping6 still not work during this period. After couple minutes, tcpdump shows that my device(cell modem) received an router advertisement (RA) message. So after that, ifconfig shows usb0 has an ipv6 address. However, SLQSGetRuntimeSettings returns NO IPv6 address, and ping6 does not work still.

My understanding is that for ipv6 client, it will send Router Solicitation (RS) message to router when it is up. And after IPv6 router receives RS, it will reply router advertisement (RA) message. And after IPv6 client receives RA message from router, it will parse this RA message can generate its own IPv6 address. Also, IPv6 router will periodically send RA as well.

My question is that:

  1. Why after established an IPv6 data session, my device or cell modem didn’t send RS message to router? It only received RA from router (I think this is the periodic RA sent by router) after couple minutes.
  2. Why as soon as cell modem received RA from router, SLQSGetRuntimeSettings returns NO IPv6 address.
  3. On the client side, who is responsible for sending RS message? Linux kernel? cell modem? Or I need some linux application software (e.g. odhcp6c). And who is responsible for parsing RA message and generate its IPv6 address? Linux kernel does it? Or I need some linux application software (e.g. odhcp6c)?