解释一下这段代码的作用if ( skb_tailroom(h_skb) > ( n_skb->len + 4 ) ) { ieee8023_header_to_rfc1042_txsc(n_skb, add_pad); memcpy(skb_put(h_skb, n_skb->len), n_skb->data, n_skb->len); rtw_skb_free(n_skb); return _SUCCESS;
时间: 2024-03-29 22:35:11 浏览: 119
这段代码的作用如下:
首先判断条件 `skb_tailroom(h_skb) > ( n_skb->len + 4 )` 是否成立,如果成立则执行花括号内的代码。其中,`skb_tailroom(h_skb)` 表示 `h_skb` 指向的数据包中尚未使用的空间大小,`n_skb->len` 表示 `n_skb` 指向的数据包的长度,4 表示 IEEE802.2 协议头的长度。因此,这个条件的意思是判断是否还有足够的空间在 `h_skb` 数据包中,以便能够将 `n_skb` 数据包添加到其中。
如果条件成立,就先将 `n_skb` 数据包转换为 RFC 1042 格式的数据包,并将转换后的数据包存储到 `add_pad` 缓冲区中。这个转换的过程涉及到数据包头的修改,具体实现可以参考 `ieee8023_header_to_rfc1042_txsc` 函数的实现。
接着,将 `n_skb` 数据包的数据区域拷贝到 `h_skb` 数据包中,以便将 `n_skb` 数据包合并到 `h_skb` 数据包中。这个操作使用了 `memcpy` 函数,将 `n_skb` 数据包的数据区域从 `n_skb->data` 地址开始的 `n_skb->len` 个字节拷贝到 `h_skb` 数据包的尾部,返回值是拷贝后 `h_skb` 数据包的尾部地址。
最后,释放 `n_skb` 数据包的内存空间,并返回 `_SUCCESS` 表示操作成功。这个操作使用了 `rtw_skb_free` 函数,释放 `n_skb` 指向的数据包的内存空间,以便不再使用这个数据包。
相关问题
rk3399 创建一个字符设备,利用dma-buf机制从网卡读取数据例程
好的,以下是一个简单的例程,用于在 rk3399 上创建一个字符设备,并利用 dma-buf 机制从网卡读取数据:
```c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/dma-mapping.h>
#define DEV_NAME "mydev"
#define BUF_SIZE 4096
static struct miscdevice my_misc_device;
static char *rx_buf;
static dma_addr_t rx_buf_dma;
static int my_open(struct inode *inode, struct file *file)
{
return 0;
}
static int my_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret = 0;
if (count > BUF_SIZE)
count = BUF_SIZE;
if (copy_to_user(buf, rx_buf, count))
ret = -EFAULT;
else
ret = count;
return ret;
}
static struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = my_open,
.release = my_release,
.read = my_read,
};
static int my_probe(struct platform_device *pdev)
{
struct net_device *dev = dev_get_by_name(&init_net, "eth0");
struct sk_buff *skb;
struct scatterlist sg;
int i, len;
if (!dev) {
pr_err("Failed to get eth0 device\n");
return -ENODEV;
}
skb = netdev_alloc_skb(dev, BUF_SIZE, GFP_KERNEL);
if (!skb) {
pr_err("Failed to allocate skb\n");
return -ENOMEM;
}
skb_reserve(skb, NET_SKB_PAD);
skb_put(skb, BUF_SIZE);
sg_init_one(&sg, skb->data, skb->len);
if (dma_map_sg(&pdev->dev, &sg, 1, DMA_FROM_DEVICE) != 1) {
pr_err("Failed to map SG to DMA buffer\n");
return -ENOMEM;
}
rx_buf = dma_alloc_coherent(&pdev->dev, BUF_SIZE, &rx_buf_dma, GFP_KERNEL);
if (!rx_buf) {
pr_err("Failed to allocate DMA buffer\n");
return -ENOMEM;
}
len = skb->len;
for (i = 0; i < len; i += skb_tailroom(skb)) {
skb_reset_tail_pointer(skb);
skb_set_tail_pointer(skb, skb->len);
sg_init_one(&sg, skb->data, skb_tailroom(skb));
dma_sync_sg_for_cpu(&pdev->dev, &sg, 1, DMA_FROM_DEVICE);
memcpy(rx_buf + i, skb->data, skb_tailroom(skb));
dma_sync_sg_for_device(&pdev->dev, &sg, 1, DMA_FROM_DEVICE);
}
netdev_rx(skb);
misc_register(&my_misc_device);
return 0;
}
static int my_remove(struct platform_device *pdev)
{
misc_deregister(&my_misc_device);
dma_free_coherent(&pdev->dev, BUF_SIZE, rx_buf, rx_buf_dma);
return 0;
}
static struct platform_driver my_driver = {
.driver = {
.name = "my_driver",
},
.probe = my_probe,
.remove = my_remove,
};
static int __init my_init(void)
{
my_misc_device.minor = MISC_DYNAMIC_MINOR;
my_misc_device.name = DEV_NAME;
my_misc_device.fops = &my_fops;
return platform_driver_register(&my_driver);
}
static void __exit my_exit(void)
{
platform_driver_unregister(&my_driver);
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
```
以上代码仅供参考,实际使用时需要根据具体需求进行修改和优化。
阅读全文