osmo-cc-misdn-endpoint/src/libmisdn/skbuff.h

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