`

dev_alloc_skb

阅读更多
/****************************************************
 *      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;
}
分享到:
评论

相关推荐

    使用dev_queue_xmit、dev_hard_start_xmit的方法实现数据包的发送.docx )

    2. **线性化处理**:如果`sk_buff`被分段存储,并且设备不支持分散/聚集(Scatter/Gather,简称SG),或者存在某些段位于高内存中(high memory),则需要通过`__skb_linearize`函数将所有片段合并到一个连续的内存...

    Linux内核API手册

    - `skb_queue_empty`:检查套接字缓冲区队列是否为空。 - `skb_get`:获取套接字缓冲区。 - `kfree_skb`:释放套接字缓冲区。 - `skb_cloned`:检查套接字缓冲区是否被克隆。 - `skb_shared`:检查套接字缓冲区是否...

    LINUX_API大全

    - **skb_orphan**:使socket缓冲区孤儿化,即不再与发送者或接收者关联。 - **skb_queue_purge**:清空socket缓冲区队列。 - **__skb_queue_purge**:同上。 - **dev_alloc_skb**:为设备分配socket缓冲区。 - ...

    The Linux Kernel API

    - **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 = ...

    LINUX API 大全

    - **`skb_cl`**:此处文档缺失,可能是`skb_clone()`,用于克隆socket缓冲区。 以上API只是Linux API大全的一个小部分,但它们涵盖了Linux操作系统中非常重要的两个方面——文件系统管理和网络编程。掌握这些API...

    Linux网络设备驱动程序培训教材.pptx

    例如,`alloc_skb`和`dev_alloc_skb`用于分配新的`sk_buff`,`kfree_skb`和`dev_kfree_skb`用于释放不再需要的`sk_buff`,`skb_put`和`skb_push`则用于在缓冲区的末尾或开头添加数据。 网络设备驱动程序的其他关键...

    Linux网络体系架构和网卡驱动设计.pdf

    此外,Linux内核还提供了内存管理功能,如dev_alloc_skb用于分配sk_buff,而函数dev_kfree_skb和kfree_skb用于释放sk_buff。这些操作对于驱动程序来说非常关键,因为它们直接关系到网络数据传输的效率和稳定性。 ...

    基于Linux系统的高性能报文捕获技术.pdf

    PF-DMA通过扩展和替换内核函数,如net_dev_alloc_skb()和dev_kfree_skb(),在不改变原有网卡驱动程序结构的基础上,实现了报文的零拷贝捕获。这种方法的优势在于,它降低了对网卡驱动的修改程度,使得报文捕获功能更...

    Linux Kernel Networking

    - **操作函数**:如`skb_pull(int len)`用于从缓冲区头部移除数据,并更新数据指针位置。 - **示例代码**:通常在内核代码中,`sk_buff`实例以“skb”变量名出现。 ##### NET_DEVICE(net_device) - **定义**:...

    Linux内核2.4.x的网络接口源码的结构

    `el_receive()`函数会对数据包进行初步检查,并为其分配一个缓冲区(`dev_alloc_skb()`函数),然后通过调用`netif_rx()`函数将数据包传递给上层处理。 ##### 3. 上下层交互机制 - **向下交互**:当接收到新的数据包...

    netfilter框架分析

    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....

    socketcan驱动流程图

    - **alloc_canfd_skb**:分配一个用于CAN FD(Flexible Data-Rate)的消息缓冲区。 - **config canfd_frame**:配置CAN FD帧。 #### 三、重要技术点分析 1. **ncan_usb_pkt_encap**:此函数实现了对发送数据的封包...

    linux内核数据流

    alloc_etherdev(&et->dev); // 分配网络设备结构 et->dev = dev; // 设置网络设备指针 ioremap_nocache(); // 映射IO内存区域 // 初始化定时器 init_timer(&et->timer); et->timer.data = (ulong)dev; et...

    sk_buff详解.pdf

    在sk_buff中还定义了一些特定的指针函数,如skb_headlen()、skb_pagelen()等,用于获取数据缓冲区的不同部分的长度。这些函数在不同的网络操作中被用到,比如网络层的数据包分片处理。 Linux内核中,sk_buff的分配...

    Linux Kernel 日常分析总结

    ARP(地址解析协议)初始化包括`arp_init`和`dev_add_pack`,后者将ARP的处理程序添加到设备中。`arp_rcv`函数接收并处理ARP请求,`consume_skb`则释放SKB(socket缓冲区)的引用。`ip_route_input_noref`、`ip_route_...

    driver-数据发包收包流程1

    当数据准备好后,通过skb_get_queue_mapping找到正确的队列映射,然后调用ieee80211_tx_prepare进行进一步处理。最后,invoke_tx_handlers函数执行,包括检查在接入点(AP)中是否需要缓冲数据等操作。 5. 实际...

Global site tag (gtag.js) - Google Analytics