📄 tcpcore.h
字号:
list->prev = (struct sk_buff *)list;
list->next = (struct sk_buff *)list;
list->qlen = 0;
}
/*
* Insert an sk_buff at the start of a list.
*
* The "__skb_xxxx()" functions are the non-atomic ones that
* can only be called with interrupts disabled.
*/
/**
* __skb_queue_head - queue a buffer at the list head
* @list: list to use
* @newsk: buffer to queue
*
* Queue a buffer at the start of a list. This function takes no locks
* and you must therefore hold required locks before calling it.
*
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
{
struct sk_buff *prev, *next;
newsk->list = list;
list->qlen++;
prev = (struct sk_buff *)list;
next = prev->next;
newsk->next = next;
newsk->prev = prev;
next->prev = newsk;
prev->next = newsk;
}
/**
* skb_queue_head - queue a buffer at the list head
* @list: list to use
* @newsk: buffer to queue
*
* Queue a buffer at the start of the list. This function takes the
* list lock and can be used safely with other locking &sk_buff functions
* safely.
*
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
{
unsigned long flags;
spin_lock_irqsave(&list->lock, flags);
__skb_queue_head(list, newsk);
spin_unlock_irqrestore(&list->lock, flags);
}
/**
* __skb_queue_tail - queue a buffer at the list tail
* @list: list to use
* @newsk: buffer to queue
*
* Queue a buffer at the end of a list. This function takes no locks
* and you must therefore hold required locks before calling it.
*
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
{
struct sk_buff *prev, *next;
newsk->list = list;
list->qlen++;
next = (struct sk_buff *)list;
prev = next->prev;
newsk->next = next;
newsk->prev = prev;
next->prev = newsk;
prev->next = newsk;
}
/**
* skb_queue_tail - queue a buffer at the list tail
* @list: list to use
* @newsk: buffer to queue
*
* Queue a buffer at the tail of the list. This function takes the
* list lock and can be used safely with other locking &sk_buff functions
* safely.
*
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
{
unsigned long flags;
spin_lock_irqsave(&list->lock, flags);
__skb_queue_tail(list, newsk);
spin_unlock_irqrestore(&list->lock, flags);
}
/**
* __skb_dequeue - remove from the head of the queue
* @list: list to dequeue from
*
* Remove the head of the list. This function does not take any locks
* so must be used with appropriate locks held only. The head item is
* returned or %NULL if the list is empty.
*/
static __inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
{
struct sk_buff *next, *prev, *result;
prev = (struct sk_buff *) list;
next = prev->next;
result = NULL;
if (next != prev) {
result = next;
next = next->next;
list->qlen--;
next->prev = prev;
prev->next = next;
result->next = NULL;
result->prev = NULL;
result->list = NULL;
}
return result;
}
/**
* skb_dequeue - remove from the head of the queue
* @list: list to dequeue from
*
* Remove the head of the list. The list lock is taken so the function
* may be used safely with other locking list functions. The head item is
* returned or %NULL if the list is empty.
*/
static __inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
{
unsigned long flags;
struct sk_buff *result;
spin_lock_irqsave(&list->lock, flags);
result = __skb_dequeue(list);
spin_unlock_irqrestore(&list->lock, flags);
return result;
}
/*
* Insert a packet on a list.
*/
static __inline void __skb_insert(struct sk_buff *newsk,
struct sk_buff * prev, struct sk_buff *next,
struct sk_buff_head * list)
{
newsk->next = next;
newsk->prev = prev;
next->prev = newsk;
prev->next = newsk;
newsk->list = list;
list->qlen++;
}
/**
* skb_insert - insert a buffer
* @old: buffer to insert before
* @newsk: buffer to insert
*
* Place a packet before a given packet in a list. The list locks are taken
* and this function is atomic with respect to other list locked calls
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
spin_lock_irqsave(&old->list->lock, flags);
__skb_insert(newsk, old->prev, old, old->list);
spin_unlock_irqrestore(&old->list->lock, flags);
}
/*
* Place a packet after a given packet in a list.
*/
static __inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
{
__skb_insert(newsk, old, old->next, old->list);
}
/**
* skb_append - append a buffer
* @old: buffer to insert after
* @newsk: buffer to insert
*
* Place a packet after a given packet in a list. The list locks are taken
* and this function is atomic with respect to other list locked calls.
* A buffer cannot be placed on two lists at the same time.
*/
static __inline void skb_append(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
spin_lock_irqsave(&old->list->lock, flags);
__skb_append(old, newsk);
spin_unlock_irqrestore(&old->list->lock, flags);
}
/*
* remove sk_buff from list. _Must_ be called atomically, and with
* the list known..
*/
static __inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
struct sk_buff * next, * prev;
list->qlen--;
next = skb->next;
prev = skb->prev;
skb->next = NULL;
skb->prev = NULL;
skb->list = NULL;
next->prev = prev;
prev->next = next;
}
/**
* skb_unlink - remove a buffer from a list
* @skb: buffer to remove
*
* Place a packet after a given packet in a list. The list locks are taken
* and this function is atomic with respect to other list locked calls
*
* Works even without knowing the list it is sitting on, which can be
* handy at times. It also means that THE LIST MUST EXIST when you
* unlink. Thus a list must have its contents unlinked before it is
* destroyed.
*/
static __inline void skb_unlink(struct sk_buff *skb)
{
struct sk_buff_head *list = skb->list;
if(list) {
unsigned long flags;
spin_lock_irqsave(&list->lock, flags);
if(skb->list == list)
__skb_unlink(skb, skb->list);
spin_unlock_irqrestore(&list->lock, flags);
}
}
/* XXX: more streamlined implementation */
/**
* __skb_dequeue_tail - remove from the tail of the queue
* @list: list to dequeue from
*
* Remove the tail of the list. This function does not take any locks
* so must be used with appropriate locks held only. The tail item is
* returned or %NULL if the list is empty.
*/
static __inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
{
struct sk_buff *skb = skb_peek_tail(list);
if (skb)
__skb_unlink(skb, list);
return skb;
}
/**
* skb_dequeue - remove from the head of the queue
* @list: list to dequeue from
*
* Remove the head of the list. The list lock is taken so the function
* may be used safely with other locking list functions. The tail item is
* returned or %NULL if the list is empty.
*/
static __inline struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
{
unsigned long flags;
struct sk_buff *result;
spin_lock_irqsave(&list->lock, flags);
result = __skb_dequeue_tail(list);
spin_unlock_irqrestore(&list->lock, flags);
return result;
}
static __inline int skb_is_nonlinear(const struct sk_buff *skb)
{
return skb->data_len;
}
static __inline int skb_headlen(const struct sk_buff *skb)
{
return skb->len - skb->data_len;
}
#define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) out_of_line_bug(); } while (0)
#define SKB_FRAG_ASSERT(skb) do { if (skb_shinfo(skb)->frag_list) out_of_line_bug(); } while (0)
#define SKB_LINEAR_ASSERT(skb) do { if (skb_is_nonlinear(skb)) out_of_line_bug(); } while (0)
/*
* 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_LINEAR_ASSERT(skb);
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)
{
#if 0
unsigned char *tmp=skb->tail;
SKB_LINEAR_ASSERT(skb);
skb->tail+=len;
skb->len+=len;
if(skb->tail>skb->end) {
skb_over_panic(skb, len, current_text_addr());
}
return tmp;
#else
return NULL;
#endif
}
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)
{
#if 0
skb->data-=len;
skb->len+=len;
if(skb->data<skb->head) {
skb_under_panic(skb, len, current_text_addr());
}
return skb->data;
#else
return NULL;
#endif
}
static __inline char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb->len-=len;
if (skb->len < skb->data_len)
out_of_line_bug();
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);
}
extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta);
static __inline char *__pskb_pull(struct sk_buff *skb, unsigned int len)
{
if (len > skb_headlen(skb) &&
__pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL)
return NULL;
skb->len -= len;
return skb->data += len;
}
static __inline unsigned char * pskb_pull(struct sk_buff *skb, unsigned int len)
{
if (len > skb->len)
return NULL;
return __pskb_pull(skb,len);
}
static __inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
{
if (len <= skb_headlen(skb))
return 1;
if (len > skb->len)
return 0;
return (__pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL);
}
/**
* 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -