diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /include/linux/skbuff.h | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/linux/skbuff.h')
-rw-r--r-- | include/linux/skbuff.h | 428 |
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 */ |