[PATCH 1/1] conntrack: use same mnl socket for bulk operations

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

 



For bulk ct entry loads (with -R option) reusing the same mnl socket
for all entries results in >1.5-time reduction of entries creation
time. This becomes signifficant when loading tens of thouthand of
entries.
E.g. in the tests performed with the tests/conntrack/bulk-load-stress.sh
the time used for loading of 131070 ct entries (2 * 0xffff)
was reduced from 1.06s to 0.7s when the same mnl socket was used.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@xxxxxxxxx>
---
 src/conntrack.c | 70 +++++++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index 679a1d2..b17ea5d 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -71,6 +71,7 @@
 struct nfct_mnl_socket {
 	struct mnl_socket	*mnl;
 	uint32_t		portid;
+	uint32_t		events;
 };
 
 static struct nfct_mnl_socket _sock;
@@ -2438,13 +2439,27 @@ static int nfct_mnl_socket_open(struct nfct_mnl_socket *socket,
 	}
 	if (mnl_socket_bind(socket->mnl, events, MNL_SOCKET_AUTOPID) < 0) {
 		perror("mnl_socket_bind");
+		mnl_socket_close(socket->mnl);
+		memset(socket, 0, sizeof(*socket));
 		return -1;
 	}
 	socket->portid = mnl_socket_get_portid(socket->mnl);
+	socket->events = events;
 
 	return 0;
 }
 
+static int nfct_mnl_socket_check_open(struct nfct_mnl_socket *socket,
+				       unsigned int events)
+{
+	if (socket->mnl != NULL) {
+		assert(events == socket->events);
+		return 0;
+	}
+
+	return nfct_mnl_socket_open(socket, events);
+}
+
 static struct nlmsghdr *
 nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type,
 		      uint16_t flags, uint8_t family)
@@ -2470,6 +2485,14 @@ static void nfct_mnl_socket_close(const struct nfct_mnl_socket *sock)
 	mnl_socket_close(sock->mnl);
 }
 
+static void nfct_mnl_socket_check_close(struct nfct_mnl_socket *sock)
+{
+	if (sock->mnl) {
+		nfct_mnl_socket_close(sock);
+		memset(sock, 0, sizeof(*sock));
+	}
+}
+
 static int __nfct_mnl_dump(struct nfct_mnl_socket *sock,
 			   const struct nlmsghdr *nlh, mnl_cb_t cb, void *data)
 {
@@ -3276,20 +3299,18 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 
 	switch(cmd->command) {
 	case CT_LIST:
-		if (nfct_mnl_socket_open(sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0)
 			exit_error(OTHER_PROBLEM, "Can't open handler");
 
 		if (cmd->type == CT_TABLE_DYING) {
 			res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
 					    IPCTNL_MSG_CT_GET_DYING,
 					    mnl_nfct_dump_cb, cmd, NULL);
-			nfct_mnl_socket_close(sock);
 			break;
 		} else if (cmd->type == CT_TABLE_UNCONFIRMED) {
 			res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
 					    IPCTNL_MSG_CT_GET_UNCONFIRMED,
 					    mnl_nfct_dump_cb, cmd, NULL);
-			nfct_mnl_socket_close(sock);
 			break;
 		}
 
@@ -3334,7 +3355,6 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 			fflush(stdout);
 		}
 
-		nfct_mnl_socket_close(sock);
 		break;
 
 	case EXP_LIST:
@@ -3365,7 +3385,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 			nfct_set_attr(cmd->tmpl.ct, ATTR_CONNLABELS,
 					xnfct_bitmask_clone(cmd->tmpl.label_modify));
 
-		res = nfct_mnl_socket_open(sock, 0);
+		res = nfct_mnl_socket_check_open(sock, 0);
 		if (res < 0)
 			exit_error(OTHER_PROBLEM, "Can't open netlink socket");
 
@@ -3376,7 +3396,6 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		if (res >= 0)
 			counter++;
 
-		nfct_mnl_socket_close(sock);
 		break;
 
 	case EXP_CREATE:
@@ -3393,8 +3412,8 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		break;
 
 	case CT_UPDATE:
-		if (nfct_mnl_socket_open(sock, 0) < 0 ||
-		    nfct_mnl_socket_open(modifier_sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0 ||
+		    nfct_mnl_socket_check_open(modifier_sock, 0) < 0)
 			exit_error(OTHER_PROBLEM, "Can't open handler");
 
 		nfct_filter_init(cmd);
@@ -3402,13 +3421,11 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 				    IPCTNL_MSG_CT_GET, mnl_nfct_update_cb,
 				    cmd, NULL);
 
-		nfct_mnl_socket_close(modifier_sock);
-		nfct_mnl_socket_close(sock);
 		break;
 
 	case CT_DELETE:
-		if (nfct_mnl_socket_open(sock, 0) < 0 ||
-		    nfct_mnl_socket_open(modifier_sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0 ||
+		    nfct_mnl_socket_check_open(modifier_sock, 0) < 0)
 			exit_error(OTHER_PROBLEM, "Can't open handler");
 
 		nfct_filter_init(cmd);
@@ -3432,8 +3449,6 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 
 		nfct_filter_dump_destroy(filter_dump);
 
-		nfct_mnl_socket_close(modifier_sock);
-		nfct_mnl_socket_close(sock);
 		break;
 
 	case EXP_DELETE:
@@ -3470,14 +3485,13 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		break;
 
 	case CT_FLUSH:
-		res = nfct_mnl_socket_open(sock, 0);
+		res = nfct_mnl_socket_check_open(sock, 0);
 		if (res < 0)
 			exit_error(OTHER_PROBLEM, "Can't open netlink socket");
 
 		res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
 				       IPCTNL_MSG_CT_DELETE, NLM_F_ACK, NULL, NULL);
 
-		nfct_mnl_socket_close(sock);
 		fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION);
 		fprintf(stderr,"connection tracking table has been emptied.\n");
 		break;
@@ -3503,9 +3517,9 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 			if (cmd->event_mask & CT_EVENT_F_DEL)
 				nl_events |= NF_NETLINK_CONNTRACK_DESTROY;
 
-			res = nfct_mnl_socket_open(sock, nl_events);
+			res = nfct_mnl_socket_check_open(sock, nl_events);
 		} else {
-			res = nfct_mnl_socket_open(sock,
+			res = nfct_mnl_socket_check_open(sock,
 						   NF_NETLINK_CONNTRACK_NEW |
 						   NF_NETLINK_CONNTRACK_UPDATE |
 						   NF_NETLINK_CONNTRACK_DESTROY);
@@ -3563,7 +3577,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 			}
 			res = mnl_cb_run(buf, res, 0, 0, event_cb, cmd);
 		}
-		mnl_socket_close(sock->mnl);
+		nfct_mnl_socket_check_close(sock);
 		break;
 
 	case EXP_EVENT:
@@ -3597,15 +3611,12 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		/* If we fail with netlink, fall back to /proc to ensure
 		 * backward compatibility.
 		 */
-		if (nfct_mnl_socket_open(sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0)
 			goto try_proc_count;
 
 		res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, AF_UNSPEC,
 				       IPCTNL_MSG_CT_GET_STATS, 0,
 				       nfct_global_stats_cb, NULL);
-
-		nfct_mnl_socket_close(sock);
-
 		/* don't look at /proc, we got the information via ctnetlink */
 		if (res >= 0)
 			break;
@@ -3642,15 +3653,12 @@ try_proc_count:
 		/* If we fail with netlink, fall back to /proc to ensure
 		 * backward compatibility.
 		 */
-		if (nfct_mnl_socket_open(sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0)
 			goto try_proc;
 
 		res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
 				    IPCTNL_MSG_CT_GET_STATS_CPU,
 				    nfct_stats_cb, NULL, NULL);
-
-		nfct_mnl_socket_close(sock);
-
 		/* don't look at /proc, we got the information via ctnetlink */
 		if (res >= 0)
 			break;
@@ -3661,15 +3669,12 @@ try_proc_count:
 		/* If we fail with netlink, fall back to /proc to ensure
 		 * backward compatibility.
 		 */
-		if (nfct_mnl_socket_open(sock, 0) < 0)
+		if (nfct_mnl_socket_check_open(sock, 0) < 0)
 			goto try_proc;
 
 		res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK_EXP,
 				    IPCTNL_MSG_EXP_GET_STATS_CPU,
 				    nfexp_stats_cb, NULL, NULL);
-
-		nfct_mnl_socket_close(sock);
-
 		/* don't look at /proc, we got the information via ctnetlink */
 		if (res >= 0)
 			break;
@@ -3931,5 +3936,8 @@ int main(int argc, char *argv[])
 		free(cmd);
 	}
 
+	nfct_mnl_socket_check_close(&_modifier_sock);
+	nfct_mnl_socket_check_close(&_sock);
+
 	return res < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
-- 
2.25.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux