diff --git a/Makefile b/Makefile index f1a1bb0..d312368 100755 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ BIN=smartdns -OBJS=smartdns.o fast_ping.o -CFLAGS=-g -O0 -CFLAGS=-Iinclude +OBJS=smartdns.o fast_ping.o lib/bitops.o +CFLAGS=-g -O0 -Wall +CFLAGS +=-Iinclude +CXXFLAGS=-g -O0 -Wall -std=c++11 +CXXFLAGS +=-Iinclude .PHONY: all diff --git a/fast_ping.c b/fast_ping.c index 73b39aa..35f7eef 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -2,6 +2,7 @@ #include "atomic.h" #include "hashtable.h" #include +#include #include #include #include @@ -45,6 +46,10 @@ struct ping_host_struct { int fd; unsigned int seq; + struct timeval last; + int interval; + int timeout; + int send; struct sockaddr_storage addr; socklen_t addr_len; struct fast_ping_packet packet; @@ -54,7 +59,7 @@ struct fast_ping_struct { int run; pthread_t tid; pthread_mutex_t lock; - int ident; + unsigned short ident; int epoll_fd; int fd_icmp; @@ -82,7 +87,7 @@ uint16_t _fast_ping_checksum(uint16_t *header, size_t len) return htons(~((sum >> 16) + (sum & 0xffff))); } -int fast_ping_result_callback(fast_ping_result result) +void fast_ping_result_callback(fast_ping_result result) { ping_callback = result; } @@ -148,7 +153,7 @@ void _fast_ping_install_filter_v4(int sock) } } -static struct addrinfo *_fast_ping_getaddr(const u_char *host, int type, int protocol) +static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int protocol) { struct addrinfo hints; struct addrinfo *result = NULL; @@ -170,7 +175,7 @@ errout: return NULL; } -static int _fast_ping_getdomain(const u_char *host) +static int _fast_ping_getdomain(const char *host) { struct addrinfo hints; struct addrinfo *result = NULL; @@ -197,12 +202,12 @@ errout: return -1; } -int _fast_ping_host_get(struct ping_host_struct *ping_host) +static void _fast_ping_host_get(struct ping_host_struct *ping_host) { atomic_inc(&ping_host->ref); } -int _fast_ping_host_put(struct ping_host_struct *ping_host) +static void _fast_ping_host_put(struct ping_host_struct *ping_host) { pthread_mutex_lock(&ping.map_lock); if (atomic_dec_and_test(&ping_host->ref)) { @@ -214,7 +219,7 @@ int _fast_ping_host_put(struct ping_host_struct *ping_host) pthread_mutex_unlock(&ping.map_lock); if (ping_host == NULL) { - return -1; + return ; } free(ping_host); @@ -280,34 +285,48 @@ errout: static int _fast_ping_sendping(struct ping_host_struct *ping_host) { + int ret = -1; + if (ping_host->type == AF_INET) { - return _fast_ping_sendping_v4(ping_host); + ret = _fast_ping_sendping_v4(ping_host); } else if (ping_host->type == AF_INET6) { - return _fast_ping_sendping_v6(ping_host); + ret = _fast_ping_sendping_v6(ping_host); } - return -1; + if (ret != 0) { + return ret; + } + + ping_host->send = 1; + gettimeofday(&ping_host->last, 0); + + return 0; } static int _fast_ping_create_sock(int protocol) { - int fd; + int fd = -1; struct ping_host_struct *icmp_host = NULL; struct epoll_event event; - fd = socket(AF_INET, SOCK_RAW, protocol); - if (fd < 0) { - fprintf(stderr, "create icmp socket failed.\n"); - goto errout; - } switch (protocol) { case IPPROTO_ICMP: + fd = socket(AF_INET, SOCK_RAW, protocol); + if (fd < 0) { + fprintf(stderr, "create icmp socket failed.\n"); + goto errout; + } _fast_ping_install_filter_v4(fd); icmp_host = &ping.icmp_host; break; case IPPROTO_ICMPV6: + fd = socket(AF_INET6, SOCK_RAW, protocol); + if (fd < 0) { + fprintf(stderr, "create icmp socket failed.\n"); + goto errout; + } _fast_ping_install_filter_v6(fd); - icmp_host = &ping.icmp_host; + icmp_host = &ping.icmp6_host; break; } @@ -371,7 +390,6 @@ int fast_ping_start(const char *host, int timeout, void *userptr) struct addrinfo *gai = NULL; int domain = -1; int icmp_proto = 0; - char ip[PING_MAX_HOSTLEN]; uint32_t hostkey; uint32_t addrkey; @@ -402,17 +420,20 @@ int fast_ping_start(const char *host, int timeout, void *userptr) goto errout; } - memset(ping_host, 0, sizeof(ping_host)); + int interval = 1000; + memset(ping_host, 0, sizeof(*ping_host)); strncpy(ping_host->host, host, PING_MAX_HOSTLEN); ping_host->type = domain; ping_host->fd = _fast_ping_create_icmp(icmp_proto); + ping_host->timeout = timeout; + ping_host->interval = interval; memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen); ping_host->addr_len = gai->ai_addrlen; atomic_set(&ping_host->ref, 0); hostkey = hash_string(ping_host->host); - addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0); + addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0); pthread_mutex_lock(&ping.map_lock); _fast_ping_host_get(ping_host); hash_add(ping.hostmap, &ping_host->host_node, hostkey); @@ -467,12 +488,10 @@ void tv_sub(struct timeval *out, struct timeval *in) static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv) { - int hlen; int icmp_len; struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data; struct icmp6_hdr *icmp6 = &packet->icmp6; struct timeval tvresult = *tvrecv; - double rtt; if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { return -1; @@ -489,7 +508,7 @@ static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *p struct timeval *tvsend = &packet->msg.tv; tv_sub(&tvresult, tvsend); - ping_callback(ping_host->host, ping_host->seq, &tvresult, ping_host->userptr); + ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr); return 0; } @@ -527,7 +546,7 @@ static int _fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *pa struct timeval *tvsend = &packet->msg.tv; tv_sub(&tvresult, tvsend); - ping_callback(ping_host->host, ping_host->seq, &tvresult, ping_host->userptr); + ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr); return 0; } @@ -551,14 +570,7 @@ errout: return -1; } -static int _fast_ping_create_tcp(struct ping_host_struct *ping_host) -{ - return -1; -} - -static int _fast_ping_ping_host(struct ping_host_struct *ping_host) {} - -static int _fast_ping_gethost_by_addr(u_char *host, struct sockaddr *addr, socklen_t addr_len) +static int _fast_ping_gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len) { struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr; host[0] = 0; @@ -603,7 +615,7 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval goto errout; } - addrkey = jhash(&from, from_len, 0); + addrkey = jhash(&from, from_len, 0); pthread_mutex_lock(&ping.map_lock); hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey) { @@ -617,6 +629,8 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval return -1; } + recv_ping_host->send = 0; + _fast_ping_recvping(recv_ping_host, inpacket, len, now); return 0; errout: @@ -628,10 +642,24 @@ static void _fast_ping_period_run() struct ping_host_struct *ping_host; struct hlist_node *tmp; int i = 0; + struct timeval now; + struct timeval interval; + uint64_t millisecond; + gettimeofday(&now, 0); + pthread_mutex_lock(&ping.map_lock); hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node) { - _fast_ping_sendping(ping_host); + interval = now; + tv_sub(&interval, &ping_host->last); + millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000; + if (millisecond > ping_host->timeout && ping_host->send == 1) { + ping_callback(ping_host->host, PING_RESULT_TIMEOUT, ping_host->seq, &interval, ping_host->userptr); + ping_host->send = 0; + } + if (millisecond >= ping_host->interval) { + _fast_ping_sendping(ping_host); + } } pthread_mutex_unlock(&ping.map_lock); } @@ -643,14 +671,19 @@ static void *_fast_ping_work(void *arg) int i; struct timeval last = { 0 }; struct timeval now = { 0 }; + struct timeval diff = {0}; + uint millisec = 0; while (ping.run) { - if (last.tv_sec != now.tv_sec) { + diff = now; + tv_sub(&diff, &last); + millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; + if (millisec >= 100) { _fast_ping_period_run(); last = now; } - num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 1000); + num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 100); if (num < 0) { gettimeofday(&now, 0); usleep(100000); @@ -727,7 +760,7 @@ errout: return -1; } -int fast_ping_exit() +void fast_ping_exit() { if (ping.tid > 0) { void *ret = NULL; @@ -737,12 +770,12 @@ int fast_ping_exit() if (ping.fd_icmp > 0) { close(ping.fd_icmp); - ping.fd_icmp < 0; + ping.fd_icmp = -1; } if (ping.fd_icmp6 > 0) { close(ping.fd_icmp6); - ping.fd_icmp6 < 0; + ping.fd_icmp6 = -1; } pthread_mutex_destroy(&ping.lock); diff --git a/fast_ping.h b/fast_ping.h index 9220d7d..ac9a41c 100755 --- a/fast_ping.h +++ b/fast_ping.h @@ -13,8 +13,13 @@ typedef enum { FAST_PING_UDP } FAST_PING_TYPE; -typedef void (*fast_ping_result)(const char *host, int seqno, struct timeval *tv, void *userptr); -int fast_ping_result_callback(fast_ping_result result); +typedef enum { + PING_RESULT_RESPONSE = 1, + PING_RESULT_TIMEOUT = 2, +} FAST_PING_RESULT; + +typedef void (*fast_ping_result)(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr); +void fast_ping_result_callback(fast_ping_result result); int fast_ping_start(const char *host, int timeout, void *userptr); @@ -22,7 +27,7 @@ int fast_ping_stop(const char *host); int fast_ping_init(); -int fast_ping_exit(); +void fast_ping_exit(); #ifdef __cpluscplus } diff --git a/include/atomic.h b/include/atomic.h index c82f5d3..2249b39 100755 --- a/include/atomic.h +++ b/include/atomic.h @@ -2,6 +2,7 @@ #ifndef _GENERIC_ATOMIC_H #define _GENERIC_ATOMIC_H + /* Check GCC version, just to be safe */ #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1) # error atomic.h works only with GCC newer than version 4.1 diff --git a/include/bitmap.h b/include/bitmap.h index 8170981..48c2cda 100644 --- a/include/bitmap.h +++ b/include/bitmap.h @@ -5,6 +5,8 @@ #include #include #include "bitops.h" +#include "findbit.h" + #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] @@ -101,7 +103,7 @@ static inline int test_and_set_bit(int nr, unsigned long *addr) */ static inline unsigned long *bitmap_alloc(int nbits) { - return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); + return (unsigned long *)calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); } /* diff --git a/include/bitops.h b/include/bitops.h index 8fb2e93..b33d7b3 100644 --- a/include/bitops.h +++ b/include/bitops.h @@ -2,6 +2,10 @@ #ifndef _GENERIC_BITOPS_H_ #define _GENERIC_BITOPS_H_ +#include +#include +#include "gcc_builtin.h" + #ifndef __WORDSIZE #define __WORDSIZE (__SIZEOF_LONG__ * 8) #endif @@ -24,6 +28,164 @@ extern unsigned int __sw_hweight32(unsigned int w); extern unsigned long __sw_hweight64(uint64_t w); +#define ffz(x) __ffs(~(x)) + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + +#if __BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +static inline int fls(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000u)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) { + x <<= 1; + r -= 1; + } + return r; +} + +/** + * fls64 - find last set bit in a 64-bit word + * @x: the word to search + * + * This is defined in a similar way as the libc and compiler builtin + * ffsll, but returns the position of the most significant set bit. + * + * fls64(value) returns 0 if value is 0 or the position of the last + * set bit if value is nonzero. The last (most significant) bit is + * at position 64. + */ +#if BITS_PER_LONG == 32 +static inline int fls64(uint64_t x) +{ + uint32_t h = x >> 32; + if (h) + return fls(h) + 32; + return fls(x); +} +#elif BITS_PER_LONG == 64 +static inline int fls64(uint64_t x) +{ + if (x == 0) + return 0; + return __fls(x) + 1; +} +#else +#error BITS_PER_LONG not 32 or 64 +#endif + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +static inline unsigned int hweight32(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return (res + (res >> 16)) & 0x000000FF; +} + +static inline unsigned int hweight16(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x5555); + res = (res & 0x3333) + ((res >> 2) & 0x3333); + res = (res + (res >> 4)) & 0x0F0F; + return (res + (res >> 8)) & 0x00FF; +} + +static inline unsigned int hweight8(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res + (res >> 4)) & 0x0F; +} + +static inline unsigned long hweight64(uint64_t w) +{ +#if BITS_PER_LONG == 32 + return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); +#elif BITS_PER_LONG == 64 +#ifdef ARCH_HAS_FAST_MULTIPLIER + w -= (w >> 1) & 0x5555555555555555ul; + w = (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul); + w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful; + return (w * 0x0101010101010101ul) >> 56; +#else + uint64_t res = w - ((w >> 1) & 0x5555555555555555ul); + res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); + res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful; + res = res + (res >> 8); + res = res + (res >> 16); + return (res + (res >> 32)) & 0x00000000000000FFul; +#endif +#endif +} + #define for_each_set_bit(bit, addr, size) \ for ((bit) = find_first_bit((addr), (size)); \ (bit) < (size); \ diff --git a/include/findbit.h b/include/findbit.h new file mode 100644 index 0000000..cac0939 --- /dev/null +++ b/include/findbit.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ +#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ + +#ifndef find_next_bit +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The bitmap size in bits + * + * Returns the bit number for the next set bit + * If no bits are set, returns @size. + */ +extern unsigned long find_next_bit(const unsigned long *addr, unsigned long + size, unsigned long offset); +#endif + +#ifndef find_next_and_bit +/** + * find_next_and_bit - find the next set bit in both memory regions + * @addr1: The first address to base the search on + * @addr2: The second address to base the search on + * @offset: The bitnumber to start searching at + * @size: The bitmap size in bits + * + * Returns the bit number for the next set bit + * If no bits are set, returns @size. + */ +extern unsigned long find_next_and_bit(const unsigned long *addr1, + const unsigned long *addr2, unsigned long size, + unsigned long offset); +#endif + +#ifndef find_next_zero_bit + +/** + * find_next_zero_bit - find the next cleared bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The bitmap size in bits + * + * Returns the bit number of the next zero bit + * If no bits are zero, returns @size. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset); +#endif + +#ifndef find_first_bit + +/** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum number of bits to search + * + * Returns the bit number of the first set bit. + * If no bits are set, returns @size. + */ +extern unsigned long find_first_bit(const unsigned long *addr, + unsigned long size); + +#endif /* find_first_bit */ + +#ifndef find_first_zero_bit + +/** + * find_first_zero_bit - find the first cleared bit in a memory region + * @addr: The address to start the search at + * @size: The maximum number of bits to search + * + * Returns the bit number of the first cleared bit. + * If no bits are zero, returns @size. + */ +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); +#endif + +#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */ \ No newline at end of file diff --git a/include/gcc_builtin.h b/include/gcc_builtin.h new file mode 100644 index 0000000..366813b --- /dev/null +++ b/include/gcc_builtin.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _TOOLS_LINUX_COMPILER_H_ +#define _TOOLS_LINUX_COMPILER_H_ + +#ifndef __compiletime_error +# define __compiletime_error(message) +#endif + +/* Optimization barrier */ +/* The "volatile" is due to gcc bugs */ +#define barrier() __asm__ __volatile__("": : :"memory") + +#ifndef __always_inline +# define __always_inline inline __attribute__((always_inline)) +#endif + +#ifndef noinline +#define noinline +#endif + +/* Are two types/vars the same type (ignoring qualifiers)? */ +#ifndef __same_type +# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +#endif + +#ifdef __ANDROID__ +/* + * FIXME: Big hammer to get rid of tons of: + * "warning: always_inline function might not be inlinable" + * + * At least on android-ndk-r12/platforms/android-24/arch-arm + */ +#undef __always_inline +#define __always_inline inline +#endif + +#define __user +#define __rcu +#define __read_mostly + +#ifndef __attribute_const__ +# define __attribute_const__ +#endif + +#ifndef __maybe_unused +# define __maybe_unused __attribute__((unused)) +#endif + +#ifndef __used +# define __used __attribute__((__unused__)) +#endif + +#ifndef __packed +# define __packed __attribute__((__packed__)) +#endif + +#ifndef __force +# define __force +#endif + +#ifndef __weak +# define __weak __attribute__((weak)) +#endif + +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef unlikely +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif + +#ifndef __init +# define __init +#endif + +#ifndef noinline +# define noinline +#endif + +#define uninitialized_var(x) x = *(&(x)) + +#ifndef __fallthrough +# define __fallthrough +#endif + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + +#ifndef max +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) +#endif + +#ifndef min +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) +#endif + +#ifndef roundup +#define roundup(x, y) ( \ +{ \ + const typeof(y) __y = y; \ + (((x) + (__y - 1)) / __y) * __y; \ +} \ +) +#endif + +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +#endif /* _TOOLS_LINUX_COMPILER_H */ \ No newline at end of file diff --git a/include/hash.h b/include/hash.h index 6d0b4ac..85ff038 100644 --- a/include/hash.h +++ b/include/hash.h @@ -1,6 +1,7 @@ #ifndef _GENERIC_HASH_H #define _GENERIC_HASH_H +#include "bitmap.h" #include "jhash.h" /* Fast hashing routine for ints, longs and pointers. @@ -113,6 +114,17 @@ int __ilog2_u64(uint64_t n) __ilog2_u64(n) \ ) + +#if BITS_PER_LONG == 32 +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32 +#define hash_long(val, bits) hash_32(val, bits) +#elif BITS_PER_LONG == 64 +#define hash_long(val, bits) hash_64(val, bits) +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64 +#else +#error Wordsize not 32 or 64 +#endif + /* * This hash multiplies the input by a large odd number and takes the * high bits. Since multiplication propagates changes to the most diff --git a/include/hashtable.h b/include/hashtable.h index 068070f..2823192 100644 --- a/include/hashtable.h +++ b/include/hashtable.h @@ -9,7 +9,6 @@ #include "list.h" #include "hash.h" -#include "bitmap.h" #ifndef __same_type # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) @@ -149,5 +148,4 @@ static inline void hash_del(struct hlist_node *node) hlist_for_each_entry_safe(obj, tmp,\ &name[hash_min(key, HASH_BITS(name))], member) - #endif \ No newline at end of file diff --git a/include/jhash.h b/include/jhash.h index bd03005..3dfcc6e 100644 --- a/include/jhash.h +++ b/include/jhash.h @@ -79,7 +79,7 @@ static inline uint32_t __get_unaligned_cpu32(const void *p) static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval) { uint32_t a, b, c; - const uint8_t *k = key; + const uint8_t *k = (uint8_t *)key; /* Set up the internal state */ a = b = c = JHASH_INITVAL + length + initval; diff --git a/include/list.h b/include/list.h index 4aa9a43..f122411 100644 --- a/include/list.h +++ b/include/list.h @@ -60,46 +60,46 @@ static inline void INIT_LIST_HEAD(struct list_head *list) } /* - * Insert a new entry between two known consecutive entries. + * Insert a add entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_add(struct list_head *new, +static inline void __list_add(struct list_head *add, struct list_head *prev, struct list_head *next) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; + next->prev = add; + add->next = next; + add->prev = prev; + prev->next = add; } /** - * list_add - add a new entry - * @new: new entry to be added + * list_add - add a add entry + * @add: add entry to be added * @head: list head to add it after * - * Insert a new entry after the specified head. + * Insert a add entry after the specified head. * This is good for implementing stacks. */ -static inline void list_add(struct list_head *new, struct list_head *head) +static inline void list_add(struct list_head *add, struct list_head *head) { - __list_add(new, head, head->next); + __list_add(add, head, head->next); } /** - * list_add_tail - add a new entry - * @new: new entry to be added + * list_add_tail - add a add entry + * @add: add entry to be added * @head: list head to add it before * - * Insert a new entry before the specified head. + * Insert a add entry before the specified head. * This is useful for implementing queues. */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) +static inline void list_add_tail(struct list_head *add, struct list_head *head) { - __list_add(new, head->prev, head); + __list_add(add, head->prev, head); } /* @@ -129,30 +129,30 @@ static inline void __list_del_entry(struct list_head *entry) static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; + entry->next = (struct list_head *)LIST_POISON1; + entry->prev = (struct list_head *)LIST_POISON2; } /** - * list_replace - replace old entry by new one + * list_replace - replace old entry by add one * @old : the element to be replaced - * @new : the new element to insert + * @add : the add element to insert * * If @old was empty, it will be overwritten. */ static inline void list_replace(struct list_head *old, - struct list_head *new) + struct list_head *add) { - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; + add->next = old->next; + add->next->prev = add; + add->prev = old->prev; + add->prev->next = add; } static inline void list_replace_init(struct list_head *old, - struct list_head *new) + struct list_head *add) { - list_replace(old, new); + list_replace(old, add); INIT_LIST_HEAD(old); } @@ -265,7 +265,7 @@ static inline void __list_cut_position(struct list_head *list, /** * list_cut_position - cut a list into two - * @list: a new list to add all removed entries + * @list: a add list to add all removed entries * @head: a list with entries * @entry: an entry within head, could be the head itself * and if so we won't cut the list @@ -307,7 +307,7 @@ static inline void __list_splice(const struct list_head *list, /** * list_splice - join two lists, this is designed for stacks - * @list: the new list to add. + * @list: the add list to add. * @head: the place to add it in the first list. */ static inline void list_splice(const struct list_head *list, @@ -319,7 +319,7 @@ static inline void list_splice(const struct list_head *list, /** * list_splice_tail - join two lists, each list being a queue - * @list: the new list to add. + * @list: the add list to add. * @head: the place to add it in the first list. */ static inline void list_splice_tail(struct list_head *list, @@ -331,7 +331,7 @@ static inline void list_splice_tail(struct list_head *list, /** * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. + * @list: the add list to add. * @head: the place to add it in the first list. * * The list at @list is reinitialised @@ -347,7 +347,7 @@ static inline void list_splice_init(struct list_head *list, /** * list_splice_tail_init - join two lists and reinitialise the emptied list - * @list: the new list to add. + * @list: the add list to add. * @head: the place to add it in the first list. * * Each of the lists is a queue. @@ -644,8 +644,8 @@ static inline void __hlist_del(struct hlist_node *n) static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; + n->next = (struct hlist_node *)LIST_POISON1; + n->pprev = (struct hlist_node **)LIST_POISON2; } static inline void hlist_del_init(struct hlist_node *n) @@ -703,11 +703,11 @@ static inline bool hlist_fake(struct hlist_node *h) * reference of the first entry if it exists. */ static inline void hlist_move_list(struct hlist_head *old, - struct hlist_head *new) + struct hlist_head *add) { - new->first = old->first; - if (new->first) - new->first->pprev = &new->first; + add->first = old->first; + if (add->first) + add->first->pprev = &add->first; old->first = NULL; } diff --git a/lib/bitops.c b/lib/bitops.c new file mode 100644 index 0000000..bffefae --- /dev/null +++ b/lib/bitops.c @@ -0,0 +1,154 @@ + +#include "bitmap.h" +#include "bitops.h" + +/* + * This is a common helper function for find_next_bit, find_next_zero_bit, and + * find_next_and_bit. The differences are: + * - The "invert" argument, which is XORed with each fetched word before + * searching it for one bits. + * - The optional "addr2", which is anded with "addr1" if present. + */ +static inline unsigned long _find_next_bit(const unsigned long *addr1, + const unsigned long *addr2, unsigned long nbits, + unsigned long start, unsigned long invert) +{ + unsigned long tmp; + + if (unlikely(start >= nbits)) + return nbits; + + tmp = addr1[start / BITS_PER_LONG]; + if (addr2) + tmp &= addr2[start / BITS_PER_LONG]; + tmp ^= invert; + + /* Handle 1st word. */ + tmp &= BITMAP_FIRST_WORD_MASK(start); + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr1[start / BITS_PER_LONG]; + if (addr2) + tmp &= addr2[start / BITS_PER_LONG]; + tmp ^= invert; + } + + return min(start + __ffs(tmp), nbits); +} + +/* + * Find the next set bit in a memory region. + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, NULL, size, offset, 0UL); +} + +/* + * Find the first set bit in a memory region. + */ +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long idx; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx]) + return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); + } + + return size; +} + +/* + * Find the first cleared bit in a memory region. + */ +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long idx; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx] != ~0UL) + return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); + } + + return size; +} + +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, NULL, size, offset, ~0UL); +} + +unsigned long find_next_and_bit(const unsigned long *addr1, + const unsigned long *addr2, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr1, addr2, size, offset, 0UL); +} + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +unsigned int __sw_hweight32(unsigned int w) +{ +#ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER + w -= (w >> 1) & 0x55555555; + w = (w & 0x33333333) + ((w >> 2) & 0x33333333); + w = (w + (w >> 4)) & 0x0f0f0f0f; + return (w * 0x01010101) >> 24; +#else + unsigned int res = w - ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return (res + (res >> 16)) & 0x000000FF; +#endif +} + +unsigned int __sw_hweight16(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x5555); + res = (res & 0x3333) + ((res >> 2) & 0x3333); + res = (res + (res >> 4)) & 0x0F0F; + return (res + (res >> 8)) & 0x00FF; +} + +unsigned int __sw_hweight8(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res + (res >> 4)) & 0x0F; +} + +unsigned long __sw_hweight64(uint64_t w) +{ +#if BITS_PER_LONG == 32 + return __sw_hweight32((unsigned int)(w >> 32)) + + __sw_hweight32((unsigned int)w); +#elif BITS_PER_LONG == 64 +#ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER + w -= (w >> 1) & 0x5555555555555555ul; + w = (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul); + w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful; + return (w * 0x0101010101010101ul) >> 56; +#else + uint64_t res = w - ((w >> 1) & 0x5555555555555555ul); + res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); + res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful; + res = res + (res >> 8); + res = res + (res >> 16); + return (res + (res >> 32)) & 0x00000000000000FFul; +#endif +#endif +} \ No newline at end of file diff --git a/smartdns.c b/smartdns.c index 404acc8..9db5a02 100755 --- a/smartdns.c +++ b/smartdns.c @@ -1,132 +1,136 @@ +#include "fast_ping.h" +#include "hashtable.h" +#include "list.h" #include #include -#include "fast_ping.h" -#include "list.h" -#include "bitmap.h" -#include "hashtable.h" -void smartdns_ping_result(const char *host, int seqno, struct timeval *tv, void *userptr) +void smartdns_ping_result(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr) { - double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; - printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt); + if (result == PING_RESULT_RESPONSE) { + double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; + printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt); + } else if (result == PING_RESULT_TIMEOUT) { + printf("%16s: seq=%d timeout\n", host, seqno); + } } int smartdns_init() { - int ret; + int ret; - ret = fast_ping_init(); - if (ret != 0) { - fprintf(stderr, "start ping failed.\n"); - goto errout; - } + ret = fast_ping_init(); + if (ret != 0) { + fprintf(stderr, "start ping failed.\n"); + goto errout; + } - fast_ping_result_callback(smartdns_ping_result); + fast_ping_result_callback(smartdns_ping_result); - return 0; + return 0; errout: - return -1; + return -1; } int smartdns_run() { - sleep(1); - fast_ping_start("192.168.1.1", 2000, 0); - fast_ping_start("192.168.1.35", 2000, 0); - fast_ping_start("14.215.177.38", 2000, 0); - fast_ping_start("113.96.161.87", 2000, 0); - //fast_ping_start("::1", 2000, 0); - while (1) { - sleep(10); - //fast_ping_stop("192.168.1.35"); - } + fast_ping_start("192.168.1.1", 2000, 0); + fast_ping_start("192.168.1.35", 2000, 0); + fast_ping_start("14.215.177.38", 2000, 0); + fast_ping_start("113.96.161.87", 2000, 0); + fast_ping_start("::1", 2000, 0); + fast_ping_start("12.4.3.1", 1000, 0); + while (1) { + sleep(10); + //fast_ping_stop("192.168.1.35"); + } } void smartdns_exit() { - fast_ping_exit(); + fast_ping_exit(); } struct data { - struct list_head list; - int n; + struct list_head list; + int n; }; void list_test() { - struct list_head head ; - struct list_head *iter; - int i = 0; + struct list_head head; + struct list_head *iter; + int i = 0; - INIT_LIST_HEAD(&head); + INIT_LIST_HEAD(&head); - for (i = 0; i < 10; i++) { - struct data *h = malloc(sizeof(struct data)); - h->n = i; - list_add(&h->list, &head); - } + for (i = 0; i < 10; i++) { + struct data *h = malloc(sizeof(struct data)); + h->n = i; + list_add(&h->list, &head); + } - list_for_each(iter, &head) { - struct data *d= list_entry(iter, struct data, list); + list_for_each(iter, &head) + { + struct data *d = list_entry(iter, struct data, list); printf("%d\n", d->n); } } struct data_hash { - struct hlist_node node; - int n; - char str[32]; + struct hlist_node node; + int n; + char str[32]; }; int hash_test() { - DEFINE_HASHTABLE(ht, 7); - struct data_hash *temp; - struct data_hash *obj; - int i; - int j; - int key; + DEFINE_HASHTABLE(ht, 7); + struct data_hash *temp; + struct data_hash *obj; + int i; + int key; - for (i = 11; i < 17; i++) { - temp = malloc(sizeof(struct data_hash)); - temp->n = i * i; - hash_add(ht, &temp->node, temp->n); - } + for (i = 11; i < 17; i++) { + temp = malloc(sizeof(struct data_hash)); + temp->n = i * i; + hash_add(ht, &temp->node, temp->n); + } - for (i = 11; i < 17; i++) { - key = i * i; - hash_for_each_possible(ht, obj, node, key) { - printf("value: %d\n", obj->n); - }; - } + for (i = 11; i < 17; i++) { + key = i * i; + hash_for_each_possible(ht, obj, node, key) + { + printf("value: %d\n", obj->n); + }; + } return 0; } int hash_string_test() { - DEFINE_HASHTABLE(ht, 7); - struct data_hash *temp; - struct data_hash *obj; - int i; - int j; - int key; + DEFINE_HASHTABLE(ht, 7); + struct data_hash *temp; + struct data_hash *obj; + int i; + int key; - for (i = 0; i < 10; i++) { - temp = malloc(sizeof(struct data_hash)); - sprintf(temp->str, "%d", i); - hash_add(ht, &temp->node, hash_string(temp->str)); - } + for (i = 0; i < 10; i++) { + temp = malloc(sizeof(struct data_hash)); + sprintf(temp->str, "%d", i); + hash_add(ht, &temp->node, hash_string(temp->str)); + } - for (i = 0; i < 10; i++) { - char key_str[32]; - sprintf(key_str, "%d", i); - key = hash_string(key_str); - hash_for_each_possible(ht, obj, node, key) { - printf("i = %d value: %s\n", i, obj->str); - }; - } + for (i = 0; i < 10; i++) { + char key_str[32]; + sprintf(key_str, "%d", i); + key = hash_string(key_str); + hash_for_each_possible(ht, obj, node, key) + { + printf("i = %d value: %s\n", i, obj->str); + }; + } return 0; } @@ -171,19 +175,19 @@ int rbtree_test() int main(int argc, char *argv[]) { - int ret; + int ret; - atexit(smartdns_exit); + atexit(smartdns_exit); - ret = smartdns_init(); - if (ret != 0) { - fprintf(stderr, "init smartdns failed.\n"); - goto errout; - } + ret = smartdns_init(); + if (ret != 0) { + fprintf(stderr, "init smartdns failed.\n"); + goto errout; + } - return smartdns_run(); + return smartdns_run(); errout: - return 1; + return 1; } \ No newline at end of file