summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-04-25 03:30:20 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-04-25 03:30:20 +0000
commitedc8d2dd343d3b2afa4a811045a4197388c63e2d (patch)
tree65d72a18ad8ada321bdf9e0accfd57af3a31fd84
parentbcbafeb95a52849329d021ad1d375a2b40dd0d6d (diff)
ead: use the new pcap features and the raw socket optimization to eliminate most of the cpu utilization overhead caused by the use of pcap live capturing
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15400 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/ead/Makefile3
-rw-r--r--package/ead/src/ead.c62
2 files changed, 61 insertions, 4 deletions
diff --git a/package/ead/Makefile b/package/ead/Makefile
index 0ecff2a8e..958577ff9 100644
--- a/package/ead/Makefile
+++ b/package/ead/Makefile
@@ -11,8 +11,10 @@ PKG_NAME:=ead
PKG_RELEASE:=1
PKG_BUILD_DEPENDS:=libpcap
+PKG_BUILD_DIR:=$(BUILD_DIR)/ead
include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
define Package/ead
SECTION:=net
@@ -29,6 +31,7 @@ endef
CONFIGURE_PATH = tinysrp
TARGET_CFLAGS += \
+ -I$(LINUX_DIR)/include \
-I$(PKG_BUILD_DIR) \
-I$(PKG_BUILD_DIR)/tinysrp \
$(TARGET_CPPFLAGS)
diff --git a/package/ead/src/ead.c b/package/ead/src/ead.c
index 9ce6f5691..36235207b 100644
--- a/package/ead/src/ead.c
+++ b/package/ead/src/ead.c
@@ -42,6 +42,10 @@
#include "libbridge_init.c"
#endif
+#ifdef linux
+#include <linux/if_packet.h>
+#endif
+
#define PASSWD_FILE "/etc/passwd"
#ifndef DEFAULT_IFNAME
@@ -111,6 +115,51 @@ static struct t_num A, *B = NULL;
unsigned char *skey;
static void
+set_recv_type(pcap_t *p, bool rx)
+{
+#ifdef PACKET_RECV_TYPE
+ struct sockaddr_ll sll;
+ struct ifreq ifr;
+ int ifindex, mask;
+ int fd, ret;
+
+ fd = pcap_get_selectable_fd(p);
+ if (fd < 0)
+ return;
+
+ if (rx)
+ mask = 1 << PACKET_BROADCAST;
+ else
+ mask = 0;
+
+ ret = setsockopt(fd, SOL_PACKET, PACKET_RECV_TYPE, &mask, sizeof(mask));
+#endif
+}
+
+
+static pcap_t *
+ead_open_pcap(const char *ifname, char *errbuf, bool rx)
+{
+ pcap_t *p;
+
+ p = pcap_create(ifname, errbuf);
+ if (p == NULL)
+ goto out;
+
+ pcap_set_snaplen(p, PCAP_MRU);
+ pcap_set_promisc(p, rx);
+ pcap_set_timeout(p, PCAP_TIMEOUT);
+#ifdef HAS_PROTO_EXTENSION
+ pcap_set_protocol(p, (rx ? htons(ETH_P_IP) : 0));
+#endif
+ pcap_set_buffer_size(p, (rx ? 10 : 1) * PCAP_MRU);
+ pcap_activate(p);
+ set_recv_type(p, rx);
+out:
+ return p;
+}
+
+static void
get_random_bytes(void *ptr, int len)
{
int fd;
@@ -647,14 +696,18 @@ ead_pcap_reopen(bool first)
pcap_fp_rx = NULL;
do {
- pcap_fp = pcap_open_live(instance->ifname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
#ifdef linux
- if (instance->bridge[0])
- pcap_fp_rx = pcap_open_live(instance->bridge, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
+ if (instance->bridge[0]) {
+ pcap_fp_rx = ead_open_pcap(instance->bridge, errbuf, 1);
+ pcap_fp = ead_open_pcap(instance->ifname, errbuf, 0);
+ } else
#endif
+ {
+ pcap_fp = ead_open_pcap(instance->ifname, errbuf, 1);
+ }
+
if (!pcap_fp_rx)
pcap_fp_rx = pcap_fp;
- pcap_setfilter(pcap_fp_rx, &pktfilter);
if (first && !pcap_fp) {
DEBUG(1, "WARNING: unable to open interface '%s'\n", instance->ifname);
first = false;
@@ -662,6 +715,7 @@ ead_pcap_reopen(bool first)
if (!pcap_fp)
sleep(1);
} while (!pcap_fp);
+ pcap_setfilter(pcap_fp_rx, &pktfilter);
}