summaryrefslogtreecommitdiffstats
path: root/include/linux/skbuff.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /include/linux/skbuff.h
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/linux/skbuff.h')
-rw-r--r--include/linux/skbuff.h428
1 files changed, 310 insertions, 118 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e831eb130..57302ca98 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -13,83 +13,131 @@
#ifndef _LINUX_SKBUFF_H
#define _LINUX_SKBUFF_H
-#include <linux/malloc.h>
-#include <linux/wait.h>
-#include <linux/time.h>
+
#include <linux/config.h>
+#include <linux/time.h>
+
+#include <asm/atomic.h>
+#include <asm/types.h>
-#undef CONFIG_SKB_CHECK
+#define CONFIG_SKB_CHECK 0
#define HAVE_ALLOC_SKB /* For the drivers to know */
+#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
#define FREE_READ 1
#define FREE_WRITE 0
+#define CHECKSUM_NONE 0
+#define CHECKSUM_HW 1
+#define CHECKSUM_UNNECESSARY 2
-struct sk_buff_head {
- struct sk_buff * volatile next;
- struct sk_buff * volatile prev;
+struct sk_buff_head
+{
+ struct sk_buff * next;
+ struct sk_buff * prev;
+ __u32 qlen; /* Must be same length as a pointer
+ for using debugging */
#if CONFIG_SKB_CHECK
- int magic_debug_cookie;
+ int magic_debug_cookie;
#endif
};
-struct sk_buff {
- struct sk_buff * volatile next; /* Next buffer in list */
- struct sk_buff * volatile prev; /* Previous buffer in list */
+struct sk_buff
+{
+ struct sk_buff * next; /* Next buffer in list */
+ struct sk_buff * prev; /* Previous buffer in list */
+ struct sk_buff_head * list; /* List we are on */
#if CONFIG_SKB_CHECK
- int magic_debug_cookie;
+ int magic_debug_cookie;
#endif
- struct sk_buff * volatile link3; /* Link for IP protocol level buffer chains */
- struct sock *sk; /* Socket we are owned by */
- volatile unsigned long when; /* used to compute rtt's */
- struct timeval stamp; /* Time we arrived */
- struct device *dev; /* Device we arrived on/are leaving by */
- struct sk_buff *mem_addr; /* Self reference (obsolete) */
- union {
- struct tcphdr *th;
- struct ethhdr *eth;
- struct iphdr *iph;
- struct udphdr *uh;
- unsigned char *raw;
- unsigned long seq;
- } h;
- struct iphdr *ip_hdr; /* For IPPROTO_RAW */
- unsigned long mem_len; /* Length of allocated memory */
- unsigned long len; /* Length of actual data */
- unsigned long fraglen; /* Unused (yet) */
- struct sk_buff *fraglist; /* Fragment list */
- unsigned long truesize; /* True buffer size (obsolete) */
- unsigned long saddr; /* IP source address */
- unsigned long daddr; /* IP target address */
- unsigned long raddr; /* IP next hop address */
- volatile char acked, /* Are we acked ? */
- used, /* Are we in use ? */
- free, /* How to free this buffer */
- arp; /* Has IP/ARP resolution finished */
- unsigned char tries, /* Times tried */
- lock, /* Are we locked ? */
- localroute, /* Local routing asserted for this frame */
- pkt_type; /* Packet class */
-#define PACKET_HOST 0 /* To us */
-#define PACKET_BROADCAST 1 /* To all */
-#define PACKET_MULTICAST 2 /* To group */
-#define PACKET_OTHERHOST 3 /* To someone else */
- unsigned short users; /* User count - see datagram.c,tcp.c */
- unsigned short protocol; /* Packet protocol from driver. */
-#ifdef CONFIG_SLAVE_BALANCING
- unsigned short in_dev_queue;
-#endif
- unsigned long padding[0]; /* Force long word alignment */
- unsigned char data[0]; /* Data follows */
+ struct sk_buff *link3; /* Link for IP protocol level buffer chains */
+ struct sock *sk; /* Socket we are owned by */
+ unsigned long when; /* used to compute rtt's */
+ struct timeval stamp; /* Time we arrived */
+ struct device *dev; /* Device we arrived on/are leaving by */
+ union
+ {
+ struct tcphdr *th;
+ struct ethhdr *eth;
+ struct iphdr *iph;
+ struct udphdr *uh;
+ unsigned char *raw;
+ /* for passing file handles in a unix domain socket */
+ void *filp;
+ } h;
+
+ union
+ {
+ /* As yet incomplete physical layer views */
+ unsigned char *raw;
+ struct ethhdr *ethernet;
+ } mac;
+
+ struct iphdr *ip_hdr; /* For IPPROTO_RAW */
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct ipv6hdr *ipv6_hdr;
+
+ /*
+ * It would be inefficient to store the nexthop address in every
+ * skb. Instead we store a pointer to the respective neighbour
+ * cache entry. This might make ndisc cache management harder.
+ */
+
+ struct neighbour *nexthop;
+#endif
+ unsigned int len; /* Length of actual data */
+ unsigned int csum; /* Checksum */
+ __u32 saddr; /* IP source address */
+ __u32 daddr; /* IP target address */
+ __u32 raddr; /* IP next hop address */
+ __u32 seq; /* TCP sequence number */
+ __u32 end_seq; /* seq [+ fin] [+ syn] + datalen */
+ __u32 ack_seq; /* TCP ack sequence number */
+ unsigned char proto_priv[16]; /* Protocol private data */
+ volatile char acked, /* Are we acked ? */
+ used, /* Are we in use ? */
+ free, /* How to free this buffer */
+ arp; /* Has IP/ARP resolution finished */
+ unsigned char tries, /* Times tried */
+ lock, /* Are we locked ? */
+ localroute, /* Local routing asserted for this frame */
+ pkt_type, /* Packet class */
+ pkt_bridged, /* Tracker for bridging */
+ ip_summed; /* Driver fed us an IP checksum */
+#define PACKET_HOST 0 /* To us */
+#define PACKET_BROADCAST 1 /* To all */
+#define PACKET_MULTICAST 2 /* To group */
+#define PACKET_OTHERHOST 3 /* To someone else */
+#define PACKET_NDISC 17 /* Outgoing NDISC packet */
+ unsigned short users; /* User count - see datagram.c,tcp.c */
+ unsigned short protocol; /* Packet protocol from driver. */
+ unsigned short truesize; /* Buffer size */
+
+ atomic_t count; /* reference count */
+ struct sk_buff *data_skb; /* Link to the actual data skb */
+ unsigned char *head; /* Head of buffer */
+ unsigned char *data; /* Data head pointer */
+ unsigned char *tail; /* Tail pointer */
+ unsigned char *end; /* End pointer */
+ void (*destructor)(struct sk_buff *); /* Destruct function */
+ __u16 redirport; /* Redirect port */
+ __u16 inclone; /* Inline clone */
+#define SKB_CLONE_ORIG 1
+#define SKB_CLONE_INLINE 2
};
+#ifdef CONFIG_SKB_LARGE
+#define SK_WMEM_MAX 65535
+#define SK_RMEM_MAX 65535
+#else
#define SK_WMEM_MAX 32767
#define SK_RMEM_MAX 32767
+#endif
-#ifdef CONFIG_SKB_CHECK
+#if CONFIG_SKB_CHECK
#define SK_FREED_SKB 0x0DE2C0DE
#define SK_GOOD_SKB 0xDEC0DED1
#define SK_HEAD_SKB 0x12231298
@@ -99,6 +147,7 @@ struct sk_buff {
/*
* Handling routines are only of interest to the kernel
*/
+#include <linux/malloc.h>
#include <asm/system.h>
@@ -113,24 +162,61 @@ extern struct sk_buff * skb_dequeue(struct sk_buff_head *list);
extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
extern void skb_unlink(struct sk_buff *buf);
+extern __u32 skb_queue_len(struct sk_buff_head *list);
extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
-extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
+extern struct sk_buff * dev_alloc_skb(unsigned int size);
+extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
+extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority);
extern void skb_device_lock(struct sk_buff *skb);
extern void skb_device_unlock(struct sk_buff *skb);
extern void dev_kfree_skb(struct sk_buff *skb, int mode);
extern int skb_device_locked(struct sk_buff *skb);
+extern unsigned char * skb_put(struct sk_buff *skb, unsigned int len);
+extern unsigned char * skb_push(struct sk_buff *skb, unsigned int len);
+extern unsigned char * skb_pull(struct sk_buff *skb, unsigned int len);
+extern int skb_headroom(struct sk_buff *skb);
+extern int skb_tailroom(struct sk_buff *skb);
+extern void skb_reserve(struct sk_buff *skb, unsigned int len);
+extern void skb_trim(struct sk_buff *skb, unsigned int len);
+
+extern __inline__ int skb_queue_empty(struct sk_buff_head *list)
+{
+ return (list->next == (struct sk_buff *) list);
+}
+
+extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri, int dir)
+{
+ struct sk_buff *nskb;
+ if(skb->users==1)
+ return skb;
+ nskb=skb_copy(skb, pri);
+ kfree_skb(skb, dir); /* Free our shared copy */
+ return nskb;
+}
+
/*
* Peek an sk_buff. Unlike most other operations you _MUST_
* be careful with this one. A peek leaves the buffer on the
* list and someone else may run off with it. For an interrupt
* type system cli() peek the buffer copy the data and sti();
*/
-static __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
+extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
+{
+ struct sk_buff *list = ((struct sk_buff *)list_)->next;
+ if (list == (struct sk_buff *)list_)
+ list = NULL;
+ return list;
+}
+
+/*
+ * Return the length of an sk_buff queue
+ */
+
+extern __inline__ __u32 skb_queue_len(struct sk_buff_head *list_)
{
- struct sk_buff *list = (struct sk_buff *)list_;
- return (list->next != list)? list->next : NULL;
+ return(list_->qlen);
}
#if CONFIG_SKB_CHECK
@@ -145,23 +231,37 @@ extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
{
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.
*/
-extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
+extern __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;
+}
+
+extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
{
unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
- newsk->next = list->next;
- newsk->prev = list;
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
+ __skb_queue_head(list, newsk);
restore_flags(flags);
}
@@ -169,74 +269,92 @@ extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff
* Insert an sk_buff at the end of a list.
*/
-extern __inline__ void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
+extern __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;
+}
+
+extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
{
unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
-
- newsk->next = list;
- newsk->prev = list->prev;
-
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
-
+ __skb_queue_tail(list, newsk);
restore_flags(flags);
}
/*
- * Remove an sk_buff from a list. This routine is also interrupt safe
- * so you can grab read and free buffers as another process adds them.
- *
- * Note we now do the ful list
+ * Remove an sk_buff from a list.
*/
-extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
+extern __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;
+}
+
+extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
{
long flags;
struct sk_buff *result;
- struct sk_buff *list = (struct sk_buff *)list_;
save_flags(flags);
cli();
+ result = __skb_dequeue(list);
+ restore_flags(flags);
+ return result;
+}
- result = list->next;
- if (result == list)
- {
- restore_flags(flags);
- return NULL;
- }
- else
- {
- result->next->prev = list;
- list->next = result->next;
-
- result->next = NULL;
- result->prev = NULL;
-
- restore_flags(flags);
+/*
+ * Insert a packet on a list.
+ */
- return result;
- }
+extern __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++;
}
/*
- * Insert a packet before another one in a list.
+ * Place a packet before a given packet in a list
*/
-
extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
- newsk->next = old;
- newsk->prev = old->prev;
- old->prev = newsk;
- newsk->prev->next = newsk;
-
+ __skb_insert(newsk, old->prev, old, old->list);
restore_flags(flags);
}
@@ -250,16 +368,29 @@ extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
save_flags(flags);
cli();
-
- newsk->prev = old;
- newsk->next = old->next;
- newsk->next->prev = newsk;
- old->next = newsk;
-
+ __skb_insert(newsk, old, old->next, old->list);
restore_flags(flags);
}
/*
+ * remove sk_buff from list. _Must_ be called atomically, and with
+ * the list known..
+ */
+extern __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;
+}
+
+/*
* Remove an sk_buff from its list. 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
@@ -272,23 +403,84 @@ extern __inline__ void skb_unlink(struct sk_buff *skb)
save_flags(flags);
cli();
+ if(skb->list)
+ __skb_unlink(skb, skb->list);
+ restore_flags(flags);
+}
+
+/*
+ * Add data to an sk_buff
+ */
+
+extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+{
+ extern char *skb_put_errstr;
+ unsigned char *tmp=skb->tail;
+ skb->tail+=len;
+ skb->len+=len;
+ if(skb->tail>skb->end)
+ {
+ __label__ here;
+ panic(skb_put_errstr,&&here,len);
+here:
+ }
+ return tmp;
+}
- if(skb->prev && skb->next)
+extern __inline__ unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+{
+ extern char *skb_push_errstr;
+ skb->data-=len;
+ skb->len+=len;
+ if(skb->data<skb->head)
{
- skb->next->prev = skb->prev;
- skb->prev->next = skb->next;
- skb->next = NULL;
- skb->prev = NULL;
+ __label__ here;
+ panic(skb_push_errstr, &&here,len);
+here:
+ }
+ return skb->data;
+}
+
+extern __inline__ unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len > skb->len)
+ return NULL;
+ skb->data+=len;
+ skb->len-=len;
+ return skb->data;
+}
+
+extern __inline__ int skb_headroom(struct sk_buff *skb)
+{
+ return skb->data-skb->head;
+}
+
+extern __inline__ int skb_tailroom(struct sk_buff *skb)
+{
+ return skb->end-skb->tail;
+}
+
+extern __inline__ void skb_reserve(struct sk_buff *skb, unsigned int len)
+{
+ skb->data+=len;
+ skb->tail+=len;
+}
+
+extern __inline__ void skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (skb->len > len) {
+ skb->len = len;
+ skb->tail = skb->data+len;
}
- restore_flags(flags);
}
#endif
extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
extern int datagram_select(struct sock *sk, int sel_type, select_table *wait);
-extern void skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
-extern void skb_free_datagram(struct sk_buff *skb);
+extern int skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
+extern int skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size);
+extern void skb_free_datagram(struct sock * sk, struct sk_buff *skb);
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */