Hello,
Guus Sliepen, on Wed 02 Dec 2015 13:53:37 +0100, wrote:> That's great! It would be good though to split
> handle_incoming_vpn_data() into a function that does the actual
> recvfrom/mmsg() and one that processes each individual packet, to reduce
> the level of indentation and make the functions a bit more readable.
> Then I'll merge it :)
Here it is.
Samuel
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index 5cdd642..fcac9d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,7 +187,7 @@ AC_CHECK_TYPES([socklen_t, struct ether_header, struct
arphdr, struct ether_arp,
dnl Checks for library functions.
AC_TYPE_SIGNAL
-AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name
gettimeofday mlockall pselect putenv random select strdup strerror strsignal
strtol system unsetenv usleep vsyslog writev],
+AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name
gettimeofday mlockall pselect putenv random recvmmsg select strdup strerror
strsignal strtol system unsetenv usleep vsyslog writev],
[], [], [#include "src/have.h"]
)
diff --git a/src/net_packet.c b/src/net_packet.c
index e67857c..174db34 100644
--- a/src/net_packet.c
+++ b/src/net_packet.c
@@ -695,31 +695,26 @@ static node_t *try_harder(const sockaddr_t *from, const
vpn_packet_t *pkt) {
return n;
}
-void handle_incoming_vpn_data(int sock) {
- vpn_packet_t pkt;
+#ifdef HAVE_RECVMMSG
+#define MAX_MSG 256
+#else
+#define MAX_MSG 1
+#endif
+
+static void handle_incoming_vpn_packet(int sock, vpn_packet_t *pkt, sockaddr_t
*from) {
char *hostname;
- sockaddr_t from;
- socklen_t fromlen = sizeof(from);
node_t *n;
- pkt.len = recvfrom(listen_socket[sock].udp, (char *) &pkt.seqno, MAXSIZE,
0, &from.sa, &fromlen);
-
- if(pkt.len < 0) {
- if(!sockwouldblock(sockerrno))
- logger(LOG_ERR, "Receiving packet failed: %s",
sockstrerror(sockerrno));
- return;
- }
-
- sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid
things. */
+ sockaddrunmap(from); /* Some braindead IPv6 implementations do stupid things.
*/
- n = lookup_node_udp(&from);
+ n = lookup_node_udp(from);
if(!n) {
- n = try_harder(&from, &pkt);
+ n = try_harder(from, pkt);
if(n)
- update_node_udp(n, &from);
+ update_node_udp(n, from);
else ifdebug(PROTOCOL) {
- hostname = sockaddr2hostname(&from);
+ hostname = sockaddr2hostname(from);
logger(LOG_WARNING, "Received UDP packet from unknown source %s",
hostname);
free(hostname);
return;
@@ -730,5 +725,55 @@ void handle_incoming_vpn_data(int sock) {
n->sock = sock;
- receive_udppacket(n, &pkt);
+ receive_udppacket(n, pkt);
+}
+
+void handle_incoming_vpn_data(int sock) {
+ vpn_packet_t pkt[MAX_MSG];
+ sockaddr_t from[MAX_MSG];
+#ifdef HAVE_RECVMMSG
+ struct mmsghdr msg[MAX_MSG];
+ struct iovec iov[MAX_MSG];
+#else
+ socklen_t fromlen = sizeof(from[0]);
+#endif
+ int num = 1, i;
+
+#ifdef HAVE_RECVMMSG
+ for(i = 0; i < MAX_MSG; i++)
+ {
+ msg[i].msg_hdr.msg_name = &from[i].sa;
+ msg[i].msg_hdr.msg_namelen = sizeof(from[i]);
+ iov[i].iov_base = &pkt[i].seqno;
+ iov[i].iov_len = MAXSIZE;
+ msg[i].msg_hdr.msg_iov = &iov[i];
+ msg[i].msg_hdr.msg_iovlen = 1;
+ msg[i].msg_hdr.msg_control = NULL;
+ msg[i].msg_hdr.msg_controllen = 0;
+ }
+ num = recvmmsg(listen_socket[sock].udp, msg, MAX_MSG, MSG_DONTWAIT, NULL);
+#else
+ pkt[0].len = recvfrom(listen_socket[sock].udp, (char *) &pkt[0].seqno,
MAXSIZE, 0, &from[0].sa, &fromlen);
+#endif
+
+#ifdef HAVE_RECVMMSG
+ if(num < 0)
+#else
+ if(pkt[0].len < 0)
+#endif
+ {
+ if(!sockwouldblock(sockerrno))
+ logger(LOG_ERR, "Receiving packet failed: %s",
sockstrerror(sockerrno));
+ return;
+ }
+
+ for(i = 0; i < num; i++)
+ {
+#ifdef HAVE_RECVMMSG
+ pkt[i].len = msg[i].msg_len;
+ if(pkt[i].len <= 0 || pkt[i].len > MAXSIZE)
+ continue;
+#endif
+ handle_incoming_vpn_packet(sock, &pkt[i], &from[i]);
+ }
}