对比寄存器解决千兆丢包问题

问题现象

客户反馈在连接局域网的场景下,相同板卡硬件(d2000+ar8035)上,嵌入式系统千兆ping丢包率很高,而ubuntu文件系统+飞腾提供的测试内核正常。

以下将工作异常的系统称为系统A。

问题复现

客户板卡上搭建测试环境,成功复现问题。

连接局域网环境下,在板卡与陪测端抓包分析:
丢了4个包:序号为2、10、13、18

在这里插入图片描述与ping结果可对应上:

在这里插入图片描述
172.30.110.35为陪测机(enx),172.30.110.37为异常板卡(eth0)。eth抓到了那4个包的request,enx没有抓到。说明板卡网口eth0可能没有发出来。

后续测试使板卡与陪测机直连,仍可复现异常现象,说明客户反馈的现象不准确。。。。。后续均以直连方式测试。

异常板卡系统A环回测试

mac环回正常

对mac做环回测试。由于,mac层是由cpu集成的gmac芯片实现的,故查看d2000软件编程手册:

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

手册里查询到,在mac配置寄存器的bit 12控制mac loopback功能。

从启动日志里输出的dts设备树文件可以确认eth0网卡对应的是GMAC0:
在这里插入图片描述

故需要向GMAC0私有寄存器的基地址加上偏移量来写入bit(12),即0x2820c000+0x0 = 0x2820c000地址的bit12。

先搭建环回测试场景,将ip配为非网线网段的ip(10.3.3.1),arp -s 10.3.3.2 本机mac 创建一条arp地址映像避免后续环回时找不到目的主机发不出ping包。

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x0
read phy addr: 0x0 reg: 0x0 value : 0x3100

root@KylinV10Embeded 20240301-jingsu# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 3C:6A:2C:3C:6A:2C
          inet addr:10.3.3.1  Bcast:10.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::3e6a:2cff:fe3c:6a2c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1165 errors:0 dropped:0 overruns:0 frame:0
          TX packets:493 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:256524 (250.5 KiB)  TX bytes:102132 (99.7 KiB)
          Interrupt:22 Base address:0x2000

root@KylinV10Embeded 20240301-jingsu# arp -n
? (10.3.3.2) at 3c:6a:2c:3c:6a:2c [ether] PERM on eth0
root@KylinV10Embeded 20240301-jingsu#
root@KylinV10Embeded 20240301-jingsu# devmem2 0x0002820c000 w
-/bin/sh: devmem2: not found
root@KylinV10Embeded 20240301-jingsu# ls
devmem2         mdio            phytool.tar.gz
root@KylinV10Embeded 20240301-jingsu# ./devmem2 0x0002820c000 w
/dev/mem opened.
Memory mapped at address 0xffffbe217000.
Memory mapped at address 0xffffbe216000.
Value at address 0x2820C000 (0xffffbe217000): 0x610C8C
root@KylinV10Embeded 20240301-jingsu# ./devmem2 0x0002820c000 w 0x611c8c                //上面读到了mac配置寄存器内容是0x610c8c,将第12bit置1后则是0x611c8c
/dev/mem opened.
Memory mapped at address 0xffffa5e5b000.
Memory mapped at address 0xffffa5e5a000.
Value at address 0x2820C000 (0xffffa5e5b000): 0x610C8C
Written 0x611C8C; readback 0x611C8C
root@KylinV10Embeded 20240301-jingsu# tcpdump -i eth0 &
root@KylinV10Embeded 20240301-jingsu# [ 3810.513776][  0] device eth0 entered promiscuous mode
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

root@KylinV10Embeded 20240301-jingsu# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2): 56 data bytes
09:03:38.456902 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 483, seq 0, length 64
09:03:38.456961 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 483, seq 0, length 64


--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
root@KylinV10Embeded 20240301-jingsu#

root@KylinV10Embeded 20240301-jingsu#
root@KylinV10Embeded 20240301-jingsu# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 3C:6A:2C:3C:6A:2C
          inet addr:10.3.3.1  Bcast:10.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::3e6a:2cff:fe3c:6a2c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1166 errors:0 dropped:0 overruns:0 frame:0
          TX packets:494 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:256622 (250.6 KiB)  TX bytes:102230 (99.8 KiB)
          Interrupt:22 Base address:0x2000

root@KylinV10Embeded 20240301-jingsu# //环回测试前后,tx由493增加到494,rx由1165增加到1166,对应了抓到的两个icmp req。

mac环回正常,网卡成功发出了一个icmp req并通过环回链路重新接收到了这个icmp req,故tx、rx均增1个。

phy1000M环回异常

测试phy环回,mdio是通过ioctl机制的SIOCSMIIREG项实现的读写phy寄存器的可执行程序。代码网上能搜到,也可以自己写。

关于phy环回测试操作之前有专门写过,正好是同型号phy芯片,这次就不细体现了:phy环回测试方法(以芯片Atheros8035为例)

网卡是由主板上的gmac网卡芯片+外接phy芯片(AR8035),查看ar8035手册,发现手册对配置环回模式有着很清晰的操作步骤。

在这里插入图片描述还是先搭建换回测试环境,先配ip并创建arp映像,再读写phy寄存器。

root@KylinV10Embeded ~# ifconfig eth0 10.3.3.1
root@KylinV10Embeded ~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 3C:6A:2C:3C:6A:2C
          inet addr:10.3.3.1  Bcast:10.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::3e6a:2cff:fe3c:6a2c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1082 errors:0 dropped:0 overruns:0 frame:0
          TX packets:487 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:248896 (243.0 KiB)  TX bytes:101588 (99.2 KiB)
          Interrupt:22 Base address:0x2000

root@KylinV10Embeded ~# arp -s 10.3.3.2 3C:6A:2C:3C:6A:2C
root@KylinV10Embeded ~# arp -n
? (10.3.3.2) at 3c:6a:2c:3c:6a:2c [ether] PERM on eth0
root@KylinV10Embeded ~# cd 20240301-jingsu/
root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x0
-/bin/sh: ./mdio: Permission denied
root@KylinV10Embeded 20240301-jingsu# chmod 777 mdio
root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x0
read phy addr: 0x0 reg: 0x0 value : 0x3100

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x0 0x4140
write phy addr: 0x0 reg: 0x0 value : 0x4140

root@KylinV10Embeded 20240301-jingsu# [ 1406.813862][  0] stmmaceth 2820c000.eth eth0: Link is Down
[ 1407.853849][  0] stmmaceth 2820c000.eth eth0: Link is Up - 1Gbps/Full - flow control off

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x0
read phy addr: 0x0 reg: 0x0 value : 0x4140

root@KylinV10Embeded 20240301-jingsu# tcpdump -i eth0 &
root@KylinV10Embeded 20240301-jingsu# [ 1436.163753][  0] device eth0 entered promiscuous mode
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

root@KylinV10Embeded 20240301-jingsu# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2): 56 data bytes
08:24:05.823585 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 444, seq 0, length 64


--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
root@KylinV10Embeded 20240301-jingsu#

phy1000M不正常,只抓到了一个req包。

phy100M+10M环回正常

同理,按照手册测试phy 100M、10M环回,操作步骤省略:

root@KylinV10Embeded 20240301-jingsu# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2): 56 data bytes
08:26:30.222649 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 453, seq 0, length 64
08:26:30.222709 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 453, seq 0, length 64

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
root@KylinV10Embeded 20240301-jingsu#

... ... ... ...
root@KylinV10Embeded 20240301-jingsu# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2): 56 data bytes
08:28:06.301826 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 458, seq 0, length 64
08:28:06.301959 IP 10.3.3.1 > 10.3.3.2: ICMP echo request, id 458, seq 0, length 64

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
root@KylinV10Embeded 20240301-jingsu#

100M、10M环回正常。

查询异常系统A的phy工作模式

cat /sys/devices/platform/soc/2820c000.eth/net/eth0/phydev/phy_interface
rgmii-txid

查看官方对于rgmii-txid接口模式的功能介绍,提及了tx delay功能。
在这里插入图片描述

查询手册里rgmii tx delay的寄存器配置参数:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
由上可知,想要修改rgmii tx clock delay control寄存器,需要先向debug port address offset register写入目的寄存器偏移地址,即debug register 5(又名rgmii tx clock delay control寄存器,偏移地址为0x05),然后读取debug port data寄存器的值,此值为目的寄存器的值。

PS:大多数控制寄存器可以直接通过基地址访问,但像“debug registers summary ”里的这几个debug寄存器就需要借助某个控制寄存器去访问。具体还是看手册里是如何定义的

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d
read phy addr: 0x0 reg: 0x1d value : 0x0

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x05
write phy addr: 0x0 reg: 0x1d value : 0x5

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x2d47

root@KylinV10Embeded 20240301-jingsu#
bit 11-8  7-4  3-0
	1101  0100  0111
  		d    4    7

查询到系统A 的rgmii_tx_clk_dly功能已开启

对比ubuntu环回测试

mac环回测试正常

省略搭建环境与配置寄存器步骤,完全 一样的硬件,寄存器地址也都相同。

root@d2000:~/sujing# ./tcpdump -i eth0 &
[1] 3590
root@d2000:~/sujing# tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

root@d2000:~/sujing# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2) 56(84) bytes of data.

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

02:40:53.658222 IP d2000 > 10.3.3.2: ICMP echo request, id 3, seq 1, length 64
02:40:53.658529 IP d2000 > 10.3.3.2: ICMP echo request, id 3, seq 1, length 64
root@d2000:~/sujing# ifconfig eth002:41:12.113515 IP6 d2000 > ip6-allrouters: ICMP6, router solicitation, length 16
02:41:12.113806 IP6 d2000 > ip6-allrouters: ICMP6, router solicitation, length 16

phy1000M正常

root@d2000:~/sujing# ./tcpdump -i eth0 &
[1] 3633
root@d2000:~/sujing# tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

root@d2000:~/sujing#
root@d2000:~/sujing# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2) 56(84) bytes of data.

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

02:47:58.450817 IP d2000 > 10.3.3.2: ICMP echo request, id 8, seq 1, length 64
02:47:58.451120 IP d2000 > 10.3.3.2: ICMP echo request, id 8, seq 1, length 64
root@d2000:~/sujing# ifconfig et02:48:52.960384 IP6 d2000 > ip6-allrouters: ICMP6, router solicitation, length 16
02:48:52.960410 IP6 d2000 > ip6-allrouters: ICMP6, router solicitation, length 16

phy100M异常

root@d2000:~/sujing# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2) 56(84) bytes of data.
02:50:22.549824 IP d2000 > 10.3.3.2: ICMP echo request, id 9, seq 1, length 64

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

root@d2000:~/sujing# 

phy10M异常

root@d2000:~/sujing# ./tool/mdio eth0 0x0 0x4100
write phy addr: 0x0 reg: 0x0 value : 0x4100

root@d2000:~/sujing# ping 10.3.3.2 -c 1
PING 10.3.3.2 (10.3.3.2) 56(84) bytes of data.
02:51:29.265757 IP d2000 > 10.3.3.2: ICMP echo request, id 10, seq 1, length 64

--- 10.3.3.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

root@d2000:~/sujing# 

重复测试多次,现象保持一致

说明 异常板卡系统A 的phy 1000M异常,与实际业务现象一致。

查询ubuntu phy工作模式

同样是rgmii-txid模式。

寄存器值列表对比测试

ubuntu寄存器

通过相同方法,借助debug port address offset register与debug port data寄存器来访问所有debug寄存器的值

在网络正常联通状态下测试
root@d2000:~/sujing# ping 172.16.3.254
PING 172.16.3.254 (172.16.3.254) 56(84) bytes of data.
64 bytes from 172.16.3.254: icmp_seq=1 ttl=255 time=3.06 ms
64 bytes from 172.16.3.254: icmp_seq=2 ttl=255 time=1.59 ms
64 bytes from 172.16.3.254: icmp_seq=3 ttl=255 time=16.8 ms
^C
--- 172.16.3.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.590/7.160/16.830/6.863 ms
root@d2000:~/sujing# ./tool/mdio eth0 0x1d
read phy addr: 0x0 reg: 0x1d value : 0x0

root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x0b
write phy addr: 0x0 reg: 0x1d value : 0xb

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0xbc40

root@d2000:~/sujing# 

root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x0
write phy addr: 0x0 reg: 0x1d value : 0x0

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x82ee

root@d2000:~/sujing# 


root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x05
write phy addr: 0x0 reg: 0x1d value : 0x5

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x2c47

root@d2000:~/sujing# 

root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x10
write phy addr: 0x0 reg: 0x1d value : 0x10

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x0

root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x11
write phy addr: 0x0 reg: 0x1d value : 0x11

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x7552

root@d2000:~/sujing# ./tool/mdio eth0 0x1d 0x12
write phy addr: 0x0 reg: 0x1d value : 0x12

root@d2000:~/sujing# ./tool/mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x4c0c

root@d2000:~/sujing# 

工作异常板卡系统A的寄存器

通过相同方法,借助debug port address offset register与debug port data寄存器来访问所有debug寄存器的值

root@KylinV10Embeded 20240301-jingsu# ping 172.30.110.35
PING 172.30.110.35 (172.30.110.35): 56 data bytes
64 bytes from 172.30.110.35: seq=1 ttl=64 time=0.604 ms
64 bytes from 172.30.110.35: seq=2 ttl=64 time=0.610 ms
64 bytes from 172.30.110.35: seq=3 ttl=64 time=0.613 ms
64 bytes from 172.30.110.35: seq=4 ttl=64 time=0.611 ms
64 bytes from 172.30.110.35: seq=5 ttl=64 time=0.605 ms
64 bytes from 172.30.110.35: seq=6 ttl=64 time=0.604 ms
^C
--- 172.30.110.35 ping statistics ---
9 packets transmitted, 6 packets received, 33% packet loss
round-trip min/avg/max = 0.604/0.607/0.613 ms
root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d
read phy addr: 0x0 reg: 0x1d value : 0x0

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x0b
write phy addr: 0x0 reg: 0x1d value : 0xb

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x3c40

root@KylinV10Embeded 20240301-jingsu# 
root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x0
write phy addr: 0x0 reg: 0x1d value : 0x0

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x82ee

root@KylinV10Embeded 20240301-jingsu# 

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x05
write phy addr: 0x0 reg: 0x1d value : 0x5

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x2d47

root@KylinV10Embeded 20240301-jingsu# 

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x10
write phy addr: 0x0 reg: 0x1d value : 0x10

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x0

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x11
write phy addr: 0x0 reg: 0x1d value : 0x11

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x7552

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1d 0x12
write phy addr: 0x0 reg: 0x1d value : 0x12

root@KylinV10Embeded 20240301-jingsu# ./mdio eth0 0x1e
read phy addr: 0x0 reg: 0x1e value : 0x4c0c

root@KylinV10Embeded 20240301-jingsu# 

两系统寄存器值差异对比表

寄存器ubuntu系统A
0x000x82ee0x82ee
0x05 0x2c47 0x2d47
0x100x00x0
0x110x75520x7552
0x120x4c0c0x4c0c
0x0b 0xbc40 0x3c40

修改寄存器测试

异常系统A 修改寄存器测试

默认状态下(千兆直连ping丢包):

  • 将0x0b改为0xbc40,0x05保持不变。网络直连ping仍丢包
  • 将0x0b改为0xbc40,0x05改为0x2c47.网络直连ping不丢包
  • 将0x0b保持不变,0x05改为0x2c47,网络直连ping不丢包

说明问题出在0x05寄存器值。只需要将寄存器0x05 bit 8 置为0,即关闭rgmii_tx_clk_dly。系统A就正常不丢包

反向测试,ubuntu修改寄存器测试

默认状态下(千兆直连ping不丢包):

  • 将0x05改为0x2d47,网络直连ping丢包

开启0x05 bit(8) ubuntu系统就会丢包,可以确定问题定位到bit(8)上,即rgmii_tx_clk_dly功能。

问题定位

由上述调试实验,可确认系统A问题出在bit(8)上的rgmii tx clk delay功能开启上。

嵌入式板卡启动使用设备树dts文件,与相关同事沟通,当前版本下的dts文件eth0配置为rgmii-txid模式,系统内核模式选择没有出现问题:

eth@2820c000 {                                                     
             compatible = "snps,dwmac";                                    
             reg = <0x0 0x2820c000 0x0 0x2000>;
             ... ...
             phy-mode = "rgmii-txid";
}

启动日志里发现,ubuntu启动用的是generic phy,异常系统A用的是at803x。故导致了两个内核在相同硬件、相同设备树配置下,启动时的寄存器配置差异。

ubuntu:mdio_bus stmmac-0:00: attached PHY driver [unbound] (mii_bus:phy_addr=stmmac-0:00, irq=POLL)
异常系统A:Atheros 8035 ethernet stmmac-0:00: attached PHY driver [Atheros 8035 ethernet] (mii_bus:phy_addr=stmmac-0:00, irq=POLL)

将异常系统A的bit(8)功能关闭后,经测试,自协商1000M模式ping包正常,手动100M、手动10M模式ping包正常。即所有带宽均正常

经查询代码,异常系统A的初始化函数是at803x_config_init、ubuntu的初始化函数是genphy_config_init

两者在初始化配置上,仅差在at803x驱动里会调用at803x_enable_tx_delay函数配置开启tx clk delay功能。与寄存器取值现象一致。

问题解决

txid模式下,根据官方文档,说明这种模式是需要开启 tx clk delay功能的。设备树配置了txid,内核启动后网卡寄存器配置的功能也正常。怀疑设备树配置问题。

让客户与硬件相关厂商沟通,最终发现硬件上mac与phy的物理连接模式是rgmii而非rgmii_txid。 -_-|||
将dts里模式修改为rgmii后,系统网络恢复正常。

多组测试,确认10M、100M、1000M均不丢包

PS

大部分定制项目场景常使用板载gmac芯片+外接phy芯片,两者一起实现网络的底层功能,这种情况下查询手册时,gmac需要查cpu手册,phy查相应型号的网卡厂商手册。有的phy芯片是集成在桥片上的,这时候就需要去查桥片的手册。

环回测试时,顺序要从上到下进行测试。如果phy层有问题,mac层的环回也可能会不正常。

  • 13
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值