包缓冲区操作的几个内嵌函数
==========================
包缓冲由sk_buff结构描述, 包缓冲数据区由其head和end成员界定,
而包数据体则由包数据区内data和tail界定的子区域来描述,
采用这种结构可以使添加或去除包头的操作变得非常方便.
skb_put(skb,len) 在包体尾部扩展长度为len的数据块, 返回扩展块的地址,
__skb_put()为未校验版本
skb_push(skb,len) 在包体前部扩展长度为len的数据块, 返回扩展块的地址,
__skb_push()为未校验版本
skb_pull(skb,len) 去除包体前部长度为len的数据块, 返回新包体的起始地址,
__skb_pull()为未校验版本
skb_headroom(skb) 返回包体前部距离包区开始的长度
skb_tailroom(skb) 返回包体尾部距离包区结束的长度
skb_reserve(skb,len) 设置包体起始位置为包区开始的len字节
skb_trim(skb,len) 将包体截断为len字节, __skb_trim()为未校验版本
; include/linux/skbuff.h:
struct sk_buff {
...
unsigned int len; /* Length of actual data */
unsigned char *head; /* Head of buffer */
unsigned char *data; /* Data head pointer */
unsigned char *tail; /* Tail pointer */
unsigned char *end; /* End pointer */
...
}
/*
* Add data to an sk_buff
*/
static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
{
unsigned char *tmp=skb->tail;
skb->tail+=len;
skb->len+=len;
return tmp;
}
/**
* skb_put - add data to a buffer
* @skb: buffer to use
* @len: amount of data to add
*
* This function extends the used data area of the buffer. If this would
* exceed the total buffer size the kernel will panic. A pointer to the
* first byte of the extra data is returned.
*/
static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
{
unsigned char *tmp=skb->tail;
skb->tail+=len;
skb->len+=len;
if(skb->tail>skb->end) {
skb_over_panic(skb, len, current_text_addr());
}
return tmp;
}
static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
{
skb->data-=len;
skb->len+=len;
return skb->data;
}
/**
* skb_push - add data to the start of a buffer
* @skb: buffer to use
* @len: amount of data to add
*
* This function extends the used data area of the buffer at the buffer
* start. If this would exceed the total buffer headroom the kernel will
* panic. A pointer to the first byte of the extra data is returned.
*/
static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
{
skb->data-=len;
skb->len+=len;
if(skb->datahead) {
skb_under_panic(skb, len, current_text_addr());
}
return skb->data;
}
static inline char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb->len-=len;
return skb->data+=len;
}
/**
* skb_pull - remove data from the start of a buffer
* @skb: buffer to use
* @len: amount of data to remove
*
* This function removes data from the start of a buffer, returning
* the memory to the headroom. A pointer to the next data in the buffer
* is returned. Once the data has been pulled future pushes will overwrite
* the old data.
*/
static inline unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
{
if (len > skb->len)
return NULL;
return __skb_pull(skb,len);
}
/**
* skb_headroom - bytes at buffer head
* @skb: buffer to check
*
* Return the number of bytes of free space at the head of an &sk_buff.
*/
static inline int skb_headroom(const struct sk_buff *skb)
{
return skb->data-skb->head;
}
/**
* skb_tailroom - bytes at buffer end
* @skb: buffer to check
*
* Return the number of bytes of free space at the tail of an sk_buff
*/
static inline int skb_tailroom(const struct sk_buff *skb)
{
return skb->end-skb->tail;
}
/**
* skb_reserve - adjust headroom
* @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, unsigned int len)
{
skb->data+=len;
skb->tail+=len;
}
static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
{
skb->len = len;
skb->tail = skb->data+len;
}
/**
* skb_trim - remove end from a buffer
* @skb: buffer to alter
* @len: new length
*
* Cut the length of a buffer down by removing data from the tail. If
* the buffer is already under the length specified it is not modified.
*/
static inline void skb_trim(struct sk_buff *skb, unsigned int len)
{
if (skb->len > len) {
__skb_trim(skb, len);
}
}
阅读(1843) | 评论(0) | 转发(1) |