DPDK mbuf 与 sk_buff转换

mbuf-> sk_buf
/*
 * RX: normal working mode
 */
static void
kni_net_rx_normal(struct kni_dev *kni)
{
    unsigned ret;
    uint32_t len;
    unsigned i, num, num_rq, num_fq;
    struct rte_kni_mbuf *kva;
    struct rte_kni_mbuf *va[MBUF_BURST_SZ];
    void * data_kva;

    struct sk_buff *skb;
    struct net_device *dev = kni->net_dev;

    /* 每次收包的个数必须为rx_q和free_q的最小值且不超过MBUF_BURST_SZ */

    /* Get the number of entries in rx_q */
    num_rq = kni_fifo_count(kni->rx_q);

    /* Get the number of free entries in free_q */
    num_fq = kni_fifo_free_count(kni->free_q);

    /* Calculate the number of entries to dequeue in rx_q */
    num = min(num_rq, num_fq);
    num = min(num, (unsigned)MBUF_BURST_SZ);

    /* Return if no entry in rx_q and no free entry in free_q */
    if (num == 0)
        return;

    /* Burst dequeue from rx_q */
    ret = kni_fifo_get(kni->rx_q, (void **)va, num);
    if (ret == 0)
        return; /* Failing should not happen */

    /* mbuf转换为skb */
    /* Transfer received packets to netif */
    for (i = 0; i < num; i++) {
        /* mbuf kva */
        kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
        len = kva->data_len;
        /* data kva */
        data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;

        skb = dev_alloc_skb(len + 2);
        if (!skb) {
            KNI_ERR("Out of mem, dropping pkts\n");
            /* Update statistics */
            kni->stats.rx_dropped++;
        }
        else {
            /* Align IP on 16B boundary */
            skb_reserve(skb, 2);
            memcpy(skb_put(skb, len), data_kva, len);
            skb->dev = dev;
            skb->protocol = eth_type_trans(skb, dev);
            skb->ip_summed = CHECKSUM_UNNECESSARY;

            /* 发送skb到协议栈 */
            /* Call netif interface */
            netif_receive_skb(skb);

            /* Update statistics */
            kni->stats.rx_bytes += len;
            kni->stats.rx_packets++;
        }
    }

    /* 通知用户空间释放mbuf */
    /* Burst enqueue mbufs into free_q */
    ret = kni_fifo_put(kni->free_q, (void **)va, num);
    if (ret != num)
        /* Failing should not happen */
        KNI_ERR("Fail to enqueue entries into free_q\n");
}


sk_buf->mbuf

static int
kni_net_tx(struct sk_buff *skb, struct net_device *dev)
{
    int len = 0;
    unsigned ret;
    struct kni_dev *kni = netdev_priv(dev);
    struct rte_kni_mbuf *pkt_kva = NULL;
    struct rte_kni_mbuf *pkt_va = NULL;

    dev->trans_start = jiffies; /* save the timestamp */

    /* Check if the length of skb is less than mbuf size */
    if (skb->len > kni->mbuf_size)
        goto drop;

    /**
     * Check if it has at least one free entry in tx_q and
     * one entry in alloc_q.
     */
    if (kni_fifo_free_count(kni->tx_q) == 0 ||
            kni_fifo_count(kni->alloc_q) == 0) {
        /**
         * If no free entry in tx_q or no entry in alloc_q,
         * drops skb and goes out.
         */
        goto drop;
    }

    /* skb转mbuf */
    /* dequeue a mbuf from alloc_q */
    ret = kni_fifo_get(kni->alloc_q, (void **)&pkt_va, 1);
    if (likely(ret == 1)) {
        void *data_kva;

        pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva;
        data_kva = pkt_kva->data - kni->mbuf_va + kni->mbuf_kva;

        len = skb->len;
        memcpy(data_kva, skb->data, len);
        if (unlikely(len < ETH_ZLEN)) {
            memset(data_kva + len, 0, ETH_ZLEN - len);
            len = ETH_ZLEN;
        }
        pkt_kva->pkt_len = len;
        pkt_kva->data_len = len;

        /* enqueue mbuf into tx_q */
        ret = kni_fifo_put(kni->tx_q, (void **)&pkt_va, 1);
        if (unlikely(ret != 1)) {
            /* Failing should not happen */
            KNI_ERR("Fail to enqueue mbuf into tx_q\n");
            goto drop;
        }
    } else {
        /* Failing should not happen */
        KNI_ERR("Fail to dequeue mbuf from alloc_q\n");
        goto drop;
    }

    /* Free skb and update statistics */
    dev_kfree_skb(skb);
    kni->stats.tx_bytes += len;
    kni->stats.tx_packets++;

    return NETDEV_TX_OK;

drop:
    /* Free skb and update statistics */
    dev_kfree_skb(skb);
    kni->stats.tx_dropped++;

    return NETDEV_TX_OK;
}


你可能感兴趣的:(DPDK mbuf 与 sk_buff转换)