log_backend_net.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright (c) 2018 Intel Corporation
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <logging/log.h>
  7. LOG_MODULE_REGISTER(log_backend_net, CONFIG_LOG_DEFAULT_LEVEL);
  8. #include <logging/log_backend.h>
  9. #include <logging/log_core.h>
  10. #include <logging/log_output.h>
  11. #include <logging/log_msg.h>
  12. #include <net/net_pkt.h>
  13. #include <net/net_context.h>
  14. /* Set this to 1 if you want to see what is being sent to server */
  15. #define DEBUG_PRINTING 0
  16. #if DEBUG_PRINTING
  17. #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
  18. #else
  19. #define DBG(fmt, ...)
  20. #endif
  21. #if defined(CONFIG_NET_IPV6) || CONFIG_NET_HOSTNAME_ENABLE
  22. #define MAX_HOSTNAME_LEN NET_IPV6_ADDR_LEN
  23. #else
  24. #define MAX_HOSTNAME_LEN NET_IPV4_ADDR_LEN
  25. #endif
  26. static char dev_hostname[MAX_HOSTNAME_LEN + 1];
  27. static uint8_t output_buf[CONFIG_LOG_BACKEND_NET_MAX_BUF_SIZE];
  28. static bool net_init_done;
  29. struct sockaddr server_addr;
  30. static bool panic_mode;
  31. const struct log_backend *log_backend_net_get(void);
  32. NET_PKT_SLAB_DEFINE(syslog_tx_pkts, CONFIG_LOG_BACKEND_NET_MAX_BUF);
  33. NET_PKT_DATA_POOL_DEFINE(syslog_tx_bufs,
  34. ROUND_UP(CONFIG_LOG_BACKEND_NET_MAX_BUF_SIZE /
  35. CONFIG_NET_BUF_DATA_SIZE, 1) *
  36. CONFIG_LOG_BACKEND_NET_MAX_BUF);
  37. static struct k_mem_slab *get_tx_slab(void)
  38. {
  39. return &syslog_tx_pkts;
  40. }
  41. struct net_buf_pool *get_data_pool(void)
  42. {
  43. return &syslog_tx_bufs;
  44. }
  45. static int line_out(uint8_t *data, size_t length, void *output_ctx)
  46. {
  47. struct net_context *ctx = (struct net_context *)output_ctx;
  48. int ret = -ENOMEM;
  49. if (ctx == NULL) {
  50. return length;
  51. }
  52. ret = net_context_send(ctx, data, length, NULL, K_NO_WAIT, NULL);
  53. if (ret < 0) {
  54. goto fail;
  55. }
  56. DBG(data);
  57. fail:
  58. return length;
  59. }
  60. LOG_OUTPUT_DEFINE(log_output_net, line_out, output_buf, sizeof(output_buf));
  61. static int do_net_init(void)
  62. {
  63. struct sockaddr *local_addr = NULL;
  64. struct sockaddr_in6 local_addr6;
  65. struct sockaddr_in local_addr4;
  66. socklen_t server_addr_len;
  67. struct net_context *ctx;
  68. int ret;
  69. if (IS_ENABLED(CONFIG_NET_IPV4) && server_addr.sa_family == AF_INET) {
  70. local_addr = (struct sockaddr *)&local_addr4;
  71. server_addr_len = sizeof(struct sockaddr_in);
  72. local_addr4.sin_port = 0U;
  73. }
  74. if (IS_ENABLED(CONFIG_NET_IPV6) && server_addr.sa_family == AF_INET6) {
  75. local_addr = (struct sockaddr *)&local_addr6;
  76. server_addr_len = sizeof(struct sockaddr_in6);
  77. local_addr6.sin6_port = 0U;
  78. }
  79. if (local_addr == NULL) {
  80. DBG("Server address unknown\n");
  81. return -EINVAL;
  82. }
  83. local_addr->sa_family = server_addr.sa_family;
  84. ret = net_context_get(server_addr.sa_family, SOCK_DGRAM, IPPROTO_UDP,
  85. &ctx);
  86. if (ret < 0) {
  87. DBG("Cannot get context (%d)\n", ret);
  88. return ret;
  89. }
  90. if (IS_ENABLED(CONFIG_NET_HOSTNAME_ENABLE)) {
  91. (void)strncpy(dev_hostname, net_hostname_get(), MAX_HOSTNAME_LEN);
  92. } else if (IS_ENABLED(CONFIG_NET_IPV6) &&
  93. server_addr.sa_family == AF_INET6) {
  94. const struct in6_addr *src;
  95. src = net_if_ipv6_select_src_addr(
  96. NULL, &net_sin6(&server_addr)->sin6_addr);
  97. if (src) {
  98. net_addr_ntop(AF_INET6, src, dev_hostname,
  99. MAX_HOSTNAME_LEN);
  100. net_ipaddr_copy(&local_addr6.sin6_addr, src);
  101. } else {
  102. goto unknown;
  103. }
  104. } else if (IS_ENABLED(CONFIG_NET_IPV4) &&
  105. server_addr.sa_family == AF_INET) {
  106. const struct in_addr *src;
  107. src = net_if_ipv4_select_src_addr(
  108. NULL, &net_sin(&server_addr)->sin_addr);
  109. if (src) {
  110. net_addr_ntop(AF_INET, src, dev_hostname,
  111. MAX_HOSTNAME_LEN);
  112. net_ipaddr_copy(&local_addr4.sin_addr, src);
  113. } else {
  114. goto unknown;
  115. }
  116. } else {
  117. unknown:
  118. DBG("Cannot setup local context\n");
  119. return -EINVAL;
  120. }
  121. ret = net_context_bind(ctx, local_addr, server_addr_len);
  122. if (ret < 0) {
  123. DBG("Cannot bind context (%d)\n", ret);
  124. return ret;
  125. }
  126. (void)net_context_connect(ctx, &server_addr, server_addr_len,
  127. NULL, K_NO_WAIT, NULL);
  128. /* We do not care about return value for this UDP connect call that
  129. * basically does nothing. Calling the connect is only useful so that
  130. * we can see the syslog connection in net-shell.
  131. */
  132. net_context_setup_pools(ctx, get_tx_slab, get_data_pool);
  133. log_output_ctx_set(&log_output_net, ctx);
  134. log_output_hostname_set(&log_output_net, dev_hostname);
  135. return 0;
  136. }
  137. static void send_output(const struct log_backend *const backend,
  138. struct log_msg *msg)
  139. {
  140. if (panic_mode) {
  141. return;
  142. }
  143. if (!net_init_done && do_net_init() == 0) {
  144. net_init_done = true;
  145. }
  146. log_msg_get(msg);
  147. log_output_msg_process(&log_output_net, msg,
  148. LOG_OUTPUT_FLAG_FORMAT_SYSLOG |
  149. LOG_OUTPUT_FLAG_TIMESTAMP |
  150. (IS_ENABLED(CONFIG_LOG_BACKEND_NET_SYST_ENABLE) ?
  151. LOG_OUTPUT_FLAG_FORMAT_SYST : 0));
  152. log_msg_put(msg);
  153. }
  154. static void process(const struct log_backend *const backend,
  155. union log_msg2_generic *msg)
  156. {
  157. uint32_t flags = LOG_OUTPUT_FLAG_FORMAT_SYSLOG | LOG_OUTPUT_FLAG_TIMESTAMP;
  158. if (panic_mode) {
  159. return;
  160. }
  161. if (!net_init_done && do_net_init() == 0) {
  162. net_init_done = true;
  163. }
  164. log_output_msg2_process(&log_output_net, &msg->log, flags);
  165. }
  166. static void init_net(struct log_backend const *const backend)
  167. {
  168. ARG_UNUSED(backend);
  169. int ret;
  170. net_sin(&server_addr)->sin_port = htons(514);
  171. ret = net_ipaddr_parse(CONFIG_LOG_BACKEND_NET_SERVER,
  172. sizeof(CONFIG_LOG_BACKEND_NET_SERVER) - 1,
  173. &server_addr);
  174. if (ret == 0) {
  175. LOG_ERR("Cannot configure syslog server address");
  176. return;
  177. }
  178. log_backend_deactivate(log_backend_net_get());
  179. }
  180. static void panic(struct log_backend const *const backend)
  181. {
  182. panic_mode = true;
  183. }
  184. static void sync_string(const struct log_backend *const backend,
  185. struct log_msg_ids src_level, uint32_t timestamp,
  186. const char *fmt, va_list ap)
  187. {
  188. uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_FORMAT_SYSLOG |
  189. LOG_OUTPUT_FLAG_TIMESTAMP |
  190. (IS_ENABLED(CONFIG_LOG_BACKEND_NET_SYST_ENABLE) ?
  191. LOG_OUTPUT_FLAG_FORMAT_SYST : 0);
  192. uint32_t key;
  193. if (!net_init_done && do_net_init() == 0) {
  194. net_init_done = true;
  195. }
  196. key = irq_lock();
  197. log_output_string(&log_output_net, src_level,
  198. timestamp, fmt, ap, flags);
  199. irq_unlock(key);
  200. }
  201. const struct log_backend_api log_backend_net_api = {
  202. .panic = panic,
  203. .init = init_net,
  204. .process = IS_ENABLED(CONFIG_LOG2) ? process : NULL,
  205. .put = IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) ? send_output : NULL,
  206. .put_sync_string = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ?
  207. sync_string : NULL,
  208. /* Currently we do not send hexdumps over network to remote server
  209. * in CONFIG_LOG_IMMEDIATE mode. This is just to save resources,
  210. * this can be revisited if needed.
  211. */
  212. .put_sync_hexdump = NULL,
  213. };
  214. /* Note that the backend can be activated only after we have networking
  215. * subsystem ready so we must not start it immediately.
  216. */
  217. LOG_BACKEND_DEFINE(log_backend_net, log_backend_net_api,
  218. IS_ENABLED(CONFIG_LOG_BACKEND_NET_AUTOSTART));
  219. const struct log_backend *log_backend_net_get(void)
  220. {
  221. return &log_backend_net;
  222. }