netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] net_random_N, reciprocal_divide helper updates
@ 2013-09-03 10:26 Daniel Borkmann
  2013-09-03 10:26 ` [PATCH net-next 1/2] net: introduce generic net_random_N helper Daniel Borkmann
  2013-09-03 10:26 ` [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it Daniel Borkmann
  0 siblings, 2 replies; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 10:26 UTC (permalink / raw)
  To: davem; +Cc: netdev

Introduce a net_random_N() helper instead of reimplementing it over and
over, plus use reciprocal_divide() helper instead of reimplementing it
as well.

Daniel Borkmann (2):
  net: introduce generic net_random_N helper
  net: use reciprocal_divide instead of reimplementing it

 drivers/net/team/team_mode_random.c | 7 +------
 include/linux/net.h                 | 7 +++++++
 include/net/red.h                   | 2 +-
 net/802/garp.c                      | 2 +-
 net/802/mrp.c                       | 2 +-
 net/core/dev.c                      | 2 +-
 net/core/flow_dissector.c           | 5 ++---
 net/ipv4/inet_hashtables.c          | 2 +-
 net/ipv4/netfilter/ipt_CLUSTERIP.c  | 2 +-
 net/ipv4/udp.c                      | 6 +++---
 net/ipv6/inet6_hashtables.c         | 2 +-
 net/ipv6/udp.c                      | 4 ++--
 net/netfilter/nf_conntrack_core.c   | 2 +-
 net/netfilter/nf_conntrack_expect.c | 2 +-
 net/netfilter/nf_nat_core.c         | 4 ++--
 net/netfilter/xt_HMARK.c            | 2 +-
 net/netfilter/xt_NFQUEUE.c          | 4 ++--
 net/netfilter/xt_cluster.c          | 2 +-
 net/netfilter/xt_hashlimit.c        | 2 +-
 net/packet/af_packet.c              | 2 +-
 net/sched/sch_choke.c               | 8 +-------
 net/sched/sch_fq_codel.c            | 2 +-
 22 files changed, 34 insertions(+), 39 deletions(-)

-- 
1.7.11.7

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

* [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 10:26 [PATCH net-next 0/2] net_random_N, reciprocal_divide helper updates Daniel Borkmann
@ 2013-09-03 10:26 ` Daniel Borkmann
  2013-09-03 11:00   ` Joe Perches
  2013-09-03 13:59   ` Eric Dumazet
  2013-09-03 10:26 ` [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it Daniel Borkmann
  1 sibling, 2 replies; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 10:26 UTC (permalink / raw)
  To: davem; +Cc: netdev

We have implemented the same function over and over, so introduce a
generic helper net_random_N() that unifies these implementations.
It internally used net_random() which eventually resolves to
prandom_u32(). Explicit include of reciprocal_div.h is not necessary.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 drivers/net/team/team_mode_random.c | 7 +------
 include/linux/net.h                 | 7 +++++++
 include/net/red.h                   | 2 +-
 net/802/garp.c                      | 2 +-
 net/802/mrp.c                       | 2 +-
 net/packet/af_packet.c              | 2 +-
 net/sched/sch_choke.c               | 8 +-------
 7 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mode_random.c
index 7f032e2..b2294f8 100644
--- a/drivers/net/team/team_mode_random.c
+++ b/drivers/net/team/team_mode_random.c
@@ -16,17 +16,12 @@
 #include <linux/reciprocal_div.h>
 #include <linux/if_team.h>
 
-static u32 random_N(unsigned int N)
-{
-	return reciprocal_divide(prandom_u32(), N);
-}
-
 static bool rnd_transmit(struct team *team, struct sk_buff *skb)
 {
 	struct team_port *port;
 	int port_index;
 
-	port_index = random_N(team->en_port_count);
+	port_index = net_random_N(team->en_port_count);
 	port = team_get_port_by_index_rcu(team, port_index);
 	if (unlikely(!port))
 		goto drop;
diff --git a/include/linux/net.h b/include/linux/net.h
index 4f27575..86ffce7 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -24,6 +24,7 @@
 #include <linux/fcntl.h>	/* For O_CLOEXEC and O_NONBLOCK */
 #include <linux/kmemcheck.h>
 #include <linux/rcupdate.h>
+#include <linux/reciprocal_div.h>
 #include <uapi/linux/net.h>
 
 struct poll_table_struct;
@@ -243,6 +244,12 @@ do {								\
 #define net_random()		prandom_u32()
 #define net_srandom(seed)	prandom_seed((__force u32)(seed))
 
+/* deliver a random number between 0 and N - 1 */
+static inline u32 net_random_N(u32 N)
+{
+	return reciprocal_divide(net_random(), N);
+}
+
 extern int   	     kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 				    struct kvec *vec, size_t num, size_t len);
 extern int   	     kernel_recvmsg(struct socket *sock, struct msghdr *msg,
diff --git a/include/net/red.h b/include/net/red.h
index ef46058..b17ed60 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -303,7 +303,7 @@ static inline unsigned long red_calc_qavg(const struct red_parms *p,
 
 static inline u32 red_random(const struct red_parms *p)
 {
-	return reciprocal_divide(net_random(), p->max_P_reciprocal);
+	return net_random_N(p->max_P_reciprocal);
 }
 
 static inline int red_mark_probability(const struct red_parms *p,
diff --git a/net/802/garp.c b/net/802/garp.c
index 5d9630a..c6fe7ca 100644
--- a/net/802/garp.c
+++ b/net/802/garp.c
@@ -397,7 +397,7 @@ static void garp_join_timer_arm(struct garp_applicant *app)
 {
 	unsigned long delay;
 
-	delay = (u64)msecs_to_jiffies(garp_join_time) * net_random() >> 32;
+	delay = net_random_N(msecs_to_jiffies(garp_join_time));
 	mod_timer(&app->join_timer, jiffies + delay);
 }
 
diff --git a/net/802/mrp.c b/net/802/mrp.c
index 1eb05d8..7338a7c 100644
--- a/net/802/mrp.c
+++ b/net/802/mrp.c
@@ -578,7 +578,7 @@ static void mrp_join_timer_arm(struct mrp_applicant *app)
 {
 	unsigned long delay;
 
-	delay = (u64)msecs_to_jiffies(mrp_join_time) * net_random() >> 32;
+	delay = net_random_N(msecs_to_jiffies(mrp_join_time));
 	mod_timer(&app->join_timer, jiffies + delay);
 }
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2e8286b..7ac669e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1162,7 +1162,7 @@ static unsigned int fanout_demux_rnd(struct packet_fanout *f,
 				     struct sk_buff *skb,
 				     unsigned int num)
 {
-	return reciprocal_divide(prandom_u32(), num);
+	return net_random_N(num);
 }
 
 static unsigned int fanout_demux_rollover(struct packet_fanout *f,
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index ef53ab8..e19b20be 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -77,12 +77,6 @@ struct choke_sched_data {
 	struct sk_buff **tab;
 };
 
-/* deliver a random number between 0 and N - 1 */
-static u32 random_N(unsigned int N)
-{
-	return reciprocal_divide(prandom_u32(), N);
-}
-
 /* number of elements in queue including holes */
 static unsigned int choke_len(const struct choke_sched_data *q)
 {
@@ -233,7 +227,7 @@ static struct sk_buff *choke_peek_random(const struct choke_sched_data *q,
 	int retrys = 3;
 
 	do {
-		*pidx = (q->head + random_N(choke_len(q))) & q->tab_mask;
+		*pidx = (q->head + net_random_N(choke_len(q))) & q->tab_mask;
 		skb = q->tab[*pidx];
 		if (skb)
 			return skb;
-- 
1.7.11.7

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

* [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it
  2013-09-03 10:26 [PATCH net-next 0/2] net_random_N, reciprocal_divide helper updates Daniel Borkmann
  2013-09-03 10:26 ` [PATCH net-next 1/2] net: introduce generic net_random_N helper Daniel Borkmann
@ 2013-09-03 10:26 ` Daniel Borkmann
  2013-09-03 14:02   ` Eric Dumazet
  1 sibling, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 10:26 UTC (permalink / raw)
  To: davem; +Cc: netdev, netfilter-devel

Replace these places with reciprocal_divide() inline function instead of
reimplementing it each time, thus it will become easier to read. We do not
need to explicitly include its header as it's pulled in from linux/net.h
anyway.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: netfilter-devel@vger.kernel.org
---
 net/core/dev.c                      | 2 +-
 net/core/flow_dissector.c           | 5 ++---
 net/ipv4/inet_hashtables.c          | 2 +-
 net/ipv4/netfilter/ipt_CLUSTERIP.c  | 2 +-
 net/ipv4/udp.c                      | 6 +++---
 net/ipv6/inet6_hashtables.c         | 2 +-
 net/ipv6/udp.c                      | 4 ++--
 net/netfilter/nf_conntrack_core.c   | 2 +-
 net/netfilter/nf_conntrack_expect.c | 2 +-
 net/netfilter/nf_nat_core.c         | 4 ++--
 net/netfilter/xt_HMARK.c            | 2 +-
 net/netfilter/xt_NFQUEUE.c          | 4 ++--
 net/netfilter/xt_cluster.c          | 2 +-
 net/netfilter/xt_hashlimit.c        | 2 +-
 net/sched/sch_fq_codel.c            | 2 +-
 15 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 6fbb0c9..bc7c839 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3040,7 +3040,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
 	}
 
 	if (map) {
-		tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32];
+		tcpu = map->cpus[reciprocal_divide(skb->rxhash, map->len)];
 
 		if (cpu_online(tcpu)) {
 			cpu = tcpu;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 159737c..59521e0 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -233,7 +233,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
 		hash = (__force u16) skb->protocol;
 	hash = jhash_1word(hash, hashrnd);
 
-	return (u16) (((u64) hash * qcount) >> 32) + qoffset;
+	return (u16) reciprocal_divide(hash, qcount) + qoffset;
 }
 EXPORT_SYMBOL(__skb_tx_hash);
 
@@ -324,8 +324,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 					hash = (__force u16) skb->protocol ^
 					    skb->rxhash;
 				hash = jhash_1word(hash, hashrnd);
-				queue_index = map->queues[
-				    ((u64)hash * map->len) >> 32];
+				queue_index = map->queues[reciprocal_divide(hash, map->len)];
 			}
 			if (unlikely(queue_index >= dev->real_num_tx_queues))
 				queue_index = -1;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7bd8983..731dcbf 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -204,7 +204,7 @@ begin:
 			}
 		} else if (score == hiscore && reuseport) {
 			matches++;
-			if (((u64)phash * matches) >> 32 == 0)
+			if (reciprocal_divide(phash, matches) == 0)
 				result = sk;
 			phash = next_pseudo_random32(phash);
 		}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 0b732ef..0fede8b 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -273,7 +273,7 @@ clusterip_hashfn(const struct sk_buff *skb,
 	}
 
 	/* node numbers are 1..n, not 0..n */
-	return (((u64)hashval * config->num_total_nodes) >> 32) + 1;
+	return reciprocal_divide(hashval, config->num_total_nodes) + 1;
 }
 
 static inline int
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 74d2c95..5db0725 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -223,7 +223,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
 		remaining = (high - low) + 1;
 
 		rand = net_random();
-		first = (((u64)rand * remaining) >> 32) + low;
+		first = reciprocal_divide(rand, remaining) + low;
 		/*
 		 * force rand to be an odd multiple of UDP_HTABLE_SIZE
 		 */
@@ -435,7 +435,7 @@ begin:
 			}
 		} else if (score == badness && reuseport) {
 			matches++;
-			if (((u64)hash * matches) >> 32 == 0)
+			if (reciprocal_divide(hash, matches) == 0)
 				result = sk;
 			hash = next_pseudo_random32(hash);
 		}
@@ -516,7 +516,7 @@ begin:
 			}
 		} else if (score == badness && reuseport) {
 			matches++;
-			if (((u64)hash * matches) >> 32 == 0)
+			if (reciprocal_divide(hash, matches) == 0)
 				result = sk;
 			hash = next_pseudo_random32(hash);
 		}
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 32b4a16..d9d8908 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -187,7 +187,7 @@ begin:
 			}
 		} else if (score == hiscore && reuseport) {
 			matches++;
-			if (((u64)phash * matches) >> 32 == 0)
+			if (reciprocal_divide(phash, matches) == 0)
 				result = sk;
 			phash = next_pseudo_random32(phash);
 		}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f405815..610013a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -226,7 +226,7 @@ begin:
 				goto exact_match;
 		} else if (score == badness && reuseport) {
 			matches++;
-			if (((u64)hash * matches) >> 32 == 0)
+			if (reciprocal_divide(hash, matches) == 0)
 				result = sk;
 			hash = next_pseudo_random32(hash);
 		}
@@ -306,7 +306,7 @@ begin:
 			}
 		} else if (score == badness && reuseport) {
 			matches++;
-			if (((u64)hash * matches) >> 32 == 0)
+			if (reciprocal_divide(hash, matches) == 0)
 				result = sk;
 			hash = next_pseudo_random32(hash);
 		}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 5d892fe..6378441 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -97,7 +97,7 @@ static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone)
 
 static u32 __hash_bucket(u32 hash, unsigned int size)
 {
-	return ((u64)hash * size) >> 32;
+	return reciprocal_divide(hash, size);
 }
 
 static u32 hash_bucket(u32 hash, const struct net *net)
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 4fd1ca9..c0865e6 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -83,7 +83,7 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple
 	hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
 		      (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
 		       (__force __u16)tuple->dst.u.all) ^ nf_conntrack_hash_rnd);
-	return ((u64)hash * nf_ct_expect_hsize) >> 32;
+	return reciprocal_divide(hash, nf_ct_expect_hsize);
 }
 
 struct nf_conntrack_expect *
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 6f0f4f7..ce9083e 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -126,7 +126,7 @@ hash_by_src(const struct net *net, u16 zone,
 	/* Original src, to ensure we map it consistently if poss. */
 	hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32),
 		      tuple->dst.protonum ^ zone ^ nf_conntrack_hash_rnd);
-	return ((u64)hash * net->ct.nat_htable_size) >> 32;
+	return reciprocal_divide(hash, net->ct.nat_htable_size);
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -274,7 +274,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
 		}
 
 		var_ipp->all[i] = (__force __u32)
-			htonl(minip + (((u64)j * dist) >> 32));
+			htonl(minip + reciprocal_divide(j, dist));
 		if (var_ipp->all[i] != range->max_addr.all[i])
 			full_range = true;
 
diff --git a/net/netfilter/xt_HMARK.c b/net/netfilter/xt_HMARK.c
index 73b73f6..3dd05c4 100644
--- a/net/netfilter/xt_HMARK.c
+++ b/net/netfilter/xt_HMARK.c
@@ -126,7 +126,7 @@ hmark_hash(struct hmark_tuple *t, const struct xt_hmark_info *info)
 	hash = jhash_3words(src, dst, t->uports.v32, info->hashrnd);
 	hash = hash ^ (t->proto & info->proto_mask);
 
-	return (((u64)hash * info->hmodulus) >> 32) + info->hoffset;
+	return reciprocal_divide(hash, info->hmodulus) + info->hoffset;
 }
 
 static void
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 1e2fae3..88443c1 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -83,10 +83,10 @@ nfqueue_hash(const struct sk_buff *skb, const struct xt_action_param *par)
 	u32 queue = info->queuenum;
 
 	if (par->family == NFPROTO_IPV4)
-		queue += ((u64) hash_v4(skb) * info->queues_total) >> 32;
+		queue += reciprocal_divide(hash_v4(skb), info->queues_total);
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 	else if (par->family == NFPROTO_IPV6)
-		queue += ((u64) hash_v6(skb) * info->queues_total) >> 32;
+		queue += reciprocal_divide(hash_v6(skb), info->queues_total);
 #endif
 
 	return queue;
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c
index f4af1bf..845fc16 100644
--- a/net/netfilter/xt_cluster.c
+++ b/net/netfilter/xt_cluster.c
@@ -55,7 +55,7 @@ xt_cluster_hash(const struct nf_conn *ct,
 		WARN_ON(1);
 		break;
 	}
-	return (((u64)hash * info->total_nodes) >> 32);
+	return reciprocal_divide(hash, info->total_nodes);
 }
 
 static inline bool
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 9ff035c..9af9021 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -135,7 +135,7 @@ hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst)
 	 * give results between [0 and cfg.size-1] and same hash distribution,
 	 * but using a multiply, less expensive than a divide
 	 */
-	return ((u64)hash * ht->cfg.size) >> 32;
+	return reciprocal_divide(hash, ht->cfg.size);
 }
 
 static struct dsthash_ent *
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 5578628..4869671 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -77,7 +77,7 @@ static unsigned int fq_codel_hash(const struct fq_codel_sched_data *q,
 	hash = jhash_3words((__force u32)keys.dst,
 			    (__force u32)keys.src ^ keys.ip_proto,
 			    (__force u32)keys.ports, q->perturbation);
-	return ((u64)hash * q->flows_cnt) >> 32;
+	return reciprocal_divide(hash, q->flows_cnt);
 }
 
 static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
-- 
1.7.11.7

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 10:26 ` [PATCH net-next 1/2] net: introduce generic net_random_N helper Daniel Borkmann
@ 2013-09-03 11:00   ` Joe Perches
  2013-09-03 11:40     ` Daniel Borkmann
  2013-09-03 13:59   ` Eric Dumazet
  1 sibling, 1 reply; 11+ messages in thread
From: Joe Perches @ 2013-09-03 11:00 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, Theodore Ts'o

On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
> We have implemented the same function over and over, so introduce a
> generic helper net_random_N() that unifies these implementations.
> It internally used net_random() which eventually resolves to
> prandom_u32(). Explicit include of reciprocal_div.h is not necessary.

Perhaps adding a generic helper to random.h like
	u32 prandom_u32_between(u32 low, u32 high);
or
	u32 prandom_u32_range(u32 bound1, u32 bound2)
would be better.

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 11:00   ` Joe Perches
@ 2013-09-03 11:40     ` Daniel Borkmann
  2013-09-03 12:15       ` Joe Perches
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 11:40 UTC (permalink / raw)
  To: Joe Perches; +Cc: davem, netdev, Theodore Ts'o

On 09/03/2013 01:00 PM, Joe Perches wrote:
> On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
>> We have implemented the same function over and over, so introduce a
>> generic helper net_random_N() that unifies these implementations.
>> It internally used net_random() which eventually resolves to
>> prandom_u32(). Explicit include of reciprocal_div.h is not necessary.
>
> Perhaps adding a generic helper to random.h like
> 	u32 prandom_u32_between(u32 low, u32 high);
> or
> 	u32 prandom_u32_range(u32 bound1, u32 bound2)
> would be better.

Sure, this could be done as a follow-up. Once, we've migrated users to
the new API, follow-ups could go ahead to do the rest, and migration
will be easy. Note that the lower bound is 0 here.

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 11:40     ` Daniel Borkmann
@ 2013-09-03 12:15       ` Joe Perches
  2013-09-03 12:26         ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Joe Perches @ 2013-09-03 12:15 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, Theodore Ts'o

On Tue, 2013-09-03 at 13:40 +0200, Daniel Borkmann wrote:
> On 09/03/2013 01:00 PM, Joe Perches wrote:
> > On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
> >> We have implemented the same function over and over, so introduce a
> >> generic helper net_random_N() that unifies these implementations.
> >> It internally used net_random() which eventually resolves to
> >> prandom_u32(). Explicit include of reciprocal_div.h is not necessary.
> >
> > Perhaps adding a generic helper to random.h like
> > 	u32 prandom_u32_between(u32 low, u32 high);
> > or
> > 	u32 prandom_u32_range(u32 bound1, u32 bound2)
> > would be better.
> 
> Sure, this could be done as a follow-up. Once, we've migrated users to
> the new API, follow-ups could go ahead to do the rest, and migration
> will be easy. Note that the lower bound is 0 here.

Part of the reason I suggested this it to make the
API more readable/intelligible.

At first glance, I have no idea what net_random_N does.

I think #define net_random() prandom_u32()
should be removed eventually as well.

If gcc doesn't already do this optimization,
perhaps there are also some use of
	net_random() % non_const
that could be optimized a bit using this API.

$ git grep -E "(prandom_u32|net_random)\s*\(\s*\)\s*\%" net
net/batman-adv/bat_iv_ogm.c:	msecs += prandom_u32() % (2 * BATADV_JITTER);
net/batman-adv/bat_iv_ogm.c:	return jiffies + msecs_to_jiffies(prandom_u32() % (BATADV_JITTER / 2));
net/core/neighbour.c:	return base ? (net_random() % base) + (base >> 1) : 0;
net/core/neighbour.c:	unsigned long sched_next = now + (net_random() % p->proxy_delay);
net/core/pktgen.c:		flow = prandom_u32() % pkt_dev->cflows;
net/core/pktgen.c:			t = prandom_u32() %
net/core/pktgen.c:			mc = prandom_u32() % pkt_dev->src_mac_count;
net/core/pktgen.c:			mc = prandom_u32() % pkt_dev->dst_mac_count;
net/core/pktgen.c:			pkt_dev->cur_udp_src = prandom_u32() %
net/core/pktgen.c:			pkt_dev->cur_udp_dst = prandom_u32() %
net/core/pktgen.c:				t = prandom_u32() % (imx - imn) + imn;
net/core/pktgen.c:						t = prandom_u32() %
net/core/pktgen.c:			t = prandom_u32() %
net/core/stream.c:		current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2;
net/ipv4/igmp.c:	int tv = net_random() % max_delay;
net/ipv4/igmp.c:	int tv = net_random() % in_dev->mr_maxdelay;
net/ipv4/igmp.c:	int tv = net_random() % delay;
net/ipv4/inet_connection_sock.c:		smallest_rover = rover = net_random() % remaining + low;
net/ipv6/addrconf.c:		rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
net/ipv6/mcast.c:	unsigned long tv = net_random() % idev->mc_maxdelay;
net/ipv6/mcast.c:	unsigned long tv = net_random() % delay;
net/ipv6/mcast.c:	unsigned long tv = net_random() % delay;
net/ipv6/mcast.c:			delay = net_random() % resptime;
net/ipv6/mcast.c:	delay = net_random() % unsolicited_report_interval(ma->idev);
net/netfilter/nf_conntrack_core.c:			(prandom_u32() % net->ct.sysctl_events_retry_timeout);
net/netfilter/nf_conntrack_core.c:		(prandom_u32() % net->ct.sysctl_events_retry_timeout);
net/sched/act_gact.c:	if (!gact->tcfg_pval || net_random() % gact->tcfg_pval)
net/sched/sch_netem.c:		skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
net/sctp/socket.c:		rover = net_random() % remaining + low;
net/sunrpc/xprtsock.c:	unsigned short rand = (unsigned short) net_random() % range;
net/xfrm/xfrm_state.c:			spi = low + net_random()%(high-low+1);

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 12:15       ` Joe Perches
@ 2013-09-03 12:26         ` Daniel Borkmann
  2013-09-03 12:41           ` Joe Perches
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 12:26 UTC (permalink / raw)
  To: Joe Perches; +Cc: davem, netdev, Theodore Ts'o

On 09/03/2013 02:15 PM, Joe Perches wrote:
> On Tue, 2013-09-03 at 13:40 +0200, Daniel Borkmann wrote:
>> On 09/03/2013 01:00 PM, Joe Perches wrote:
>>> On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
>>>> We have implemented the same function over and over, so introduce a
>>>> generic helper net_random_N() that unifies these implementations.
>>>> It internally used net_random() which eventually resolves to
>>>> prandom_u32(). Explicit include of reciprocal_div.h is not necessary.
>>>
>>> Perhaps adding a generic helper to random.h like
>>> 	u32 prandom_u32_between(u32 low, u32 high);
>>> or
>>> 	u32 prandom_u32_range(u32 bound1, u32 bound2)
>>> would be better.
>>
>> Sure, this could be done as a follow-up. Once, we've migrated users to
>> the new API, follow-ups could go ahead to do the rest, and migration
>> will be easy. Note that the lower bound is 0 here.
>
> Part of the reason I suggested this it to make the
> API more readable/intelligible.
>
> At first glance, I have no idea what net_random_N does.
>
> I think #define net_random() prandom_u32()
> should be removed eventually as well.

Why? Assume there could be different PRNGs in future that have different properties
(e.g. speed vs. period, etc). Then, changing net_random() to something else is way
easier and less error-prone than searching through the whole subtree of net and
replacing every occurrence of prandom_u32().

> If gcc doesn't already do this optimization,
> perhaps there are also some use of
> 	net_random() % non_const
> that could be optimized a bit using this API.

I agree with you, needs to be evaluated on a case by case basis for future work.

> $ git grep -E "(prandom_u32|net_random)\s*\(\s*\)\s*\%" net
> net/batman-adv/bat_iv_ogm.c:	msecs += prandom_u32() % (2 * BATADV_JITTER);
> net/batman-adv/bat_iv_ogm.c:	return jiffies + msecs_to_jiffies(prandom_u32() % (BATADV_JITTER / 2));
> net/core/neighbour.c:	return base ? (net_random() % base) + (base >> 1) : 0;
> net/core/neighbour.c:	unsigned long sched_next = now + (net_random() % p->proxy_delay);
> net/core/pktgen.c:		flow = prandom_u32() % pkt_dev->cflows;
> net/core/pktgen.c:			t = prandom_u32() %
> net/core/pktgen.c:			mc = prandom_u32() % pkt_dev->src_mac_count;
> net/core/pktgen.c:			mc = prandom_u32() % pkt_dev->dst_mac_count;
> net/core/pktgen.c:			pkt_dev->cur_udp_src = prandom_u32() %
> net/core/pktgen.c:			pkt_dev->cur_udp_dst = prandom_u32() %
> net/core/pktgen.c:				t = prandom_u32() % (imx - imn) + imn;
> net/core/pktgen.c:						t = prandom_u32() %
> net/core/pktgen.c:			t = prandom_u32() %
> net/core/stream.c:		current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2;
> net/ipv4/igmp.c:	int tv = net_random() % max_delay;
> net/ipv4/igmp.c:	int tv = net_random() % in_dev->mr_maxdelay;
> net/ipv4/igmp.c:	int tv = net_random() % delay;
> net/ipv4/inet_connection_sock.c:		smallest_rover = rover = net_random() % remaining + low;
> net/ipv6/addrconf.c:		rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
> net/ipv6/mcast.c:	unsigned long tv = net_random() % idev->mc_maxdelay;
> net/ipv6/mcast.c:	unsigned long tv = net_random() % delay;
> net/ipv6/mcast.c:	unsigned long tv = net_random() % delay;
> net/ipv6/mcast.c:			delay = net_random() % resptime;
> net/ipv6/mcast.c:	delay = net_random() % unsolicited_report_interval(ma->idev);
> net/netfilter/nf_conntrack_core.c:			(prandom_u32() % net->ct.sysctl_events_retry_timeout);
> net/netfilter/nf_conntrack_core.c:		(prandom_u32() % net->ct.sysctl_events_retry_timeout);
> net/sched/act_gact.c:	if (!gact->tcfg_pval || net_random() % gact->tcfg_pval)
> net/sched/sch_netem.c:		skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
> net/sctp/socket.c:		rover = net_random() % remaining + low;
> net/sunrpc/xprtsock.c:	unsigned short rand = (unsigned short) net_random() % range;
> net/xfrm/xfrm_state.c:			spi = low + net_random()%(high-low+1);
>
>

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 12:26         ` Daniel Borkmann
@ 2013-09-03 12:41           ` Joe Perches
  0 siblings, 0 replies; 11+ messages in thread
From: Joe Perches @ 2013-09-03 12:41 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, Theodore Ts'o

On Tue, 2013-09-03 at 14:26 +0200, Daniel Borkmann wrote:
> On 09/03/2013 02:15 PM, Joe Perches wrote:
> > I think #define net_random() prandom_u32()
> > should be removed eventually as well.
> 
> Why? Assume there could be different PRNGs in future that have different properties
> (e.g. speed vs. period, etc). Then, changing net_random() to something else is way
> easier and less error-prone than searching through the whole subtree of net and
> replacing every occurrence of prandom_u32().

Maybe.  There are already instances of prandom_u32
in the net tree.  I don't find value in the indirection.

Akinobu Mita once posted a s/net_random/prandom_u32/
patch: https://lkml.org/lkml/2012/12/23/140

> > If gcc doesn't already do this optimization,
> > perhaps there are also some use of
> > 	net_random() % non_const
> > that could be optimized a bit using this API.
> 
> I agree with you, needs to be evaluated on a case by case basis for future work.

__builtin_constant_p is useful.

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

* Re: [PATCH net-next 1/2] net: introduce generic net_random_N helper
  2013-09-03 10:26 ` [PATCH net-next 1/2] net: introduce generic net_random_N helper Daniel Borkmann
  2013-09-03 11:00   ` Joe Perches
@ 2013-09-03 13:59   ` Eric Dumazet
  1 sibling, 0 replies; 11+ messages in thread
From: Eric Dumazet @ 2013-09-03 13:59 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev

On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
> We have implemented the same function over and over, so introduce a
> generic helper net_random_N() that unifies these implementations.
> It internally used net_random() which eventually resolves to
> prandom_u32(). Explicit include of reciprocal_div.h is not necessary.
> 
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> ---

It was private, so the name was whatever we chose at that time.

If we want to make it generic, why still doing a net_something() ?

Really this patch should be discussed on lkml and netdev and we should
use a generic name.

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

* Re: [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it
  2013-09-03 10:26 ` [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it Daniel Borkmann
@ 2013-09-03 14:02   ` Eric Dumazet
  2013-09-03 14:35     ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Eric Dumazet @ 2013-09-03 14:02 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, netfilter-devel

On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
> Replace these places with reciprocal_divide() inline function instead of
> reimplementing it each time, thus it will become easier to read. We do not
> need to explicitly include its header as it's pulled in from linux/net.h
> anyway.

Sure, (((u64) hash * qcount) >> 32) happens to be
reciprocal_divide(hash, qcount) but the result depends on hash being
well distributed in [0 .. ~0U] space.

So 'reciprocal' and 'divide' do not accurately describe this exact
operation.

I suggest making the thing more descriptive.

(And discussed on lkml btw)



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

* Re: [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it
  2013-09-03 14:02   ` Eric Dumazet
@ 2013-09-03 14:35     ` Daniel Borkmann
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel Borkmann @ 2013-09-03 14:35 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: davem, netdev, netfilter-devel

On 09/03/2013 04:02 PM, Eric Dumazet wrote:
> On Tue, 2013-09-03 at 12:26 +0200, Daniel Borkmann wrote:
>> Replace these places with reciprocal_divide() inline function instead of
>> reimplementing it each time, thus it will become easier to read. We do not
>> need to explicitly include its header as it's pulled in from linux/net.h
>> anyway.
>
> Sure, (((u64) hash * qcount) >> 32) happens to be
> reciprocal_divide(hash, qcount) but the result depends on hash being
> well distributed in [0 .. ~0U] space.
>
> So 'reciprocal' and 'divide' do not accurately describe this exact
> operation.
>
> I suggest making the thing more descriptive.
>
> (And discussed on lkml btw)

Sure, we can do that. Then lets drop these two for now.

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

end of thread, other threads:[~2013-09-03 14:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-03 10:26 [PATCH net-next 0/2] net_random_N, reciprocal_divide helper updates Daniel Borkmann
2013-09-03 10:26 ` [PATCH net-next 1/2] net: introduce generic net_random_N helper Daniel Borkmann
2013-09-03 11:00   ` Joe Perches
2013-09-03 11:40     ` Daniel Borkmann
2013-09-03 12:15       ` Joe Perches
2013-09-03 12:26         ` Daniel Borkmann
2013-09-03 12:41           ` Joe Perches
2013-09-03 13:59   ` Eric Dumazet
2013-09-03 10:26 ` [PATCH net-next 2/2] net: use reciprocal_divide instead of reimplementing it Daniel Borkmann
2013-09-03 14:02   ` Eric Dumazet
2013-09-03 14:35     ` Daniel Borkmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).