All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] netem: add cell concept to simulate special MAC behavior
@ 2011-12-10 15:15 Hagen Paul Pfeifer
  2011-12-10 16:43 ` Eric Dumazet
  0 siblings, 1 reply; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-10 15:15 UTC (permalink / raw)
  To: netdev
  Cc: davem, eric.dumazet, shemminger, Hagen Paul Pfeifer, Florian Westphal

So I hope Eric's div/mod concerns are addressed with this version!? ;-)
No "hot-path" div/mod operation anymore. tc_netem_rate was introduced in
current net-next tree so there are no API f*ckups.


From: Hagen Paul Pfeifer <hagen@jauu.net>

This extension can be used to simulate special link layer
characteristics. Simulate because packet data is not modified, only the
calculation base is changed to delay a packet based on the original
packet size and artificial cell information.

packet_overhead can be used to simulate a link layer header compression
scheme (e.g. set packet_overhead to -20) or with a positive
packet_overhead value an additional MAC header can be simulated. It is
also possible to "replace" the 14 byte Ethernet header with something
else.

cell_size and cell_overhead can be used to simulate link layer schemes,
based on cells, like some TDMA schemes. Another application area are MAC
schemes using a link layer fragmentation with a (small) header each.
Cell size is the maximum amount of data bytes within one cell. Cell
overhead is an additional variable to change the per-cell-overhead
(e.g.  5 byte header per fragment).

Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
cell overhead 5 byte):

  tc qdisc add dev eth0 root netem rate 5kbit 20 100 5

Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/pkt_sched.h |    3 +++
 net/sched/sch_netem.c     |   33 +++++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 8786ea7..8daced3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -502,6 +502,9 @@ struct tc_netem_corrupt {
 
 struct tc_netem_rate {
 	__u32	rate;	/* byte/s */
+	__s32	packet_overhead;
+	__u32	cell_size;
+	__s32	cell_overhead;
 };
 
 enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bfd733..31ab06e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
+#include <linux/reciprocal_div.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -80,6 +81,10 @@ struct netem_sched_data {
 	u32 reorder;
 	u32 corrupt;
 	u32 rate;
+	s32 packet_overhead;
+	u32 cell_size;
+	u32 cell_size_reciprocal;
+	s32 cell_overhead;
 
 	struct crndstate {
 		u32 last;
@@ -299,11 +304,23 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
 	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
+static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 {
-	u64 ticks = (u64)len * NSEC_PER_SEC;
+	u64 ticks;
 
-	do_div(ticks, rate);
+	len += q->packet_overhead;
+
+	if (q->cell_size) {
+		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
+
+		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
+			cells++;
+		len = cells * (q->cell_size + q->cell_overhead);
+	}
+
+	ticks = (u64)len * NSEC_PER_SEC;
+
+	do_div(ticks, q->rate);
 	return PSCHED_NS2TICKS(ticks);
 }
 
@@ -384,7 +401,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		if (q->rate) {
 			struct sk_buff_head *list = &q->qdisc->q;
 
-			delay += packet_len_2_sched_time(skb->len, q->rate);
+			delay += packet_len_2_sched_time(skb->len, q);
 
 			if (!skb_queue_empty(list)) {
 				/*
@@ -568,6 +585,11 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 	const struct tc_netem_rate *r = nla_data(attr);
 
 	q->rate = r->rate;
+	q->packet_overhead = r->packet_overhead;
+	q->cell_size = r->cell_size;
+	q->cell_size_reciprocal = reciprocal_value(q->cell_size);
+	q->cell_size = q->cell_size;
+	q->cell_overhead = r->cell_overhead;
 }
 
 static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
@@ -909,6 +931,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
 	rate.rate = q->rate;
+	rate.packet_overhead = q->packet_overhead;
+	rate.cell_size = q->cell_size;
+	rate.cell_overhead = q->cell_overhead;
 	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 
 	if (dump_loss_model(q, skb) != 0)
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH net-next] netem: add cell concept to simulate special MAC behavior
  2011-12-10 15:15 [PATCH net-next] netem: add cell concept to simulate special MAC behavior Hagen Paul Pfeifer
@ 2011-12-10 16:43 ` Eric Dumazet
  2011-12-10 23:36   ` [PATCH] " Hagen Paul Pfeifer
  2011-12-12 17:18   ` [PATCH net-next] " Stephen Hemminger
  0 siblings, 2 replies; 12+ messages in thread
From: Eric Dumazet @ 2011-12-10 16:43 UTC (permalink / raw)
  To: Hagen Paul Pfeifer; +Cc: netdev, davem, shemminger, Florian Westphal

Le samedi 10 décembre 2011 à 16:15 +0100, Hagen Paul Pfeifer a écrit :
> So I hope Eric's div/mod concerns are addressed with this version!? ;-)

Yes, finaly ;)

But please read two other comments.

> No "hot-path" div/mod operation anymore. tc_netem_rate was introduced in
> current net-next tree so there are no API f*ckups.
> 
> 
> From: Hagen Paul Pfeifer <hagen@jauu.net>
> 
> This extension can be used to simulate special link layer
> characteristics. Simulate because packet data is not modified, only the
> calculation base is changed to delay a packet based on the original
> packet size and artificial cell information.
> 
> packet_overhead can be used to simulate a link layer header compression
> scheme (e.g. set packet_overhead to -20) or with a positive
> packet_overhead value an additional MAC header can be simulated. It is
> also possible to "replace" the 14 byte Ethernet header with something
> else.
> 
> cell_size and cell_overhead can be used to simulate link layer schemes,
> based on cells, like some TDMA schemes. Another application area are MAC
> schemes using a link layer fragmentation with a (small) header each.
> Cell size is the maximum amount of data bytes within one cell. Cell
> overhead is an additional variable to change the per-cell-overhead
> (e.g.  5 byte header per fragment).
> 
> Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
> cell overhead 5 byte):
> 
>   tc qdisc add dev eth0 root netem rate 5kbit 20 100 5
> 
> Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  include/linux/pkt_sched.h |    3 +++
>  net/sched/sch_netem.c     |   33 +++++++++++++++++++++++++++++----
>  2 files changed, 32 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
> index 8786ea7..8daced3 100644
> --- a/include/linux/pkt_sched.h
> +++ b/include/linux/pkt_sched.h
> @@ -502,6 +502,9 @@ struct tc_netem_corrupt {
>  
>  struct tc_netem_rate {
>  	__u32	rate;	/* byte/s */
> +	__s32	packet_overhead;
> +	__u32	cell_size;
> +	__s32	cell_overhead;

Adding fields in existing structure is convenient, but this means a
previous tc binary wont work anymore.

(because of this line in netem_policy[] :)
[TCA_NETEM_RATE]    = { .len = sizeof(struct tc_netem_rate) },

I guess netem users are capable to fetch new iproute2 package, but its
worth to mention this in changelog.

>  };
>  
>  enum {
> diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
> index 3bfd733..31ab06e 100644
> --- a/net/sched/sch_netem.c
> +++ b/net/sched/sch_netem.c
> @@ -22,6 +22,7 @@
>  #include <linux/skbuff.h>
>  #include <linux/vmalloc.h>
>  #include <linux/rtnetlink.h>
> +#include <linux/reciprocal_div.h>
>  
>  #include <net/netlink.h>
>  #include <net/pkt_sched.h>
> @@ -80,6 +81,10 @@ struct netem_sched_data {
>  	u32 reorder;
>  	u32 corrupt;
>  	u32 rate;
> +	s32 packet_overhead;
> +	u32 cell_size;
> +	u32 cell_size_reciprocal;
> +	s32 cell_overhead;
>  
>  	struct crndstate {
>  		u32 last;
> @@ -299,11 +304,23 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
>  	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
>  }
>  
> -static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
> +static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
>  {
> -	u64 ticks = (u64)len * NSEC_PER_SEC;
> +	u64 ticks;
>  
> -	do_div(ticks, rate);
> +	len += q->packet_overhead;
> +
> +	if (q->cell_size) {
> +		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
> +
> +		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
> +			cells++;
> +		len = cells * (q->cell_size + q->cell_overhead);
> +	}
> +
> +	ticks = (u64)len * NSEC_PER_SEC;
> +
> +	do_div(ticks, q->rate);
>  	return PSCHED_NS2TICKS(ticks);
>  }
>  
> @@ -384,7 +401,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
>  		if (q->rate) {
>  			struct sk_buff_head *list = &q->qdisc->q;
>  
> -			delay += packet_len_2_sched_time(skb->len, q->rate);
> +			delay += packet_len_2_sched_time(skb->len, q);
>  
>  			if (!skb_queue_empty(list)) {
>  				/*
> @@ -568,6 +585,11 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
>  	const struct tc_netem_rate *r = nla_data(attr);
>  
>  	q->rate = r->rate;
> +	q->packet_overhead = r->packet_overhead;
> +	q->cell_size = r->cell_size;
> +	q->cell_size_reciprocal = reciprocal_value(q->cell_size);

Here you get a crash if cell_size is 0. (divide by 0)


> +	q->cell_size = q->cell_size;
> +	q->cell_overhead = r->cell_overhead;
>  }
>  
>  static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
> @@ -909,6 +931,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
>  	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
>  
>  	rate.rate = q->rate;
> +	rate.packet_overhead = q->packet_overhead;
> +	rate.cell_size = q->cell_size;
> +	rate.cell_overhead = q->cell_overhead;
>  	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
>  
>  	if (dump_loss_model(q, skb) != 0)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-10 16:43 ` Eric Dumazet
@ 2011-12-10 23:36   ` Hagen Paul Pfeifer
  2011-12-10 23:58     ` Florian Westphal
  2011-12-12 17:18   ` [PATCH net-next] " Stephen Hemminger
  1 sibling, 1 reply; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-10 23:36 UTC (permalink / raw)
  To: netdev; +Cc: eric.dumazet, shemminger, Hagen Paul Pfeifer, Florian Westphal

This extension can be used to simulate special link layer
characteristics. Simulate because packet data is not modified, only the
calculation base is changed to delay a packet based on the original
packet size and artificial cell information.

packet_overhead can be used to simulate a link layer header compression
scheme (e.g. set packet_overhead to -20) or with a positive
packet_overhead value an additional MAC header can be simulated. It is
also possible to "replace" the 14 byte Ethernet header with something
else.

cell_size and cell_overhead can be used to simulate link layer schemes,
based on cells, like some TDMA schemes. Another application area are MAC
schemes using a link layer fragmentation with a (small) header each.
Cell size is the maximum amount of data bytes within one cell. Cell
overhead is an additional variable to change the per-cell-overhead (e.g.
5 byte header per fragment).

Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
cell overhead 5 byte):

  tc qdisc add dev eth0 root netem rate 5kbit 20 100 5

Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---


reciprocal_value() by zero fixed. Second: I thought that API modification
_within_ one merge window are ok? My patchset was thought to be one atomic
patchset, I splitted rate and cell-rate for better patch review. Next time I
will sent API changes in one separate patch. Thanks Eric!


 include/linux/pkt_sched.h |    3 +++
 net/sched/sch_netem.c     |   42 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 8786ea7..8daced3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -502,6 +502,9 @@ struct tc_netem_corrupt {
 
 struct tc_netem_rate {
 	__u32	rate;	/* byte/s */
+	__s32	packet_overhead;
+	__u32	cell_size;
+	__s32	cell_overhead;
 };
 
 enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bfd733..c946ff8 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
+#include <linux/reciprocal_div.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -80,6 +81,10 @@ struct netem_sched_data {
 	u32 reorder;
 	u32 corrupt;
 	u32 rate;
+	s32 packet_overhead;
+	u32 cell_size;
+	u32 cell_size_reciprocal;
+	s32 cell_overhead;
 
 	struct crndstate {
 		u32 last;
@@ -299,11 +304,32 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
 	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
+static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 {
-	u64 ticks = (u64)len * NSEC_PER_SEC;
+	u64 ticks;
 
-	do_div(ticks, rate);
+	len += q->packet_overhead;
+
+	if (q->cell_size) {
+		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
+		u32 mod_carry = len - cells * q->cell_size;
+
+		if (mod_carry)
+			mod_carry = (len > q->cell_size || !cells) ?
+				q->cell_size - mod_carry : len - mod_carry;
+
+		if (q->cell_overhead) {
+			if (mod_carry)
+				++cells;
+			len += cells * q->cell_overhead;
+		}
+
+		len += mod_carry;
+	}
+
+	ticks = (u64)len * NSEC_PER_SEC;
+
+	do_div(ticks, q->rate);
 	return PSCHED_NS2TICKS(ticks);
 }
 
@@ -384,7 +410,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		if (q->rate) {
 			struct sk_buff_head *list = &q->qdisc->q;
 
-			delay += packet_len_2_sched_time(skb->len, q->rate);
+			delay += packet_len_2_sched_time(skb->len, q);
 
 			if (!skb_queue_empty(list)) {
 				/*
@@ -568,6 +594,11 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 	const struct tc_netem_rate *r = nla_data(attr);
 
 	q->rate = r->rate;
+	q->packet_overhead = r->packet_overhead;
+	q->cell_size = r->cell_size;
+	if (q->cell_size)
+		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
+	q->cell_overhead = r->cell_overhead;
 }
 
 static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
@@ -909,6 +940,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
 	rate.rate = q->rate;
+	rate.packet_overhead = q->packet_overhead;
+	rate.cell_size = q->cell_size;
+	rate.cell_overhead = q->cell_overhead;
 	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 
 	if (dump_loss_model(q, skb) != 0)
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-10 23:36   ` [PATCH] " Hagen Paul Pfeifer
@ 2011-12-10 23:58     ` Florian Westphal
  2011-12-11  0:02       ` Hagen Paul Pfeifer
  0 siblings, 1 reply; 12+ messages in thread
From: Florian Westphal @ 2011-12-10 23:58 UTC (permalink / raw)
  To: Hagen Paul Pfeifer; +Cc: netdev, eric.dumazet, shemminger, Florian Westphal

Hagen Paul Pfeifer <hagen@jauu.net> wrote:
> +static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
>  {
[..]
> +	if (q->cell_size) {
> +		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
> +		u32 mod_carry = len - cells * q->cell_size;
> +
> +		if (mod_carry)
> +			mod_carry = (len > q->cell_size || !cells) ?
> +				q->cell_size - mod_carry : len - mod_carry;
> +
> +		if (q->cell_overhead) {
> +			if (mod_carry)
> +				++cells;
> +			len += cells * q->cell_overhead;
> +		}
> +
> +		len += mod_carry;

Why did you chose to replace the previous version?

if (q->cell_size) {
      u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);

      if (len > cells * q->cell_size)  /* extra cell needed for remainder */
                        cells++;
      len = cells * (q->cell_size + q->cell_overhead);
}

I think that it is a lot easier to read -- did you find a problem with it?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-10 23:58     ` Florian Westphal
@ 2011-12-11  0:02       ` Hagen Paul Pfeifer
  2011-12-11  0:08         ` Hagen Paul Pfeifer
  0 siblings, 1 reply; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-11  0:02 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, eric.dumazet, shemminger

* Florian Westphal | 2011-12-11 00:58:22 [+0100]:

>I think that it is a lot easier to read -- did you find a problem with it?

My mistake, switched from my workstation to the laptop and the old patch was
in the queue. Just ignore this one.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-11  0:02       ` Hagen Paul Pfeifer
@ 2011-12-11  0:08         ` Hagen Paul Pfeifer
  2011-12-11  0:11           ` Hagen Paul Pfeifer
  0 siblings, 1 reply; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-11  0:08 UTC (permalink / raw)
  To: netdev; +Cc: eric.dumazet, shemminger, Hagen Paul Pfeifer, Florian Westphal

This extension can be used to simulate special link layer
characteristics. Simulate because packet data is not modified, only the
calculation base is changed to delay a packet based on the original
packet size and artificial cell information.

packet_overhead can be used to simulate a link layer header compression
scheme (e.g. set packet_overhead to -20) or with a positive
packet_overhead value an additional MAC header can be simulated. It is
also possible to "replace" the 14 byte Ethernet header with something
else.

cell_size and cell_overhead can be used to simulate link layer schemes,
based on cells, like some TDMA schemes. Another application area are MAC
schemes using a link layer fragmentation with a (small) header each.
Cell size is the maximum amount of data bytes within one cell. Cell
overhead is an additional variable to change the per-cell-overhead
(e.g.  5 byte header per fragment).

Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
cell overhead 5 byte):

  tc qdisc add dev eth0 root netem rate 5kbit 20 100 5

Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---

reciprocal_value() by zero fixed. Second: I thought that API modification
_within_ one merge window are ok? My patchset was thought to be one atomic
patchset, I splitted rate and cell-rate for better patch review. Next time I
will sent API changes in one separate patch. Thanks Eric!


 include/linux/pkt_sched.h |    3 +++
 net/sched/sch_netem.c     |   34 ++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 8786ea7..8daced3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -502,6 +502,9 @@ struct tc_netem_corrupt {
 
 struct tc_netem_rate {
 	__u32	rate;	/* byte/s */
+	__s32	packet_overhead;
+	__u32	cell_size;
+	__s32	cell_overhead;
 };
 
 enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bfd733..b6a16bd 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
+#include <linux/reciprocal_div.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -80,6 +81,10 @@ struct netem_sched_data {
 	u32 reorder;
 	u32 corrupt;
 	u32 rate;
+	s32 packet_overhead;
+	u32 cell_size;
+	u32 cell_size_reciprocal;
+	s32 cell_overhead;
 
 	struct crndstate {
 		u32 last;
@@ -299,11 +304,23 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
 	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
+static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 {
-	u64 ticks = (u64)len * NSEC_PER_SEC;
+	u64 ticks;
 
-	do_div(ticks, rate);
+	len += q->packet_overhead;
+
+	if (q->cell_size) {
+		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
+
+		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
+			cells++;
+		len = cells * (q->cell_size + q->cell_overhead);
+	}
+
+	ticks = (u64)len * NSEC_PER_SEC;
+
+	do_div(ticks, q->rate);
 	return PSCHED_NS2TICKS(ticks);
 }
 
@@ -384,7 +401,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		if (q->rate) {
 			struct sk_buff_head *list = &q->qdisc->q;
 
-			delay += packet_len_2_sched_time(skb->len, q->rate);
+			delay += packet_len_2_sched_time(skb->len, q);
 
 			if (!skb_queue_empty(list)) {
 				/*
@@ -568,6 +585,12 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 	const struct tc_netem_rate *r = nla_data(attr);
 
 	q->rate = r->rate;
+	q->packet_overhead = r->packet_overhead;
+	q->cell_size = r->cell_size;
+	if (q->cell_size)
+		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
+	q->cell_size = q->cell_size;
+	q->cell_overhead = r->cell_overhead;
 }
 
 static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
@@ -909,6 +932,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
 	rate.rate = q->rate;
+	rate.packet_overhead = q->packet_overhead;
+	rate.cell_size = q->cell_size;
+	rate.cell_overhead = q->cell_overhead;
 	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 
 	if (dump_loss_model(q, skb) != 0)
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-11  0:08         ` Hagen Paul Pfeifer
@ 2011-12-11  0:11           ` Hagen Paul Pfeifer
  2011-12-12 17:19             ` Stephen Hemminger
  2011-12-13  0:01             ` David Miller
  0 siblings, 2 replies; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-11  0:11 UTC (permalink / raw)
  To: netdev; +Cc: eric.dumazet, shemminger, Hagen Paul Pfeifer, Florian Westphal

This extension can be used to simulate special link layer
characteristics. Simulate because packet data is not modified, only the
calculation base is changed to delay a packet based on the original
packet size and artificial cell information.

packet_overhead can be used to simulate a link layer header compression
scheme (e.g. set packet_overhead to -20) or with a positive
packet_overhead value an additional MAC header can be simulated. It is
also possible to "replace" the 14 byte Ethernet header with something
else.

cell_size and cell_overhead can be used to simulate link layer schemes,
based on cells, like some TDMA schemes. Another application area are MAC
schemes using a link layer fragmentation with a (small) header each.
Cell size is the maximum amount of data bytes within one cell. Cell
overhead is an additional variable to change the per-cell-overhead
(e.g.  5 byte header per fragment).

Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
cell overhead 5 byte):

  tc qdisc add dev eth0 root netem rate 5kbit 20 100 5

Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---

reciprocal_value() by zero fixed. Second: I thought that API modification
_within_ one merge window are ok? My patchset was thought to be one atomic
patchset, I splitted rate and cell-rate for better patch review. Next time I
will sent API changes in one separate patch. Thanks Eric!


 include/linux/pkt_sched.h |    3 +++
 net/sched/sch_netem.c     |   34 ++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 8786ea7..8daced3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -502,6 +502,9 @@ struct tc_netem_corrupt {
 
 struct tc_netem_rate {
 	__u32	rate;	/* byte/s */
+	__s32	packet_overhead;
+	__u32	cell_size;
+	__s32	cell_overhead;
 };
 
 enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bfd733..b6a16bd 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
+#include <linux/reciprocal_div.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -80,6 +81,10 @@ struct netem_sched_data {
 	u32 reorder;
 	u32 corrupt;
 	u32 rate;
+	s32 packet_overhead;
+	u32 cell_size;
+	u32 cell_size_reciprocal;
+	s32 cell_overhead;
 
 	struct crndstate {
 		u32 last;
@@ -299,11 +304,23 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
 	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
+static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 {
-	u64 ticks = (u64)len * NSEC_PER_SEC;
+	u64 ticks;
 
-	do_div(ticks, rate);
+	len += q->packet_overhead;
+
+	if (q->cell_size) {
+		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
+
+		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
+			cells++;
+		len = cells * (q->cell_size + q->cell_overhead);
+	}
+
+	ticks = (u64)len * NSEC_PER_SEC;
+
+	do_div(ticks, q->rate);
 	return PSCHED_NS2TICKS(ticks);
 }
 
@@ -384,7 +401,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		if (q->rate) {
 			struct sk_buff_head *list = &q->qdisc->q;
 
-			delay += packet_len_2_sched_time(skb->len, q->rate);
+			delay += packet_len_2_sched_time(skb->len, q);
 
 			if (!skb_queue_empty(list)) {
 				/*
@@ -568,6 +585,12 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 	const struct tc_netem_rate *r = nla_data(attr);
 
 	q->rate = r->rate;
+	q->packet_overhead = r->packet_overhead;
+	q->cell_size = r->cell_size;
+	if (q->cell_size)
+		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
+	q->cell_overhead = r->cell_overhead;
 }
 
 static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
@@ -909,6 +932,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
 	rate.rate = q->rate;
+	rate.packet_overhead = q->packet_overhead;
+	rate.cell_size = q->cell_size;
+	rate.cell_overhead = q->cell_overhead;
 	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 
 	if (dump_loss_model(q, skb) != 0)
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH net-next] netem: add cell concept to simulate special MAC behavior
  2011-12-10 16:43 ` Eric Dumazet
  2011-12-10 23:36   ` [PATCH] " Hagen Paul Pfeifer
@ 2011-12-12 17:18   ` Stephen Hemminger
  1 sibling, 0 replies; 12+ messages in thread
From: Stephen Hemminger @ 2011-12-12 17:18 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Hagen Paul Pfeifer, netdev, davem, Florian Westphal

On Sat, 10 Dec 2011 17:43:52 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> >  struct tc_netem_rate {
> >  	__u32	rate;	/* byte/s */
> > +	__s32	packet_overhead;
> > +	__u32	cell_size;
> > +	__s32	cell_overhead;  
> 
> Adding fields in existing structure is convenient, but this means a
> previous tc binary wont work anymore.

In this case it is ok because there  has not been a release
using this structure yet.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-11  0:11           ` Hagen Paul Pfeifer
@ 2011-12-12 17:19             ` Stephen Hemminger
  2011-12-13  0:01             ` David Miller
  1 sibling, 0 replies; 12+ messages in thread
From: Stephen Hemminger @ 2011-12-12 17:19 UTC (permalink / raw)
  To: Hagen Paul Pfeifer, David Miller; +Cc: netdev, eric.dumazet, Florian Westphal

On Sun, 11 Dec 2011 01:11:54 +0100
Hagen Paul Pfeifer <hagen@jauu.net> wrote:

> This extension can be used to simulate special link layer
> characteristics. Simulate because packet data is not modified, only the
> calculation base is changed to delay a packet based on the original
> packet size and artificial cell information.
> 
> packet_overhead can be used to simulate a link layer header compression
> scheme (e.g. set packet_overhead to -20) or with a positive
> packet_overhead value an additional MAC header can be simulated. It is
> also possible to "replace" the 14 byte Ethernet header with something
> else.
> 
> cell_size and cell_overhead can be used to simulate link layer schemes,
> based on cells, like some TDMA schemes. Another application area are MAC
> schemes using a link layer fragmentation with a (small) header each.
> Cell size is the maximum amount of data bytes within one cell. Cell
> overhead is an additional variable to change the per-cell-overhead
> (e.g.  5 byte header per fragment).
> 
> Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
> cell overhead 5 byte):
> 
>   tc qdisc add dev eth0 root netem rate 5kbit 20 100 5
> 
> Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
> Signed-off-by: Florian Westphal <fw@strlen.de>

Acked-by: Stephen Hemminger <shemminger@vyatta.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-11  0:11           ` Hagen Paul Pfeifer
  2011-12-12 17:19             ` Stephen Hemminger
@ 2011-12-13  0:01             ` David Miller
  2011-12-13  0:30               ` Hagen Paul Pfeifer
  1 sibling, 1 reply; 12+ messages in thread
From: David Miller @ 2011-12-13  0:01 UTC (permalink / raw)
  To: hagen; +Cc: netdev, eric.dumazet, shemminger, fw

From: Hagen Paul Pfeifer <hagen@jauu.net>
Date: Sun, 11 Dec 2011 01:11:54 +0100

> @@ -568,6 +585,12 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
>  	const struct tc_netem_rate *r = nla_data(attr);
>  
>  	q->rate = r->rate;
> +	q->packet_overhead = r->packet_overhead;
> +	q->cell_size = r->cell_size;
> +	if (q->cell_size)
> +		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
> +	q->cell_overhead = r->cell_overhead;
>  }
>  
>  static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)

This patch is corrupted.  The hunk header here says there should be 6 lines
of content before the change and 12 lines afterwards, but there are only 11
lines of content afterwards.

Please fix this up and resubmit.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-13  0:01             ` David Miller
@ 2011-12-13  0:30               ` Hagen Paul Pfeifer
  2011-12-13  0:45                 ` David Miller
  0 siblings, 1 reply; 12+ messages in thread
From: Hagen Paul Pfeifer @ 2011-12-13  0:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, Hagen Paul Pfeifer, Florian Westphal

This extension can be used to simulate special link layer
characteristics. Simulate because packet data is not modified, only the
calculation base is changed to delay a packet based on the original
packet size and artificial cell information.

packet_overhead can be used to simulate a link layer header compression
scheme (e.g. set packet_overhead to -20) or with a positive
packet_overhead value an additional MAC header can be simulated. It is
also possible to "replace" the 14 byte Ethernet header with something
else.

cell_size and cell_overhead can be used to simulate link layer schemes,
based on cells, like some TDMA schemes. Another application area are MAC
schemes using a link layer fragmentation with a (small) header each.
Cell size is the maximum amount of data bytes within one cell. Cell
overhead is an additional variable to change the per-cell-overhead
(e.g.  5 byte header per fragment).

Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
cell overhead 5 byte):

  tc qdisc add dev eth0 root netem rate 5kbit 20 100 5

Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
---
 include/linux/pkt_sched.h |    3 +++
 net/sched/sch_netem.c     |   33 +++++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 8786ea7..8daced3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -502,6 +502,9 @@ struct tc_netem_corrupt {
 
 struct tc_netem_rate {
 	__u32	rate;	/* byte/s */
+	__s32	packet_overhead;
+	__u32	cell_size;
+	__s32	cell_overhead;
 };
 
 enum {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 3bfd733..1fa2f90 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
+#include <linux/reciprocal_div.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -80,6 +81,10 @@ struct netem_sched_data {
 	u32 reorder;
 	u32 corrupt;
 	u32 rate;
+	s32 packet_overhead;
+	u32 cell_size;
+	u32 cell_size_reciprocal;
+	s32 cell_overhead;
 
 	struct crndstate {
 		u32 last;
@@ -299,11 +304,23 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
 	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate)
+static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 {
-	u64 ticks = (u64)len * NSEC_PER_SEC;
+	u64 ticks;
 
-	do_div(ticks, rate);
+	len += q->packet_overhead;
+
+	if (q->cell_size) {
+		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
+
+		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
+			cells++;
+		len = cells * (q->cell_size + q->cell_overhead);
+	}
+
+	ticks = (u64)len * NSEC_PER_SEC;
+
+	do_div(ticks, q->rate);
 	return PSCHED_NS2TICKS(ticks);
 }
 
@@ -384,7 +401,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		if (q->rate) {
 			struct sk_buff_head *list = &q->qdisc->q;
 
-			delay += packet_len_2_sched_time(skb->len, q->rate);
+			delay += packet_len_2_sched_time(skb->len, q);
 
 			if (!skb_queue_empty(list)) {
 				/*
@@ -568,6 +585,11 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 	const struct tc_netem_rate *r = nla_data(attr);
 
 	q->rate = r->rate;
+	q->packet_overhead = r->packet_overhead;
+	q->cell_size = r->cell_size;
+	if (q->cell_size)
+		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
+	q->cell_overhead = r->cell_overhead;
 }
 
 static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
@@ -909,6 +931,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
 	rate.rate = q->rate;
+	rate.packet_overhead = q->packet_overhead;
+	rate.cell_size = q->cell_size;
+	rate.cell_overhead = q->cell_overhead;
 	NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 
 	if (dump_loss_model(q, skb) != 0)
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] netem: add cell concept to simulate special MAC behavior
  2011-12-13  0:30               ` Hagen Paul Pfeifer
@ 2011-12-13  0:45                 ` David Miller
  0 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2011-12-13  0:45 UTC (permalink / raw)
  To: hagen; +Cc: netdev, fw

From: Hagen Paul Pfeifer <hagen@jauu.net>
Date: Tue, 13 Dec 2011 01:30:00 +0100

> This extension can be used to simulate special link layer
> characteristics. Simulate because packet data is not modified, only the
> calculation base is changed to delay a packet based on the original
> packet size and artificial cell information.
> 
> packet_overhead can be used to simulate a link layer header compression
> scheme (e.g. set packet_overhead to -20) or with a positive
> packet_overhead value an additional MAC header can be simulated. It is
> also possible to "replace" the 14 byte Ethernet header with something
> else.
> 
> cell_size and cell_overhead can be used to simulate link layer schemes,
> based on cells, like some TDMA schemes. Another application area are MAC
> schemes using a link layer fragmentation with a (small) header each.
> Cell size is the maximum amount of data bytes within one cell. Cell
> overhead is an additional variable to change the per-cell-overhead
> (e.g.  5 byte header per fragment).
> 
> Example (5 kbit/s, 20 byte per packet overhead, cell-size 100 byte, per
> cell overhead 5 byte):
> 
>   tc qdisc add dev eth0 root netem rate 5kbit 20 100 5
> 
> Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> Acked-by: Stephen Hemminger <shemminger@vyatta.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2011-12-13  0:45 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-10 15:15 [PATCH net-next] netem: add cell concept to simulate special MAC behavior Hagen Paul Pfeifer
2011-12-10 16:43 ` Eric Dumazet
2011-12-10 23:36   ` [PATCH] " Hagen Paul Pfeifer
2011-12-10 23:58     ` Florian Westphal
2011-12-11  0:02       ` Hagen Paul Pfeifer
2011-12-11  0:08         ` Hagen Paul Pfeifer
2011-12-11  0:11           ` Hagen Paul Pfeifer
2011-12-12 17:19             ` Stephen Hemminger
2011-12-13  0:01             ` David Miller
2011-12-13  0:30               ` Hagen Paul Pfeifer
2011-12-13  0:45                 ` David Miller
2011-12-12 17:18   ` [PATCH net-next] " Stephen Hemminger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.