From 3bcd5ec746a5575c0c66f8b34922c038eb363b0a Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 19 Jul 2019 18:23:37 +0200 Subject: [PATCH] Reorganize structs for better packing and access patterns. Used the pahole tool to find gaps in structs. Move the lesser accessed members to the end of the struct. --- src/connection.h | 59 +++++++++++----------- src/edge.h | 8 +-- src/event.c | 2 - src/event.h | 22 ++++---- src/meshlink_internal.h | 109 ++++++++++++++++++++++------------------ src/net.h | 4 +- src/node.h | 87 +++++++++++++++++--------------- src/sptps.h | 23 ++++++--- 8 files changed, 168 insertions(+), 146 deletions(-) diff --git a/src/connection.h b/src/connection.h index d9e04f8c..27513e97 100644 --- a/src/connection.h +++ b/src/connection.h @@ -31,21 +31,15 @@ #define OPTION_VERSION(x) ((x) >> 24) /* Top 8 bits are for protocol minor version */ typedef struct connection_status_t { - unsigned int pinged: 1; /* sent ping */ - unsigned int active: 1; /* 1 if active.. */ - unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */ - unsigned int unused_termreq: 1; /* the termination of this connection was requested */ - unsigned int remove_unused: 1; /* Set to 1 if you want this connection removed */ - unsigned int timeout_unused: 1; /* 1 if gotten timeout */ - unsigned int unused_encryptout: 1; /* 1 if we can encrypt outgoing traffic */ - unsigned int unused_decryptin: 1; /* 1 if we have to decrypt incoming traffic */ - unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */ - unsigned int control: 1; /* 1 if this is a control connection */ - unsigned int pcap: 1; /* 1 if this is a control connection requesting packet capture */ - unsigned int log: 1; /* 1 if this is a control connection requesting log dump */ - unsigned int invitation: 1; /* 1 if this is an invitation */ - unsigned int invitation_used: 1; /* 1 if the invitation has been consumed */ - unsigned int unused: 19; + uint16_t pinged: 1; /* sent ping */ + uint16_t active: 1; /* 1 if active.. */ + uint16_t connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */ + uint16_t mst: 1; /* 1 if this connection is part of a minimum spanning tree */ + uint16_t control: 1; /* 1 if this is a control connection */ + uint16_t pcap: 1; /* 1 if this is a control connection requesting packet capture */ + uint16_t log: 1; /* 1 if this is a control connection requesting log dump */ + uint16_t invitation: 1; /* 1 if this is an invitation */ + uint16_t invitation_used: 1; /* 1 if the invitation has been consumed */ } connection_status_t; #include "ecdsa.h" @@ -56,34 +50,37 @@ typedef struct connection_status_t { typedef struct connection_t { char *name; /* name he claims to have */ + struct node_t *node; /* node associated with the other end */ - union sockaddr_t address; /* his real (internet) ip */ - int protocol_major; /* used protocol */ - int protocol_minor; /* used protocol */ - - int socket; /* socket used for this connection */ - uint32_t options; /* options for this connection */ connection_status_t status; /* status info */ - struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ + int socket; /* socket used for this connection */ + union sockaddr_t address; /* his real (internet) ip */ struct meshlink_handle *mesh; /* the mesh this connection belongs to */ - struct node_t *node; /* node associated with the other end */ - struct edge_t *edge; /* edge associated with this connection */ - ecdsa_t *ecdsa; /* his public ECDSA key */ + // I/O sptps_t sptps; - struct submesh_t *submesh; /* his submesh handle if available in invitation file */ - - int incompression; - int outcompression; - struct buffer_t inbuf; struct buffer_t outbuf; io_t io; /* input/output event on this metadata connection */ int tcplen; /* length of incoming TCPpacket */ int allow_request; /* defined if there's only one request possible */ - time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */ + + struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ + + struct edge_t *edge; /* edge associated with this connection */ + struct submesh_t *submesh; /* his submesh handle if available in invitation file */ + + // Only used during authentication + ecdsa_t *ecdsa; /* his public ECDSA key */ + int protocol_major; /* used protocol */ + int protocol_minor; /* used protocol */ + + // Unused/deprecated + uint32_t options; /* options for this connection */ + int incompression; + int outcompression; } connection_t; extern void init_connections(struct meshlink_handle *mesh); diff --git a/src/edge.h b/src/edge.h index cc7a449b..c86acee3 100644 --- a/src/edge.h +++ b/src/edge.h @@ -30,11 +30,13 @@ typedef struct edge_t { struct node_t *to; sockaddr_t address; - uint32_t options; /* options turned on for this edge */ - int weight; /* weight of this edge */ - struct connection_t *connection; /* connection associated with this edge, if available */ struct edge_t *reverse; /* edge in the opposite direction, if available */ + + int weight; /* weight of this edge */ + + // Deprecated + uint32_t options; /* options turned on for this edge */ } edge_t; extern void init_edges(struct meshlink_handle *mesh); diff --git a/src/event.c b/src/event.c index 3978c30b..61e6d8d7 100644 --- a/src/event.c +++ b/src/event.c @@ -181,11 +181,9 @@ static void pipe_init(event_loop_t *loop) { } void signal_trigger(event_loop_t *loop, signal_t *sig) { - uint8_t signum = sig->signum; write(loop->pipefd[1], &signum, 1); return; - } void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum) { diff --git a/src/event.h b/src/event.h index cf3c70a1..245656a3 100644 --- a/src/event.h +++ b/src/event.h @@ -35,46 +35,46 @@ typedef void (*signal_cb_t)(event_loop_t *loop, void *data); typedef struct timeval(*idle_cb_t)(event_loop_t *loop, void *data); typedef struct io_t { + struct splay_node_t node; int fd; int flags; io_cb_t cb; void *data; - struct splay_node_t node; } io_t; typedef struct timeout_t { + struct splay_node_t node; struct timeval tv; timeout_cb_t cb; void *data; - struct splay_node_t node; } timeout_t; typedef struct signal_t { + struct splay_node_t node; int signum; signal_cb_t cb; void *data; - struct splay_node_t node; } signal_t; struct event_loop_t { - fd_set readfds; - fd_set writefds; + void *data; volatile bool running; - struct timeval now; bool deletion; - splay_tree_t ios; - splay_tree_t timeouts; - splay_tree_t signals; + struct timeval now; + splay_tree_t timeouts; idle_cb_t idle_cb; void *idle_data; + splay_tree_t ios; + splay_tree_t signals; + + fd_set readfds; + fd_set writefds; io_t signalio; int pipefd[2]; - - void *data; }; extern void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int flags); diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index b31c16eb..c711aa57 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -35,7 +35,7 @@ #include -#define MAXSOCKETS 8 /* Probably overkill... */ +#define MAXSOCKETS 4 /* Probably overkill... */ static const char meshlink_invitation_label[] = "MeshLink invitation"; static const char meshlink_tcp_label[] = "MeshLink TCP"; @@ -78,43 +78,35 @@ struct meshlink_open_params { /// A handle for an instance of MeshLink. struct meshlink_handle { + // public members char *name; void *priv; - char *appname; - int32_t devclass; - - char *confbase; - FILE *conffile; - - meshlink_receive_cb_t receive_cb; - meshlink_node_status_cb_t node_status_cb; + // private members + pthread_mutex_t mesh_mutex; + event_loop_t loop; + struct node_t *self; meshlink_log_cb_t log_cb; meshlink_log_level_t log_level; - meshlink_channel_accept_cb_t channel_accept_cb; - meshlink_node_duplicate_cb_t node_duplicate_cb; - meshlink_connection_try_cb_t connection_try_cb; - - pthread_t thread; - bool threadstarted; - pthread_mutex_t mesh_mutex; - event_loop_t loop; - listen_socket_t listen_socket[MAXSOCKETS]; + // The most important network-related members come first int listen_sockets; + listen_socket_t listen_socket[MAXSOCKETS]; + + meshlink_receive_cb_t receive_cb; + meshlink_queue_t outpacketqueue; signal_t datafromapp; - struct node_t *self; + hash_t *node_udp_cache; - struct splay_tree_t *edges; struct splay_tree_t *nodes; + struct splay_tree_t *edges; struct list_t *connections; struct list_t *outgoings; struct list_t *submeshes; - meshlink_queue_t outpacketqueue; - + // Meta-connection-related members struct splay_tree_t *past_request_tree; timeout_t past_request_timeout; @@ -125,42 +117,46 @@ struct meshlink_handle { timeout_t pingtimer; timeout_t periodictimer; - char *myport; - - char *proxyhost; - char *proxyport; - char *proxyuser; - char *proxypass; - proxytype_t proxytype; + struct connection_t *everyone; - bool discovery; // Whether Catta is enabled or not - bool localdiscovery; - sockaddr_t localdiscovery_address; + // Infrequently used callbacks + meshlink_node_status_cb_t node_status_cb; + meshlink_channel_accept_cb_t channel_accept_cb; + meshlink_node_duplicate_cb_t node_duplicate_cb; + meshlink_connection_try_cb_t connection_try_cb; - bool default_blacklist; + // Mesh parameters + char *appname; + char *myport; - hash_t *node_udp_cache; - struct connection_t *everyone; struct ecdsa *private_key; struct ecdsa *invitation_key; - int invitation_timeout; + int32_t devclass; + + int invitation_timeout; int pinginterval; /* seconds between pings */ int pingtimeout; /* seconds to wait for response */ int maxtimeout; - int sock; - sptps_t sptps; - char cookie[18], hash[18]; - char *data; - size_t thedatalen; - bool success; - char line[4096]; - char buffer[4096]; - size_t blen; + int netns; - pthread_t discovery_thread; + bool default_blacklist; + bool discovery; // Whether Catta is enabled or not + + + // Configuration + char *confbase; + FILE *conffile; + void *config_key; + + // Thread management + pthread_t thread; + bool threadstarted; bool discovery_threadstarted; + + // Catta + pthread_t discovery_thread; struct CattaServer *catta_server; struct CattaSServiceBrowser *catta_browser; struct CattaSimplePoll *catta_poll; @@ -168,8 +164,25 @@ struct meshlink_handle { char *catta_servicetype; unsigned int catta_interfaces; - int netns; - void *config_key; + // State used for meshlink_join() + int sock; + char cookie[18], hash[18]; + bool success; + sptps_t sptps; + char *data; + size_t thedatalen; + size_t blen; + char line[4096]; + char buffer[4096]; + + // Unused variables + char *proxyhost; + char *proxyport; + char *proxyuser; + char *proxypass; + proxytype_t proxytype; + sockaddr_t localdiscovery_address; + bool localdiscovery; }; /// A handle for a MeshLink node. diff --git a/src/net.h b/src/net.h index 9277e6d9..6d27baf4 100644 --- a/src/net.h +++ b/src/net.h @@ -36,8 +36,8 @@ #define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) typedef struct vpn_packet_t { - unsigned int probe: 1; - unsigned int tcp: 1; + uint16_t probe: 1; + int16_t tcp: 1; uint16_t len; /* the actual number of bytes in the `data' field */ uint8_t data[MAXSIZE]; } vpn_packet_t; diff --git a/src/node.h b/src/node.h index 2568f182..f03afb25 100644 --- a/src/node.h +++ b/src/node.h @@ -27,45 +27,65 @@ #include "submesh.h" typedef struct node_status_t { - unsigned int unused_active: 1; /* 1 if active (not used for nodes) */ - unsigned int validkey: 1; /* 1 if we currently have a valid key for him */ - unsigned int waitingforkey: 1; /* 1 if we already sent out a request */ - unsigned int visited: 1; /* 1 if this node has been visited by one of the graph algorithms */ - unsigned int reachable: 1; /* 1 if this node is reachable in the graph */ - unsigned int indirect: 1; /* 1 if this node is not directly reachable by us */ - unsigned int unused_sptps: 1; /* 1 if this node supports SPTPS */ - unsigned int udp_confirmed: 1; /* 1 if the address is one that we received UDP traffic on */ - unsigned int broadcast: 1; /* 1 if the next UDP packet should be broadcast to the local network */ - unsigned int blacklisted: 1; /* 1 if the node is blacklist so we never want to speak with him anymore */ - unsigned int destroyed: 1; /* 1 if the node is being destroyed, deallocate channels when any callback is triggered */ - unsigned int duplicate: 1; /* 1 if the node is duplicate, ie. multiple nodes using the same Name are online */ - unsigned int dirty: 1; /* 1 if the configuration of the node is dirty and needs to be written out */ - unsigned int unused: 19; + uint16_t validkey: 1; /* 1 if we currently have a valid key for him */ + uint16_t waitingforkey: 1; /* 1 if we already sent out a request */ + uint16_t visited: 1; /* 1 if this node has been visited by one of the graph algorithms */ + uint16_t reachable: 1; /* 1 if this node is reachable in the graph */ + uint16_t indirect: 1; /* 1 if this node is not directly reachable by us */ + uint16_t udp_confirmed: 1; /* 1 if the address is one that we received UDP traffic on */ + uint16_t broadcast: 1; /* 1 if the next UDP packet should be broadcast to the local network */ + uint16_t blacklisted: 1; /* 1 if the node is blacklist so we never want to speak with him anymore */ + uint16_t destroyed: 1; /* 1 if the node is being destroyed, deallocate channels when any callback is triggered */ + uint16_t duplicate: 1; /* 1 if the node is duplicate, ie. multiple nodes using the same Name are online */ + uint16_t dirty: 1; /* 1 if the configuration of the node is dirty and needs to be written out */ } node_status_t; typedef struct node_t { + // Public member variables char *name; /* name of this node */ void *priv; - uint32_t options; /* options turned on for this node */ + // Private member variables + node_status_t status; + uint16_t minmtu; /* Probed minimum MTU */ int32_t devclass; - struct meshlink_handle *mesh; /* The mesh this node belongs to */ - struct submesh_t *submesh; /* Nodes Sub-Mesh Handle*/ - + // Used for packet I/O + sptps_t sptps; int sock; /* Socket to use for outgoing UDP packets */ sockaddr_t address; /* his real (internet) ip to send UDP packets to */ - node_status_t status; + struct utcp *utcp; + + // Traffic counters + uint64_t in_packets; + uint64_t in_bytes; + uint64_t out_packets; + uint64_t out_bytes; + + // MTU probes + timeout_t mtutimeout; /* Probe event */ + int mtuprobes; /* Number of probes */ + uint16_t mtu; /* Maximum size of packets to send to this node */ + uint16_t maxmtu; /* Probed maximum MTU */ + + // Used for meta-connection I/O, timeouts + struct meshlink_handle *mesh; /* The mesh this node belongs to */ + struct submesh_t *submesh; /* Nodes Sub-Mesh Handle*/ + time_t last_state_change; time_t last_req_key; struct ecdsa *ecdsa; /* His public ECDSA key */ - sptps_t sptps; - int incompression; /* Compressionlevel, 0 = no compression */ - int outcompression; /* Compressionlevel, 0 = no compression */ + struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ + time_t last_connect_try; + time_t last_successfull_connection; + char *canonical_address; /* The canonical address of this node, if known */ + sockaddr_t recent[5]; /* Recently seen addresses */ + + // Graph-related member variables int distance; struct node_t *nexthop; /* nearest node from us to him */ struct edge_t *prevedge; /* nearest node from him to us */ @@ -73,25 +93,10 @@ typedef struct node_t { struct splay_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ - struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ - time_t last_connect_try; - time_t last_successfull_connection; - - uint16_t mtu; /* Maximum size of packets to send to this node */ - uint16_t minmtu; /* Probed minimum MTU */ - uint16_t maxmtu; /* Probed maximum MTU */ - int mtuprobes; /* Number of probes */ - timeout_t mtutimeout; /* Probe event */ - - struct utcp *utcp; - - uint64_t in_packets; - uint64_t in_bytes; - uint64_t out_packets; - uint64_t out_bytes; - - char *canonical_address; /* The canonical address of this node, if known */ - sockaddr_t recent[5]; /* Recently seen addresses */ + // Unused + uint32_t options; /* options turned on for this node */ + int incompression; /* Compressionlevel, 0 = no compression */ + int outcompression; /* Compressionlevel, 0 = no compression */ } node_t; extern void init_nodes(struct meshlink_handle *mesh); diff --git a/src/sptps.h b/src/sptps.h index 11c0d2e6..d1e3607e 100644 --- a/src/sptps.h +++ b/src/sptps.h @@ -43,25 +43,35 @@ typedef bool (*send_data_t)(void *handle, uint8_t type, const void *data, size_t typedef bool (*receive_record_t)(void *handle, uint8_t type, const void *data, uint16_t len); typedef struct sptps { + // State bool initiator; bool datagram; + bool instate; + bool outstate; + int state; + // Main member variables char *inbuf; size_t buflen; - uint16_t reclen; - bool instate; chacha_poly1305_ctx_t *incipher; + uint32_t replaywin; uint32_t inseqno; uint32_t received; - unsigned int replaywin; - char *late; + uint16_t reclen; - bool outstate; chacha_poly1305_ctx_t *outcipher; uint32_t outseqno; + char *late; + + // Callbacks + void *handle; + send_data_t send_data; + receive_record_t receive_record; + + // Variables used for the authentication phase ecdsa_t *mykey; ecdsa_t *hiskey; ecdh_t *ecdh; @@ -72,9 +82,6 @@ typedef struct sptps { char *label; size_t labellen; - void *handle; - send_data_t send_data; - receive_record_t receive_record; } sptps_t; extern unsigned int sptps_replaywin; -- 2.39.2