[PATCH 1/2] socket: set NL_MAX_USED_PORT, NL_BITS_FOR_PID and NR_BITS macros

Julien Courtat julien.courtat at 6wind.com
Thu Jun 4 08:07:16 PDT 2015


Instead of setting hardcoded value 22 for masking pid bits, use macro
NL_BITS_FOR_PID everywhere needed and automatically compute pid mask
with it.
Compute size of open port array in macro NL_MAX_USED_PORT using
NL_BITS_FOR_PID, which is more flexible.
Additionnaly, a third macro NR_BITS is defined to get number of bits of
any structure.

Those macros are useful in port mask computation in order to ease
understanding of what is related with index in used_port_map table, and
the bitfield within an entry of this table.

Signed-off-by: Julien Courtat <julien.courtat at 6wind.com>
---
 include/netlink-private/socket.h |    5 +++++
 lib/nl.c                         |    2 +-
 lib/socket.c                     |   45 +++++++++++++++++++++-----------------
 3 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/include/netlink-private/socket.h b/include/netlink-private/socket.h
index 86a440c..62c7d4b 100644
--- a/include/netlink-private/socket.h
+++ b/include/netlink-private/socket.h
@@ -18,6 +18,11 @@
 extern "C" {
 #endif
 
+#define NL_BITS_FOR_PID 22
+/* there are 32 - NL_BITS_FOR_PID left for the port id per application,
+ * divided by 32 (>>5) to get used_port_map max table size */
+#define NL_MAX_USED_PORT (1 << (32 - NL_BITS_FOR_PID - 5))
+
 int _nl_socket_is_local_port_unspecified (struct nl_sock *sk);
 uint32_t _nl_socket_generate_local_port_no_release(struct nl_sock *sk);
 
diff --git a/lib/nl.c b/lib/nl.c
index 8fc9ec1..05fe29d 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -128,7 +128,7 @@ int nl_connect(struct nl_sock *sk, int protocol)
 
 	if (_nl_socket_is_local_port_unspecified (sk)) {
 		uint32_t port;
-		uint32_t used_ports[32] = { 0 };
+		uint32_t used_ports[NL_MAX_USED_PORT] = { 0 };
 
 		while (1) {
 			port = _nl_socket_generate_local_port_no_release(sk);
diff --git a/lib/socket.c b/lib/socket.c
index b29d1da..b1e9de9 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -41,6 +41,10 @@
 
 static int default_cb = NL_CB_DEFAULT;
 
+#define BIT(n)          (1 << (n))
+#define BIT_MASK(len)   (BIT(len) - 1)
+#define NR_BITS(t)      (8 * sizeof(t))
+
 static void __init init_default_cb(void)
 {
 	char *nlcb;
@@ -59,14 +63,14 @@ static void __init init_default_cb(void)
 	}
 }
 
-static uint32_t used_ports_map[32];
+static uint32_t used_ports_map[NL_MAX_USED_PORT];
 static NL_RW_LOCK(port_map_lock);
 
 static uint32_t generate_local_port(void)
 {
 	int i, j, n, m;
 	static uint16_t idx_state = 0;
-	uint32_t pid = getpid() & 0x3FFFFF;
+	uint32_t pid = getpid() & BIT_MASK(NL_BITS_FOR_PID);
 
 	nl_write_lock(&port_map_lock);
 
@@ -81,34 +85,35 @@ static uint32_t generate_local_port(void)
 
 	i = idx_state >> 5;
 	n = idx_state;
-	for (j = 0; j < 32; j++) {
+	for (j = 0; j < NL_MAX_USED_PORT; j++) {
 		/* walk the index somewhat randomized, with always leaving the block
 		 * #0 as last. The reason is that libnl-1 will start at block #0,
-		 * so just leave the first 32 ports preferably for libnl-1 owned sockets
+		 * so just leave the first NL_MAX_USED_PORT ports preferably for libnl-1 owned sockets
 		 * (this is relevant only if the applications ends up using both versions
 		 * of the library and doesn't hurt otherwise). */
-		if (j == 31)
+		if (j == NL_MAX_USED_PORT-1)
 			i = 0;
 		else
-			i = (((i-1) + 7) % 31) + 1;
+			i = (((i-1) + 7) % (NL_MAX_USED_PORT-1)) + 1;
 
 		if (used_ports_map[i] == 0xFFFFFFFF)
 			continue;
 
-		for (m = 0; m < 32; m++) {
-			n = (n + 13) % 32;
+		for (m = 0; m < NR_BITS(uint32_t); m++) {
+			n = (n + 13) % NR_BITS(uint32_t);
 			if (1UL & (used_ports_map[i] >> n))
 				continue;
 
 			used_ports_map[i] |= (1UL << n);
-			n += (i * 32);
+			n += (i * NR_BITS(uint32_t));
 
-			/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
-			 * to, i.e. 1024 unique ports per application. */
+			/* PID_MAX_LIMIT is currently at 2^NL_BITS_FOR_PID, leaving
+			 * (32 - NL_BITS_FOR_PID) bits to,
+			 * i.e. (32 - NL_BITS_FOR_PID)^2 unique ports per application. */
 
 			nl_write_unlock(&port_map_lock);
 
-			return pid + (((uint32_t)n) << 22);
+			return pid + (((uint32_t)n) << NL_BITS_FOR_PID);
 		}
 	}
 
@@ -129,9 +134,9 @@ static void release_local_port(uint32_t port)
 
 	BUG_ON(port == 0);
 
-	nr = port >> 22;
-	mask = 1UL << (nr % 32);
-	nr /= 32;
+	nr = port >> NL_BITS_FOR_PID;
+	mask = 1UL << (nr % NR_BITS(uint32_t));
+	nr /= NR_BITS(uint32_t);
 
 	nl_write_lock(&port_map_lock);
 	BUG_ON((used_ports_map[nr] & mask) != mask);
@@ -144,10 +149,10 @@ void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
 {
 	int i;
 
-	for (i = 0; i < 32; i++) {
+	for (i = 0; i < NL_MAX_USED_PORT; i++) {
 		if (used_ports[i] != 0) {
 			nl_write_lock(&port_map_lock);
-			for (; i < 32; i++) {
+			for (; i < NL_MAX_USED_PORT; i++) {
 				BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
 				used_ports_map[i] &= ~(used_ports[i]);
 			}
@@ -162,9 +167,9 @@ void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
 	int nr;
 	int32_t mask;
 
-	nr = port >> 22;
-	mask = 1UL << (nr % 32);
-	nr /= 32;
+	nr = port >> NL_BITS_FOR_PID;
+	mask = 1UL << (nr % NR_BITS(uint32_t));
+	nr /= NR_BITS(uint32_t);
 
 	/*
 	BUG_ON(port == UINT32_MAX || port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
-- 
1.7.10.4




More information about the libnl mailing list