[RFC] netem: de-GSO packets before enqueing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Probably something like this is needed (untested).

This issue was discovered when looking at the skb_checksum path for the
netem corruption operation, but it is a general problem.
Network emulation operations like corruption and drop want to operate
on a per-packet (not per-segment) basis. This patch does GSO in software
if necessary to break up packets.  Code is similar to logic in xfrm_output.

Although it appears that the operation is not work conserving, it is okay
because the higher level qdisc operations account for packets by incrementing
by gso_size.

Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxxxx>

--- a/net/sched/sch_netem.c	2012-01-12 14:57:59.218796226 -0800
+++ b/net/sched/sch_netem.c	2012-01-12 15:21:07.614162912 -0800
@@ -128,6 +128,8 @@ struct netem_skb_cb {
 	psched_time_t	time_to_send;
 };
 
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch);
+
 static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
 {
 	BUILD_BUG_ON(sizeof(skb->cb) <
@@ -355,6 +357,41 @@ static int tfifo_enqueue(struct sk_buff
 	return qdisc_reshape_fail(nskb, sch);
 }
 
+static int netem_enqueue_gso(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct sk_buff *segs;
+	int rc;
+
+	segs = skb_gso_segment(skb, 0);
+	kfree_skb(skb);
+
+	if (IS_ERR(segs)) {
+		sch->qstats.drops++;
+		return NET_XMIT_DROP;
+	}
+
+	do {
+		struct sk_buff *nskb = segs->next;
+		int ret;
+
+		segs->next = NULL;
+		ret = netem_enqueue(segs, sch);
+		if (ret == NET_XMIT_DROP) {
+			while ((segs = nskb)) {
+				nskb = segs->next;
+				segs->next = NULL;
+				kfree_skb(segs);
+			}
+			return ret;
+		}
+
+		segs = nskb;
+	} while (segs);
+
+	return NET_XMIT_SUCCESS;
+}
+
+
 /*
  * Insert one skb into qdisc.
  * Note: parent depends on return value to account for queue length.
@@ -370,6 +407,10 @@ static int netem_enqueue(struct sk_buff
 	int ret;
 	int count = 1;
 
+	/* Want to operate on per-packet basis */
+	if (skb_is_gso(skb))
+		return netem_enqueue_gso(skb, sch);
+
 	/* Random duplication */
 	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
 		++count;
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux