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

View File

@@ -2,6 +2,7 @@
#include "atomic.h"
#include "hashtable.h"
#include <errno.h>
#include <arpa/inet.h>
#include <linux/filter.h>
#include <netdb.h>
#include <netinet/icmp6.h>
@@ -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);

View File

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

View File

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

View File

@@ -5,6 +5,8 @@
#include <string.h>
#include <stdlib.h>
#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));
}
/*

View File

@@ -2,6 +2,10 @@
#ifndef _GENERIC_BITOPS_H_
#define _GENERIC_BITOPS_H_
#include <unistd.h>
#include <stdint.h>
#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); \

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
#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

View File

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

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)
{
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;

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
* 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;
}

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