diff options
Diffstat (limited to 'thirdparty/apps/testapp/lb')
-rw-r--r-- | thirdparty/apps/testapp/lb/api.h | 169 | ||||
-rw-r--r-- | thirdparty/apps/testapp/lb/lb.c | 1290 | ||||
-rw-r--r-- | thirdparty/apps/testapp/lb/lb.h | 731 |
3 files changed, 2190 insertions, 0 deletions
diff --git a/thirdparty/apps/testapp/lb/api.h b/thirdparty/apps/testapp/lb/api.h new file mode 100644 index 0000000..f930227 --- /dev/null +++ b/thirdparty/apps/testapp/lb/api.h @@ -0,0 +1,169 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _API_H_ +#define _API_H_ + +#if defined(NSOCKET) +#define VERSION_NAME "NSTACK" +#define _socket nstack_socket +#define _fcntl nstack_fcntl +#define _bind nstack_bind +#define _listen nstack_listen +#define _accept nstack_accept +#define _accept4 nstack_accept4 +#define _connect nstack_connect +#define _close nstack_close +#define _shutdown nstack_shutdown +#define _recv nstack_recv +#define _send nstack_send +#define _getsockname nstack_getsockname +#define _getpeername nstack_getpeername +#define _getsockopt nstack_getsockopt +#define _setsockopt nstack_setsockopt +#define _recvfrom nstack_recvfrom +#define _sendto nstack_sendto +#define _read nstack_read +#define _write nstack_write +#define _epoll_create nstack_epoll_create +#define _epoll_ctl nstack_epoll_ctl +#define _epoll_wait nstack_epoll_wait +#elif defined(LWIP) +#define VERSION_NAME "LWIP" +#define _socket lwip_socket +#define _fcntl lwip_fcntl +#define _bind lwip_bind +#define _listen lwip_listen +#define _accept lwip_accept +#define _accept4 lwip_accept4 +#define _connect lwip_connect +#define _close lwip_close +#define _shutdown lwip_shutdown +#define _recv lwip_recv +#define _send lwip_send +#define _getsockname lwip_getsockname +#define _getpeername lwip_getpeername +#define _getsockopt lwip_getsockopt +#define _setsockopt lwip_setsockopt +#define _recvfrom lwip_recvfrom +#define _sendto lwip_sendto +#define _read lwip_read +#define _write lwip_write +#define _epoll_create lwip_epoll_create +#define _epoll_ctl lwip_epoll_ctl +#define _epoll_wait lwip_epoll_wait +#else +#define VERSION_NAME "POSIX" +#define _socket socket +#define _fcntl fcntl +#define _bind bind +#define _listen listen +#define _accept accept +#define _accept4 accept4 +#define _connect connect +#define _close close +#define _shutdown shutdown +#define _recv recv +#define _send send +#define _getsockname getsockname +#define _getpeername getpeername +#define _getsockopt getsockopt +#define _setsockopt setsockopt +#define _recvfrom recvfrom +#define _sendto sendto +#define _read read +#define _write write +#define _epoll_create epoll_create +#define _epoll_ctl epoll_ctl +#define _epoll_wait epoll_wait +#endif + +#endif /* #ifndef _API_H_ */ + +#ifndef SOCKET_WARP_LB_H_ +#define SOCKET_WARP_LB_H_ + +inline static int +set_nonblock_v (int fd, int nonblock) +{ + int fl = _fcntl (fd, F_GETFL, 0); + + if (fl < 0) + return fl; + + if (nonblock) + { + if (fl & O_NONBLOCK) + return 0; + fl |= O_NONBLOCK; + } + else + { + if (0 == (fl & O_NONBLOCK)) + return 0; + fl &= ~(O_NONBLOCK); + } + + return _fcntl (fd, F_SETFL, fl | O_NONBLOCK); +} + +inline static int +set_nonblock (int fd) +{ + int fl = _fcntl (fd, F_GETFL, 0); + if (fl < 0) + return fl; + return _fcntl (fd, F_SETFL, fl | O_NONBLOCK); +} + +inline static int +set_nodelay (int fd, int nodelay) +{ + return _setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, + sizeof (nodelay)); +} + +inline static int +set_rcvtimeo (int fd, int us) +{ + struct timeval timeout = {.tv_sec = us / USOFS,.tv_usec = us % USOFS }; + return _setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, + sizeof (timeout)); +} + +inline static int +set_reuseaddr (int fd, int reuseaddr) +{ + return _setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr, + sizeof (reuseaddr)); +} + +inline static int +set_reuseport (int fd, int reuseport) +{ + return _setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuseport, + sizeof (reuseport)); +} + +inline static int +set_sndtimeo (int fd, int us) +{ + struct timeval timeout = {.tv_sec = us / USOFS,.tv_usec = us % USOFS }; + return _setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, + sizeof (timeout)); +} + +#endif /* #ifndef SOCKET_WARP_LB_H_ */ diff --git a/thirdparty/apps/testapp/lb/lb.c b/thirdparty/apps/testapp/lb/lb.c new file mode 100644 index 0000000..058ddce --- /dev/null +++ b/thirdparty/apps/testapp/lb/lb.c @@ -0,0 +1,1290 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "lb.h" + +int enable_debug = 1; + +#ifdef COLOR_LB_H_ + +const static struct lb_color lb_color_list[2] = { + [LB_DEF_COLOR] = { + .clear = "\033[0m", + .high = "\033[1m", + .uline = "\033[4m", + .flash = "\033[5m", + .rev = "\033[7m", + + .fblack = "\033[30m", + .fr__ = "\033[31m", + .f_g_ = "\033[32m", + .f__b = "\033[34m", + .frg_ = "\033[33m", + .fr_b = "\033[35m", + .f_gb = "\033[36m", + .fwhite = "\033[37m", + + .bblack = "\033[40m", + .br__ = "\033[41m", + .b_g_ = "\033[42m", + .b__b = "\033[44m", + .brg_ = "\033[43m", + .br_b = "\033[45m", + .b_gb = "\033[46m", + .bwhite = "\033[47m", + }, + [LB_NO_COLOR] = { + .clear = "", + .high = "", + .uline = "", + .flash = "", + .rev = "", + + .fblack = "", + .fr__ = "", + .f_g_ = "", + .f__b = "", + .frg_ = "", + .fr_b = "", + .f_gb = "", + .fwhite = "", + + .bblack = "", + .br__ = "", + .b_g_ = "", + .b__b = "", + .brg_ = "", + .br_b = "", + .b_gb = "", + .bwhite = "", + }, +}; + +const struct lb_color *lb_color = &lb_color_list[0]; +int lb_color_index = 0; + +void +lb_set_color (int index) +{ + lb_color_index = index; + lb_color = &lb_color_list[index]; +} + +#endif + +#ifdef FORMAT_LB_H_ + +static __thread char s_fmt_buf[64][64]; +static __thread uint32_t s_fmt_id = 0; + +#if 0 +const char * +f_in6 (const struct in6_addr *ip6) +{ + char *buf = s_fmt_buf[(s_fmt_id++) & 63]; + char *p = buf; + int i; + + for (i = 0; i < 8; ++i) + { + uint16_t c, v = htons (ip6->s6_addr16[i]); + + c = v >> 12; + if (c > 9) + *p++ = 'A' + c - 10; + else if (c > 0) + *p++ = '0' + c; + + c = (v >> 8) & 0xF; + if (c > 9) + *p++ = 'A' + c - 10; + else if (v > 0x00FF) + *p++ = '0' + c; + + c = (v >> 4) & 0xF; + if (c > 9) + *p++ = 'A' + c - 10; + else if (v > 0x000F) + *p++ = '0' + c; + + c = v & 0xF; + if (c > 9) + *p++ = 'A' + c - 10; + else + *p++ = '0' + c; + + *p++ = ':'; + } + + p--; + *p = 0; + return buf; +} +#endif + +static int +f_in6_f (char *buf, int len, uint16_t val) +{ + uint16_t v; + int num = 0; + + if (val > 0xFFF) + { + if (num >= len) + return -1; + v = val >> 12; + if (v < 10) + buf[num++] = v + '0'; + else + buf[num++] = v + 'a' - 10; + } + if (val > 0xff) + { + if (num >= len) + return -1; + v = (val >> 8) & 0xF; + if (v < 10) + buf[num++] = v + '0'; + else + buf[num++] = v + 'a' - 10; + } + if (val > 0xf) + { + if (num >= len) + return -1; + v = (val >> 4) & 0xF; + if (v < 10) + buf[num++] = v + '0'; + else + buf[num++] = v + 'a' - 10; + } + + if (num >= len) + return -1; + v = val & 0xF; + if (v < 10) + buf[num++] = v + '0'; + else + buf[num++] = v + 'a' - 10; + + return num; +} + +static void +f_in6_z (const struct in6_addr *addr, int *pos, int *num) +{ + int zero_pos = 8, zero_num = 0; + int try_pos = -1, try_num = 0; + int i; + + for (i = 0; i < 8; ++i) + { + if (addr->s6_addr16[i] == 0) + { + if (try_num) + { + try_num++; + } + else + { + try_pos = i; + try_num = 1; + } + } + else if (try_num) + { + if (try_num > zero_num) + { + zero_pos = try_pos; + zero_num = try_num; + } + try_num = 0; + } + } + + if (try_num && try_num > zero_num) + { + *pos = try_pos; + *num = try_num; + } + else + { + *pos = zero_pos; + *num = zero_num; + } +} + +int +f_in6_s (char *buf, int size, const struct in6_addr *addr) +{ + int ret, i, num = 0; + int zero_pos, zero_num; + + f_in6_z (addr, &zero_pos, &zero_num); + + if (zero_pos == 0) + { + if (num >= size) + return -1; + buf[num++] = ':'; + } + else + { + for (i = 0; i < zero_pos; ++i) + { + ret = f_in6_f (&buf[num], size - num, htons (addr->s6_addr16[i])); + if (ret < 0) + return -1; + num += ret; + if (num >= size) + return -1; + buf[num++] = ':'; + } + if (zero_pos == 8) + { + buf[--num] = 0; + return num; + } + } + + if (zero_pos + zero_num == 8) + { + if (num >= size) + return -1; + buf[num++] = ':'; + } + else + { + for (i = zero_pos + zero_num; i < 8; ++i) + { + if (num >= size) + return -1; + buf[num++] = ':'; + ret = f_in6_f (&buf[num], size - num, htons (addr->s6_addr16[i])); + if (ret < 0) + return -1; + num += ret; + } + } + + if (num >= size) + return -1; + buf[num] = 0; + + return num; +} + +const char * +f_in6_r (const struct in6_addr *addr, char *buf, int buflen) +{ + if (f_in6_s (buf, buflen, addr) <= 0) + return NULL; + return buf; +} + +const char * +f_in6 (const struct in6_addr *addr) +{ + char *buf = s_fmt_buf[(s_fmt_id++) & 63]; + return f_in6_r (addr, buf, sizeof (s_fmt_buf[0])); +} + +const char * +f_inaddr (const struct sockaddr_in *addr) +{ + char *buf = s_fmt_buf[(s_fmt_id++) & 63]; + char *p = buf; + const uint8_t *ip = (uint8_t *) & addr->sin_addr.s_addr; + const uint16_t pt = ntohs (addr->sin_port); + +#define IPP(v) do { \ + if (v > 99) { *p++ = '0' + v / 100 % 10; } \ + if (v > 9) { *p++ = '0' + v / 10 % 10; } \ + *p++ = '0' + v % 10; \ +} while (0) + +#define PTP(v) do { \ + if (v > 9999) { *p++ = '0' + v / 10000 % 10; } \ + if (v > 999) { *p++ = '0' + v / 1000 % 10; } \ + IPP(v); \ +} while (0) + + IPP (ip[0]); + *p++ = '.'; + IPP (ip[1]); + *p++ = '.'; + IPP (ip[2]); + *p++ = '.'; + IPP (ip[3]); + *p++ = ':'; + PTP (pt); + *p = 0; + + return buf; +} + +const char * +f_in6addr (const struct sockaddr_in6 *addr) +{ + char *p, *buf = s_fmt_buf[(s_fmt_id++) & 63]; + const uint16_t pt = htons (addr->sin6_port); + int len = f_in6_s (buf, sizeof (s_fmt_buf[0]), &addr->sin6_addr); + + if (len < 0) + return ""; + + p = buf + len; + *p++ = '.'; + PTP (pt); + *p = 0; + + return buf; +} + +inline static int +r_uint_use (uint64_t val) +{ + const static uint64_t LB_VAL[21] = { + 0, + 9, + 99, + 999, + 9999, + 99999, + 999999, + 9999999, + 99999999, + 999999999, + 9999999999, + 99999999999, + 999999999999, + 9999999999999, + 99999999999999, + 999999999999999, + 9999999999999999, + 99999999999999999, + 999999999999999999, + 9999999999999999999u, + 18446744073709551615u, + /* --%%%***+++###^^^@@@ */ + }; + + int a = 1, b = 20; + + do + { + int i = (a + b) / 2; + if (val > LB_VAL[i]) + a = i + 1; + else + b = i; + } + while (a != b); + + return a; +} + +inline static int +r_uint_wide (uint64_t val) +{ + int wide = r_uint_use (val); + + wide = wide + (wide - 1) / 3; + + return wide; +} + +inline static void +r_uint_fmt (char *buf, uint64_t val, int wide) +{ + char *p = buf + wide; + + *p-- = 0; + + while (1) + { + *p-- = ('0' + val % 10); + if ((val /= 10) == 0) + break; + + *p-- = ('0' + val % 10); + if ((val /= 10) == 0) + break; + + *p-- = ('0' + val % 10); + if ((val /= 10) == 0) + break; + + *p-- = ','; + } + + while (p >= buf) + *p-- = ' '; +} + +int +r_uint (char *buf, uint64_t val, int wide) +{ + const int size = r_uint_wide (val); + + if (size > wide) + wide = size; + + r_uint_fmt (buf, val, wide); + + return wide; +} + +inline int +s_uint (char *buf, uint64_t val) +{ + char *p = buf; + +#define F_NUM(n) if (val >= n) { *p++ = '0' + val / n % 10; } +#define C_NUM(n) if (val >= n) { *p++ = '0' + val / n % 10; *p++ = ','; } + + if (val >= 10000000ul) + { + if (val >= 1000000000000ul) + { + F_NUM (10000000000000000000ul); + C_NUM (1000000000000000000ul); + F_NUM (100000000000000000ul); + F_NUM (10000000000000000ul); + C_NUM (1000000000000000ul); + F_NUM (100000000000000ul); + F_NUM (10000000000000ul); + C_NUM (1000000000000ul); + } + F_NUM (100000000000ul); + F_NUM (10000000000ul); + C_NUM (1000000000ul); + F_NUM (100000000ul); + F_NUM (10000000ul); + } + C_NUM (1000000ul); + F_NUM (100000ul); + F_NUM (10000ul); + C_NUM (1000ul); + F_NUM (100ul); + F_NUM (10ul); + *p++ = '0' + val % 10; + *p = 0; + +#undef F_NUM +#undef C_NUM + return p - buf; +} + +const char * +f_uint (uint64_t val) +{ + char *buf = s_fmt_buf[(s_fmt_id++) & 63]; + (void) s_uint (buf, val); + return buf; +} + +#endif +#ifdef PARSE_LB_H_ + +#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') +#define IS_hex(c) ((c) >= 'a' && (c) <= 'f') +#define IS_HEX(c) ((c) >= 'A' && (c) <= 'F') + +uint64_t +p_hex (const char *arg, const char **end) +{ + int i; + uint64_t val = 0; + + while (*arg) + { + if (IS_DIGIT (*arg)) + val = (val << 4) | (uint64_t) (*arg++ - '0'); + else if (IS_hex (*arg)) + val = (val << 4) | (uint64_t) (*arg++ - 'a' + 0xa); + else if (IS_HEX (*arg)) + val = (val << 4) | (uint64_t) (*arg++ - 'A' + 0xA); + else + break; + if (val > 0x0FFFffffFFFFffff) + break; + } + + if (end) + *end = arg; + return val; +} + +#define P_UINT_RET(ret, out) ((*end = (out)), (ret)) + +uint64_t +p_uint (const char *arg, uint64_t max, const char **end) +{ + int i; + uint64_t v; + const char *out; + + if (!end) + end = &out; + + if (!arg) + goto P_UINT_ERR; + + if (*arg == '0') + { + if (IS_DIGIT (arg[1])) + goto P_UINT_ERR; + return P_UINT_RET (0, arg + 1); + } + + if (!IS_DIGIT (*arg)) + return P_UINT_RET (0, NULL); + + v = *arg++ - '0'; + if (v > max) + goto P_UINT_ERR; + + for (i = 2; i <= 19; ++i) + { + if (!IS_DIGIT (*arg)) + return P_UINT_RET (v, arg); + v = v * 10 + (*arg++ - '0'); + if (v > max) + goto P_UINT_ERR; + } + + if (IS_DIGIT (*arg)) + { + uint64_t n; + if (v > (UINT64_MAX / 10)) + goto P_UINT_ERR; + n = v * 10; + if (UINT64_MAX - n > (*arg - '0')) + goto P_UINT_ERR; + v = n + (*arg - '0'); + if (v > max) + goto P_UINT_ERR; + arg++; + if (IS_DIGIT (*arg)) + goto P_UINT_ERR; + } + + return P_UINT_RET (v, arg); + +P_UINT_ERR: + return P_UINT_RET (UINT64_MAX, NULL); +} + +inline uint32_t +p_ip (const char **arg) +{ + uint32_t b1, b2, b3, b4; + const char *p = *arg; + + b1 = (uint32_t) p_uint (p, 255, &p); + if (!p || *p++ != '.') + goto P_IP_ERR; + b2 = (uint32_t) p_uint (p, 255, &p); + if (!p || *p++ != '.') + goto P_IP_ERR; + b3 = (uint32_t) p_uint (p, 255, &p); + if (!p || *p++ != '.') + goto P_IP_ERR; + b4 = (uint32_t) p_uint (p, 255, &p); + if (!p) + goto P_IP_ERR; + + *arg = p; + return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + +P_IP_ERR: + *arg = NULL; + return 0; +} + +int +p_addr (const char *arg, struct sockaddr_in *addr) +{ + uint16_t port; + + if (*arg != ':') + { + uint32_t ip = p_ip (&arg); + if (!arg) + return -1; + addr->sin_addr.s_addr = htonl (ip); + if (*arg == 0) + return 0; + if (*arg != ':') + return -1; + arg++; + } + + port = (uint16_t) p_uint (arg, 0xffff, &arg); + if (!arg || *arg != 0) + return -1; + addr->sin_port = htons (port); + + return 0; +} + +const char * +p_addr_set (const char *arg, struct inaddrs *addr, uint32_t flag) +{ + addr->ip = p_ip (&arg); + if (!arg) + return NULL; + + if (!(flag & PA_NO_TO_IP) && *arg == '-') + { + uint8_t to; + to = (uint8_t) p_uint (arg + 1, 255, &arg); + if (!arg) + return NULL; + addr->ip_num = to - (uint8_t) addr->ip; + if (addr->ip_num >= 0) + ++addr->ip_num; + else if (flag & PA_MAY_INV_IP) + --addr->ip_num; + else + return NULL; + } + else if (!(flag & PA_NO_NUM_IP) && *arg == '+') + { + addr->ip_num = (int) p_uint (arg + 1, 0x7FFFffff, &arg); + if (!arg || addr->ip_num == 0 || 0xFFFFFFFF - addr->ip < addr->ip_num) + return NULL; + } + else + { + addr->ip_num = 1; + } + + if ((flag & PA_DEF_PORT) == PA_NO_PORT) + return arg; + + if (*arg != ':') + { + if ((flag & PA_DEF_PORT) == PA_MUST_PORT) + return NULL; + if ((flag & PA_DEF_PORT) == PA_DEF_PORT) + { + addr->port = (uint16_t) (flag); + addr->port_num = 1; + } + else + { + addr->port = 0; + addr->port_num = 0; + } + return arg; + } + + addr->port = (uint16_t) p_uint (arg + 1, 0xffff, &arg); + if (!arg) + return NULL; + + if (!(flag & PA_NO_TO_PORT) && *arg == '-') + { + uint16_t to = (uint16_t) p_uint (arg + 1, 0xffff, &arg); + if (!arg || to < addr->port) + return NULL; + addr->port_num = to - addr->port + 1; + } + else if (!(flag & PA_NO_NUM_PORT) && *arg == '+') + { + addr->port_num = (uint16_t) p_uint (arg + 1, 0xffff, &arg); + if (!arg || addr->port_num == 0 || 0xFFFF - addr->port < addr->port_num) + return NULL; + } + else + { + addr->port_num = 1; + } + + if (flag & PA_MULTI_ONE) + { + if (addr->ip_num > 1 && addr->port_num > 1) + return NULL; + } + + return arg; +} + +inline static const char * +pal_trim (const char *arg, uint32_t flag) +{ + if (flag & PAL_NO_SPACE) + return arg; + + if (flag & PAL_WITH_NL) + { + while (*arg == ' ' || *arg == '\t' || *arg == '\r' || *arg == '\n') + arg++; + } + else + { + while (*arg == ' ' || *arg == '\t') + arg++; + } + + return arg; +} + +int +p_addr_list (const char *arg, struct inaddrs *list, int num, uint32_t flag, + const char **end) +{ + int count = 0; + + while (count < num) + { + arg = pal_trim (arg, flag); + arg = p_addr_set (arg, list, flag); + count++; + if (!arg) + return -count; + arg = pal_trim (arg, flag); + if (*arg != ',') + break; + arg++; + list++; + } + + if (end) + *end = arg; + else if (*arg) + return -count; + + return count; +} + +int +addr_total (const struct inaddrs *list, int num, uint32_t mode) +{ + int total = 0; + + mode &= PAL_CROSS_MASK; + + for (--num; num >= 0; --num) + { + if (mode == PAL_IP_X_PORT || mode == PAL_PORT_X_IP) + { + total += list[num].ip_num * list[num].port_num; + } + else if (mode == PAL_INC_BOTH) + { + int iip = 0; + uint16_t iport = 0; + do + { + total++; + if (++iip == list[num].ip_num) + iip = 0; + if (++iport == list[num].port_num) + iport = 0; + } + while (iip != 0 && iport != 0); + } + else + return -1; + } + + return total; +} + +int +addr_layout (const struct inaddrs *list, int list_num, + struct sockaddr_in *addr, int addr_num, uint32_t mode) +{ + uint16_t ipt; + int i, iip, count = 0; + + mode &= PAL_CROSS_MASK; + + if (mode == PAL_IP_X_PORT) + { + for (i = 0; i < list_num; ++i) + { + if (count + list[i].ip_num * list[i].port_num > addr_num) + return -1; + for (iip = 0; iip < list[i].ip_num; ++iip) + { + for (ipt = 0; ipt < list[i].port_num; ++ipt) + { + addr[count].sin_family = AF_INET; + addr[count].sin_addr.s_addr = htonl (list[i].ip + iip); + addr[count].sin_port = htons (list[i].port + ipt); + count++; + } + } + } + } + else if (mode == PAL_PORT_X_IP) + { + for (i = 0; i < list_num; ++i) + { + if (count + list[i].ip_num * list[i].port_num > addr_num) + return -1; + for (ipt = 0; ipt < list[i].port_num; ++ipt) + { + for (iip = 0; iip < list[i].ip_num; ++iip) + { + addr[count].sin_family = AF_INET; + addr[count].sin_addr.s_addr = htonl (list[i].ip + iip); + addr[count].sin_port = htons (list[i].port + ipt); + count++; + } + } + } + } + else if (mode == PAL_INC_BOTH) + { + for (i = 0; i < list_num; ++i) + { + do + { + if (count >= addr_num) + return -1; + addr[count].sin_family = AF_INET; + addr[count].sin_addr.s_addr = htonl (list[i].ip + iip); + addr[count].sin_port = htons (list[i].port + ipt); + count++; + if (++iip >= list[i].ip_num) + iip = 0; + if (++ipt >= list[i].port_num) + ipt = 0; + } + while (iip != 0 && ipt != 0); + } + } + else + { + return -1; + } + + return count; +} + +inline static const char * +p_ip6_se (const char *p, uint16_t * val) +{ + int i; + uint32_t v = 0; + + for (i = 0; i < 4; ++i) + { + if (p[i] >= '0' && p[i] <= '9') + v = (v << 4) + p[i] - '0'; + else if (p[i] >= 'a' && p[i] <= 'f') + v = (v << 4) + p[i] - 'a' + 10; + else if (p[i] >= 'A' && p[i] <= 'F') + v = (v << 4) + p[i] - 'A' + 10; + else + break; + } + + if (i == 0) + return NULL; + + *val = htons (v); + return p + i; +} + +const char * +p_ip6 (const char *pos, struct in6_addr *ip) +{ + int zero = -1, num = 0; + const char *last; + + if (*pos == ':') + { + pos++; + if (*pos != ':') + return NULL; + pos++; + zero = 0; + } + + last = pos; + + while (*pos) + { + pos = p_ip6_se (pos, &ip->s6_addr16[num]); + if (!pos) + { + if (zero == num) + break; + return NULL; + } + + num++; + if (num == 8) + break; + + if (*pos == ':') + { + pos++; + if (*pos == ':') + { + if (zero >= 0) + return NULL; + zero = num; + pos++; + } + last = pos; + } + else if (*pos == '.') + { + if (num > 6) + return NULL; + *(uint32_t *) (&ip->s6_addr16[num - 1]) = htonl (p_ip (&last)); + if (!last) + return NULL; + pos = last; + num++; + break; + } + else + { + break; + } + } + + if (num == 0) + { + if (zero != 0) + return NULL; + ip->s6_addr32[0] = htonl (0); + ip->s6_addr32[1] = htonl (0); + ip->s6_addr32[2] = htonl (0); + ip->s6_addr32[3] = htonl (0); + return pos; + } + + if (num < 8) + { + int i, cp; + if (zero < 0) + return NULL; + /* move */ + for (i = num - 1, cp = 7; i >= zero; --i) + ip->s6_addr16[cp--] = ip->s6_addr16[i]; + /* fill 0 */ + for (i = num, cp = zero; i < 8; ++i) + ip->s6_addr16[cp++] = htons (0); + } + else if (zero >= 0) + { + return NULL; + } + + return pos; +} + +int +p_addr6 (const char *arg, struct sockaddr_in6 *addr) +{ + uint16_t port; + + if (*arg != '.') + { + arg = p_ip6 (arg, &addr->sin6_addr); + if (!arg) + return -1; + if (*arg == 0) + return 0; + if (*arg != '.') + return -1; + arg++; + } + + port = (uint16_t) p_uint (arg, 0xffff, &arg); + if (!arg || *arg != 0) + return -1; + addr->sin6_port = htons (port); + + return 0; +} + +#endif +#ifdef UNIT_LB_H_ + +const static uint64_t UNITS[UNIT_NUM] = { + [UNIT_1] = 1, + [UNIT_k] = 1000, + [UNIT_m] = 1000 * 1000, + [UNIT_g] = 1000 * 1000 * 1000, + [UNIT_w] = 10000, + [UNIT_K] = 1024, + [UNIT_M] = 1024 * 1024, + [UNIT_G] = 1024 * 1024 * 1024, + + [UNIT_hour] = 60 * 60, + [UNIT_min] = 60, + [UNIT_sec] = 1, + + [UNIT_hn] = 1000ull * 1000 * 1000 * 60 * 60, + [UNIT_mn] = 1000ull * 1000 * 1000 * 60, + [UNIT_sn] = 1000 * 1000 * 1000, + [UNIT_1n] = 1000 * 1000 * 1000, + [UNIT_ms] = 1000 * 1000, + [UNIT_us] = 1000, + [UNIT_ns] = 1, + + [UNIT_PC] = 1, +}; + +#define P_UNIT_END(ret, end) ({ \ + *arg = (end); \ + if (unit) *unit = UNITS[ret]; \ + ret; \ +}) + +int +p_unit (const char **arg, int mask, uint64_t * unit) +{ + const char *opt = *arg; + int ret; + + switch (*opt) + { + case 'w': + ret = UNIT_w; + break; + case 'm': + if ((mask & UB_ms) && opt[1] == 's') + return P_UNIT_END (UNIT_ms, opt + 2); + if (mask & UB_min) + return P_UNIT_END (UNIT_min, opt + 1); + ret = UNIT_m; + break; + case 'k': + ret = UNIT_k; + break; + case 'g': + ret = UNIT_g; + break; + + case 'h': + ret = UNIT_hour; + break; + case 's': + ret = UNIT_sec; + break; + case 'u': + if ((mask & UB_us) && opt[1] == 's') + return P_UNIT_END (UNIT_us, opt + 2); + goto NO_UNIT; + case 'n': + if ((mask & UB_ns) && opt[1] == 's') + return P_UNIT_END (UNIT_ns, opt + 2); + goto NO_UNIT; + + case '%': + ret = UNIT_PC; + break; + + case 'K': + ret = UNIT_K; + break; + case 'M': + ret = UNIT_M; + break; + case 'G': + ret = UNIT_G; + break; + + default: + goto NO_UNIT; + } + + if ((1 << ret) & mask) + return P_UNIT_END (ret, opt + 1); + +NO_UNIT: + if (0 == (mask & UB_1)) + return -1; + + return P_UNIT_END (UNIT_1, opt); +} + +#endif +#ifdef CACHED_OUTPUT_LB_H_ + +int +co_app_ch (char buf[], char ch) +{ + struct cohead *head = (struct cohead *) buf; + + buf += sizeof (struct cohead); + + if (head->free > 3) + { + buf += (head->size - head->free); + buf[0] = ch; + buf[1] = 0; + head->free -= 1; + } + else + { + (void) fprintf (CO_OUT (head), "%s%c", buf, ch); + buf[0] = 0; + head->free = head->size; + } + + return 1; +} + +int +co_append (char buf[], cosize_t max, const char *fmt, ...) +{ + int ret; + va_list ap; + struct cohead *head = (struct cohead *) buf; + + /* no space for max+1 size -> output if cached */ + if (max >= head->free && head->free < head->size) + _co_flush (head); + + /* enough space -> try cache format */ + if (max < head->free) + { + char *p = buf + (sizeof (struct cohead) + head->size - head->free); + va_start (ap, fmt); + ret = vsnprintf (p, head->free, fmt, ap); + va_end (ap); + if (ret >= 0 && ret < head->free) + { + head->free -= ret; + return ret; + } + } + + /* no space or format failed -> output if cached */ + if (head->free != head->size) + _co_flush (head); + + /* direct output */ + va_start (ap, fmt); + ret = fprintf (CO_OUT (head), fmt, ap); + va_end (ap); + + return ret; +} + +int +co_wr_uint (char buf[], uint64_t val, int wide) +{ + struct cohead *head = (struct cohead *) buf; + int size = r_uint_wide (val); + char *p; + + if (size > wide) + wide = size; + + if (head->free <= wide) + _co_flush (head); + + if (head->free <= wide) + { + assert (0); + } + + p = buf + (sizeof (struct cohead) + head->size - head->free); + + r_uint_fmt (p, val, wide); + + head->free -= wide; + + return wide; +} + +#endif + +#ifdef SYSTEM_LB_H_ + +pthread_t +lb_thread (void *(*proc) (void *), void *arg, const char *fmt, ...) +{ + pthread_t tid; + int ret; + + ret = pthread_create (&tid, NULL, proc, arg); + if (ret) + return 0; + + if (fmt) + { + char name[20]; + va_list args; + + va_start (args, fmt); + ret = vsnprintf (name, sizeof (name), fmt, args); + va_end (args); + + if (ret > 0) + { + name[sizeof (name) - 1] = 0; + (void) pthread_setname_np (tid, name); + } + } + + return tid; +} + +static void +lb_sigsegv_proc (int s) +{ + int num; + void *buf[128]; + + out ("Signal SIGSEGV, Segmentation fault!\n"); + + num = backtrace (buf, 128); + if (num > 0) + backtrace_symbols_fd (buf, num, STDOUT_FILENO); + exit (1); +} + +void +lb_sigsegv_setup () +{ + struct sigaction s = { 0 }; + + (void) sigemptyset (&s.sa_mask); + + s.sa_flags = SA_NODEFER; + s.sa_handler = (void *) lb_sigsegv_proc; + (void) sigaction (SIGSEGV, &s, NULL); +} + +#endif + +#ifdef KERNEL_SYSCALL_API + +#define KAPI(name) (typeof name) *k_##name = ##name; +#include "kapi.h" +#undef API + +void +kapi_init () +{ +#define KAPI(name) k_##name = ld_load; +} + +#endif diff --git a/thirdparty/apps/testapp/lb/lb.h b/thirdparty/apps/testapp/lb/lb.h new file mode 100644 index 0000000..b7e4ddb --- /dev/null +++ b/thirdparty/apps/testapp/lb/lb.h @@ -0,0 +1,731 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _LB_H_ +#define _LB_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <assert.h> +#include <time.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/un.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/epoll.h> +#include <sys/poll.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/eventfd.h> +#include <sys/syscall.h> +#include <sys/sysinfo.h> +#include <netinet/tcp.h> +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <poll.h> +#include <fcntl.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <pthread.h> +#include <sched.h> +#include <getopt.h> +#include <execinfo.h> +#include <linux/futex.h> + +#define KB 1000 +#define MB (1000 * KB) +#define GB (1000 * MB) +#define TB (1000 * GB) + +#define MSOFS (1000) +#define USOFS (1000 * 1000) +#define NSOFS (1000 * 1000 * 1000) +#define NSOFMS (1000 * 1000) + +#define NOINLINE __attribute__((noinline)) +#define no_inline __attribute__((noinline)) + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + +#include "api.h" + +#define out(fmt, arg...) (void)printf(fmt, ##arg) + +#define info(fmt, arg...) (void)printf("%s[I:%d]%s " fmt, CR, __LINE__, CC, ##arg) +#define wrn(fmt, arg...) (void)printf("%s[W:%d]%s " fmt, FR__, __LINE__, CC, ##arg) +#define err(fmt, arg...) (void)fprintf(stderr, "%s[E:%d]%s " fmt, BR__, __LINE__, CC, ##arg) + +#define WRN(cond, fmt, arg...) do { if (cond) wrn(fmt, ##arg); } while (0) + +#define ERR_RETURN(cond, ret, fmt, arg...) do { \ + if (cond) { \ + if (fmt) err(fmt, ##arg); \ + return ret; \ + } \ +} while(0) + +#define ERR_GOTO(cond, TO, fmt, arg...) do { \ + if (cond) { \ + if (fmt) err(fmt, ##arg); \ + goto TO; \ + } \ +} while (0) + +#define DBGOPT "D" +#define DBGOPT_LONG {"debug", 0, 0, 'D'}, + +extern int enable_debug; + +#define DBG(fmt, arg...) do { \ + if (enable_debug) \ + out("[D:%d]%s " fmt, __LINE__, __func__, ##arg); \ +} while (0) + +#define T DBG("\n"); + +#define CNT_OF(a) (sizeof(a) / sizeof(a[0])) + +#define OFF_OF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define CON_OF(ptr, type, member) ({ \ + const typeof( ((type*)0)->member ) *__mptr = (ptr); \ + (type*)( (char*)__mptr - OFF_OF(type, member) ); \ +}) +#define NUM_OF(a) (sizeof((a)) / sizeof((a)[0])) + +#if 1 +#define TIMEPOINT + +#define TP(name) struct timespec _tp_##name; \ + (void)clock_gettime(CLOCK_MONOTONIC, &_tp_##name) +#define TO(from, to) do { \ + struct timespec _t; \ + LB_SUB_TS(_tp_##to, _tp_##from, _t); \ + out("@TP>%s:%d:%s %lu.%09lu %s-%s\n", __FILE__, __LINE__, __func__, \ + _t.tv_sec, _t.tv_nsec, #from, #to); \ +} while (0) +#define TN(from, to, NUM) do { \ + static uint64_t _n = 0; \ + static struct timespec _t = {0}; \ + _t.tv_nsec += (_tp_##to.tv_nsec - _tp_##from.tv_nsec); \ + _t.tv_sec += (_tp_##to.tv_sec - _tp_##from.tv_sec); \ + if (++_n >= NUM) { \ + uint64_t _nsec = _t.tv_sec * 1000000000ul + _t.tv_nsec; \ + _nsec /= _n; \ + out("@TP<%lu>%s:%d:%s %lu.%09lu %s-%s\n", _n, __FILE__, __LINE__, __func__, \ + _nsec/1000000000ul, _nsec%1000000000ul, #from, #to); \ + _t.tv_sec = 0; \ + _t.tv_nsec = 0; \ + _n = 0; \ + } \ +} while (0) +#else + +#define TP(name) ((void)0) +#define TO(from, to) ((void)0) +#define TN(from, to, NUM) ((void)0) + +#endif + +#define TQ(name) do { TP(__); TO(name, __); } while (0) +#define TM(name, NUM) do { TP(__); TN(name, __, NUM); } while (0) + +#define TO1(n1,n2) TO(n1,n2) +#define TO2(n1,n2,n3) do { TO(n1,n2); TO1(n2,n3); } while(0) +#define TO3(n1,n2,n3...) do { TO(n1,n2); TO2(n2,n3); } while(0) +#define TO4(n1,n2,n3...) do { TO(n1,n2); TO3(n2,n3); } while(0) +#define TO5(n1,n2,n3...) do { TO(n1,n2); TO4(n2,n3); } while(0) +#define TO6(n1,n2,n3...) do { TO(n1,n2); TO5(n2,n3); } while(0) + +#define TE(N,n...) do { TP(__); TO##N(n, __);} while (0) + +#define tp1 TP(1) +#define tq1 TQ(1) +#define tp2 TP(2) +#define tq2 TQ(2) +#define tp3 TP(3) +#define tq3 TQ(3) +#define tp4 TP(4) +#define tq4 TQ(4) +#define tp5 TP(5) +#define tq5 TQ(5) + +#ifndef COLOR_LB_H_ +#define COLOR_LB_H_ + +struct lb_color +{ + const char *clear; + const char *high; + const char *uline; + const char *flash; + const char *rev; + + const char *fblack; + const char *fr__; + const char *f_g_; + const char *f__b; + const char *frg_; + const char *fr_b; + const char *f_gb; + const char *fwhite; + + const char *bblack; + const char *br__; + const char *b_g_; + const char *b__b; + const char *brg_; + const char *br_b; + const char *b_gb; + const char *bwhite; +}; + +enum +{ + LB_DEF_COLOR = 0, + LB_NO_COLOR = 1, +}; + +extern const struct lb_color *lb_color; +extern int lb_color_index; +void lb_set_color (int index); + +#define CC lb_color->clear +#define CR lb_color->rev +#define CH lb_color->high +#define CU lb_color->uline +#define CF lb_color->flash + +#define FBLACK lb_color->fblack +#define FR__ lb_color->fr__ +#define F_G_ lb_color->f_g_ +#define F__B lb_color->f__b +#define FRG_ lb_color->frg_ +#define FR_B lb_color->fr_b +#define F_GB lb_color->f_gb +#define FWHITE lb_color->fwhite + +#define BBLACK lb_color->bblack +#define BR__ lb_color->br__ +#define B_G_ lb_color->b_g_ +#define B__B lb_color->b__b +#define BRG_ lb_color->brg_ +#define BR_B lb_color->br_b +#define B_GB lb_color->b_gb +#define BWHITE lb_color->bwhite + +#endif + +#ifndef TIME_LB_H_ +#define TIME_LB_H_ + +#define LB_RAND(num) ((int) ((random() / (RAND_MAX + 1.0)) * num)) + +#define LB_TIME(now) (void)clock_gettime(CLOCK_MONOTONIC, &(now)) +#define LB_REALTIME(now) (void)clock_gettime(CLOCK_REALTIME, &(now)) + +#define LB_SUB_OS(end, begin) ((end).tv_sec - (begin).tv_sec) +#define LB_SUB_NS(end, begin) (((end).tv_sec - (begin).tv_sec) * NSOFS + (end).tv_nsec - (begin).tv_nsec) + +#define LB_SUB_TS(end, begin, out) ({ \ + if ((end).tv_nsec >= (begin).tv_nsec) { \ + (out).tv_nsec = (end).tv_nsec - (begin).tv_nsec; \ + (out).tv_sec = (end).tv_sec - (begin).tv_sec; \ + } else { \ + (out).tv_nsec = (end).tv_nsec + NSOFS - (begin).tv_nsec; \ + (out).tv_sec = (end).tv_sec - (begin).tv_sec - 1; \ + } \ +}) + +#define LB_CMP(end, begin) ((end).tv_sec > (begin).tv_sec ? 1 : ( \ + (end).tv_sec < (begin).tv_sec ? -1 : (end).tv_nsec - (begin).tv_nsec)) + +#define LB_CMP_SN(end, begin, sec, nsec) ({ \ + time_t _s = (end).tv_sec - (begin).tv_sec; \ + (_s > (sec)) || (_s == (sec) && (end).tv_nsec - (begin).tv_nsec >= (nsec)); \ +}) + +#define LB_CMP_TS(end, begin, ts) LB_CMP_SN((end), (begin), (ts).tv_sec, (ts).tv_nsec) +#define LB_CMP_S(end, begin, sec) LB_CMP_SN((end), (begin), (sec), 0) +#define LB_CMP_NS(end, begin, nsec) LB_CMP_SN((end), (begin), 0, (nsec)) + +#endif /* #ifndef TIME_LB_H_ */ + +#ifndef MATH_LB_H_ +#define MATH_LB_H_ + +/* return a * 10^9 / b */ +inline static uint64_t +lb_gdiv (uint64_t a, uint64_t b) +{ + const uint64_t M = 0xFFFFffffFFFFfffful; + const uint64_t N = 1000 * 1000 * 1000; + const uint64_t P = 1000; + + uint64_t r; + + if (b == 0) + b = 1; + + if (a <= M / N) + return a * N / b; + + r = a / b; + + a = a % b * P; + r = r * P + a / b; + + a = a % b * P; + r = r * P + a / b; + + a = a % b * P; + r = r * P + a / b; + + return r; +} + +inline static uint64_t +lb_sdiv (uint64_t a, uint64_t b) +{ + if (b) + return a / b; + return 0; +} + +#endif /* #ifndef MATH_LB_H_ */ +#ifndef RUN_LB_H_ +#define RUN_LB_H_ + +struct lb_slot +{ + struct timespec begin; + uint64_t count; +}; + +struct lb_run +{ + uint32_t index; + uint32_t mask; + uint32_t rate; + uint32_t time; + uint64_t total; + struct lb_slot slot[0]; +}; + +/* num:1 << N; time: ns */ +inline static void +run_init (struct lb_run *run, uint32_t rate, uint32_t num, uint32_t time) +{ + int i; + struct lb_slot *slot = run->slot; + struct timespec begin; + + LB_TIME (begin); + + run->index = 0; + run->mask = num - 1; + run->rate = rate; + run->time = time; + run->total = 0; + + for (i = 0; i < num; ++i, ++slot) + { + slot->begin = begin; + slot->count = 0; + } +} + +/* return: the number should add for run to now */ +inline static int64_t +run_test (struct lb_run *run, struct timespec *now) +{ + uint64_t time, num; + struct lb_slot *slot = run->slot; + struct lb_slot *cur = slot + (run->index & run->mask); + + if (LB_CMP_NS (*now, cur->begin, run->time)) + { + cur = slot + ((++run->index) & run->mask); + run->total -= cur->count; + cur->count = 0; + cur->begin = *now; + } + + slot += ((run->index + 1) & run->mask); + time = LB_SUB_NS (*now, slot->begin); + num = time * run->rate; + + if ((num % NSOFS) >= (NSOFS / 2)) + return num / NSOFS - run->total + 1; + return num / NSOFS - run->total; +} + +inline static int +run_add (struct lb_run *run, int64_t num) +{ + run->total += num; + run->slot[run->index & run->mask].count += num; +} + +#endif + +#ifndef FORMAT_LB_H_ +#define FORMAT_LB_H_ + +const char *f_in6 (const struct in6_addr *ip6); +const char *f_in6addr (const struct sockaddr_in6 *addr); +const char *f_inaddr (const struct sockaddr_in *addr); +const char *f_uint (uint64_t val); +int s_uint (char *buf, uint64_t val); +int r_uint (char *buf, uint64_t val, int size); + +#endif + +#ifndef PARSE_LB_H_ +#define PARSE_LB_H_ + +uint64_t p_hex (const char *arg, const char **end); +uint64_t p_uint (const char *arg, uint64_t max, const char **end); +inline static long +p_int (const char *arg, long max, const char **end) +{ + return (long) (unsigned long) p_uint (arg, (uint64_t) (unsigned long) max, + end); +} + +struct inaddrs +{ + uint32_t ip; +#if 0 + uint32_t ip_num; + uint32_t ip_step; +#else + int ip_num; +#endif + uint16_t port; + uint16_t port_num; +}; + +uint32_t p_ip (const char **arg); +int p_addr (const char *str, struct sockaddr_in *addr); +const char *p_addr_set (const char *arg, struct inaddrs *addr, uint32_t flag); +int p_addr_list (const char *arg, struct inaddrs *list, int num, + uint32_t flag, const char **end); +int addr_total (const struct inaddrs *list, int num, uint32_t mode); +int addr_layout (const struct inaddrs *list, int list_num, + struct sockaddr_in *addr, int addr_num, uint32_t mode); +inline static int +p_addrin_list (const char *arg, struct sockaddr_in **addr, int max, + uint32_t flag, const char **end) +{ + int num, total; + struct inaddrs list[max]; + struct sockaddr_in *out; + + num = p_addr_list (arg, list, max, flag, end); + if (num <= 0) + return -1; + + total = addr_total (list, num, flag); + if (total > max) + return -1; + + out = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in) * total); + if (!out) + return -1; + + num = addr_layout (list, num, out, total, flag); + + if (num != total) + { + free (out); + return -1; + } + + *addr = out; + return num; +} + +#define PA_DEFPORT_MASK 0x0000FFFF + +#define PA_NO_TO_IP 0x00010000 +#define PA_NO_NUM_IP 0x00020000 +#define PA_MAY_INV_IP 0x00040000 +#define PA_MULTI_ONE 0x00080000 + +#define PA_NO_TO_PORT 0x00100000 +#define PA_NO_NUM_PORT 0x00200000 +#define PA_NO_PORT 0x00400000 +#define PA_MUST_PORT 0x00800000 +#define PA_DEF_PORT 0x00C00000 + +#define PA_NO_TO_ALL (PA_NO_TO_IP | PA_NO_TO_PORT) +#define PA_NO_NUM_ALL (PA_NO_NUM_IP | PA_NO_NUM_PORT) +#define PA_SINGLE_IP (PA_NO_TO_IP | PA_NO_NUM_IP) +#define PA_SINGLE_PORT (PA_NO_TO_PORT | PA_NO_NUM_PORT) + +#define PAL_NO_SPACE 0x10000000 +#define PAL_WITH_NL 0x20000000 +//#define PAL_SC_SPLIT 0x40000000 + +#define PAL_CROSS_MASK 0x03000000 +#define PAL_IP_X_PORT 0x00000000 +#define PAL_INC_BOTH 0x01000000 +#define PAL_PORT_X_IP 0x02000000 + +const char *p_ip6 (const char *pos, struct in6_addr *ip); +inline static int +inet6_aton (const char *cp, struct in6_addr *addr) +{ + cp = p_ip6 (cp, addr); + if (!cp || cp[0] != 0) + return 0; + return 1; +} + +int p_addr6 (const char *arg, struct sockaddr_in6 *addr); + +#endif + +#ifndef UNIT_LB_H_ +#define UNIT_LB_H_ + +enum unit_type +{ + UNIT_1, + + UNIT_k, + UNIT_m, + UNIT_g, + UNIT_w, + + UNIT_K, + UNIT_M, + UNIT_G, + + UNIT_hour, + UNIT_min, + UNIT_sec, + + UNIT_1n, + UNIT_hn, + UNIT_mn, + UNIT_sn, + UNIT_ms, + UNIT_us, + UNIT_ns, + + UNIT_PC, + + UNIT_NUM, + + UB_1 = 1 << UNIT_1, + + UB_k = 1 << UNIT_k, + UB_m = 1 << UNIT_m, + UB_g = 1 << UNIT_g, + UB_w = 1 << UNIT_w, + + UB_K = 1 << UNIT_K, + UB_M = 1 << UNIT_M, + UB_G = 1 << UNIT_G, + + UB_hour = 1 << UNIT_hour, + UB_min = 1 << UNIT_min, + UB_sec = 1 << UNIT_sec, + + UB_hn = 1 << UNIT_hn, + UB_mn = 1 << UNIT_mn, + UB_sn = 1 << UNIT_sn, + UB_1n = 1 << UNIT_1n, + UB_ms = 1 << UNIT_ms, + UB_us = 1 << UNIT_us, + UB_ns = 1 << UNIT_ns, + + UB_PC = 1 << UNIT_PC, + + UB_T1U_MASK = 3 << UNIT_NUM, + UB_T1U_ns = 0 << UNIT_NUM, + UB_T1U_us = 1 << UNIT_NUM, + UB_T1U_ms = 2 << UNIT_NUM, + UB_T1U_s = 3 << UNIT_NUM, + + UB_kmgw = UB_k | UB_m | UB_g | UB_w, + UB_KMG = UB_K | UB_M | UB_G, + UB_1kmgwKMG = UB_1 | UB_kmgw | UB_KMG, + + UB_smun = UB_sn | UB_ms | UB_us | UB_ns, + UB_hms1 = UB_hour | UB_min | UB_sec | UB_1, + +}; + +int p_unit (const char **arg, int mask, uint64_t * unit); + +inline static uint64_t +p_value (const char *arg, uint64_t max, int mask, const char **end) +{ + uint64_t val = p_uint (arg, max, &arg); + + if (arg) + { + uint64_t unit; + if (p_unit (&arg, mask, &unit) >= 0) + { + val *= unit; + if (val <= max) + { + if (end) + *end = arg; + return val; + } + } + } + + if (end) + *end = NULL; + return 0; +} + +#endif + +#ifndef CACHED_OUTPUT_LB_H_ +#define CACHED_OUTPUT_LB_H_ + +typedef uint16_t cosize_t; + +struct cohead +{ + cosize_t size; + cosize_t free; +}; + +#define CO_OUT(head) stdout +#define CO_INIT(buf) co_init(buf, sizeof(buf)) + +inline static void +co_init (char buf[], cosize_t size) +{ + struct cohead *head = (struct cohead *) buf; + head->size = size - sizeof (struct cohead); + head->free = head->size; + buf[sizeof (struct cohead)] = 0; +} + +inline static void +_co_flush (struct cohead *head) +{ + char *buf = (char *) (head + 1); + (void) fputs (buf, CO_OUT (head)); + head->free = head->size; + *buf = 0; +} + +inline static void +co_flush (char buf[]) +{ + struct cohead *head = (struct cohead *) buf; + if (head->free != head->size) + _co_flush (head); +} + +int co_wr_uint (char buf[], uint64_t val, int wide); + +int co_app_ch (char buf[], char ch); +#define co_ch_if(cond, buf, ch) ( \ + (!!(cond)) ? co_app_ch((buf), (ch)) : 0) + +int co_append (char buf[], cosize_t max, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +#define co_app_if(cond, buf, max, fmt, arg...) ( \ + (!!(cond)) ? co_append((buf), (max), (fmt), ##arg) : 0) +#define co_app_fls(buf, max, fmt, arg...) do { \ + co_append(buf, max, fmt, ##arg); \ + co_flush(); \ +} while (0) + +#endif + +#ifndef SYSTEM_LB_H_ +#define SYSTEM_LB_H_ + +inline static void +futex_wait (volatile int *addr, int val) +{ + while (*addr == val) + { + (void) syscall (SYS_futex, addr, FUTEX_WAIT, val, NULL, NULL, 0); + } +} + +inline static void +futex_wake (volatile int *addr, int num) +{ + (void) syscall (SYS_futex, addr, FUTEX_WAKE, num, NULL, NULL, 0); +} + +pthread_t lb_thread (void *(*proc) (void *), void *arg, const char *fmt, ...); + +inline static int +lb_setcpu (pthread_t thread, int cpu) +{ + cpu_set_t set; + CPU_ZERO (&set); + CPU_SET (cpu, &set); + return pthread_setaffinity_np (thread, sizeof (set), &set); +} + +inline static int +lb_sleep (time_t sec, long nsec) +{ +const struct timespec timeout = { tv_sec: sec, tv_nsec:nsec }; + return nanosleep (&timeout, NULL); +} + +void lb_sigsegv_setup (); + +#endif /* #ifndef SYSTEM_LB_H_ */ + +#define FD_CLOSE(fd) do { \ + if(fd >= 0) { \ + _close(fd); \ + fd = -1; \ + } \ +} while(0) + +#define BUF_FREE(p) do { \ + if (p) { \ + free(p); \ + p = NULL; \ + } \ +} while (0) + +#endif + +#ifdef KERNEL_SYSCALL_API +#define KERNEL_SYSCALL_API + +#define KAPI(name) extern (typeof name) *k_##name; +#include "kapi.h" +#undef API + +#endif |