Ejemplo n.º 1
0
/*
 * Transmit a packet (low level interface)
 * 真正的处理的发送数据包
 */
 void snull_hw_tx(char *buf, int len, struct net_device *dev)
 {
    printk("snull_hw_tx\n");

    struct iphdr *ih;//ip头部
    struct snull_priv *priv = netdev_priv(dev);//获取私有数据
    u32 *saddr, *daddr;//源设备地址与目标设备地址

    //检查数据长度大小
    if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) 
    {
        printk("snull: Hmm... packet too short (%i octets)\n",len);
        return;
    }


    /* 开始发送数据(此处获取了ip地址用于打印)*/
    ih = (struct iphdr *)(buf + sizeof(struct ethhdr));
    saddr = &ih->saddr;
    daddr = &ih->daddr;
    printk("%pI4->%pI4\n", saddr, daddr);
    /* 调用中断模拟发送完毕 */
    priv->status = SNULL_TX_INTR;
    priv->rx_packetlen = len;
    priv->rx_packetdata = buf;
    snull_interrupt(0, dev, NULL);

    return;
}
Ejemplo n.º 2
0
/*
 * Deal with a transmit timeout.
 */
void snull_tx_timeout (struct net_device *dev)
{
    struct snull_priv *priv = (struct snull_priv *)dev->priv;

    PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies,
                    jiffies - dev->trans_start);
    priv->status = SNULL_TX_INTR;
    snull_interrupt(0, dev, NULL);
    priv->stats.tx_errors++;
    netif_wake_queue(dev);
}
Ejemplo n.º 3
0
/*
 * 一旦超出watchdog_timeo就会调用snull_tx_timeout
 */
 void snull_tx_timeout (struct net_device *dev)
 {
    printk("snull_tx_timeout\n");

    struct snull_priv *priv = netdev_priv(dev);
    printk(KERN_INFO"Transmit timeout at %ld, latency %ld\n", jiffies,jiffies - dev->trans_start);

    priv->status = SNULL_TX_INTR;
    snull_interrupt(0, dev, NULL);//超时后发生中断
    priv->stats.tx_errors++;//发送的错误数
    netif_wake_queue(dev);//为了再次发送数据,调用此函数,重新启动发送队列

    return;
}
Ejemplo n.º 4
0
/*
 * Transmit a packet (low level interface)
 */
void snull_hw_tx(char *buf, int len, struct net_device *dev)
{
    /*
     * This function deals with hw details. This interface loops
     * back the packet to the other snull interface (if any).
     * In other words, this function implements the snull behaviour,
     * while all other procedures are rather device-independent
     */
    struct iphdr *ih;
    struct net_device *dest;
    struct snull_priv *privp;
    u32 *saddr, *daddr;

    /* I am paranoid. Ain't I? */
    if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
        printk("snull: Hmm... packet too short (%i octets)\n",
               len);
        return;
    }

    if (0) { /* enable this conditional to look at the data */
        int i;
        PDEBUG("len is %i\n" KERN_DEBUG "data:",len);
        for (i=14 ; i<len; i++)
            printk(" %02x",buf[i]&0xff);
        printk("\n");
    }
    /*
     * Ethhdr is 14 bytes, but the kernel arranges for iphdr
     * to be aligned (i.e., ethhdr is unaligned)
     */
    ih = (struct iphdr *)(buf+sizeof(struct ethhdr));
    saddr = &ih->saddr;
    daddr = &ih->daddr;

    ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
    ((u8 *)daddr)[2] ^= 1;

    ih->check = 0;         /* and rebuild the checksum (ip needs it) */
    ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);

    if (dev == snull_devs)
        PDEBUGG("%08x:%05i --> %08x:%05i\n",
               ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source),
               ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest));
    else
        PDEBUGG("%08x:%05i <-- %08x:%05i\n",
               ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest),
               ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source));

    /*
     * Ok, now the packet is ready for transmission: first simulate a
     * receive interrupt on the twin device, then  a
     * transmission-done on the transmitting device
     */
    dest = snull_devs + (dev==snull_devs ? 1 : 0);
    privp = (struct snull_priv *)dest->priv;
    privp->status = SNULL_RX_INTR;
    privp->rx_packetlen = len;
    privp->rx_packetdata = buf;
    snull_interrupt(0, dest, NULL);

    privp = (struct snull_priv *)dev->priv;
    privp->status = SNULL_TX_INTR;
    privp->tx_packetlen = len;
    privp->tx_packetdata = buf;
    if (lockup && ((privp->stats.tx_packets + 1) % lockup) == 0) {
        /* Simulate a dropped transmit interrupt */
        netif_stop_queue(dev);
        PDEBUG("Simulate lockup at %ld, txp %ld\n", jiffies,
                        (unsigned long) privp->stats.tx_packets);
    }
    else
        snull_interrupt(0, dev, NULL);
}