updat code

This commit is contained in:
Nick Peng
2018-04-24 00:24:44 +08:00
parent c6af293927
commit d3960e1018
14 changed files with 744 additions and 175 deletions

View File

@@ -1,8 +1,10 @@
BIN=smartdns BIN=smartdns
OBJS=smartdns.o fast_ping.o OBJS=smartdns.o fast_ping.o lib/bitops.o
CFLAGS=-g -O0 CFLAGS=-g -O0 -Wall
CFLAGS=-Iinclude CFLAGS +=-Iinclude
CXXFLAGS=-g -O0 -Wall -std=c++11
CXXFLAGS +=-Iinclude
.PHONY: all .PHONY: all

View File

@@ -2,6 +2,7 @@
#include "atomic.h" #include "atomic.h"
#include "hashtable.h" #include "hashtable.h"
#include <errno.h> #include <errno.h>
#include <arpa/inet.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
@@ -45,6 +46,10 @@ struct ping_host_struct {
int fd; int fd;
unsigned int seq; unsigned int seq;
struct timeval last;
int interval;
int timeout;
int send;
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t addr_len; socklen_t addr_len;
struct fast_ping_packet packet; struct fast_ping_packet packet;
@@ -54,7 +59,7 @@ struct fast_ping_struct {
int run; int run;
pthread_t tid; pthread_t tid;
pthread_mutex_t lock; pthread_mutex_t lock;
int ident; unsigned short ident;
int epoll_fd; int epoll_fd;
int fd_icmp; int fd_icmp;
@@ -82,7 +87,7 @@ uint16_t _fast_ping_checksum(uint16_t *header, size_t len)
return htons(~((sum >> 16) + (sum & 0xffff))); 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; 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 hints;
struct addrinfo *result = NULL; struct addrinfo *result = NULL;
@@ -170,7 +175,7 @@ errout:
return NULL; return NULL;
} }
static int _fast_ping_getdomain(const u_char *host) static int _fast_ping_getdomain(const char *host)
{ {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *result = NULL; struct addrinfo *result = NULL;
@@ -197,12 +202,12 @@ errout:
return -1; 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); 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); pthread_mutex_lock(&ping.map_lock);
if (atomic_dec_and_test(&ping_host->ref)) { 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); pthread_mutex_unlock(&ping.map_lock);
if (ping_host == NULL) { if (ping_host == NULL) {
return -1; return ;
} }
free(ping_host); free(ping_host);
@@ -280,34 +285,48 @@ errout:
static int _fast_ping_sendping(struct ping_host_struct *ping_host) static int _fast_ping_sendping(struct ping_host_struct *ping_host)
{ {
int ret = -1;
if (ping_host->type == AF_INET) { 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) { } 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) static int _fast_ping_create_sock(int protocol)
{ {
int fd; int fd = -1;
struct ping_host_struct *icmp_host = NULL; struct ping_host_struct *icmp_host = NULL;
struct epoll_event event; 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) { switch (protocol) {
case IPPROTO_ICMP: 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); _fast_ping_install_filter_v4(fd);
icmp_host = &ping.icmp_host; icmp_host = &ping.icmp_host;
break; break;
case IPPROTO_ICMPV6: 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); _fast_ping_install_filter_v6(fd);
icmp_host = &ping.icmp_host; icmp_host = &ping.icmp6_host;
break; break;
} }
@@ -371,7 +390,6 @@ int fast_ping_start(const char *host, int timeout, void *userptr)
struct addrinfo *gai = NULL; struct addrinfo *gai = NULL;
int domain = -1; int domain = -1;
int icmp_proto = 0; int icmp_proto = 0;
char ip[PING_MAX_HOSTLEN];
uint32_t hostkey; uint32_t hostkey;
uint32_t addrkey; uint32_t addrkey;
@@ -402,17 +420,20 @@ int fast_ping_start(const char *host, int timeout, void *userptr)
goto errout; 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); strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
ping_host->type = domain; ping_host->type = domain;
ping_host->fd = _fast_ping_create_icmp(icmp_proto); 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); memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
ping_host->addr_len = gai->ai_addrlen; ping_host->addr_len = gai->ai_addrlen;
atomic_set(&ping_host->ref, 0); atomic_set(&ping_host->ref, 0);
hostkey = hash_string(ping_host->host); 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); pthread_mutex_lock(&ping.map_lock);
_fast_ping_host_get(ping_host); _fast_ping_host_get(ping_host);
hash_add(ping.hostmap, &ping_host->host_node, hostkey); 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) 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; int icmp_len;
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data; struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
struct icmp6_hdr *icmp6 = &packet->icmp6; struct icmp6_hdr *icmp6 = &packet->icmp6;
struct timeval tvresult = *tvrecv; struct timeval tvresult = *tvrecv;
double rtt;
if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) {
return -1; 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; struct timeval *tvsend = &packet->msg.tv;
tv_sub(&tvresult, tvsend); 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; 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; struct timeval *tvsend = &packet->msg.tv;
tv_sub(&tvresult, tvsend); 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; return 0;
} }
@@ -551,14 +570,7 @@ errout:
return -1; return -1;
} }
static int _fast_ping_create_tcp(struct ping_host_struct *ping_host) static int _fast_ping_gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len)
{
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)
{ {
struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr; struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr;
host[0] = 0; host[0] = 0;
@@ -603,7 +615,7 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
goto errout; goto errout;
} }
addrkey = jhash(&from, from_len, 0); addrkey = jhash(&from, from_len, 0);
pthread_mutex_lock(&ping.map_lock); pthread_mutex_lock(&ping.map_lock);
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey) 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; return -1;
} }
recv_ping_host->send = 0;
_fast_ping_recvping(recv_ping_host, inpacket, len, now); _fast_ping_recvping(recv_ping_host, inpacket, len, now);
return 0; return 0;
errout: errout:
@@ -628,10 +642,24 @@ static void _fast_ping_period_run()
struct ping_host_struct *ping_host; struct ping_host_struct *ping_host;
struct hlist_node *tmp; struct hlist_node *tmp;
int i = 0; int i = 0;
struct timeval now;
struct timeval interval;
uint64_t millisecond;
gettimeofday(&now, 0);
pthread_mutex_lock(&ping.map_lock); pthread_mutex_lock(&ping.map_lock);
hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node) 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); pthread_mutex_unlock(&ping.map_lock);
} }
@@ -643,14 +671,19 @@ static void *_fast_ping_work(void *arg)
int i; int i;
struct timeval last = { 0 }; struct timeval last = { 0 };
struct timeval now = { 0 }; struct timeval now = { 0 };
struct timeval diff = {0};
uint millisec = 0;
while (ping.run) { 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(); _fast_ping_period_run();
last = now; 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) { if (num < 0) {
gettimeofday(&now, 0); gettimeofday(&now, 0);
usleep(100000); usleep(100000);
@@ -727,7 +760,7 @@ errout:
return -1; return -1;
} }
int fast_ping_exit() void fast_ping_exit()
{ {
if (ping.tid > 0) { if (ping.tid > 0) {
void *ret = NULL; void *ret = NULL;
@@ -737,12 +770,12 @@ int fast_ping_exit()
if (ping.fd_icmp > 0) { if (ping.fd_icmp > 0) {
close(ping.fd_icmp); close(ping.fd_icmp);
ping.fd_icmp < 0; ping.fd_icmp = -1;
} }
if (ping.fd_icmp6 > 0) { if (ping.fd_icmp6 > 0) {
close(ping.fd_icmp6); close(ping.fd_icmp6);
ping.fd_icmp6 < 0; ping.fd_icmp6 = -1;
} }
pthread_mutex_destroy(&ping.lock); pthread_mutex_destroy(&ping.lock);

View File

@@ -13,8 +13,13 @@ typedef enum {
FAST_PING_UDP FAST_PING_UDP
} FAST_PING_TYPE; } FAST_PING_TYPE;
typedef void (*fast_ping_result)(const char *host, int seqno, struct timeval *tv, void *userptr); typedef enum {
int fast_ping_result_callback(fast_ping_result result); 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); 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_init();
int fast_ping_exit(); void fast_ping_exit();
#ifdef __cpluscplus #ifdef __cpluscplus
} }

View File

@@ -2,6 +2,7 @@
#ifndef _GENERIC_ATOMIC_H #ifndef _GENERIC_ATOMIC_H
#define _GENERIC_ATOMIC_H #define _GENERIC_ATOMIC_H
/* Check GCC version, just to be safe */ /* Check GCC version, just to be safe */
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1) #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
# error atomic.h works only with GCC newer than version 4.1 # error atomic.h works only with GCC newer than version 4.1

View File

@@ -5,6 +5,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "bitops.h" #include "bitops.h"
#include "findbit.h"
#define DECLARE_BITMAP(name,bits) \ #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(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) 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));
} }
/* /*

View File

@@ -2,6 +2,10 @@
#ifndef _GENERIC_BITOPS_H_ #ifndef _GENERIC_BITOPS_H_
#define _GENERIC_BITOPS_H_ #define _GENERIC_BITOPS_H_
#include <unistd.h>
#include <stdint.h>
#include "gcc_builtin.h"
#ifndef __WORDSIZE #ifndef __WORDSIZE
#define __WORDSIZE (__SIZEOF_LONG__ * 8) #define __WORDSIZE (__SIZEOF_LONG__ * 8)
#endif #endif
@@ -24,6 +28,164 @@ extern unsigned int __sw_hweight32(unsigned int w);
extern unsigned long __sw_hweight64(uint64_t 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) \ #define for_each_set_bit(bit, addr, size) \
for ((bit) = find_first_bit((addr), (size)); \ for ((bit) = find_first_bit((addr), (size)); \
(bit) < (size); \ (bit) < (size); \

78
include/findbit.h Normal file
View File

@@ -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_ */

118
include/gcc_builtin.h Normal file
View File

@@ -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 */

View File

@@ -1,6 +1,7 @@
#ifndef _GENERIC_HASH_H #ifndef _GENERIC_HASH_H
#define _GENERIC_HASH_H #define _GENERIC_HASH_H
#include "bitmap.h"
#include "jhash.h" #include "jhash.h"
/* Fast hashing routine for ints, longs and pointers. /* Fast hashing routine for ints, longs and pointers.
@@ -113,6 +114,17 @@ int __ilog2_u64(uint64_t n)
__ilog2_u64(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 * This hash multiplies the input by a large odd number and takes the
* high bits. Since multiplication propagates changes to the most * high bits. Since multiplication propagates changes to the most

View File

@@ -9,7 +9,6 @@
#include "list.h" #include "list.h"
#include "hash.h" #include "hash.h"
#include "bitmap.h"
#ifndef __same_type #ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) # 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,\ hlist_for_each_entry_safe(obj, tmp,\
&name[hash_min(key, HASH_BITS(name))], member) &name[hash_min(key, HASH_BITS(name))], member)
#endif #endif

View File

@@ -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) static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
{ {
uint32_t a, b, c; uint32_t a, b, c;
const uint8_t *k = key; const uint8_t *k = (uint8_t *)key;
/* Set up the internal state */ /* Set up the internal state */
a = b = c = JHASH_INITVAL + length + initval; a = b = c = JHASH_INITVAL + length + initval;

View File

@@ -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 * This is only for internal list manipulation where we know
* the prev/next entries already! * 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 *prev,
struct list_head *next) struct list_head *next)
{ {
next->prev = new; next->prev = add;
new->next = next; add->next = next;
new->prev = prev; add->prev = prev;
prev->next = new; prev->next = add;
} }
/** /**
* list_add - add a new entry * list_add - add a add entry
* @new: new entry to be added * @add: add entry to be added
* @head: list head to add it after * @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. * 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 * list_add_tail - add a add entry
* @new: new entry to be added * @add: add entry to be added
* @head: list head to add it before * @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. * 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) static inline void list_del(struct list_head *entry)
{ {
__list_del(entry->prev, entry->next); __list_del(entry->prev, entry->next);
entry->next = LIST_POISON1; entry->next = (struct list_head *)LIST_POISON1;
entry->prev = LIST_POISON2; 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 * @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. * If @old was empty, it will be overwritten.
*/ */
static inline void list_replace(struct list_head *old, static inline void list_replace(struct list_head *old,
struct list_head *new) struct list_head *add)
{ {
new->next = old->next; add->next = old->next;
new->next->prev = new; add->next->prev = add;
new->prev = old->prev; add->prev = old->prev;
new->prev->next = new; add->prev->next = add;
} }
static inline void list_replace_init(struct list_head *old, 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); 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_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 * @head: a list with entries
* @entry: an entry within head, could be the head itself * @entry: an entry within head, could be the head itself
* and if so we won't cut the list * 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_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. * @head: the place to add it in the first list.
*/ */
static inline void list_splice(const struct list_head *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_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. * @head: the place to add it in the first list.
*/ */
static inline void list_splice_tail(struct list_head *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_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. * @head: the place to add it in the first list.
* *
* The list at @list is reinitialised * 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_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. * @head: the place to add it in the first list.
* *
* Each of the lists is a queue. * 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) static inline void hlist_del(struct hlist_node *n)
{ {
__hlist_del(n); __hlist_del(n);
n->next = LIST_POISON1; n->next = (struct hlist_node *)LIST_POISON1;
n->pprev = LIST_POISON2; n->pprev = (struct hlist_node **)LIST_POISON2;
} }
static inline void hlist_del_init(struct hlist_node *n) 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. * reference of the first entry if it exists.
*/ */
static inline void hlist_move_list(struct hlist_head *old, static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new) struct hlist_head *add)
{ {
new->first = old->first; add->first = old->first;
if (new->first) if (add->first)
new->first->pprev = &new->first; add->first->pprev = &add->first;
old->first = NULL; old->first = NULL;
} }

154
lib/bitops.c Normal file
View File

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

View File

@@ -1,132 +1,136 @@
#include "fast_ping.h"
#include "hashtable.h"
#include "list.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#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; if (result == PING_RESULT_RESPONSE) {
printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt); 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 smartdns_init()
{ {
int ret; int ret;
ret = fast_ping_init(); ret = fast_ping_init();
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "start ping failed.\n"); fprintf(stderr, "start ping failed.\n");
goto errout; goto errout;
} }
fast_ping_result_callback(smartdns_ping_result); fast_ping_result_callback(smartdns_ping_result);
return 0; return 0;
errout: errout:
return -1; return -1;
} }
int smartdns_run() int smartdns_run()
{ {
sleep(1); fast_ping_start("192.168.1.1", 2000, 0);
fast_ping_start("192.168.1.1", 2000, 0); fast_ping_start("192.168.1.35", 2000, 0);
fast_ping_start("192.168.1.35", 2000, 0); fast_ping_start("14.215.177.38", 2000, 0);
fast_ping_start("14.215.177.38", 2000, 0); fast_ping_start("113.96.161.87", 2000, 0);
fast_ping_start("113.96.161.87", 2000, 0); fast_ping_start("::1", 2000, 0);
//fast_ping_start("::1", 2000, 0); fast_ping_start("12.4.3.1", 1000, 0);
while (1) { while (1) {
sleep(10); sleep(10);
//fast_ping_stop("192.168.1.35"); //fast_ping_stop("192.168.1.35");
} }
} }
void smartdns_exit() void smartdns_exit()
{ {
fast_ping_exit(); fast_ping_exit();
} }
struct data { struct data {
struct list_head list; struct list_head list;
int n; int n;
}; };
void list_test() void list_test()
{ {
struct list_head head ; struct list_head head;
struct list_head *iter; struct list_head *iter;
int i = 0; int i = 0;
INIT_LIST_HEAD(&head); INIT_LIST_HEAD(&head);
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
struct data *h = malloc(sizeof(struct data)); struct data *h = malloc(sizeof(struct data));
h->n = i; h->n = i;
list_add(&h->list, &head); list_add(&h->list, &head);
} }
list_for_each(iter, &head) { list_for_each(iter, &head)
struct data *d= list_entry(iter, struct data, list); {
struct data *d = list_entry(iter, struct data, list);
printf("%d\n", d->n); printf("%d\n", d->n);
} }
} }
struct data_hash { struct data_hash {
struct hlist_node node; struct hlist_node node;
int n; int n;
char str[32]; char str[32];
}; };
int hash_test() int hash_test()
{ {
DEFINE_HASHTABLE(ht, 7); DEFINE_HASHTABLE(ht, 7);
struct data_hash *temp; struct data_hash *temp;
struct data_hash *obj; struct data_hash *obj;
int i; int i;
int j; int key;
int key;
for (i = 11; i < 17; i++) { for (i = 11; i < 17; i++) {
temp = malloc(sizeof(struct data_hash)); temp = malloc(sizeof(struct data_hash));
temp->n = i * i; temp->n = i * i;
hash_add(ht, &temp->node, temp->n); hash_add(ht, &temp->node, temp->n);
} }
for (i = 11; i < 17; i++) { for (i = 11; i < 17; i++) {
key = i * i; key = i * i;
hash_for_each_possible(ht, obj, node, key) { hash_for_each_possible(ht, obj, node, key)
printf("value: %d\n", obj->n); {
}; printf("value: %d\n", obj->n);
} };
}
return 0; return 0;
} }
int hash_string_test() int hash_string_test()
{ {
DEFINE_HASHTABLE(ht, 7); DEFINE_HASHTABLE(ht, 7);
struct data_hash *temp; struct data_hash *temp;
struct data_hash *obj; struct data_hash *obj;
int i; int i;
int j; int key;
int key;
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
temp = malloc(sizeof(struct data_hash)); temp = malloc(sizeof(struct data_hash));
sprintf(temp->str, "%d", i); sprintf(temp->str, "%d", i);
hash_add(ht, &temp->node, hash_string(temp->str)); hash_add(ht, &temp->node, hash_string(temp->str));
} }
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
char key_str[32]; char key_str[32];
sprintf(key_str, "%d", i); sprintf(key_str, "%d", i);
key = hash_string(key_str); key = hash_string(key_str);
hash_for_each_possible(ht, obj, node, key) { hash_for_each_possible(ht, obj, node, key)
printf("i = %d value: %s\n", i, obj->str); {
}; printf("i = %d value: %s\n", i, obj->str);
} };
}
return 0; return 0;
} }
@@ -171,19 +175,19 @@ int rbtree_test()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret; int ret;
atexit(smartdns_exit); atexit(smartdns_exit);
ret = smartdns_init(); ret = smartdns_init();
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "init smartdns failed.\n"); fprintf(stderr, "init smartdns failed.\n");
goto errout; goto errout;
} }
return smartdns_run(); return smartdns_run();
errout: errout:
return 1; return 1;
} }