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

SVN-Revision: 15400
This commit is contained in:
Felix Fietkau 2009-04-25 03:30:20 +00:00
parent 4898039703
commit 73883e9aef
2 changed files with 61 additions and 4 deletions

View file

@ -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)

View file

@ -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
@ -110,6 +114,51 @@ static struct t_server *ts = NULL;
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)
{
@ -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);
}