summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordmitry pervushin <dmitry.pervushin@linaro.org>2013-04-22 20:58:38 +0200
committerdmitry pervushin <dmitry.pervushin@linaro.org>2013-04-24 21:25:43 +0200
commitf9c1d809cd9b78e6edeb4b2832deeb09b0f101ce (patch)
tree22d13f2e811876687f5ba656c6d2099c1fa13a60
parent888a139eb72e584f86f8ccb586ccb8be73120cc7 (diff)
downloadlinaro-android-kernel-test-f9c1d809cd9b78e6edeb4b2832deeb09b0f101ce.tar.gz
netfilter: idletimer testing
-rw-r--r--netfilter/Android.mk21
-rw-r--r--netfilter/ipt-idletimer.sh144
-rw-r--r--netfilter/nl.c193
-rw-r--r--product.mk4
4 files changed, 361 insertions, 1 deletions
diff --git a/netfilter/Android.mk b/netfilter/Android.mk
new file mode 100644
index 0000000..1906e7b
--- /dev/null
+++ b/netfilter/Android.mk
@@ -0,0 +1,21 @@
+
+#############################################################################
+# Copyright (c) 2013 Linaro
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Linaro <linaro-dev@lists.linaro.org>
+#############################################################################
+
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := nl.c
+LOCAL_MODULE := nl-listener
+LOCAL_MODULE_TAGS := optional tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/netfilter/ipt-idletimer.sh b/netfilter/ipt-idletimer.sh
new file mode 100644
index 0000000..fdc70bb
--- /dev/null
+++ b/netfilter/ipt-idletimer.sh
@@ -0,0 +1,144 @@
+#!/system/bin/sh
+
+mount -o rw,remount /
+mkdir -p /tmp
+
+IFACE=lo
+T=5
+LABEL=sample
+NLLOG=/tmp/nl.$$.log
+NLEXE=/system/bin/nl-listener
+
+function init_modules() {
+ PWD=`pwd`
+ cd /system/modules
+ insmod x_tables.ko
+ insmod ip_tables.ko
+ insmod iptable_filter.ko
+ insmod iptable_raw.ko
+ insmod xt_IDLETIMER.ko
+ cd $PWD
+}
+
+function init_iptables() {
+ iptables -F
+ iptables -t raw -F idletimer_PREROUTING
+ iptables -t raw -N idletimer_PREROUTING
+ iptables -t raw -D PREROUTING -j idletimer_PREROUTING
+ iptables -t raw -I PREROUTING -j idletimer_PREROUTING
+}
+
+function fail() {
+ rc=$1
+ shift
+ echo "FAIL: $*"
+ return $rc
+}
+
+function pass() {
+ echo "PASS: $*"
+ return 0
+}
+
+function note() {
+ echo "NOTE: $*"
+ return 0
+}
+
+function iptables_set() {
+ iptables -t raw -F
+ iptables -t raw -N idletimer_PREROUTING
+ iptables -t raw -A idletimer_PREROUTING -i $1 -j IDLETIMER --timeout $2 --label $3 $4
+ rc=$?
+ note "iptables_set: exit code $rc"
+ return $rc
+}
+
+function test_5() {
+
+ A="Xyz -1 17" # each value is incorrect
+
+ for a in $A; do
+ iptables_set $IFACE $T $LABEL "--send_nl_msg $a"
+ rc=$?
+ if [ $rc -eq 0 ]; then
+ fail $rc "iptables should fail on --send_nl_msg $a"
+ return $?
+ fi
+ done
+ pass $1
+}
+
+function test_1_2() {
+ #
+ # The idea of test is:
+ # 1. flush iptables rules
+ # 2. set rule to fire IDLETIMER after T seconds (with additional parameter, probably)
+ # 3. start listener with timeout of T+2 seconds
+ # 3a. do nothing for T seconds... DONE!
+ # 4. verify that:
+ # a. listener caught the event
+ # b. listener printed it with "OK" -- event was correct
+ # c. time between end and start of listener is no greater than T
+ # 5. print the log, just for reference
+ #
+
+ iptables_set $IFACE $T $LABEL "$2"
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ fail $rc "iptables failed"
+ return $?
+ fi
+
+ note "Waiting for event..."
+
+ T1=`date +%s`
+ $NLEXE "$3" --timeout $(($T+2)) > $NLLOG
+ rc=$?
+ T2=`date +%s`
+ if [ $rc -ne 0 ]; then
+ #
+ # for example, timeout
+ #
+ fail $rc "nl-listener failed"
+ return $?
+ fi
+ if [ `grep "^OK" $NLLOG | wc -l` -ne "1" ]; then
+ #
+ # No OK in the log? Fail!
+ #
+ fail -1 "No 'OK' in nl-listener output"
+ return $?
+ fi
+ if [ $(($T2-$T1)) -lt $(($T-1)) ]; then
+ #
+ # nl-listener garantees us that it will wait no longer than T+2
+ # now, check that delay was no shorter than T-1
+ #
+ fail -1 "Too short delay! $(($T2-$T1)) instead of $T"
+ return $rc
+ fi
+ note "nl-listener log is below"
+ echo "---===== listener log =====---"
+ cat $NLLOG
+ echo "---=====++++++++++++++=====---"
+ pass "$1"
+ return 0
+}
+
+note "Starting tests"
+
+init_modules
+init_iptables
+
+echo -e "\nTest 1: verify sysfs events"
+test_1_2 "Test 1" "" "--sysfs=$LABEL"
+echo -e "\nTest 2: verify netlink events"
+test_1_2 "Test 2" "--send_nl_msg 1" "--netlink"
+echo -e "\nTest 3: verify sysfs events even in case of --send-nl-msg 1"
+test_1_2 "Test 3" "--send_nl_msg 1" "--sysfs=$LABEL"
+echo -e "\nTest 4: verify sysfs events in case of --send_nl_msg 0"
+test_1_2 "Test 4" "--send_nl_msg 0" "--sysfs=$LABEL"
+echo -e "\nTest 5: verify parameters of send-nl-msg"
+test_5 "Test 5"
+exit 0
diff --git a/netfilter/nl.c b/netfilter/nl.c
new file mode 100644
index 0000000..ca71ca0
--- /dev/null
+++ b/netfilter/nl.c
@@ -0,0 +1,193 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <linux/netlink.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+
+enum type_t {
+ TYPE_SYSFS,
+ TYPE_NETLINK,
+};
+
+int dump(void *_a, size_t s)
+{
+ size_t i, j;
+ unsigned char *p = _a;
+
+ for (i = 0; i < s; i += 16) {
+ for (j = 0; j < 16; j ++ ) {
+ if (j == 8)
+ printf(" - ");
+ if (i + j > s) {
+ printf(" ");
+ } else {
+ printf("%c", (isprint(p[i+j])) ? p[i+j] : '.');
+ }
+ }
+ printf(" ");
+ for (j = 0; j < 16; j ++ ) {
+ if (j == 8)
+ printf(" - ");
+ printf("%02X ", p[i+j]);
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
+int sysfs_handle_open(char *name)
+{
+ char sysfs[256] = "/sys/devices/virtual/xt_idletimer/timers/";
+ char buffer[256];
+ int r, rd;
+
+ strcat(sysfs, name);
+ r = open(sysfs, O_RDONLY);
+ if (r < 0)
+ return r;
+ rd = read(r, buffer, sizeof(buffer));
+ return r;
+}
+
+#define sysfs_handle_close(h) close(h)
+
+int netlink_socket_open(struct sockaddr_nl *s_nladdr)
+{
+ int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ bind(fd, (struct sockaddr*)s_nladdr, sizeof(*s_nladdr));
+ return fd;
+}
+
+#define netlink_socket_close(h) close(h)
+
+int do_wait(char *nick, enum type_t type, int seconds)
+{
+ struct pollfd pfd;
+ int r;
+ short exp;
+ struct sockaddr_nl s_nladdr;
+ static char buffer[256];
+ char *ptr;
+
+ pfd.revents = 0;
+
+ if (type == TYPE_SYSFS) {
+
+ pfd.fd = sysfs_handle_open(nick);
+ pfd.events = POLLPRI | POLLERR;
+ exp = POLLPRI | POLLERR;
+
+ }
+
+ if (type == TYPE_NETLINK) {
+
+ memset(&s_nladdr, 0 ,sizeof(s_nladdr));
+ s_nladdr.nl_family = AF_NETLINK ;
+ s_nladdr.nl_pid = getpid();
+ s_nladdr.nl_groups = 0xffffffff;
+
+ pfd.fd = netlink_socket_open(&s_nladdr);
+ pfd.events = POLLIN;
+ exp = POLLIN;
+ }
+
+ r = poll(&pfd, 1, seconds * 1000);
+ if (r <= 0)
+ return r;
+
+ if (type == TYPE_NETLINK) {
+ struct msghdr msg;
+ struct iovec iov[2];
+ struct nlmsghdr nlh;
+
+ iov[0].iov_base = (void *)&nlh;
+ iov[0].iov_len = sizeof(nlh);
+ iov[1].iov_base = (void *)buffer;
+ iov[1].iov_len = sizeof(buffer);
+ msg.msg_name = &s_nladdr;
+ msg.msg_namelen = sizeof(s_nladdr);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
+ memset(buffer, 0, sizeof(buffer));
+
+ r = recvmsg(pfd.fd, &msg, 0);
+ } else {
+ lseek(pfd.fd, 0, SEEK_SET);
+ r = read(pfd.fd, buffer, sizeof(buffer));
+ }
+ if (r < 0)
+ return r;
+
+ for (ptr = buffer; ptr - buffer < r; ptr = ptr + strlen(ptr) + 1) {
+ if (strlen(ptr) == 0)
+ continue;
+ printf("%s\n", ptr);
+ }
+ return 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int c, r, opti;
+ int timeout_sec = 10;
+ struct option lopt[] = {
+ { "timeout", required_argument, NULL, 't' },
+ { "sysfs", required_argument, NULL, 's' },
+ { "netlink", no_argument, NULL, 'n' },
+ { NULL, 0, NULL, 0 },
+ };
+ char *shopt = "ts:n";
+ char *nick = NULL;
+ enum type_t type;
+
+ while ((c = getopt_long(argc, argv, shopt, lopt, &opti)) != -1 ) {
+ switch (c) {
+ case 't':
+ timeout_sec = atoi(optarg);
+ break;
+ case 's':
+ case 'n':
+ if (!nick) {
+ if (optarg) {
+ nick = strdup(optarg);
+ } else {
+ nick = (char*)0xffffffff;
+ }
+ type = (c == 's' ? TYPE_SYSFS : TYPE_NETLINK);
+ } else {
+ printf("sysfs and netlink could not be used at the same time\n");
+ exit(1);
+ }
+ break;
+ default:
+ printf("Hmmm, c = 0x%x (%c)\n", c, isprint(c) ? c : '*');
+ break;
+ }
+ }
+ if (!nick) {
+ printf("Sorry, you have to provide one of --sysfs=ARG or --netlink\n");
+ return EINVAL;
+ }
+
+ r = do_wait(nick, type, timeout_sec);
+ if (r < 0) {
+ perror("do_wait");
+ return r;
+ }
+ else if (r == 0) {
+ printf("No data within %d seconds\n", timeout_sec);
+ return 1;
+ }
+ printf("OK\n");
+ return 0;
+}
+
diff --git a/product.mk b/product.mk
index 35fcbf0..9867f2f 100644
--- a/product.mk
+++ b/product.mk
@@ -14,9 +14,11 @@ PRODUCT_PACKAGES += alarm-dev-test \
ashmemtest \
ashmemtest-expanded \
loggerdevtest \
- sync-basic
+ sync-basic \
+ nl-listener
PRODUCT_COPY_FILES += external/linaro-android-kernel-test/binder/bindertest.sh:system/bin/bindertest.sh
PRODUCT_COPY_FILES += external/linaro-android-kernel-test/linaro-android-kernel-tests.sh:system/bin/linaro-android-kernel-tests.sh
+PRODUCT_COPY_FILES += external/linaro-android-kernel-test/netfilter/ipt-idletimer.sh:system/bin/ipt-idletimer.sh
# put expanded ashmemtest in/out files on the device filesystem
PRODUCT_COPY_FILES += \