242 lines
4.9 KiB
C
242 lines
4.9 KiB
C
|
|
#ifndef _MISDN_MSKBUFF_H
|
|
#define _MISDN_MSKBUFF_H
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define GFP_ATOMIC 0
|
|
#define GFP_KERNEL 1
|
|
typedef unsigned int __bitwise gfp_t;
|
|
|
|
/*
|
|
* head data tail end
|
|
* | | len | |
|
|
* -----> --------> ----->
|
|
* headroom tailroom
|
|
*/
|
|
|
|
struct sk_buff {
|
|
struct sk_buff *next;
|
|
struct sk_buff *prev;
|
|
|
|
char cb[48];
|
|
|
|
gfp_t priority;
|
|
|
|
unsigned int len;
|
|
|
|
unsigned char *head,
|
|
*data,
|
|
*tail,
|
|
*end;
|
|
|
|
/* the buffer begins behind sk_buff structure size */
|
|
unsigned char buffer[0];
|
|
};
|
|
|
|
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
|
|
union { \
|
|
struct { MEMBERS } ATTRS; \
|
|
struct TAG { MEMBERS } ATTRS NAME; \
|
|
}
|
|
|
|
#define struct_group_tagged(TAG, NAME, MEMBERS...) \
|
|
__struct_group(TAG, NAME, /* no attrs */, MEMBERS)
|
|
|
|
struct sk_buff_head {
|
|
/* These two members must be first to match sk_buff. */
|
|
struct_group_tagged(sk_buff_list, list,
|
|
struct sk_buff *next;
|
|
struct sk_buff *prev;
|
|
);
|
|
|
|
__u32 qlen;
|
|
// spinlock_t lock;
|
|
};
|
|
|
|
static inline struct sk_buff *alloc_skb(unsigned int size,
|
|
gfp_t priority)
|
|
{
|
|
struct sk_buff *skb = calloc(1, sizeof(*skb) + size);
|
|
|
|
skb->head = skb->buffer;
|
|
skb->data = skb->buffer;
|
|
skb->tail = skb->buffer;
|
|
skb->end = skb->buffer + size;
|
|
|
|
skb->len = 0;
|
|
|
|
skb->priority = priority;
|
|
|
|
return skb;
|
|
}
|
|
|
|
static inline struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int headroom)
|
|
{
|
|
/* headroom is incremented, but never shrinks! this way copying is easy */
|
|
if (skb->data - skb->head > headroom)
|
|
headroom = skb->data - skb->head;
|
|
size_t osize = skb->end - skb->head;
|
|
size_t nsize = skb->end - skb->data + headroom;
|
|
struct sk_buff *n = alloc_skb(nsize, skb->priority);
|
|
|
|
if (!n)
|
|
return NULL;
|
|
|
|
n->data = n->head + headroom;
|
|
n->tail = n->data + (skb->tail - skb->data);
|
|
n->len = n->tail - n->data;
|
|
memcpy(n->end - osize, skb->head, osize);
|
|
memcpy(n->cb, skb->cb, sizeof(n->cb));
|
|
|
|
return n;
|
|
}
|
|
|
|
static inline struct sk_buff *skb_clone(struct sk_buff *skb)
|
|
{
|
|
return skb_realloc_headroom(skb, skb->data - skb->head);
|
|
}
|
|
|
|
static inline struct sk_buff *skb_copy(struct sk_buff *skb, gfp_t priority)
|
|
{
|
|
struct sk_buff *n = skb_realloc_headroom(skb, skb->data - skb->head);
|
|
|
|
if (!n)
|
|
return NULL;
|
|
|
|
n->priority = priority;
|
|
return n;
|
|
}
|
|
|
|
static inline void kfree_skb(struct sk_buff *skb)
|
|
{
|
|
free(skb);
|
|
}
|
|
|
|
static inline void __net_timestamp(struct sk_buff __attribute__((unused)) *skb)
|
|
{
|
|
// skb->tstamp = ktime_get_real();
|
|
}
|
|
|
|
#define dev_kfree_skb(a) kfree_skb(a)
|
|
|
|
static inline void skb_reserve(struct sk_buff *skb, int len)
|
|
{
|
|
skb->data += len;
|
|
skb->tail += len;
|
|
}
|
|
|
|
static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
|
|
{
|
|
return skb->tail;
|
|
}
|
|
|
|
static inline void *skb_put(struct sk_buff *skb, unsigned int len)
|
|
{
|
|
void *tmp = skb_tail_pointer(skb);
|
|
skb->tail += len;
|
|
skb->len += len;
|
|
if (skb->tail > skb->end)
|
|
abort();
|
|
return tmp;
|
|
}
|
|
|
|
|
|
static inline void *skb_put_data(struct sk_buff *skb, const void *data,
|
|
unsigned int len)
|
|
{
|
|
void *tmp = skb_put(skb, len);
|
|
|
|
memcpy(tmp, data, len);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
static inline void skb_trim(struct sk_buff *skb, unsigned int len)
|
|
{
|
|
skb->tail = skb->data + len;
|
|
skb->len = len;
|
|
}
|
|
|
|
static inline void *skb_push(struct sk_buff *skb, unsigned int len)
|
|
{
|
|
skb->data -= len;
|
|
skb->len += len;
|
|
return skb->data;
|
|
}
|
|
|
|
static inline void *skb_pull(struct sk_buff *skb, unsigned int len)
|
|
{
|
|
void *tmp = skb->data;
|
|
if (skb->len < len)
|
|
abort();
|
|
skb->len -= len;
|
|
skb->data += len;
|
|
return tmp;
|
|
}
|
|
|
|
static inline void skb_queue_head_init(struct sk_buff_head *list)
|
|
{
|
|
list->prev = list->next = (struct sk_buff *)list;
|
|
list->qlen = 0;
|
|
}
|
|
|
|
static inline void skb_queue_tail(struct sk_buff_head *list,
|
|
struct sk_buff *newsk)
|
|
{
|
|
newsk->prev = list->prev;
|
|
newsk->next = (struct sk_buff *)list;
|
|
list->prev->next = newsk;
|
|
list->prev = newsk;
|
|
list->qlen++;
|
|
}
|
|
|
|
static inline void skb_queue_head(struct sk_buff_head *list,
|
|
struct sk_buff *newsk)
|
|
{
|
|
newsk->prev = (struct sk_buff *)list;
|
|
newsk->next = list->next;
|
|
list->next->prev = newsk;
|
|
list->next = newsk;
|
|
list->qlen++;
|
|
}
|
|
|
|
static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
|
|
{
|
|
struct sk_buff *skb;
|
|
if (list->next == (struct sk_buff *)list)
|
|
return NULL;
|
|
skb = list->next;
|
|
list->next = list->next->next;
|
|
list->next->prev = (struct sk_buff *)list;
|
|
list->qlen--;
|
|
skb->prev = skb->next = NULL;
|
|
return skb;
|
|
}
|
|
|
|
static inline void skb_queue_purge(struct sk_buff_head *list)
|
|
{
|
|
struct sk_buff *skb;
|
|
while ((skb = skb_dequeue(list)) != NULL)
|
|
kfree_skb(skb);
|
|
}
|
|
|
|
static inline int skb_queue_empty(const struct sk_buff_head *list)
|
|
{
|
|
return list->next == (const struct sk_buff *) list;
|
|
}
|
|
|
|
static inline __u32 skb_queue_len(const struct sk_buff_head *list)
|
|
{
|
|
return list->qlen;
|
|
}
|
|
|
|
static inline int skb_tailroom(const struct sk_buff *skb)
|
|
{
|
|
return skb->end - skb->tail;
|
|
}
|
|
|
|
#endif
|
|
|