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 ------>
",
                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------>
",
                NIP6(hdr->saddr), NIP6(hdr->daddr));
        }else if(hdr->nexthdr == NEXTHDR_TCP) {
            printk(" dev source: "NIP6_FMT"  Dest: " NIP6_FMT"  dev_netif_receive tcp------>
",
                NIP6(hdr->saddr), NIP6(hdr->daddr));
            
        }else {
            printk("dev source: "NIP6_FMT"  Dest: " NIP6_FMT"  dev_netif_receive ipporttype:0x%x---0x%x--->
",
                   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
", 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
", retval);

    return 0;
}

void kp_exit(void)
{
    unregister_jprobe(&ipv6_recv_probe);
    unregister_jprobe(&probe_netif_receive_skb);
    pr_notice("module removed
 ");
}

所以此时认为是 驱动将报文丢弃! 由于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的胖子
原文地址:https://www.cnblogs.com/codestack/p/14851280.html