将 urb 转换为 skbuff

发布于 2024-10-05 00:20:51 字数 1694 浏览 7 评论 0原文

我正在尝试编写一个内核模块,它是 USB 驱动程序和网络驱动程序的组合,现在每当 USB 驱动程序接收到数据时,它将位于 struct urb 中,但网络驱动程序所需的数据是 sk_buff ,现在我如何将 urb 转换为 sk_buff,我发现在 Phonet 协议中正在执行类似的操作,但我无法理解,这是如何完成的。有人可以解释一下这段代码吗?

驱动程序/net/usb/cdc-phonet.c

static void rx_complete(struct urb *req)
{
struct net_device *dev = req->context;
struct usbpn_dev *pnd = netdev_priv(dev);
struct page *page = virt_to_page(req->transfer_buffer);
struct sk_buff *skb;
unsigned long flags;
int status = req->status;

switch (status) {
case 0:
spin_lock_irqsave(&pnd->rx_lock, flags);
skb = pnd->rx_skb;
if (!skb) {
skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
if (likely(skb)) {
/* Can't use pskb_pull() on page in IRQ */
memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 1, req->actual_length);
page = NULL;
}
} else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 0, req->actual_length);
page = NULL;
}
if (req->actual_length < PAGE_SIZE)
pnd->rx_skb = NULL; /* Last fragment */
else
skb = NULL;
spin_unlock_irqrestore(&pnd->rx_lock, flags);
if (skb) {
skb->protocol = htons(ETH_P_PHONET);
skb_reset_mac_header(skb);
__skb_pull(skb, 1);
skb->dev = dev;
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;

netif_rx(skb);
}
goto resubmit;

case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
req = NULL;
break;

case -EOVERFLOW:
dev->stats.rx_over_errors++;
dev_dbg(&dev->dev, "RX overflow\n");
break;

case -EILSEQ:
dev->stats.rx_crc_errors++;
break;
}

dev->stats.rx_errors++;
resubmit:
if (page)
netdev_free_page(dev, page);
if (req)
rx_submit(pnd, req, GFP_ATOMIC);
}

I am trying to write a kernel module which is the combination of the usb driver and a network driver, now whenever the data is recieved by the usb driver it will be in struct urb, but the data that is required by the net driver is sk_buff, now how do i convert a urb to sk_buff, i found something similar is being done in the phonet protocol, but i couldnt understand, howexactly this is being done. Can someone explain this code.

drivers/net/usb/cdc-phonet.c

static void rx_complete(struct urb *req)
{
struct net_device *dev = req->context;
struct usbpn_dev *pnd = netdev_priv(dev);
struct page *page = virt_to_page(req->transfer_buffer);
struct sk_buff *skb;
unsigned long flags;
int status = req->status;

switch (status) {
case 0:
spin_lock_irqsave(&pnd->rx_lock, flags);
skb = pnd->rx_skb;
if (!skb) {
skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
if (likely(skb)) {
/* Can't use pskb_pull() on page in IRQ */
memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 1, req->actual_length);
page = NULL;
}
} else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 0, req->actual_length);
page = NULL;
}
if (req->actual_length < PAGE_SIZE)
pnd->rx_skb = NULL; /* Last fragment */
else
skb = NULL;
spin_unlock_irqrestore(&pnd->rx_lock, flags);
if (skb) {
skb->protocol = htons(ETH_P_PHONET);
skb_reset_mac_header(skb);
__skb_pull(skb, 1);
skb->dev = dev;
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;

netif_rx(skb);
}
goto resubmit;

case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
req = NULL;
break;

case -EOVERFLOW:
dev->stats.rx_over_errors++;
dev_dbg(&dev->dev, "RX overflow\n");
break;

case -EILSEQ:
dev->stats.rx_crc_errors++;
break;
}

dev->stats.rx_errors++;
resubmit:
if (page)
netdev_free_page(dev, page);
if (req)
rx_submit(pnd, req, GFP_ATOMIC);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

GRAY°灰色天空 2024-10-12 00:20:51

URB 结构不包含实际传输的数据,而是包含指向数据的指针,即transfer_buffer 元素。

该代码基本上将数据从传输缓冲区复制到 sk 缓冲区。 virt_to_page / page_address 将返回transfer_buffer 页开头的虚拟地址。

The URB struct doesn't contain the actual transfered data rather it contains a pointer to the data, the transfer_buffer element.

The code basically copies data from the transfer buffer to the sk buff. The virt_to_page / page_address will return the virtual address of the start of the transfer_buffer page.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文