[NETEM]: Support time based reordering
Change netem to support packets getting reordered because of variations in
delay. Introduce a special case version of FIFO that queues packets in order
based on the netem delay.
Since netem is classful, those users that don't want jitter based reordering
can just insert a pfifo instead of the default.
This required changes to generic skbuff code to allow finer grain manipulation
of sk_buff_head. Insertion into the middle and reverse walk.
Signed-off-by: Stephen Hemminger <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4286d83..fdfb8fe 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -603,6 +603,30 @@
*/
/**
+ * __skb_queue_after - queue a buffer at the list head
+ * @list: list to use
+ * @prev: place after this buffer
+ * @newsk: buffer to queue
+ *
+ * Queue a buffer int the middle 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_after(struct sk_buff_head *list,
+ struct sk_buff *prev,
+ struct sk_buff *newsk)
+{
+ struct sk_buff *next;
+ list->qlen++;
+
+ next = prev->next;
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = prev->next = newsk;
+}
+
+/**
* __skb_queue_head - queue a buffer at the list head
* @list: list to use
* @newsk: buffer to queue
@@ -616,14 +640,7 @@
static inline void __skb_queue_head(struct sk_buff_head *list,
struct sk_buff *newsk)
{
- struct sk_buff *prev, *next;
-
- list->qlen++;
- prev = (struct sk_buff *)list;
- next = prev->next;
- newsk->next = next;
- newsk->prev = prev;
- next->prev = prev->next = newsk;
+ __skb_queue_after(list, (struct sk_buff *)list, newsk);
}
/**
@@ -1203,6 +1220,11 @@
prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \
skb = skb->next)
+#define skb_queue_reverse_walk(queue, skb) \
+ for (skb = (queue)->prev; \
+ prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \
+ skb = skb->prev)
+
extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
int noblock, int *err);