/****************************************************
* dev_alloc_skb - 分配内存为接受的包
* @length: 分配的长度
* GFP_ATOMIC:原子类型,此函数经常用于终端上下文中
***************************************************/
struct sk_buff *dev_alloc_skb(unsigned int length)
{
return __dev_alloc_skb(length, GFP_ATOMIC);
}
EXPORT_SYMBOL(dev_alloc_skb);
#ifndef NET_SKB_PAD
#define NET_SKB_PAD 32
#endif
/*************************************************************
*gfp_mask: get_free_pages mask, passed to alloc_skb
*alloc_skb()增加32字节的空间,优化读写的效率
**************************************************************/
static inline struct sk_buff *__dev_alloc_skb(unsigned int length, gfp_t gfp_mask)
{
struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
if (likely(skb))
skb_reserve(skb, NET_SKB_PAD);
return skb;
}
static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority)
{
return __alloc_skb(size, priority, 0, -1);
}
/****************************************************************************
* __alloc_skb 分配network的缓冲区
* @size: 分配的内存大小
* @gfp_mask: 分配的标签
* @fclone: 从fclone缓存分配内存并分配一个克隆的skb
* @node: 分配的节点号,一般为-1
****************************************************************************/
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone, int node)
{
struct kmem_cache *cache;
struct skb_shared_info *shinfo;
struct sk_buff *skb;
u8 *data;
cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
/* 获取头 */
skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
if (!skb)
goto out;
size = SKB_DATA_ALIGN(size); //字节对齐
data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),gfp_mask, node);
if (!data)
goto nodata;
memset(skb, 0, offsetof(struct sk_buff, tail));
skb->truesize = size + sizeof(struct sk_buff);
atomic_set(&skb->users, 1);
skb->head = data;
skb->data = data;
skb_reset_tail_pointer(skb);
skb->end = skb->tail + size;
shinfo = skb_shinfo(skb);
atomic_set(&shinfo->dataref, 1);
shinfo->nr_frags = 0;
shinfo->gso_size = 0;
shinfo->gso_segs = 0;
shinfo->gso_type = 0;
shinfo->ip6_frag_id = 0;
shinfo->tx_flags.flags = 0;
shinfo->frag_list = NULL;
memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps));
if (fclone)
{
struct sk_buff *child = skb + 1;
atomic_t *fclone_ref = (atomic_t *) (child + 1);
skb->fclone = SKB_FCLONE_ORIG;
atomic_set(fclone_ref, 1);
child->fclone = SKB_FCLONE_UNAVAILABLE;
}
out:
return skb;
nodata:
kmem_cache_free(cache, skb);
skb = NULL;
goto out;
}
EXPORT_SYMBOL(__alloc_skb);
/**
* @skb: buffer to alter
* @len: bytes to move
*
* Increase the headroom of an empty &sk_buff by reducing the tail
* room. This is only allowed for an empty buffer.
*/
static inline void skb_reserve(struct sk_buff *skb, int len)
{
skb->data += len;
skb->tail += len;
}
分享到:
相关推荐
2. **线性化处理**:如果`sk_buff`被分段存储,并且设备不支持分散/聚集(Scatter/Gather,简称SG),或者存在某些段位于高内存中(high memory),则需要通过`__skb_linearize`函数将所有片段合并到一个连续的内存...
- `skb_queue_empty`:检查套接字缓冲区队列是否为空。 - `skb_get`:获取套接字缓冲区。 - `kfree_skb`:释放套接字缓冲区。 - `skb_cloned`:检查套接字缓冲区是否被克隆。 - `skb_shared`:检查套接字缓冲区是否...
- **skb_orphan**:使socket缓冲区孤儿化,即不再与发送者或接收者关联。 - **skb_queue_purge**:清空socket缓冲区队列。 - **__skb_queue_purge**:同上。 - **dev_alloc_skb**:为设备分配socket缓冲区。 - ...
- **dev_alloc_skb()**、**skb_cow()**、**skb_over_panic()**、**skb_under_panic()**、**alloc_skb()**、**__kfree_skb()**:用于分配、拷贝、回收socket buffer。 总结而言,Linux内核API覆盖了从文件系统到网络...
memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); /* Write metadata, and then pass to the receive level */ skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = ...
- **`skb_cl`**:此处文档缺失,可能是`skb_clone()`,用于克隆socket缓冲区。 以上API只是Linux API大全的一个小部分,但它们涵盖了Linux操作系统中非常重要的两个方面——文件系统管理和网络编程。掌握这些API...
例如,`alloc_skb`和`dev_alloc_skb`用于分配新的`sk_buff`,`kfree_skb`和`dev_kfree_skb`用于释放不再需要的`sk_buff`,`skb_put`和`skb_push`则用于在缓冲区的末尾或开头添加数据。 网络设备驱动程序的其他关键...
此外,Linux内核还提供了内存管理功能,如dev_alloc_skb用于分配sk_buff,而函数dev_kfree_skb和kfree_skb用于释放sk_buff。这些操作对于驱动程序来说非常关键,因为它们直接关系到网络数据传输的效率和稳定性。 ...
PF-DMA通过扩展和替换内核函数,如net_dev_alloc_skb()和dev_kfree_skb(),在不改变原有网卡驱动程序结构的基础上,实现了报文的零拷贝捕获。这种方法的优势在于,它降低了对网卡驱动的修改程度,使得报文捕获功能更...
- **操作函数**:如`skb_pull(int len)`用于从缓冲区头部移除数据,并更新数据指针位置。 - **示例代码**:通常在内核代码中,`sk_buff`实例以“skb”变量名出现。 ##### NET_DEVICE(net_device) - **定义**:...
`el_receive()`函数会对数据包进行初步检查,并为其分配一个缓冲区(`dev_alloc_skb()`函数),然后通过调用`netif_rx()`函数将数据包传递给上层处理。 ##### 3. 上下层交互机制 - **向下交互**:当接收到新的数据包...
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos); done: in_dev_put(in_dev); if (free_res) fib_res_put(&res); out: return err; local_input: rth = dst_alloc(&ipv4_dst_ops); rth->u....
- **alloc_canfd_skb**:分配一个用于CAN FD(Flexible Data-Rate)的消息缓冲区。 - **config canfd_frame**:配置CAN FD帧。 #### 三、重要技术点分析 1. **ncan_usb_pkt_encap**:此函数实现了对发送数据的封包...
alloc_etherdev(&et->dev); // 分配网络设备结构 et->dev = dev; // 设置网络设备指针 ioremap_nocache(); // 映射IO内存区域 // 初始化定时器 init_timer(&et->timer); et->timer.data = (ulong)dev; et...
在sk_buff中还定义了一些特定的指针函数,如skb_headlen()、skb_pagelen()等,用于获取数据缓冲区的不同部分的长度。这些函数在不同的网络操作中被用到,比如网络层的数据包分片处理。 Linux内核中,sk_buff的分配...
ARP(地址解析协议)初始化包括`arp_init`和`dev_add_pack`,后者将ARP的处理程序添加到设备中。`arp_rcv`函数接收并处理ARP请求,`consume_skb`则释放SKB(socket缓冲区)的引用。`ip_route_input_noref`、`ip_route_...
当数据准备好后,通过skb_get_queue_mapping找到正确的队列映射,然后调用ieee80211_tx_prepare进行进一步处理。最后,invoke_tx_handlers函数执行,包括检查在接入点(AP)中是否需要缓冲数据等操作。 5. 实际...