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