debug ipv6 不通 ngbe驱动丢包
目前遇到问题如下:IPv6 http以及ping 不通主机 同一个网段!
为了找出原因:想用systemtap 但是编译对应环境的systemtap 失败,x86正常 但是 arm-linux 失败,没办法只能选择使用kprobe了
排查的问题的时候,使用tcpdump 抓包能抓到包, 然后就通了!!
使用kprobe debug 了一下 netif_receive_skb ; 发现没有收到报文!!
#define NIP6(addr) \ ntohs((addr).s6_addr16[0]), \ ntohs((addr).s6_addr16[1]), \ ntohs((addr).s6_addr16[2]), \ ntohs((addr).s6_addr16[3]), \ ntohs((addr).s6_addr16[4]), \ ntohs((addr).s6_addr16[5]), \ ntohs((addr).s6_addr16[6]), \ ntohs((addr).s6_addr16[7]) #define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" static void print_skb_ipv6(const struct sk_buff* skb) { struct ipv6hdr* ip6h; struct tcphdr* th; struct in6_addr ip6_sip, ip6_dip; int sport, dport; ip6h = ipv6_hdr(skb); ip6_sip = ip6h->saddr; ip6_dip = ip6h->daddr; if (ip6h->nexthdr != NEXTHDR_TCP && ip6h->nexthdr != NEXTHDR_ICMP ) { return; } if (ip6h->nexthdr == NEXTHDR_ICMP) { printk(" Source: "NIP6_FMT" Dest: " NIP6_FMT" icmp ------>\n", NIP6(ip6_sip), NIP6(ip6_dip)); return; } //skb->transport_header = skb->network_header + sizeof(*ip6h); th = tcp_hdr(skb); sport = ntohs(th->source); dport = ntohs(th->dest); printk("tcp Source: "NIP6_FMT" sport:%d --->Dest: "NIP6_FMT" dport:%d --->n", NIP6(ip6_sip), sport, NIP6(ip6_dip), dport); return; } static int ipv6_rcv_hook(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { print_skb_ipv6(skb); jprobe_return(); return 0; } static struct jprobe ipv6_recv_probe; static int probe_netif_receive_skb_fun(struct sk_buff *skb) { __be16 type; type = skb->protocol; if (type == htons(ETH_P_IPV6)) { struct ipv6hdr *hdr; hdr = (struct ipv6hdr *)(skb->data); if (hdr->nexthdr == NEXTHDR_ICMP ) { printk(" dev source: "NIP6_FMT" Dest: " NIP6_FMT" dev_netif_receive icmp------>\n", NIP6(hdr->saddr), NIP6(hdr->daddr)); }else if(hdr->nexthdr == NEXTHDR_TCP) { printk(" dev source: "NIP6_FMT" Dest: " NIP6_FMT" dev_netif_receive tcp------>\n", NIP6(hdr->saddr), NIP6(hdr->daddr)); }else { printk("dev source: "NIP6_FMT" Dest: " NIP6_FMT" dev_netif_receive ipporttype:0x%x---0x%x--->\n", NIP6(hdr->saddr), NIP6(hdr->daddr), hdr->nexthdr , ntohs(hdr->nexthdr)); } } jprobe_return(); return 0; } static struct jprobe probe_netif_receive_skb; int kp_init(void) { int retval; ipv6_recv_probe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("ipv6_rcv"); ipv6_recv_probe.entry = (kprobe_opcode_t*)ipv6_rcv_hook; retval = register_jprobe(&ipv6_recv_probe); pr_notice("init register_jprobe %d\n", retval); probe_netif_receive_skb.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("netif_receive_skb"); probe_netif_receive_skb.entry = (kprobe_opcode_t*)probe_netif_receive_skb_fun; retval = register_jprobe(&probe_netif_receive_skb); pr_notice("init probe_netif_receive_skb register_jprobe %d\n", retval); return 0; } void kp_exit(void) { unregister_jprobe(&ipv6_recv_probe); unregister_jprobe(&probe_netif_receive_skb); pr_notice("module removed\n "); }
所以此时认为是 驱动将报文丢弃! 由于tcpdump会将驱动dev的属性设置为
hw->addr_ctrl.user_set_promisc = false; if (netdev->flags & IFF_PROMISC) { hw->addr_ctrl.user_set_promisc = true; fctrl |= (NGBE_PSR_CTL_UPE | NGBE_PSR_CTL_MPE); /* pf don't want packets routing to vf, so clear UPE */ vmolr |= NGBE_PSR_VM_L2CTL_MPE; vlnctrl &= ~NGBE_PSR_VLAN_CTL_VFE; }
在 set_rx_mode 属性中可以看到 #define NGBE_PSR_VM_L2CTL_MPE 0x00001000U /* multicast promiscuous */
设置 抓取组播报文!! 由于ipv6 中的邻居协议 探测 ip 对应的mac 时, 其nd 邻居协议发送探测报文对应的使用 组播mac ,所以可能驱动不设置的时候 会将 报文丢弃!!
/* This is useful for sniffing bad packets. */ if (netdev->features & NETIF_F_RXALL) { vmolr |= (NGBE_PSR_VM_L2CTL_UPE | NGBE_PSR_VM_L2CTL_MPE); vlnctrl &= ~NGBE_PSR_VLAN_CTL_VFE; /* receive bad packets */ wr32m(hw, NGBE_RSEC_CTL, NGBE_RSEC_CTL_SAVE_MAC_ERR, NGBE_RSEC_CTL_SAVE_MAC_ERR);
驱动中还有 rxall 标志!! 所以设置为rx_all 在测试其是否正常!
目前看 设置此标志后!! 能够解决问题
后续在 分析这里面使用到的 hook_napi 技术
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2020-06-04 独享椅栏吹风