diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-04-25 03:30:20 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-04-25 03:30:20 +0000 |
commit | edc8d2dd343d3b2afa4a811045a4197388c63e2d (patch) | |
tree | 65d72a18ad8ada321bdf9e0accfd57af3a31fd84 /package/ead/src | |
parent | bcbafeb95a52849329d021ad1d375a2b40dd0d6d (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
Diffstat (limited to 'package/ead/src')
-rw-r--r-- | package/ead/src/ead.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/package/ead/src/ead.c b/package/ead/src/ead.c index 9ce6f56911..36235207bc 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); } |