我正在尝试使用 dhclient 从LTE蜂窝调制解调器模块获取IP地址, dhclient 无法识别传入的DHCP回复。
这些模块在Linux中显示为“wwan0”接口。这类似于常规以太网接口,但由于它们是点对点接口,因此它们不会使用MAC地址并使用链接原始帧格式。
这意味着没有14字节以太网标头,并且它们具有 NOARP 标志集:
wwan0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet6 addr: fe80::619f:fc5a:2124:a16a/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:101 errors:0 dropped:0 overruns:0 frame:0
TX packets:155 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
dhclient 需要一个小补丁来处理NOARP接口,但它会发出有效的DHCP REQUEST
并输入select()
等待回复。
DHCP OFFER
从LTE模块返回,但select()
永远不会返回。 dhclient超时,我无法弄清楚原因。这是我到目前为止所发现的:
select()
或epoll()
选项编译 dhclient 并不重要,两者的行为相同。这是典型DHCP请求/回复的tcpdump:
$ sudo /usr/sbin/tcpdump -nXXs 1600 -vv -i wwan0
tcpdump: listening on wwan0, link-type RAW (Raw IP), capture size 1600 bytes
10:49:54.532975 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request, length 300, htype 254, hlen 0, xid 0x72731a0f, Flags [none] (0x0000)
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: Discover
Parameter-Request Option 55, length 9:
Subnet-Mask, BR, Time-Zone, Default-Gateway
Domain-Name, Domain-Name-Server, Hostname, Netbios-Name-Server
Netbios-Scope
0x0000: 4510 0148 0000 0000 8011 3996 0000 0000 E..H......9.....
0x0010: ffff ffff 0044 0043 0134 2813 01fe 0000 .....D.C.4(.....
0x0020: 7273 1a0f 0000 0000 0000 0000 0000 0000 rs..............
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
[... all zeros ...]
0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0100: 0000 0000 0000 0000 6382 5363 3501 0137 ........c.Sc5..7
0x0110: 0901 1c02 030f 060c 2c2f ff00 0000 0000 ........,/......
0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0130: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0140: 0000 0000 0000 0000 ........
10:49:54.540519 IP (tos 0x0, ttl 255, id 178, offset 0, flags [none], proto UDP (17), length 306)
10.176.3.160.67 > 10.176.3.159.68: [udp sum ok] BOOTP/DHCP, Reply, length 278, htype 254, hlen 0, xid 0x72731a0f, Flags [none] (0x0000)
Your-IP 10.176.3.159
Server-IP 10.176.3.160
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: Offer
Subnet-Mask Option 1, length 4: 255.255.255.192
Default-Gateway Option 3, length 4: 10.176.3.160
Domain-Name-Server Option 6, length 8: 199.7.156.169,199.7.156.168
Lease-Time Option 51, length 4: 7200
Server-ID Option 54, length 4: 10.176.3.160
0x0000: 4500 0132 00b2 0000 ff11 9d6a 0ab0 03a0 E..2.......j....
0x0010: 0ab0 039f 0043 0044 011e 4a14 02fe 0000 .....C.D..J.....
0x0020: 7273 1a0f 0000 0000 0000 0000 0ab0 039f rs..............
0x0030: 0ab0 03a0 0000 0000 0000 0000 0000 0000 ................
0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
[... all zeros ...]
0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0100: 0000 0000 0000 0000 6382 5363 3501 0201 ........c.Sc5...
0x0110: 04ff ffff c003 040a b003 a006 08c7 079c ................
0x0120: a9c7 079c a833 0400 001c 2036 040a b003 .....3.....6....
0x0130: a0ff ..
有没有人知道为什么select()
/ epoll()
无法接收DHCP回复?是因为它既没有MAC地址也没有IP地址可以用来匹配传入的帧?鉴于套接字绑定到IP 0.0.0.0
,恕我直言并不是一个令人满意的解释。
如果重要,这些LTE模块是USB设备。他们使用usbnet框架和qmi-wwan驱动程序。
下面是一个ftrace代码段,显示传入的数据包由qmi_wwan_rx_fixup()
处理,但随后在ip_route_input_rcu()
中出错。有什么想法吗?
0) | irq_exit() {
0) | __do_softirq() {
0) | tasklet_action() {
0) | usbnet_bh() {
0) | skb_dequeue() {
0) 0.539 us | _raw_spin_lock_irqsave();
0) 0.461 us | _raw_spin_unlock_irqrestore();
0) 7.077 us | }
0) 1.000 us | qmi_wwan_rx_fixup();
0) | usbnet_skb_return() {
0) 0.615 us | skb_defer_rx_timestamp();
0) | netif_rx() {
0) | netif_rx_internal() {
0) | enqueue_to_backlog() {
0) 0.615 us | _raw_spin_lock();
0) 0.539 us | __raise_softirq_irqoff();
0) 8.615 us | }
0) + 12.077 us | }
0) + 15.307 us | }
0) + 22.923 us | }
0) | skb_dequeue() {
0) 0.462 us | _raw_spin_lock_irqsave();
0) 0.538 us | _raw_spin_unlock_irqrestore();
0) 7.154 us | }
0) 0.846 us | netif_tx_wake_queue();
0) + 55.847 us | }
0) + 60.231 us | }
0) 0.770 us | rcu_bh_qs();
0) | net_rx_action() {
0) 0.616 us | __usecs_to_jiffies();
0) | process_backlog() {
0) 0.462 us | _raw_spin_lock();
0) | __netif_receive_skb() {
0) | __netif_receive_skb_core() {
0) | packet_rcv() {
0) | run_filter() {
0) | __bpf_prog_run32() {
0) 3.000 us | ___bpf_prog_run();
0) 6.308 us | }
0) + 10.616 us | }
0) 1.077 us | consume_skb();
0) + 19.000 us | }
0) | ip_rcv() {
0) | nf_hook_slow() {
0) 0.846 us | ipv4_conntrack_defrag();
0) | iptable_raw_hook() {
0) | ipt_do_table() {
0) 1.308 us | udp_mt();
0) 0.538 us | __local_bh_enable_ip();
0) + 19.692 us | }
0) + 23.307 us | }
0) | ipv4_conntrack_in() {
[...]
0) ! 126.384 us | }
0) | iptable_mangle_hook() {
0) | ipt_do_table() {
0) 0.384 us | __local_bh_enable_ip();
0) 5.385 us | }
0) 8.769 us | }
0) | iptable_nat_ipv4_in() {
[...]
0) + 80.539 us | }
0) ! 255.923 us | }
0) | ip_rcv_finish() {
0) | udp_v4_early_demux() {
0) 0.615 us | udp4_portaddr_hash();
0) 4.693 us | }
0) | ip_route_input_noref() {
0) | ip_route_input_rcu() {
0) 0.615 us | make_kuid();
0) | __fib_lookup() {
0) | l3mdev_update_flow() {
0) 0.615 us | dev_get_by_index_rcu();
0) 0.462 us | l3mdev_master_ifindex_rcu();
0) 7.077 us | }
0) | fib_rules_lookup() {
[...]
0) + 51.769 us | }
0) + 64.769 us | }
0) | rt_dst_alloc() {
0) | dst_alloc() {
0) 0.615 us | kmem_cache_alloc();
0) 1.462 us | dst_init();
0) 8.461 us | }
0) + 12.384 us | }
0) + 89.153 us | }
0) + 92.538 us | }
0) | ip_error() {
0) 0.615 us | __local_bh_enable_ip();
0) 0.462 us | l3mdev_master_ifindex_rcu();
0) | inet_getpeer() {
0) 2.384 us | lookup();
0) 6.230 us | }
0) 0.615 us | inet_putpeer();
0) | icmp_send() {
[...]
0) ! 457.462 us | }
0) | kfree_skb() {