ebpf_socket.c 91 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include <sys/resource.h>
  3. #include "ebpf.h"
  4. #include "ebpf_socket.h"
  5. /*****************************************************************
  6. *
  7. * GLOBAL VARIABLES
  8. *
  9. *****************************************************************/
  10. static char *socket_dimension_names[NETDATA_MAX_SOCKET_VECTOR] = { "sent", "received", "close", "sent",
  11. "received", "retransmitted" };
  12. static char *socket_id_names[NETDATA_MAX_SOCKET_VECTOR] = { "tcp_sendmsg", "tcp_cleanup_rbuf", "tcp_close",
  13. "udp_sendmsg", "udp_recvmsg", "tcp_retransmit_skb" };
  14. static netdata_idx_t *socket_hash_values = NULL;
  15. static netdata_syscall_stat_t socket_aggregated_data[NETDATA_MAX_SOCKET_VECTOR];
  16. static netdata_publish_syscall_t socket_publish_aggregated[NETDATA_MAX_SOCKET_VECTOR];
  17. static ebpf_data_t socket_data;
  18. ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
  19. static ebpf_bandwidth_t *bandwidth_vector = NULL;
  20. static int socket_apps_created = 0;
  21. pthread_mutex_t nv_mutex;
  22. int wait_to_plot = 0;
  23. int read_thread_closed = 1;
  24. netdata_vector_plot_t inbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
  25. netdata_vector_plot_t outbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
  26. netdata_socket_t *socket_values;
  27. ebpf_network_viewer_port_list_t *listen_ports = NULL;
  28. static int *map_fd = NULL;
  29. static struct bpf_object *objects = NULL;
  30. static struct bpf_link **probe_links = NULL;
  31. struct config socket_config = { .first_section = NULL,
  32. .last_section = NULL,
  33. .mutex = NETDATA_MUTEX_INITIALIZER,
  34. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  35. .rwlock = AVL_LOCK_INITIALIZER } };
  36. /*****************************************************************
  37. *
  38. * PROCESS DATA AND SEND TO NETDATA
  39. *
  40. *****************************************************************/
  41. /**
  42. * Update publish structure before to send data to Netdata.
  43. *
  44. * @param publish the first output structure with independent dimensions
  45. * @param tcp structure to store IO from tcp sockets
  46. * @param udp structure to store IO from udp sockets
  47. * @param input the structure with the input data.
  48. */
  49. static void ebpf_update_global_publish(
  50. netdata_publish_syscall_t *publish, netdata_publish_vfs_common_t *tcp, netdata_publish_vfs_common_t *udp,
  51. netdata_syscall_stat_t *input)
  52. {
  53. netdata_publish_syscall_t *move = publish;
  54. while (move) {
  55. if (input->call != move->pcall) {
  56. // This condition happens to avoid initial values with dimensions higher than normal values.
  57. if (move->pcall) {
  58. move->ncall = (input->call > move->pcall) ? input->call - move->pcall : move->pcall - input->call;
  59. move->nbyte = (input->bytes > move->pbyte) ? input->bytes - move->pbyte : move->pbyte - input->bytes;
  60. move->nerr = (input->ecall > move->nerr) ? input->ecall - move->perr : move->perr - input->ecall;
  61. } else {
  62. move->ncall = 0;
  63. move->nbyte = 0;
  64. move->nerr = 0;
  65. }
  66. move->pcall = input->call;
  67. move->pbyte = input->bytes;
  68. move->perr = input->ecall;
  69. } else {
  70. move->ncall = 0;
  71. move->nbyte = 0;
  72. move->nerr = 0;
  73. }
  74. input = input->next;
  75. move = move->next;
  76. }
  77. tcp->write = -(long)publish[0].nbyte;
  78. tcp->read = (long)publish[1].nbyte;
  79. udp->write = -(long)publish[3].nbyte;
  80. udp->read = (long)publish[4].nbyte;
  81. }
  82. /**
  83. * Update Network Viewer plot data
  84. *
  85. * @param plot the structure where the data will be stored
  86. * @param sock the last update from the socket
  87. */
  88. static inline void update_nv_plot_data(netdata_plot_values_t *plot, netdata_socket_t *sock)
  89. {
  90. if (sock->ct > plot->last_time) {
  91. plot->last_time = sock->ct;
  92. plot->plot_recv_packets = sock->recv_packets;
  93. plot->plot_sent_packets = sock->sent_packets;
  94. plot->plot_recv_bytes = sock->recv_bytes;
  95. plot->plot_sent_bytes = sock->sent_bytes;
  96. plot->plot_retransmit = sock->retransmit;
  97. }
  98. sock->recv_packets = 0;
  99. sock->sent_packets = 0;
  100. sock->recv_bytes = 0;
  101. sock->sent_bytes = 0;
  102. sock->retransmit = 0;
  103. }
  104. /**
  105. * Calculate Network Viewer Plot
  106. *
  107. * Do math with collected values before to plot data.
  108. */
  109. static inline void calculate_nv_plot()
  110. {
  111. uint32_t i;
  112. uint32_t end = inbound_vectors.next;
  113. for (i = 0; i < end; i++) {
  114. update_nv_plot_data(&inbound_vectors.plot[i].plot, &inbound_vectors.plot[i].sock);
  115. }
  116. inbound_vectors.max_plot = end;
  117. // The 'Other' dimension is always calculated for the chart to have at least one dimension
  118. update_nv_plot_data(&inbound_vectors.plot[inbound_vectors.last].plot,
  119. &inbound_vectors.plot[inbound_vectors.last].sock);
  120. end = outbound_vectors.next;
  121. for (i = 0; i < end; i++) {
  122. update_nv_plot_data(&outbound_vectors.plot[i].plot, &outbound_vectors.plot[i].sock);
  123. }
  124. outbound_vectors.max_plot = end;
  125. // The 'Other' dimension is always calculated for the chart to have at least one dimension
  126. update_nv_plot_data(&outbound_vectors.plot[outbound_vectors.last].plot,
  127. &outbound_vectors.plot[outbound_vectors.last].sock);
  128. }
  129. /**
  130. * Network viewer send bytes
  131. *
  132. * @param ptr the structure with values to plot
  133. * @param chart the chart name.
  134. */
  135. static inline void ebpf_socket_nv_send_bytes(netdata_vector_plot_t *ptr, char *chart)
  136. {
  137. uint32_t i;
  138. uint32_t end = ptr->last_plot;
  139. netdata_socket_plot_t *w = ptr->plot;
  140. collected_number value;
  141. write_begin_chart(NETDATA_EBPF_FAMILY, chart);
  142. for (i = 0; i < end; i++) {
  143. value = ((collected_number) w[i].plot.plot_sent_bytes);
  144. write_chart_dimension(w[i].dimension_sent, value);
  145. value = (collected_number) w[i].plot.plot_recv_bytes;
  146. write_chart_dimension(w[i].dimension_recv, value);
  147. }
  148. i = ptr->last;
  149. value = ((collected_number) w[i].plot.plot_sent_bytes);
  150. write_chart_dimension(w[i].dimension_sent, value);
  151. value = (collected_number) w[i].plot.plot_recv_bytes;
  152. write_chart_dimension(w[i].dimension_recv, value);
  153. write_end_chart();
  154. }
  155. /**
  156. * Network Viewer Send packets
  157. *
  158. * @param ptr the structure with values to plot
  159. * @param chart the chart name.
  160. */
  161. static inline void ebpf_socket_nv_send_packets(netdata_vector_plot_t *ptr, char *chart)
  162. {
  163. uint32_t i;
  164. uint32_t end = ptr->last_plot;
  165. netdata_socket_plot_t *w = ptr->plot;
  166. collected_number value;
  167. write_begin_chart(NETDATA_EBPF_FAMILY, chart);
  168. for (i = 0; i < end; i++) {
  169. value = ((collected_number)w[i].plot.plot_sent_packets);
  170. write_chart_dimension(w[i].dimension_sent, value);
  171. value = (collected_number) w[i].plot.plot_recv_packets;
  172. write_chart_dimension(w[i].dimension_recv, value);
  173. }
  174. i = ptr->last;
  175. value = ((collected_number)w[i].plot.plot_sent_packets);
  176. write_chart_dimension(w[i].dimension_sent, value);
  177. value = (collected_number)w[i].plot.plot_recv_packets;
  178. write_chart_dimension(w[i].dimension_recv, value);
  179. write_end_chart();
  180. }
  181. /**
  182. * Network Viewer Send Retransmit
  183. *
  184. * @param ptr the structure with values to plot
  185. * @param chart the chart name.
  186. */
  187. static inline void ebpf_socket_nv_send_retransmit(netdata_vector_plot_t *ptr, char *chart)
  188. {
  189. uint32_t i;
  190. uint32_t end = ptr->last_plot;
  191. netdata_socket_plot_t *w = ptr->plot;
  192. collected_number value;
  193. write_begin_chart(NETDATA_EBPF_FAMILY, chart);
  194. for (i = 0; i < end; i++) {
  195. value = (collected_number) w[i].plot.plot_retransmit;
  196. write_chart_dimension(w[i].dimension_retransmit, value);
  197. }
  198. i = ptr->last;
  199. value = (collected_number)w[i].plot.plot_retransmit;
  200. write_chart_dimension(w[i].dimension_retransmit, value);
  201. write_end_chart();
  202. }
  203. /**
  204. * Send network viewer data
  205. *
  206. * @param ptr the pointer to plot data
  207. */
  208. static void ebpf_socket_send_nv_data(netdata_vector_plot_t *ptr)
  209. {
  210. if (!ptr->flags)
  211. return;
  212. if (ptr == (netdata_vector_plot_t *)&outbound_vectors) {
  213. ebpf_socket_nv_send_bytes(ptr, NETDATA_NV_OUTBOUND_BYTES);
  214. fflush(stdout);
  215. ebpf_socket_nv_send_packets(ptr, NETDATA_NV_OUTBOUND_PACKETS);
  216. fflush(stdout);
  217. ebpf_socket_nv_send_retransmit(ptr, NETDATA_NV_OUTBOUND_RETRANSMIT);
  218. fflush(stdout);
  219. } else {
  220. ebpf_socket_nv_send_bytes(ptr, NETDATA_NV_INBOUND_BYTES);
  221. fflush(stdout);
  222. ebpf_socket_nv_send_packets(ptr, NETDATA_NV_INBOUND_PACKETS);
  223. fflush(stdout);
  224. }
  225. }
  226. /**
  227. * Send data to Netdata calling auxiliar functions.
  228. *
  229. * @param em the structure with thread information
  230. */
  231. static void ebpf_socket_send_data(ebpf_module_t *em)
  232. {
  233. netdata_publish_vfs_common_t common_tcp;
  234. netdata_publish_vfs_common_t common_udp;
  235. ebpf_update_global_publish(socket_publish_aggregated, &common_tcp, &common_udp, socket_aggregated_data);
  236. // We read bytes from function arguments, but bandiwdth is given in bits,
  237. // so we need to multiply by 8 to convert for the final value.
  238. write_count_chart(
  239. NETDATA_TCP_FUNCTION_COUNT, NETDATA_EBPF_FAMILY, socket_publish_aggregated, 3);
  240. write_io_chart(
  241. NETDATA_TCP_FUNCTION_BITS, NETDATA_EBPF_FAMILY, socket_id_names[0], common_tcp.write*8/1000,
  242. socket_id_names[1], common_tcp.read*8/1000);
  243. if (em->mode < MODE_ENTRY) {
  244. write_err_chart(
  245. NETDATA_TCP_FUNCTION_ERROR, NETDATA_EBPF_FAMILY, socket_publish_aggregated, 2);
  246. }
  247. write_count_chart(
  248. NETDATA_TCP_RETRANSMIT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT],
  249. 1);
  250. write_count_chart(
  251. NETDATA_UDP_FUNCTION_COUNT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
  252. 2);
  253. write_io_chart(
  254. NETDATA_UDP_FUNCTION_BITS, NETDATA_EBPF_FAMILY,
  255. socket_id_names[3],(long long)common_udp.write*8/100,
  256. socket_id_names[4], (long long)common_udp.read*8/1000);
  257. if (em->mode < MODE_ENTRY) {
  258. write_err_chart(
  259. NETDATA_UDP_FUNCTION_ERROR, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_UDP_START],
  260. 2);
  261. }
  262. }
  263. /**
  264. * Sum values for pid
  265. *
  266. * @param root the structure with all available PIDs
  267. *
  268. * @param offset the address that we are reading
  269. *
  270. * @return it returns the sum of all PIDs
  271. */
  272. long long ebpf_socket_sum_values_for_pids(struct pid_on_target *root, size_t offset)
  273. {
  274. long long ret = 0;
  275. while (root) {
  276. int32_t pid = root->pid;
  277. ebpf_socket_publish_apps_t *w = socket_bandwidth_curr[pid];
  278. if (w) {
  279. ret += get_value_from_structure((char *)w, offset);
  280. }
  281. root = root->next;
  282. }
  283. return ret;
  284. }
  285. /**
  286. * Send data to Netdata calling auxiliar functions.
  287. *
  288. * @param em the structure with thread information
  289. * @param root the target list.
  290. */
  291. void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root)
  292. {
  293. UNUSED(em);
  294. if (!socket_apps_created)
  295. return;
  296. struct target *w;
  297. collected_number value;
  298. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_SENT);
  299. for (w = root; w; w = w->next) {
  300. if (unlikely(w->exposed && w->processes)) {
  301. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  302. bytes_sent));
  303. // We multiply by 0.008, because we read bytes, but we display bits
  304. write_chart_dimension(w->name, ((value)*8)/1000);
  305. }
  306. }
  307. write_end_chart();
  308. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_RECV);
  309. for (w = root; w; w = w->next) {
  310. if (unlikely(w->exposed && w->processes)) {
  311. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  312. bytes_received));
  313. // We multiply by 0.008, because we read bytes, but we display bits
  314. write_chart_dimension(w->name, ((value)*8)/1000);
  315. }
  316. }
  317. write_end_chart();
  318. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS);
  319. for (w = root; w; w = w->next) {
  320. if (unlikely(w->exposed && w->processes)) {
  321. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  322. call_tcp_sent));
  323. write_chart_dimension(w->name, value);
  324. }
  325. }
  326. write_end_chart();
  327. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS);
  328. for (w = root; w; w = w->next) {
  329. if (unlikely(w->exposed && w->processes)) {
  330. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  331. call_tcp_received));
  332. write_chart_dimension(w->name, value);
  333. }
  334. }
  335. write_end_chart();
  336. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT);
  337. for (w = root; w; w = w->next) {
  338. if (unlikely(w->exposed && w->processes)) {
  339. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  340. retransmit));
  341. write_chart_dimension(w->name, value);
  342. }
  343. }
  344. write_end_chart();
  345. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS);
  346. for (w = root; w; w = w->next) {
  347. if (unlikely(w->exposed && w->processes)) {
  348. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  349. call_udp_sent));
  350. write_chart_dimension(w->name, value);
  351. }
  352. }
  353. write_end_chart();
  354. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS);
  355. for (w = root; w; w = w->next) {
  356. if (unlikely(w->exposed && w->processes)) {
  357. value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t,
  358. call_udp_received));
  359. write_chart_dimension(w->name, value);
  360. }
  361. }
  362. write_end_chart();
  363. }
  364. /*****************************************************************
  365. *
  366. * FUNCTIONS TO CREATE CHARTS
  367. *
  368. *****************************************************************/
  369. /**
  370. * Create global charts
  371. *
  372. * Call ebpf_create_chart to create the charts for the collector.
  373. *
  374. * @param em a pointer to the structure with the default values.
  375. */
  376. static void ebpf_create_global_charts(ebpf_module_t *em)
  377. {
  378. ebpf_create_chart(NETDATA_EBPF_FAMILY,
  379. NETDATA_TCP_FUNCTION_COUNT,
  380. "Calls to internal functions",
  381. EBPF_COMMON_DIMENSION_CALL,
  382. NETDATA_SOCKET_GROUP,
  383. NULL,
  384. NETDATA_EBPF_CHART_TYPE_LINE,
  385. 21070,
  386. ebpf_create_global_dimension,
  387. socket_publish_aggregated,
  388. 3);
  389. ebpf_create_chart(NETDATA_EBPF_FAMILY, NETDATA_TCP_FUNCTION_BITS,
  390. "TCP bandwidth", EBPF_COMMON_DIMENSION_BITS,
  391. NETDATA_SOCKET_GROUP,
  392. NULL,
  393. NETDATA_EBPF_CHART_TYPE_LINE,
  394. 21071,
  395. ebpf_create_global_dimension,
  396. socket_publish_aggregated,
  397. 3);
  398. if (em->mode < MODE_ENTRY) {
  399. ebpf_create_chart(NETDATA_EBPF_FAMILY,
  400. NETDATA_TCP_FUNCTION_ERROR,
  401. "TCP errors",
  402. EBPF_COMMON_DIMENSION_CALL,
  403. NETDATA_SOCKET_GROUP,
  404. NULL,
  405. NETDATA_EBPF_CHART_TYPE_LINE,
  406. 21072,
  407. ebpf_create_global_dimension,
  408. socket_publish_aggregated,
  409. 2);
  410. }
  411. ebpf_create_chart(NETDATA_EBPF_FAMILY,
  412. NETDATA_TCP_RETRANSMIT,
  413. "Packages retransmitted",
  414. EBPF_COMMON_DIMENSION_CALL,
  415. NETDATA_SOCKET_GROUP,
  416. NULL,
  417. NETDATA_EBPF_CHART_TYPE_LINE,
  418. 21073,
  419. ebpf_create_global_dimension,
  420. &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT],
  421. 1);
  422. ebpf_create_chart(NETDATA_EBPF_FAMILY,
  423. NETDATA_UDP_FUNCTION_COUNT,
  424. "UDP calls",
  425. EBPF_COMMON_DIMENSION_CALL,
  426. NETDATA_SOCKET_GROUP,
  427. NULL,
  428. NETDATA_EBPF_CHART_TYPE_LINE,
  429. 21074,
  430. ebpf_create_global_dimension,
  431. &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
  432. 2);
  433. ebpf_create_chart(NETDATA_EBPF_FAMILY, NETDATA_UDP_FUNCTION_BITS,
  434. "UDP bandwidth", EBPF_COMMON_DIMENSION_BITS,
  435. NETDATA_SOCKET_GROUP,
  436. NULL,
  437. NETDATA_EBPF_CHART_TYPE_LINE,
  438. 21075,
  439. ebpf_create_global_dimension,
  440. &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
  441. 2);
  442. if (em->mode < MODE_ENTRY) {
  443. ebpf_create_chart(NETDATA_EBPF_FAMILY,
  444. NETDATA_UDP_FUNCTION_ERROR,
  445. "UDP errors",
  446. EBPF_COMMON_DIMENSION_CALL,
  447. NETDATA_SOCKET_GROUP,
  448. NULL,
  449. NETDATA_EBPF_CHART_TYPE_LINE,
  450. 21076,
  451. ebpf_create_global_dimension,
  452. &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
  453. 2);
  454. }
  455. }
  456. /**
  457. * Create apps charts
  458. *
  459. * Call ebpf_create_chart to create the charts on apps submenu.
  460. *
  461. * @param em a pointer to the structure with the default values.
  462. * @param ptr a pointer for targets
  463. */
  464. void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
  465. {
  466. UNUSED(em);
  467. struct target *root = ptr;;
  468. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_SENT,
  469. "Bytes sent", EBPF_COMMON_DIMENSION_BITS,
  470. NETDATA_APPS_NET_GROUP,
  471. NETDATA_EBPF_CHART_TYPE_STACKED,
  472. 20080,
  473. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  474. root);
  475. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_RECV,
  476. "bytes received", EBPF_COMMON_DIMENSION_BITS,
  477. NETDATA_APPS_NET_GROUP,
  478. NETDATA_EBPF_CHART_TYPE_STACKED,
  479. 20081,
  480. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  481. root);
  482. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS,
  483. "Calls for tcp_sendmsg",
  484. EBPF_COMMON_DIMENSION_CALL,
  485. NETDATA_APPS_NET_GROUP,
  486. NETDATA_EBPF_CHART_TYPE_STACKED,
  487. 20082,
  488. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  489. root);
  490. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS,
  491. "Calls for tcp_cleanup_rbuf",
  492. EBPF_COMMON_DIMENSION_CALL,
  493. NETDATA_APPS_NET_GROUP,
  494. NETDATA_EBPF_CHART_TYPE_STACKED,
  495. 20083,
  496. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  497. root);
  498. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT,
  499. "Calls for tcp_retransmit",
  500. EBPF_COMMON_DIMENSION_CALL,
  501. NETDATA_APPS_NET_GROUP,
  502. NETDATA_EBPF_CHART_TYPE_STACKED,
  503. 20084,
  504. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  505. root);
  506. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS,
  507. "Calls for udp_sendmsg",
  508. EBPF_COMMON_DIMENSION_CALL,
  509. NETDATA_APPS_NET_GROUP,
  510. NETDATA_EBPF_CHART_TYPE_STACKED,
  511. 20085,
  512. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  513. root);
  514. ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS,
  515. "Calls for udp_recvmsg",
  516. EBPF_COMMON_DIMENSION_CALL,
  517. NETDATA_APPS_NET_GROUP,
  518. NETDATA_EBPF_CHART_TYPE_STACKED,
  519. 20086,
  520. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  521. root);
  522. socket_apps_created = 1;
  523. }
  524. /**
  525. * Create network viewer chart
  526. *
  527. * Create common charts.
  528. *
  529. * @param id the chart id
  530. * @param title the chart title
  531. * @param units the units label
  532. * @param family the group name used to attach the chart on dashaboard
  533. * @param order the chart order
  534. * @param ptr the plot structure with values.
  535. */
  536. static void ebpf_socket_create_nv_chart(char *id, char *title, char *units,
  537. char *family, int order, netdata_vector_plot_t *ptr)
  538. {
  539. ebpf_write_chart_cmd(NETDATA_EBPF_FAMILY,
  540. id,
  541. title,
  542. units,
  543. family,
  544. NETDATA_EBPF_CHART_TYPE_STACKED,
  545. NULL,
  546. order);
  547. uint32_t i;
  548. uint32_t end = ptr->last_plot;
  549. netdata_socket_plot_t *w = ptr->plot;
  550. for (i = 0; i < end; i++) {
  551. fprintf(stdout, "DIMENSION %s '' incremental -1 1\n", w[i].dimension_sent);
  552. fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w[i].dimension_recv);
  553. }
  554. end = ptr->last;
  555. fprintf(stdout, "DIMENSION %s '' incremental -1 1\n", w[end].dimension_sent);
  556. fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w[end].dimension_recv);
  557. }
  558. /**
  559. * Create network viewer retransmit
  560. *
  561. * Create a specific chart.
  562. *
  563. * @param id the chart id
  564. * @param title the chart title
  565. * @param units the units label
  566. * @param family the group name used to attach the chart on dashaboard
  567. * @param order the chart order
  568. * @param ptr the plot structure with values.
  569. */
  570. static void ebpf_socket_create_nv_retransmit(char *id, char *title, char *units,
  571. char *family, int order, netdata_vector_plot_t *ptr)
  572. {
  573. ebpf_write_chart_cmd(NETDATA_EBPF_FAMILY,
  574. id,
  575. title,
  576. units,
  577. family,
  578. NETDATA_EBPF_CHART_TYPE_STACKED,
  579. NULL,
  580. order);
  581. uint32_t i;
  582. uint32_t end = ptr->last_plot;
  583. netdata_socket_plot_t *w = ptr->plot;
  584. for (i = 0; i < end; i++) {
  585. fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w[i].dimension_retransmit);
  586. }
  587. end = ptr->last;
  588. fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w[end].dimension_retransmit);
  589. }
  590. /**
  591. * Create Network Viewer charts
  592. *
  593. * Recreate the charts when new sockets are created.
  594. *
  595. * @param ptr a pointer for inbound or outbound vectors.
  596. */
  597. static void ebpf_socket_create_nv_charts(netdata_vector_plot_t *ptr)
  598. {
  599. // We do not have new sockets, so we do not need move forward
  600. if (ptr->max_plot == ptr->last_plot)
  601. return;
  602. ptr->last_plot = ptr->max_plot;
  603. if (ptr == (netdata_vector_plot_t *)&outbound_vectors) {
  604. ebpf_socket_create_nv_chart(NETDATA_NV_OUTBOUND_BYTES,
  605. "Outbound connections (bytes).", EBPF_COMMON_DIMENSION_BYTES,
  606. NETDATA_NETWORK_CONNECTIONS_GROUP,
  607. 21080,
  608. ptr);
  609. ebpf_socket_create_nv_chart(NETDATA_NV_OUTBOUND_PACKETS,
  610. "Outbound connections (packets)",
  611. EBPF_COMMON_DIMENSION_PACKETS,
  612. NETDATA_NETWORK_CONNECTIONS_GROUP,
  613. 21082,
  614. ptr);
  615. ebpf_socket_create_nv_retransmit(NETDATA_NV_OUTBOUND_RETRANSMIT,
  616. "Retransmitted packets",
  617. EBPF_COMMON_DIMENSION_CALL,
  618. NETDATA_NETWORK_CONNECTIONS_GROUP,
  619. 21083,
  620. ptr);
  621. } else {
  622. ebpf_socket_create_nv_chart(NETDATA_NV_INBOUND_BYTES,
  623. "Inbound connections (bytes)", EBPF_COMMON_DIMENSION_BYTES,
  624. NETDATA_NETWORK_CONNECTIONS_GROUP,
  625. 21084,
  626. ptr);
  627. ebpf_socket_create_nv_chart(NETDATA_NV_INBOUND_PACKETS,
  628. "Inbound connections (packets)",
  629. EBPF_COMMON_DIMENSION_PACKETS,
  630. NETDATA_NETWORK_CONNECTIONS_GROUP,
  631. 21085,
  632. ptr);
  633. }
  634. ptr->flags |= NETWORK_VIEWER_CHARTS_CREATED;
  635. }
  636. /*****************************************************************
  637. *
  638. * READ INFORMATION FROM KERNEL RING
  639. *
  640. *****************************************************************/
  641. /**
  642. * Is specific ip inside the range
  643. *
  644. * Check if the ip is inside a IP range previously defined
  645. *
  646. * @param cmp the IP to compare
  647. * @param family the IP family
  648. *
  649. * @return It returns 1 if the IP is inside the range and 0 otherwise
  650. */
  651. static int is_specific_ip_inside_range(union netdata_ip_t *cmp, int family)
  652. {
  653. if (!network_viewer_opt.excluded_ips && !network_viewer_opt.included_ips)
  654. return 1;
  655. uint32_t ipv4_test = ntohl(cmp->addr32[0]);
  656. ebpf_network_viewer_ip_list_t *move = network_viewer_opt.excluded_ips;
  657. while (move) {
  658. if (family == AF_INET) {
  659. if (ntohl(move->first.addr32[0]) <= ipv4_test &&
  660. ipv4_test <= ntohl(move->last.addr32[0]) )
  661. return 0;
  662. } else {
  663. if (memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
  664. memcmp(move->last.addr8, cmp->addr8, sizeof(union netdata_ip_t)) >= 0) {
  665. return 0;
  666. }
  667. }
  668. move = move->next;
  669. }
  670. move = network_viewer_opt.included_ips;
  671. while (move) {
  672. if (family == AF_INET) {
  673. if (ntohl(move->first.addr32[0]) <= ipv4_test &&
  674. ntohl(move->last.addr32[0]) >= ipv4_test)
  675. return 1;
  676. } else {
  677. if (memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
  678. memcmp(move->last.addr8, cmp->addr8, sizeof(union netdata_ip_t)) >= 0) {
  679. return 1;
  680. }
  681. }
  682. move = move->next;
  683. }
  684. return 0;
  685. }
  686. /**
  687. * Is port inside range
  688. *
  689. * Verify if the cmp port is inside the range [first, last].
  690. * This function expects only the last parameter as big endian.
  691. *
  692. * @param cmp the value to compare
  693. *
  694. * @return It returns 1 when cmp is inside and 0 otherwise.
  695. */
  696. static int is_port_inside_range(uint16_t cmp)
  697. {
  698. // We do not have restrictions for ports.
  699. if (!network_viewer_opt.excluded_port && !network_viewer_opt.included_port)
  700. return 1;
  701. // Test if port is excluded
  702. ebpf_network_viewer_port_list_t *move = network_viewer_opt.excluded_port;
  703. cmp = htons(cmp);
  704. while (move) {
  705. if (move->cmp_first <= cmp && cmp <= move->cmp_last)
  706. return 0;
  707. move = move->next;
  708. }
  709. // Test if the port is inside allowed range
  710. move = network_viewer_opt.included_port;
  711. while (move) {
  712. if (move->cmp_first <= cmp && cmp <= move->cmp_last)
  713. return 1;
  714. move = move->next;
  715. }
  716. return 0;
  717. }
  718. /**
  719. * Hostname matches pattern
  720. *
  721. * @param cmp the value to compare
  722. *
  723. * @return It returns 1 when the value matches and zero otherwise.
  724. */
  725. int hostname_matches_pattern(char *cmp)
  726. {
  727. if (!network_viewer_opt.included_hostnames && !network_viewer_opt.excluded_hostnames)
  728. return 1;
  729. ebpf_network_viewer_hostname_list_t *move = network_viewer_opt.excluded_hostnames;
  730. while (move) {
  731. if (simple_pattern_matches(move->value_pattern, cmp))
  732. return 0;
  733. move = move->next;
  734. }
  735. move = network_viewer_opt.included_hostnames;
  736. while (move) {
  737. if (simple_pattern_matches(move->value_pattern, cmp))
  738. return 1;
  739. move = move->next;
  740. }
  741. return 0;
  742. }
  743. /**
  744. * Is socket allowed?
  745. *
  746. * Compare destination addresses and destination ports to define next steps
  747. *
  748. * @param key the socket read from kernel ring
  749. * @param family the family used to compare IPs (AF_INET and AF_INET6)
  750. *
  751. * @return It returns 1 if this socket is inside the ranges and 0 otherwise.
  752. */
  753. int is_socket_allowed(netdata_socket_idx_t *key, int family)
  754. {
  755. if (!is_port_inside_range(key->dport))
  756. return 0;
  757. return is_specific_ip_inside_range(&key->daddr, family);
  758. }
  759. /**
  760. * Compare sockets
  761. *
  762. * Compare destination address and destination port.
  763. * We do not compare source port, because it is random.
  764. * We also do not compare source address, because inbound and outbound connections are stored in separated AVL trees.
  765. *
  766. * @param a pointer to netdata_socket_plot
  767. * @param b pointer to netdata_socket_plot
  768. *
  769. * @return It returns 0 case the values are equal, 1 case a is bigger than b and -1 case a is smaller than b.
  770. */
  771. static int compare_sockets(void *a, void *b)
  772. {
  773. struct netdata_socket_plot *val1 = a;
  774. struct netdata_socket_plot *val2 = b;
  775. int cmp;
  776. // We do not need to compare val2 family, because data inside hash table is always from the same family
  777. if (val1->family == AF_INET) { //IPV4
  778. if (val1->flags & NETDATA_INBOUND_DIRECTION) {
  779. if (val1->index.sport == val2->index.sport)
  780. cmp = 0;
  781. else {
  782. cmp = (val1->index.sport > val2->index.sport)?1:-1;
  783. }
  784. } else {
  785. cmp = memcmp(&val1->index.dport, &val2->index.dport, sizeof(uint16_t));
  786. if (!cmp) {
  787. cmp = memcmp(&val1->index.daddr.addr32[0], &val2->index.daddr.addr32[0], sizeof(uint32_t));
  788. }
  789. }
  790. } else {
  791. if (val1->flags & NETDATA_INBOUND_DIRECTION) {
  792. if (val1->index.sport == val2->index.sport)
  793. cmp = 0;
  794. else {
  795. cmp = (val1->index.sport > val2->index.sport)?1:-1;
  796. }
  797. } else {
  798. cmp = memcmp(&val1->index.dport, &val2->index.dport, sizeof(uint16_t));
  799. if (!cmp) {
  800. cmp = memcmp(&val1->index.daddr.addr32, &val2->index.daddr.addr32, 4*sizeof(uint32_t));
  801. }
  802. }
  803. }
  804. return cmp;
  805. }
  806. /**
  807. * Build dimension name
  808. *
  809. * Fill dimension name vector with values given
  810. *
  811. * @param dimname the output vector
  812. * @param hostname the hostname for the socket.
  813. * @param service_name the service used to connect.
  814. * @param proto the protocol used in this connection
  815. * @param family is this IPV4(AF_INET) or IPV6(AF_INET6)
  816. *
  817. * @return it returns the size of the data copied on success and -1 otherwise.
  818. */
  819. static inline int build_outbound_dimension_name(char *dimname, char *hostname, char *service_name,
  820. char *proto, int family)
  821. {
  822. return snprintf(dimname, CONFIG_MAX_NAME - 7, (family == AF_INET)?"%s:%s:%s_":"%s:%s:[%s]_",
  823. service_name, proto,
  824. hostname);
  825. }
  826. /**
  827. * Fill inbound dimension name
  828. *
  829. * Mount the dimension name with the input given
  830. *
  831. * @param dimname the output vector
  832. * @param service_name the service used to connect.
  833. * @param proto the protocol used in this connection
  834. *
  835. * @return it returns the size of the data copied on success and -1 otherwise.
  836. */
  837. static inline int build_inbound_dimension_name(char *dimname, char *service_name, char *proto)
  838. {
  839. return snprintf(dimname, CONFIG_MAX_NAME - 7, "%s:%s_", service_name,
  840. proto);
  841. }
  842. /**
  843. * Fill Resolved Name
  844. *
  845. * Fill the resolved name structure with the value given.
  846. * The hostname is the largest value possible, if it is necessary to cut some value, it must be cut.
  847. *
  848. * @param ptr the output vector
  849. * @param hostname the hostname resolved or IP.
  850. * @param length the length for the hostname.
  851. * @param service_name the service name associated to the connection
  852. * @param is_outbound the is this an outbound connection
  853. */
  854. static inline void fill_resolved_name(netdata_socket_plot_t *ptr, char *hostname, size_t length,
  855. char *service_name, int is_outbound)
  856. {
  857. if (length < NETDATA_MAX_NETWORK_COMBINED_LENGTH)
  858. ptr->resolved_name = strdupz(hostname);
  859. else {
  860. length = NETDATA_MAX_NETWORK_COMBINED_LENGTH;
  861. ptr->resolved_name = mallocz( NETDATA_MAX_NETWORK_COMBINED_LENGTH + 1);
  862. memcpy(ptr->resolved_name, hostname, length);
  863. ptr->resolved_name[length] = '\0';
  864. }
  865. char dimname[CONFIG_MAX_NAME];
  866. int size;
  867. char *protocol;
  868. if (ptr->sock.protocol == IPPROTO_UDP) {
  869. protocol = "UDP";
  870. } else if (ptr->sock.protocol == IPPROTO_TCP) {
  871. protocol = "TCP";
  872. } else {
  873. protocol = "ALL";
  874. }
  875. if (is_outbound)
  876. size = build_outbound_dimension_name(dimname, hostname, service_name, protocol, ptr->family);
  877. else
  878. size = build_inbound_dimension_name(dimname,service_name, protocol);
  879. if (size > 0) {
  880. strcpy(&dimname[size], "sent");
  881. dimname[size + 4] = '\0';
  882. ptr->dimension_sent = strdupz(dimname);
  883. strcpy(&dimname[size], "recv");
  884. ptr->dimension_recv = strdupz(dimname);
  885. dimname[size - 1] = '\0';
  886. ptr->dimension_retransmit = strdupz(dimname);
  887. }
  888. }
  889. /**
  890. * Mount dimension names
  891. *
  892. * Fill the vector names after to resolve the addresses
  893. *
  894. * @param ptr a pointer to the structure where the values are stored.
  895. * @param is_outbound is a outbound ptr value?
  896. *
  897. * @return It returns 1 if the name is valid and 0 otherwise.
  898. */
  899. int fill_names(netdata_socket_plot_t *ptr, int is_outbound)
  900. {
  901. char hostname[NI_MAXHOST], service_name[NI_MAXSERV];
  902. if (ptr->resolved)
  903. return 1;
  904. int ret;
  905. static int resolve_name = -1;
  906. static int resolve_service = -1;
  907. if (resolve_name == -1)
  908. resolve_name = network_viewer_opt.hostname_resolution_enabled;
  909. if (resolve_service == -1)
  910. resolve_service = network_viewer_opt.service_resolution_enabled;
  911. netdata_socket_idx_t *idx = &ptr->index;
  912. char *errname = { "Not resolved" };
  913. // Resolve Name
  914. if (ptr->family == AF_INET) { //IPV4
  915. struct sockaddr_in myaddr;
  916. memset(&myaddr, 0 , sizeof(myaddr));
  917. myaddr.sin_family = ptr->family;
  918. if (is_outbound) {
  919. myaddr.sin_port = idx->dport;
  920. myaddr.sin_addr.s_addr = idx->daddr.addr32[0];
  921. } else {
  922. myaddr.sin_port = idx->sport;
  923. myaddr.sin_addr.s_addr = idx->saddr.addr32[0];
  924. }
  925. ret = (!resolve_name)?-1:getnameinfo((struct sockaddr *)&myaddr, sizeof(myaddr), hostname,
  926. sizeof(hostname), service_name, sizeof(service_name), NI_NAMEREQD);
  927. if (!ret && !resolve_service) {
  928. snprintf(service_name, sizeof(service_name), "%u", ntohs(myaddr.sin_port));
  929. }
  930. if (ret) {
  931. // I cannot resolve the name, I will use the IP
  932. if (!inet_ntop(AF_INET, &myaddr.sin_addr.s_addr, hostname, NI_MAXHOST)) {
  933. strncpy(hostname, errname, 13);
  934. }
  935. snprintf(service_name, sizeof(service_name), "%u", ntohs(myaddr.sin_port));
  936. ret = 1;
  937. }
  938. } else { // IPV6
  939. struct sockaddr_in6 myaddr6;
  940. memset(&myaddr6, 0 , sizeof(myaddr6));
  941. myaddr6.sin6_family = AF_INET6;
  942. if (is_outbound) {
  943. myaddr6.sin6_port = idx->dport;
  944. memcpy(myaddr6.sin6_addr.s6_addr, idx->daddr.addr8, sizeof(union netdata_ip_t));
  945. } else {
  946. myaddr6.sin6_port = idx->sport;
  947. memcpy(myaddr6.sin6_addr.s6_addr, idx->saddr.addr8, sizeof(union netdata_ip_t));
  948. }
  949. ret = (!resolve_name)?-1:getnameinfo((struct sockaddr *)&myaddr6, sizeof(myaddr6), hostname,
  950. sizeof(hostname), service_name, sizeof(service_name), NI_NAMEREQD);
  951. if (!ret && !resolve_service) {
  952. snprintf(service_name, sizeof(service_name), "%u", ntohs(myaddr6.sin6_port));
  953. }
  954. if (ret) {
  955. // I cannot resolve the name, I will use the IP
  956. if (!inet_ntop(AF_INET6, myaddr6.sin6_addr.s6_addr, hostname, NI_MAXHOST)) {
  957. strncpy(hostname, errname, 13);
  958. }
  959. snprintf(service_name, sizeof(service_name), "%u", ntohs(myaddr6.sin6_port));
  960. ret = 1;
  961. }
  962. }
  963. fill_resolved_name(ptr, hostname,
  964. strlen(hostname) + strlen(service_name)+ NETDATA_DOTS_PROTOCOL_COMBINED_LENGTH,
  965. service_name, is_outbound);
  966. if (resolve_name && !ret)
  967. ret = hostname_matches_pattern(hostname);
  968. ptr->resolved++;
  969. return ret;
  970. }
  971. /**
  972. * Fill last Network Viewer Dimension
  973. *
  974. * Fill the unique dimension that is always plotted.
  975. *
  976. * @param ptr the pointer for the last dimension
  977. * @param is_outbound is this an inbound structure?
  978. */
  979. static void fill_last_nv_dimension(netdata_socket_plot_t *ptr, int is_outbound)
  980. {
  981. char hostname[NI_MAXHOST], service_name[NI_MAXSERV];
  982. char *other = { "other" };
  983. // We are also copying the NULL bytes to avoid warnings in new compilers
  984. strncpy(hostname, other, 6);
  985. strncpy(service_name, other, 6);
  986. ptr->family = AF_INET;
  987. ptr->sock.protocol = 255;
  988. ptr->flags = (!is_outbound)?NETDATA_INBOUND_DIRECTION:NETDATA_OUTBOUND_DIRECTION;
  989. fill_resolved_name(ptr, hostname, 10 + NETDATA_DOTS_PROTOCOL_COMBINED_LENGTH, service_name, is_outbound);
  990. #ifdef NETDATA_INTERNAL_CHECKS
  991. info("Last %s dimension added: ID = %u, IP = OTHER, NAME = %s, DIM1 = %s, DIM2 = %s, DIM3 = %s",
  992. (is_outbound)?"outbound":"inbound", network_viewer_opt.max_dim - 1, ptr->resolved_name,
  993. ptr->dimension_recv, ptr->dimension_sent, ptr->dimension_retransmit);
  994. #endif
  995. }
  996. /**
  997. * Update Socket Data
  998. *
  999. * Update the socket information with last collected data
  1000. *
  1001. * @param sock
  1002. * @param lvalues
  1003. */
  1004. static inline void update_socket_data(netdata_socket_t *sock, netdata_socket_t *lvalues)
  1005. {
  1006. sock->recv_packets += lvalues->recv_packets;
  1007. sock->sent_packets += lvalues->sent_packets;
  1008. sock->recv_bytes += lvalues->recv_bytes;
  1009. sock->sent_bytes += lvalues->sent_bytes;
  1010. sock->retransmit += lvalues->retransmit;
  1011. if (lvalues->ct > sock->ct)
  1012. sock->ct = lvalues->ct;
  1013. }
  1014. /**
  1015. * Store socket inside avl
  1016. *
  1017. * Store the socket values inside the avl tree.
  1018. *
  1019. * @param out the structure with information used to plot charts.
  1020. * @param lvalues Values read from socket ring.
  1021. * @param lindex the index information, the real socket.
  1022. * @param family the family associated to the socket
  1023. * @param flags the connection flags
  1024. */
  1025. static void store_socket_inside_avl(netdata_vector_plot_t *out, netdata_socket_t *lvalues,
  1026. netdata_socket_idx_t *lindex, int family, uint32_t flags)
  1027. {
  1028. netdata_socket_plot_t test, *ret ;
  1029. memcpy(&test.index, lindex, sizeof(netdata_socket_idx_t));
  1030. test.flags = flags;
  1031. ret = (netdata_socket_plot_t *) avl_search_lock(&out->tree, (avl_t *)&test);
  1032. if (ret) {
  1033. if (lvalues->ct > ret->plot.last_time) {
  1034. update_socket_data(&ret->sock, lvalues);
  1035. }
  1036. } else {
  1037. uint32_t curr = out->next;
  1038. uint32_t last = out->last;
  1039. netdata_socket_plot_t *w = &out->plot[curr];
  1040. int resolved;
  1041. if (curr == last) {
  1042. if (lvalues->ct > w->plot.last_time) {
  1043. update_socket_data(&w->sock, lvalues);
  1044. }
  1045. return;
  1046. } else {
  1047. memcpy(&w->sock, lvalues, sizeof(netdata_socket_t));
  1048. memcpy(&w->index, lindex, sizeof(netdata_socket_idx_t));
  1049. w->family = family;
  1050. resolved = fill_names(w, out != (netdata_vector_plot_t *)&inbound_vectors);
  1051. }
  1052. if (!resolved) {
  1053. freez(w->resolved_name);
  1054. freez(w->dimension_sent);
  1055. freez(w->dimension_recv);
  1056. freez(w->dimension_retransmit);
  1057. memset(w, 0, sizeof(netdata_socket_plot_t));
  1058. return;
  1059. }
  1060. w->flags = flags;
  1061. netdata_socket_plot_t *check ;
  1062. check = (netdata_socket_plot_t *) avl_insert_lock(&out->tree, (avl_t *)w);
  1063. if (check != w)
  1064. error("Internal error, cannot insert the AVL tree.");
  1065. #ifdef NETDATA_INTERNAL_CHECKS
  1066. char iptext[INET6_ADDRSTRLEN];
  1067. if (inet_ntop(family, &w->index.daddr.addr8, iptext, sizeof(iptext)))
  1068. info("New %s dimension added: ID = %u, IP = %s, NAME = %s, DIM1 = %s, DIM2 = %s, DIM3 = %s",
  1069. (out == &inbound_vectors)?"inbound":"outbound", curr, iptext, w->resolved_name,
  1070. w->dimension_recv, w->dimension_sent, w->dimension_retransmit);
  1071. #endif
  1072. curr++;
  1073. if (curr > last)
  1074. curr = last;
  1075. out->next = curr;
  1076. }
  1077. }
  1078. /**
  1079. * Compare Vector to store
  1080. *
  1081. * Compare input values with local address to select table to store.
  1082. *
  1083. * @param direction store inbound and outbound direction.
  1084. * @param cmp index read from hash table.
  1085. * @param proto the protocol read.
  1086. *
  1087. * @return It returns the structure with address to compare.
  1088. */
  1089. netdata_vector_plot_t * select_vector_to_store(uint32_t *direction, netdata_socket_idx_t *cmp, uint8_t proto)
  1090. {
  1091. if (!listen_ports) {
  1092. *direction = NETDATA_OUTBOUND_DIRECTION;
  1093. return &outbound_vectors;
  1094. }
  1095. ebpf_network_viewer_port_list_t *move_ports = listen_ports;
  1096. while (move_ports) {
  1097. if (move_ports->protocol == proto && move_ports->first == cmp->sport) {
  1098. *direction = NETDATA_INBOUND_DIRECTION;
  1099. return &inbound_vectors;
  1100. }
  1101. move_ports = move_ports->next;
  1102. }
  1103. *direction = NETDATA_OUTBOUND_DIRECTION;
  1104. return &outbound_vectors;
  1105. }
  1106. /**
  1107. * Hash accumulator
  1108. *
  1109. * @param values the values used to calculate the data.
  1110. * @param key the key to store data.
  1111. * @param removesock check if this socket must be removed .
  1112. * @param family the connection family
  1113. * @param end the values size.
  1114. */
  1115. static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key, int *removesock, int family, int end)
  1116. {
  1117. uint64_t bsent = 0, brecv = 0, psent = 0, precv = 0;
  1118. uint16_t retransmit = 0;
  1119. int i;
  1120. uint8_t protocol = values[0].protocol;
  1121. uint64_t ct = values[0].ct;
  1122. for (i = 1; i < end; i++) {
  1123. netdata_socket_t *w = &values[i];
  1124. precv += w->recv_packets;
  1125. psent += w->sent_packets;
  1126. brecv += w->recv_bytes;
  1127. bsent += w->sent_bytes;
  1128. retransmit += w->retransmit;
  1129. if (!protocol)
  1130. protocol = w->protocol;
  1131. if (w->ct > ct)
  1132. ct = w->ct;
  1133. *removesock += (int)w->removeme;
  1134. }
  1135. values[0].recv_packets += precv;
  1136. values[0].sent_packets += psent;
  1137. values[0].recv_bytes += brecv;
  1138. values[0].sent_bytes += bsent;
  1139. values[0].retransmit += retransmit;
  1140. values[0].removeme += (uint8_t)*removesock;
  1141. values[0].protocol = (!protocol)?IPPROTO_TCP:protocol;
  1142. values[0].ct = ct;
  1143. if (is_socket_allowed(key, family)) {
  1144. uint32_t dir;
  1145. netdata_vector_plot_t *table = select_vector_to_store(&dir, key, protocol);
  1146. store_socket_inside_avl(table, &values[0], key, family, dir);
  1147. }
  1148. }
  1149. /**
  1150. * Read socket hash table
  1151. *
  1152. * Read data from hash tables created on kernel ring.
  1153. *
  1154. * @param fd the hash table with data.
  1155. * @param family the family associated to the hash table
  1156. *
  1157. * @return it returns 0 on success and -1 otherwise.
  1158. */
  1159. static void read_socket_hash_table(int fd, int family, int network_connection)
  1160. {
  1161. if (wait_to_plot)
  1162. return;
  1163. netdata_socket_idx_t key = {};
  1164. netdata_socket_idx_t next_key;
  1165. netdata_socket_idx_t removeme;
  1166. int removesock = 0;
  1167. netdata_socket_t *values = socket_values;
  1168. size_t length = ebpf_nprocs*sizeof(netdata_socket_t);
  1169. int test, end = (running_on_kernel < NETDATA_KERNEL_V4_15) ? 1 : ebpf_nprocs;
  1170. while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
  1171. // We need to reset the values when we are working on kernel 4.15 or newer, because kernel does not create
  1172. // values for specific processor unless it is used to store data. As result of this behavior one the next socket
  1173. // can have values from the previous one.
  1174. memset(values, 0, length);
  1175. test = bpf_map_lookup_elem(fd, &key, values);
  1176. if (test < 0) {
  1177. key = next_key;
  1178. continue;
  1179. }
  1180. if (removesock)
  1181. bpf_map_delete_elem(fd, &removeme);
  1182. if (network_connection) {
  1183. removesock = 0;
  1184. hash_accumulator(values, &key, &removesock, family, end);
  1185. }
  1186. if (removesock)
  1187. removeme = key;
  1188. key = next_key;
  1189. }
  1190. if (removesock)
  1191. bpf_map_delete_elem(fd, &removeme);
  1192. test = bpf_map_lookup_elem(fd, &next_key, values);
  1193. if (test < 0) {
  1194. return;
  1195. }
  1196. if (network_connection) {
  1197. removesock = 0;
  1198. hash_accumulator(values, &next_key, &removesock, family, end);
  1199. }
  1200. if (removesock)
  1201. bpf_map_delete_elem(fd, &next_key);
  1202. }
  1203. /**
  1204. * Update listen table
  1205. *
  1206. * Update link list when it is necessary.
  1207. *
  1208. * @param value the ports we are listen to.
  1209. * @param proto the protocol used with port connection.
  1210. */
  1211. void update_listen_table(uint16_t value, uint8_t proto)
  1212. {
  1213. ebpf_network_viewer_port_list_t *w;
  1214. if (likely(listen_ports)) {
  1215. ebpf_network_viewer_port_list_t *move = listen_ports, *store = listen_ports;
  1216. while (move) {
  1217. if (move->protocol == proto && move->first == value)
  1218. return;
  1219. store = move;
  1220. move = move->next;
  1221. }
  1222. w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
  1223. w->first = value;
  1224. w->protocol = proto;
  1225. store->next = w;
  1226. } else {
  1227. w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
  1228. w->first = value;
  1229. w->protocol = proto;
  1230. listen_ports = w;
  1231. }
  1232. #ifdef NETDATA_INTERNAL_CHECKS
  1233. info("The network viewer is monitoring inbound connections for port %u", ntohs(value));
  1234. #endif
  1235. }
  1236. /**
  1237. * Read listen table
  1238. *
  1239. * Read the table with all ports that we are listen on host.
  1240. */
  1241. static void read_listen_table()
  1242. {
  1243. uint16_t key = 0;
  1244. uint16_t next_key;
  1245. int fd = map_fd[NETDATA_SOCKET_LISTEN_TABLE];
  1246. uint8_t value;
  1247. while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
  1248. int test = bpf_map_lookup_elem(fd, &key, &value);
  1249. if (test < 0) {
  1250. key = next_key;
  1251. continue;
  1252. }
  1253. // The correct protocol must come from kernel
  1254. update_listen_table(htons(key), (key == 53)?IPPROTO_UDP:IPPROTO_TCP);
  1255. key = next_key;
  1256. }
  1257. if (next_key) {
  1258. // The correct protocol must come from kernel
  1259. update_listen_table(htons(next_key), (key == 53)?IPPROTO_UDP:IPPROTO_TCP);
  1260. }
  1261. }
  1262. /**
  1263. * Socket read hash
  1264. *
  1265. * This is the thread callback.
  1266. * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
  1267. *
  1268. * @param ptr It is a NULL value for this thread.
  1269. *
  1270. * @return It always returns NULL.
  1271. */
  1272. void *ebpf_socket_read_hash(void *ptr)
  1273. {
  1274. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1275. read_thread_closed = 0;
  1276. heartbeat_t hb;
  1277. heartbeat_init(&hb);
  1278. usec_t step = NETDATA_SOCKET_READ_SLEEP_MS * em->update_time;
  1279. int fd_ipv4 = map_fd[NETDATA_SOCKET_IPV4_HASH_TABLE];
  1280. int fd_ipv6 = map_fd[NETDATA_SOCKET_IPV6_HASH_TABLE];
  1281. int network_connection = em->optional;
  1282. while (!close_ebpf_plugin) {
  1283. usec_t dt = heartbeat_next(&hb, step);
  1284. (void)dt;
  1285. pthread_mutex_lock(&nv_mutex);
  1286. read_listen_table();
  1287. read_socket_hash_table(fd_ipv4, AF_INET, network_connection);
  1288. read_socket_hash_table(fd_ipv6, AF_INET6, network_connection);
  1289. wait_to_plot = 1;
  1290. pthread_mutex_unlock(&nv_mutex);
  1291. }
  1292. read_thread_closed = 1;
  1293. return NULL;
  1294. }
  1295. /**
  1296. * Read the hash table and store data to allocated vectors.
  1297. */
  1298. static void read_hash_global_tables()
  1299. {
  1300. uint64_t idx;
  1301. netdata_idx_t res[NETDATA_SOCKET_COUNTER];
  1302. netdata_idx_t *val = socket_hash_values;
  1303. int fd = map_fd[NETDATA_SOCKET_GLOBAL_HASH_TABLE];
  1304. for (idx = 0; idx < NETDATA_SOCKET_COUNTER; idx++) {
  1305. if (!bpf_map_lookup_elem(fd, &idx, val)) {
  1306. uint64_t total = 0;
  1307. int i;
  1308. int end = (running_on_kernel < NETDATA_KERNEL_V4_15) ? 1 : ebpf_nprocs;
  1309. for (i = 0; i < end; i++)
  1310. total += val[i];
  1311. res[idx] = total;
  1312. } else {
  1313. res[idx] = 0;
  1314. }
  1315. }
  1316. socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].call = res[NETDATA_KEY_CALLS_TCP_SENDMSG];
  1317. socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].call = res[NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF];
  1318. socket_aggregated_data[NETDATA_IDX_TCP_CLOSE].call = res[NETDATA_KEY_CALLS_TCP_CLOSE];
  1319. socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].call = res[NETDATA_KEY_CALLS_UDP_RECVMSG];
  1320. socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].call = res[NETDATA_KEY_CALLS_UDP_SENDMSG];
  1321. socket_aggregated_data[NETDATA_IDX_TCP_RETRANSMIT].call = res[NETDATA_KEY_TCP_RETRANSMIT];
  1322. socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_TCP_SENDMSG];
  1323. socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].ecall = res[NETDATA_KEY_ERROR_TCP_CLEANUP_RBUF];
  1324. socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].ecall = res[NETDATA_KEY_ERROR_UDP_RECVMSG];
  1325. socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_UDP_SENDMSG];
  1326. socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_TCP_SENDMSG];
  1327. socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].bytes = res[NETDATA_KEY_BYTES_TCP_CLEANUP_RBUF];
  1328. socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].bytes = res[NETDATA_KEY_BYTES_UDP_RECVMSG];
  1329. socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_UDP_SENDMSG];
  1330. }
  1331. /**
  1332. * Fill publish apps when necessary.
  1333. *
  1334. * @param current_pid the PID that I am updating
  1335. * @param eb the structure with data read from memory.
  1336. */
  1337. void ebpf_socket_fill_publish_apps(uint32_t current_pid, ebpf_bandwidth_t *eb)
  1338. {
  1339. ebpf_socket_publish_apps_t *curr = socket_bandwidth_curr[current_pid];
  1340. if (!curr) {
  1341. curr = callocz(1, sizeof(ebpf_socket_publish_apps_t));
  1342. socket_bandwidth_curr[current_pid] = curr;
  1343. }
  1344. curr->bytes_sent = eb->bytes_sent;
  1345. curr->bytes_received = eb->bytes_received;
  1346. curr->call_tcp_sent = eb->call_tcp_sent;
  1347. curr->call_tcp_received = eb->call_tcp_received;
  1348. curr->retransmit = eb->retransmit;
  1349. curr->call_udp_sent = eb->call_udp_sent;
  1350. curr->call_udp_received = eb->call_udp_received;
  1351. }
  1352. /**
  1353. * Bandwidth accumulator.
  1354. *
  1355. * @param out the vector with the values to sum
  1356. */
  1357. void ebpf_socket_bandwidth_accumulator(ebpf_bandwidth_t *out)
  1358. {
  1359. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  1360. ebpf_bandwidth_t *total = &out[0];
  1361. for (i = 1; i < end; i++) {
  1362. ebpf_bandwidth_t *move = &out[i];
  1363. total->bytes_sent += move->bytes_sent;
  1364. total->bytes_received += move->bytes_received;
  1365. total->call_tcp_sent += move->call_tcp_sent;
  1366. total->call_tcp_received += move->call_tcp_received;
  1367. total->retransmit += move->retransmit;
  1368. total->call_udp_sent += move->call_udp_sent;
  1369. total->call_udp_received += move->call_udp_received;
  1370. }
  1371. }
  1372. /**
  1373. * Update the apps data reading information from the hash table
  1374. */
  1375. static void ebpf_socket_update_apps_data()
  1376. {
  1377. int fd = map_fd[NETDATA_SOCKET_APPS_HASH_TABLE];
  1378. ebpf_bandwidth_t *eb = bandwidth_vector;
  1379. uint32_t key;
  1380. struct pid_stat *pids = root_of_pids;
  1381. while (pids) {
  1382. key = pids->pid;
  1383. if (bpf_map_lookup_elem(fd, &key, eb)) {
  1384. pids = pids->next;
  1385. continue;
  1386. }
  1387. ebpf_socket_bandwidth_accumulator(eb);
  1388. ebpf_socket_fill_publish_apps(key, eb);
  1389. pids = pids->next;
  1390. }
  1391. }
  1392. /*****************************************************************
  1393. *
  1394. * FUNCTIONS WITH THE MAIN LOOP
  1395. *
  1396. *****************************************************************/
  1397. struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
  1398. NULL, NULL, 1, NULL,
  1399. NULL, ebpf_socket_read_hash };
  1400. /**
  1401. * Main loop for this collector.
  1402. *
  1403. * @param step the number of microseconds used with heart beat
  1404. * @param em the structure with thread information
  1405. */
  1406. static void socket_collector(usec_t step, ebpf_module_t *em)
  1407. {
  1408. UNUSED(em);
  1409. UNUSED(step);
  1410. heartbeat_t hb;
  1411. heartbeat_init(&hb);
  1412. socket_threads.thread = mallocz(sizeof(netdata_thread_t));
  1413. netdata_thread_create(socket_threads.thread, socket_threads.name,
  1414. NETDATA_THREAD_OPTION_JOINABLE, ebpf_socket_read_hash, em);
  1415. int socket_apps_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].apps_charts;
  1416. int socket_global_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].global_charts;
  1417. int network_connection = em->optional;
  1418. while (!close_ebpf_plugin) {
  1419. pthread_mutex_lock(&collect_data_mutex);
  1420. pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
  1421. if (socket_global_enabled)
  1422. read_hash_global_tables();
  1423. if (socket_apps_enabled)
  1424. ebpf_socket_update_apps_data();
  1425. calculate_nv_plot();
  1426. pthread_mutex_lock(&lock);
  1427. if (socket_global_enabled)
  1428. ebpf_socket_send_data(em);
  1429. if (socket_apps_enabled)
  1430. ebpf_socket_send_apps_data(em, apps_groups_root_target);
  1431. fflush(stdout);
  1432. if (network_connection) {
  1433. // We are calling fflush many times, because when we have a lot of dimensions
  1434. // we began to have not expected outputs and Netdata closed the plugin.
  1435. pthread_mutex_lock(&nv_mutex);
  1436. ebpf_socket_create_nv_charts(&inbound_vectors);
  1437. fflush(stdout);
  1438. ebpf_socket_send_nv_data(&inbound_vectors);
  1439. ebpf_socket_create_nv_charts(&outbound_vectors);
  1440. fflush(stdout);
  1441. ebpf_socket_send_nv_data(&outbound_vectors);
  1442. wait_to_plot = 0;
  1443. pthread_mutex_unlock(&nv_mutex);
  1444. }
  1445. pthread_mutex_unlock(&collect_data_mutex);
  1446. pthread_mutex_unlock(&lock);
  1447. }
  1448. }
  1449. /*****************************************************************
  1450. *
  1451. * FUNCTIONS TO CLOSE THE THREAD
  1452. *
  1453. *****************************************************************/
  1454. /**
  1455. * Clean internal socket plot
  1456. *
  1457. * Clean all structures allocated with strdupz.
  1458. *
  1459. * @param ptr the pointer with addresses to clean.
  1460. */
  1461. static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
  1462. {
  1463. freez(ptr->dimension_recv);
  1464. freez(ptr->dimension_sent);
  1465. freez(ptr->resolved_name);
  1466. freez(ptr->dimension_retransmit);
  1467. }
  1468. /**
  1469. * Clean socket plot
  1470. *
  1471. * Clean the allocated data for inbound and outbound vectors.
  1472. */
  1473. static void clean_allocated_socket_plot()
  1474. {
  1475. uint32_t i;
  1476. uint32_t end = inbound_vectors.last;
  1477. netdata_socket_plot_t *plot = inbound_vectors.plot;
  1478. for (i = 0; i < end; i++) {
  1479. clean_internal_socket_plot(&plot[i]);
  1480. }
  1481. clean_internal_socket_plot(&plot[inbound_vectors.last]);
  1482. end = outbound_vectors.last;
  1483. plot = outbound_vectors.plot;
  1484. for (i = 0; i < end; i++) {
  1485. clean_internal_socket_plot(&plot[i]);
  1486. }
  1487. clean_internal_socket_plot(&plot[outbound_vectors.last]);
  1488. }
  1489. /**
  1490. * Clean netowrk ports allocated during initializaion.
  1491. *
  1492. * @param ptr a pointer to the link list.
  1493. */
  1494. static void clean_network_ports(ebpf_network_viewer_port_list_t *ptr)
  1495. {
  1496. if (unlikely(!ptr))
  1497. return;
  1498. while (ptr) {
  1499. ebpf_network_viewer_port_list_t *next = ptr->next;
  1500. freez(ptr->value);
  1501. freez(ptr);
  1502. ptr = next;
  1503. }
  1504. }
  1505. /**
  1506. * Clean service names
  1507. *
  1508. * Clean the allocated link list that stores names.
  1509. *
  1510. * @param names the link list.
  1511. */
  1512. static void clean_service_names(ebpf_network_viewer_dim_name_t *names)
  1513. {
  1514. if (unlikely(!names))
  1515. return;
  1516. while (names) {
  1517. ebpf_network_viewer_dim_name_t *next = names->next;
  1518. freez(names->name);
  1519. freez(names);
  1520. names = next;
  1521. }
  1522. }
  1523. /**
  1524. * Clean hostnames
  1525. *
  1526. * @param hostnames the hostnames to clean
  1527. */
  1528. static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
  1529. {
  1530. if (unlikely(!hostnames))
  1531. return;
  1532. while (hostnames) {
  1533. ebpf_network_viewer_hostname_list_t *next = hostnames->next;
  1534. freez(hostnames->value);
  1535. simple_pattern_free(hostnames->value_pattern);
  1536. freez(hostnames);
  1537. hostnames = next;
  1538. }
  1539. }
  1540. void clean_thread_structures() {
  1541. struct pid_stat *pids = root_of_pids;
  1542. while (pids) {
  1543. freez(socket_bandwidth_curr[pids->pid]);
  1544. pids = pids->next;
  1545. }
  1546. }
  1547. /**
  1548. * Cleanup publish syscall
  1549. *
  1550. * @param nps list of structures to clean
  1551. */
  1552. void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
  1553. {
  1554. while (nps) {
  1555. freez(nps->algorithm);
  1556. nps = nps->next;
  1557. }
  1558. }
  1559. /**
  1560. * Clean port Structure
  1561. *
  1562. * Clean the allocated list.
  1563. *
  1564. * @param clean the list that will be cleaned
  1565. */
  1566. void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
  1567. {
  1568. ebpf_network_viewer_port_list_t *move = *clean;
  1569. while (move) {
  1570. ebpf_network_viewer_port_list_t *next = move->next;
  1571. freez(move->value);
  1572. freez(move);
  1573. move = next;
  1574. }
  1575. *clean = NULL;
  1576. }
  1577. /**
  1578. * Clean IP structure
  1579. *
  1580. * Clean the allocated list.
  1581. *
  1582. * @param clean the list that will be cleaned
  1583. */
  1584. static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
  1585. {
  1586. ebpf_network_viewer_ip_list_t *move = *clean;
  1587. while (move) {
  1588. ebpf_network_viewer_ip_list_t *next = move->next;
  1589. freez(move->value);
  1590. freez(move);
  1591. move = next;
  1592. }
  1593. *clean = NULL;
  1594. }
  1595. /**
  1596. * Clean up the main thread.
  1597. *
  1598. * @param ptr thread data.
  1599. */
  1600. static void ebpf_socket_cleanup(void *ptr)
  1601. {
  1602. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1603. if (!em->enabled)
  1604. return;
  1605. heartbeat_t hb;
  1606. heartbeat_init(&hb);
  1607. uint32_t tick = 2*USEC_PER_MS;
  1608. while (!read_thread_closed) {
  1609. usec_t dt = heartbeat_next(&hb, tick);
  1610. UNUSED(dt);
  1611. }
  1612. ebpf_cleanup_publish_syscall(socket_publish_aggregated);
  1613. freez(socket_hash_values);
  1614. clean_thread_structures();
  1615. freez(socket_bandwidth_curr);
  1616. freez(bandwidth_vector);
  1617. freez(socket_values);
  1618. clean_allocated_socket_plot();
  1619. freez(inbound_vectors.plot);
  1620. freez(outbound_vectors.plot);
  1621. clean_port_structure(&listen_ports);
  1622. ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled = 0;
  1623. clean_network_ports(network_viewer_opt.included_port);
  1624. clean_network_ports(network_viewer_opt.excluded_port);
  1625. clean_service_names(network_viewer_opt.names);
  1626. clean_hostnames(network_viewer_opt.included_hostnames);
  1627. clean_hostnames(network_viewer_opt.excluded_hostnames);
  1628. pthread_mutex_destroy(&nv_mutex);
  1629. freez(socket_data.map_fd);
  1630. freez(socket_threads.thread);
  1631. struct bpf_program *prog;
  1632. size_t i = 0 ;
  1633. bpf_object__for_each_program(prog, objects) {
  1634. bpf_link__destroy(probe_links[i]);
  1635. i++;
  1636. }
  1637. bpf_object__close(objects);
  1638. finalized_threads = 1;
  1639. }
  1640. /*****************************************************************
  1641. *
  1642. * FUNCTIONS TO START THREAD
  1643. *
  1644. *****************************************************************/
  1645. /**
  1646. * Allocate vectors used with this thread.
  1647. * We are not testing the return, because callocz does this and shutdown the software
  1648. * case it was not possible to allocate.
  1649. *
  1650. * @param length is the length for the vectors used inside the collector.
  1651. */
  1652. static void ebpf_socket_allocate_global_vectors(size_t length)
  1653. {
  1654. memset(socket_aggregated_data, 0 ,length * sizeof(netdata_syscall_stat_t));
  1655. memset(socket_publish_aggregated, 0 ,length * sizeof(netdata_publish_syscall_t));
  1656. socket_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
  1657. socket_bandwidth_curr = callocz((size_t)pid_max, sizeof(ebpf_socket_publish_apps_t *));
  1658. bandwidth_vector = callocz((size_t)ebpf_nprocs, sizeof(ebpf_bandwidth_t));
  1659. socket_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_socket_t));
  1660. inbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
  1661. outbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
  1662. }
  1663. /**
  1664. * Set local function pointers, this function will never be compiled with static libraries
  1665. */
  1666. static void set_local_pointers()
  1667. {
  1668. map_fd = socket_data.map_fd;
  1669. }
  1670. /**
  1671. * Initialize Inbound and Outbound
  1672. *
  1673. * Initialize the common outbound and inbound sockets.
  1674. */
  1675. static void initialize_inbound_outbound()
  1676. {
  1677. inbound_vectors.last = network_viewer_opt.max_dim - 1;
  1678. outbound_vectors.last = inbound_vectors.last;
  1679. fill_last_nv_dimension(&inbound_vectors.plot[inbound_vectors.last], 0);
  1680. fill_last_nv_dimension(&outbound_vectors.plot[outbound_vectors.last], 1);
  1681. }
  1682. /*****************************************************************
  1683. *
  1684. * EBPF SOCKET THREAD
  1685. *
  1686. *****************************************************************/
  1687. /**
  1688. * Fill Port list
  1689. *
  1690. * @param out a pointer to the link list.
  1691. * @param in the structure that will be linked.
  1692. */
  1693. static inline void fill_port_list(ebpf_network_viewer_port_list_t **out, ebpf_network_viewer_port_list_t *in)
  1694. {
  1695. if (likely(*out)) {
  1696. ebpf_network_viewer_port_list_t *move = *out, *store = *out;
  1697. uint16_t first = ntohs(in->first);
  1698. uint16_t last = ntohs(in->last);
  1699. while (move) {
  1700. uint16_t cmp_first = ntohs(move->first);
  1701. uint16_t cmp_last = ntohs(move->last);
  1702. if (cmp_first <= first && first <= cmp_last &&
  1703. cmp_first <= last && last <= cmp_last ) {
  1704. info("The range/value (%u, %u) is inside the range/value (%u, %u) already inserted, it will be ignored.",
  1705. first, last, cmp_first, cmp_last);
  1706. freez(in->value);
  1707. freez(in);
  1708. return;
  1709. } else if (first <= cmp_first && cmp_first <= last &&
  1710. first <= cmp_last && cmp_last <= last) {
  1711. info("The range (%u, %u) is bigger than previous range (%u, %u) already inserted, the previous will be ignored.",
  1712. first, last, cmp_first, cmp_last);
  1713. freez(move->value);
  1714. move->value = in->value;
  1715. move->first = in->first;
  1716. move->last = in->last;
  1717. freez(in);
  1718. return;
  1719. }
  1720. store = move;
  1721. move = move->next;
  1722. }
  1723. store->next = in;
  1724. } else {
  1725. *out = in;
  1726. }
  1727. #ifdef NETDATA_INTERNAL_CHECKS
  1728. info("Adding values %s( %u, %u) to %s port list used on network viewer",
  1729. in->value, ntohs(in->first), ntohs(in->last),
  1730. (*out == network_viewer_opt.included_port)?"included":"excluded");
  1731. #endif
  1732. }
  1733. /**
  1734. * Parse Service List
  1735. *
  1736. * @param out a pointer to store the link list
  1737. * @param service the service used to create the structure that will be linked.
  1738. */
  1739. static void parse_service_list(void **out, char *service)
  1740. {
  1741. ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
  1742. struct servent *serv = getservbyname((const char *)service, "tcp");
  1743. if (!serv)
  1744. serv = getservbyname((const char *)service, "udp");
  1745. if (!serv) {
  1746. info("Cannot resolv the service '%s' with protocols TCP and UDP, it will be ignored", service);
  1747. return;
  1748. }
  1749. ebpf_network_viewer_port_list_t *w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
  1750. w->value = strdupz(service);
  1751. w->hash = simple_hash(service);
  1752. w->first = w->last = (uint16_t)serv->s_port;
  1753. fill_port_list(list, w);
  1754. }
  1755. /**
  1756. * Netmask
  1757. *
  1758. * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
  1759. *
  1760. * @param prefix create the netmask based in the CIDR value.
  1761. *
  1762. * @return
  1763. */
  1764. static inline in_addr_t netmask(int prefix) {
  1765. if (prefix == 0)
  1766. return (~((in_addr_t) - 1));
  1767. else
  1768. return (in_addr_t)(~((1 << (32 - prefix)) - 1));
  1769. }
  1770. /**
  1771. * Broadcast
  1772. *
  1773. * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
  1774. *
  1775. * @param addr is the ip address
  1776. * @param prefix is the CIDR value.
  1777. *
  1778. * @return It returns the last address of the range
  1779. */
  1780. static inline in_addr_t broadcast(in_addr_t addr, int prefix)
  1781. {
  1782. return (addr | ~netmask(prefix));
  1783. }
  1784. /**
  1785. * Network
  1786. *
  1787. * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
  1788. *
  1789. * @param addr is the ip address
  1790. * @param prefix is the CIDR value.
  1791. *
  1792. * @return It returns the first address of the range.
  1793. */
  1794. static inline in_addr_t ipv4_network(in_addr_t addr, int prefix)
  1795. {
  1796. return (addr & netmask(prefix));
  1797. }
  1798. /**
  1799. * IP to network long
  1800. *
  1801. * @param dst the vector to store the result
  1802. * @param ip the source ip given by our users.
  1803. * @param domain the ip domain (IPV4 or IPV6)
  1804. * @param source the original string
  1805. *
  1806. * @return it returns 0 on success and -1 otherwise.
  1807. */
  1808. static inline int ip2nl(uint8_t *dst, char *ip, int domain, char *source)
  1809. {
  1810. if (inet_pton(domain, ip, dst) <= 0) {
  1811. error("The address specified (%s) is invalid ", source);
  1812. return -1;
  1813. }
  1814. return 0;
  1815. }
  1816. /**
  1817. * Get IPV6 Last Address
  1818. *
  1819. * @param out the address to store the last address.
  1820. * @param in the address used to do the math.
  1821. * @param prefix number of bits used to calculate the address
  1822. */
  1823. static void get_ipv6_last_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
  1824. {
  1825. uint64_t mask,tmp;
  1826. uint64_t ret[2];
  1827. memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
  1828. if (prefix == 128) {
  1829. memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
  1830. return;
  1831. } else if (!prefix) {
  1832. ret[0] = ret[1] = 0xFFFFFFFFFFFFFFFF;
  1833. memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
  1834. return;
  1835. } else if (prefix <= 64) {
  1836. ret[1] = 0xFFFFFFFFFFFFFFFFULL;
  1837. tmp = be64toh(ret[0]);
  1838. if (prefix > 0) {
  1839. mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
  1840. tmp |= ~mask;
  1841. }
  1842. ret[0] = htobe64(tmp);
  1843. } else {
  1844. mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
  1845. tmp = be64toh(ret[1]);
  1846. tmp |= ~mask;
  1847. ret[1] = htobe64(tmp);
  1848. }
  1849. memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
  1850. }
  1851. /**
  1852. * Calculate ipv6 first address
  1853. *
  1854. * @param out the address to store the first address.
  1855. * @param in the address used to do the math.
  1856. * @param prefix number of bits used to calculate the address
  1857. */
  1858. static void get_ipv6_first_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
  1859. {
  1860. uint64_t mask,tmp;
  1861. uint64_t ret[2];
  1862. memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
  1863. if (prefix == 128) {
  1864. memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
  1865. return;
  1866. } else if (!prefix) {
  1867. ret[0] = ret[1] = 0;
  1868. memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
  1869. return;
  1870. } else if (prefix <= 64) {
  1871. ret[1] = 0ULL;
  1872. tmp = be64toh(ret[0]);
  1873. if (prefix > 0) {
  1874. mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
  1875. tmp &= mask;
  1876. }
  1877. ret[0] = htobe64(tmp);
  1878. } else {
  1879. mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
  1880. tmp = be64toh(ret[1]);
  1881. tmp &= mask;
  1882. ret[1] = htobe64(tmp);
  1883. }
  1884. memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
  1885. }
  1886. /**
  1887. * Is ip inside the range
  1888. *
  1889. * Check if the ip is inside a IP range
  1890. *
  1891. * @param rfirst the first ip address of the range
  1892. * @param rlast the last ip address of the range
  1893. * @param cmpfirst the first ip to compare
  1894. * @param cmplast the last ip to compare
  1895. * @param family the IP family
  1896. *
  1897. * @return It returns 1 if the IP is inside the range and 0 otherwise
  1898. */
  1899. static int is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rlast,
  1900. union netdata_ip_t *cmpfirst, union netdata_ip_t *cmplast, int family)
  1901. {
  1902. if (family == AF_INET) {
  1903. if (ntohl(rfirst->addr32[0]) <= ntohl(cmpfirst->addr32[0]) &&
  1904. ntohl(rlast->addr32[0]) >= ntohl(cmplast->addr32[0]))
  1905. return 1;
  1906. } else {
  1907. if (memcmp(rfirst->addr8, cmpfirst->addr8, sizeof(union netdata_ip_t)) <= 0 &&
  1908. memcmp(rlast->addr8, cmplast->addr8, sizeof(union netdata_ip_t)) >= 0) {
  1909. return 1;
  1910. }
  1911. }
  1912. return 0;
  1913. }
  1914. /**
  1915. * Fill IP list
  1916. *
  1917. * @param out a pointer to the link list.
  1918. * @param in the structure that will be linked.
  1919. */
  1920. void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table)
  1921. {
  1922. #ifndef NETDATA_INTERNAL_CHECKS
  1923. UNUSED(table);
  1924. #endif
  1925. if (likely(*out)) {
  1926. ebpf_network_viewer_ip_list_t *move = *out, *store = *out;
  1927. while (move) {
  1928. if (in->ver == move->ver && is_ip_inside_range(&move->first, &move->last, &in->first, &in->last, in->ver)) {
  1929. info("The range/value (%s) is inside the range/value (%s) already inserted, it will be ignored.",
  1930. in->value, move->value);
  1931. freez(in->value);
  1932. freez(in);
  1933. return;
  1934. }
  1935. store = move;
  1936. move = move->next;
  1937. }
  1938. store->next = in;
  1939. } else {
  1940. *out = in;
  1941. }
  1942. #ifdef NETDATA_INTERNAL_CHECKS
  1943. char first[512], last[512];
  1944. if (in->ver == AF_INET) {
  1945. if (inet_ntop(AF_INET, in->first.addr8, first, INET_ADDRSTRLEN) &&
  1946. inet_ntop(AF_INET, in->last.addr8, last, INET_ADDRSTRLEN))
  1947. info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
  1948. first, last,
  1949. (*out == network_viewer_opt.included_ips)?"included":"excluded",
  1950. table);
  1951. } else {
  1952. if (inet_ntop(AF_INET6, in->first.addr8, first, INET6_ADDRSTRLEN) &&
  1953. inet_ntop(AF_INET6, in->last.addr8, last, INET6_ADDRSTRLEN))
  1954. info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
  1955. first, last,
  1956. (*out == network_viewer_opt.included_ips)?"included":"excluded",
  1957. table);
  1958. }
  1959. #endif
  1960. }
  1961. /**
  1962. * Parse IP List
  1963. *
  1964. * Parse IP list and link it.
  1965. *
  1966. * @param out a pointer to store the link list
  1967. * @param ip the value given as parameter
  1968. */
  1969. static void parse_ip_list(void **out, char *ip)
  1970. {
  1971. ebpf_network_viewer_ip_list_t **list = (ebpf_network_viewer_ip_list_t **)out;
  1972. char *ipdup = strdupz(ip);
  1973. union netdata_ip_t first = { };
  1974. union netdata_ip_t last = { };
  1975. char *is_ipv6;
  1976. if (*ip == '*' && *(ip+1) == '\0') {
  1977. memset(first.addr8, 0, sizeof(first.addr8));
  1978. memset(last.addr8, 0xFF, sizeof(last.addr8));
  1979. is_ipv6 = ip;
  1980. clean_ip_structure(list);
  1981. goto storethisip;
  1982. }
  1983. char *end = ip;
  1984. // Move while I cannot find a separator
  1985. while (*end && *end != '/' && *end != '-') end++;
  1986. // We will use only the classic IPV6 for while, but we could consider the base 85 in a near future
  1987. // https://tools.ietf.org/html/rfc1924
  1988. is_ipv6 = strchr(ip, ':');
  1989. int select;
  1990. if (*end && !is_ipv6) { // IPV4 range
  1991. select = (*end == '/') ? 0 : 1;
  1992. *end++ = '\0';
  1993. if (*end == '!') {
  1994. info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
  1995. goto cleanipdup;
  1996. }
  1997. if (!select) { // CIDR
  1998. select = ip2nl(first.addr8, ip, AF_INET, ipdup);
  1999. if (select)
  2000. goto cleanipdup;
  2001. select = (int) str2i(end);
  2002. if (select < NETDATA_MINIMUM_IPV4_CIDR || select > NETDATA_MAXIMUM_IPV4_CIDR) {
  2003. info("The specified CIDR %s is not valid, the IP %s will be ignored.", end, ip);
  2004. goto cleanipdup;
  2005. }
  2006. last.addr32[0] = htonl(broadcast(ntohl(first.addr32[0]), select));
  2007. // This was added to remove
  2008. // https://app.codacy.com/manual/netdata/netdata/pullRequest?prid=5810941&bid=19021977
  2009. UNUSED(last.addr32[0]);
  2010. uint32_t ipv4_test = htonl(ipv4_network(ntohl(first.addr32[0]), select));
  2011. if (first.addr32[0] != ipv4_test) {
  2012. first.addr32[0] = ipv4_test;
  2013. struct in_addr ipv4_convert;
  2014. ipv4_convert.s_addr = ipv4_test;
  2015. char ipv4_msg[INET_ADDRSTRLEN];
  2016. if(inet_ntop(AF_INET, &ipv4_convert, ipv4_msg, INET_ADDRSTRLEN))
  2017. info("The network value of CIDR %s was updated for %s .", ipdup, ipv4_msg);
  2018. }
  2019. } else { // Range
  2020. select = ip2nl(first.addr8, ip, AF_INET, ipdup);
  2021. if (select)
  2022. goto cleanipdup;
  2023. select = ip2nl(last.addr8, end, AF_INET, ipdup);
  2024. if (select)
  2025. goto cleanipdup;
  2026. }
  2027. if (htonl(first.addr32[0]) > htonl(last.addr32[0])) {
  2028. info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
  2029. ipdup);
  2030. goto cleanipdup;
  2031. }
  2032. } else if (is_ipv6) { // IPV6
  2033. if (!*end) { // Unique
  2034. select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
  2035. if (select)
  2036. goto cleanipdup;
  2037. memcpy(last.addr8, first.addr8, sizeof(first.addr8));
  2038. } else if (*end == '-') {
  2039. *end++ = 0x00;
  2040. if (*end == '!') {
  2041. info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
  2042. goto cleanipdup;
  2043. }
  2044. select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
  2045. if (select)
  2046. goto cleanipdup;
  2047. select = ip2nl(last.addr8, end, AF_INET6, ipdup);
  2048. if (select)
  2049. goto cleanipdup;
  2050. } else { // CIDR
  2051. *end++ = 0x00;
  2052. if (*end == '!') {
  2053. info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
  2054. goto cleanipdup;
  2055. }
  2056. select = str2i(end);
  2057. if (select < 0 || select > 128) {
  2058. info("The CIDR %s is not valid, the address %s will be ignored.", end, ip);
  2059. goto cleanipdup;
  2060. }
  2061. uint64_t prefix = (uint64_t)select;
  2062. select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
  2063. if (select)
  2064. goto cleanipdup;
  2065. get_ipv6_last_addr(&last, &first, prefix);
  2066. union netdata_ip_t ipv6_test;
  2067. get_ipv6_first_addr(&ipv6_test, &first, prefix);
  2068. if (memcmp(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t)) != 0) {
  2069. memcpy(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t));
  2070. struct in6_addr ipv6_convert;
  2071. memcpy(ipv6_convert.s6_addr, ipv6_test.addr8, sizeof(union netdata_ip_t));
  2072. char ipv6_msg[INET6_ADDRSTRLEN];
  2073. if(inet_ntop(AF_INET6, &ipv6_convert, ipv6_msg, INET6_ADDRSTRLEN))
  2074. info("The network value of CIDR %s was updated for %s .", ipdup, ipv6_msg);
  2075. }
  2076. }
  2077. if ((be64toh(*(uint64_t *)&first.addr32[2]) > be64toh(*(uint64_t *)&last.addr32[2]) &&
  2078. !memcmp(first.addr32, last.addr32, 2*sizeof(uint32_t))) ||
  2079. (be64toh(*(uint64_t *)&first.addr32) > be64toh(*(uint64_t *)&last.addr32)) ) {
  2080. info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
  2081. ipdup);
  2082. goto cleanipdup;
  2083. }
  2084. } else { // Unique ip
  2085. select = ip2nl(first.addr8, ip, AF_INET, ipdup);
  2086. if (select)
  2087. goto cleanipdup;
  2088. memcpy(last.addr8, first.addr8, sizeof(first.addr8));
  2089. }
  2090. ebpf_network_viewer_ip_list_t *store;
  2091. storethisip:
  2092. store = callocz(1, sizeof(ebpf_network_viewer_ip_list_t));
  2093. store->value = ipdup;
  2094. store->hash = simple_hash(ipdup);
  2095. store->ver = (uint8_t)(!is_ipv6)?AF_INET:AF_INET6;
  2096. memcpy(store->first.addr8, first.addr8, sizeof(first.addr8));
  2097. memcpy(store->last.addr8, last.addr8, sizeof(last.addr8));
  2098. fill_ip_list(list, store, "socket");
  2099. return;
  2100. cleanipdup:
  2101. freez(ipdup);
  2102. }
  2103. /**
  2104. * Parse IP Range
  2105. *
  2106. * Parse the IP ranges given and create Network Viewer IP Structure
  2107. *
  2108. * @param ptr is a pointer with the text to parse.
  2109. */
  2110. static void parse_ips(char *ptr)
  2111. {
  2112. // No value
  2113. if (unlikely(!ptr))
  2114. return;
  2115. while (likely(ptr)) {
  2116. // Move forward until next valid character
  2117. while (isspace(*ptr)) ptr++;
  2118. // No valid value found
  2119. if (unlikely(!*ptr))
  2120. return;
  2121. // Find space that ends the list
  2122. char *end = strchr(ptr, ' ');
  2123. if (end) {
  2124. *end++ = '\0';
  2125. }
  2126. int neg = 0;
  2127. if (*ptr == '!') {
  2128. neg++;
  2129. ptr++;
  2130. }
  2131. if (isascii(*ptr)) { // Parse port
  2132. parse_ip_list((!neg)?(void **)&network_viewer_opt.included_ips:(void **)&network_viewer_opt.excluded_ips,
  2133. ptr);
  2134. }
  2135. ptr = end;
  2136. }
  2137. }
  2138. /**
  2139. * Parse port list
  2140. *
  2141. * Parse an allocated port list with the range given
  2142. *
  2143. * @param out a pointer to store the link list
  2144. * @param range the informed range for the user.
  2145. */
  2146. static void parse_port_list(void **out, char *range)
  2147. {
  2148. int first, last;
  2149. ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
  2150. char *copied = strdupz(range);
  2151. if (*range == '*' && *(range+1) == '\0') {
  2152. first = 1;
  2153. last = 65535;
  2154. clean_port_structure(list);
  2155. goto fillenvpl;
  2156. }
  2157. char *end = range;
  2158. //Move while I cannot find a separator
  2159. while (*end && *end != ':' && *end != '-') end++;
  2160. //It has a range
  2161. if (likely(*end)) {
  2162. *end++ = '\0';
  2163. if (*end == '!') {
  2164. info("The exclusion cannot be in the second part of the range, the range %s will be ignored.", copied);
  2165. freez(copied);
  2166. return;
  2167. }
  2168. last = str2i((const char *)end);
  2169. } else {
  2170. last = 0;
  2171. }
  2172. first = str2i((const char *)range);
  2173. if (first < NETDATA_MINIMUM_PORT_VALUE || first > NETDATA_MAXIMUM_PORT_VALUE) {
  2174. info("The first port %d of the range \"%s\" is invalid and it will be ignored!", first, copied);
  2175. freez(copied);
  2176. return;
  2177. }
  2178. if (!last)
  2179. last = first;
  2180. if (last < NETDATA_MINIMUM_PORT_VALUE || last > NETDATA_MAXIMUM_PORT_VALUE) {
  2181. info("The second port %d of the range \"%s\" is invalid and the whole range will be ignored!", last, copied);
  2182. freez(copied);
  2183. return;
  2184. }
  2185. if (first > last) {
  2186. info("The specified order %s is wrong, the smallest value is always the first, it will be ignored!", copied);
  2187. freez(copied);
  2188. return;
  2189. }
  2190. ebpf_network_viewer_port_list_t *w;
  2191. fillenvpl:
  2192. w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
  2193. w->value = copied;
  2194. w->hash = simple_hash(copied);
  2195. w->first = (uint16_t)htons((uint16_t)first);
  2196. w->last = (uint16_t)htons((uint16_t)last);
  2197. w->cmp_first = (uint16_t)first;
  2198. w->cmp_last = (uint16_t)last;
  2199. fill_port_list(list, w);
  2200. }
  2201. /**
  2202. * Read max dimension.
  2203. *
  2204. * Netdata plot two dimensions per connection, so it is necessary to adjust the values.
  2205. *
  2206. * @param cfg the configuration structure
  2207. */
  2208. static void read_max_dimension(struct config *cfg)
  2209. {
  2210. int maxdim ;
  2211. maxdim = (int) appconfig_get_number(cfg,
  2212. EBPF_NETWORK_VIEWER_SECTION,
  2213. EBPF_MAXIMUM_DIMENSIONS,
  2214. NETDATA_NV_CAP_VALUE);
  2215. if (maxdim < 0) {
  2216. error("'maximum dimensions = %d' must be a positive number, Netdata will change for default value %ld.",
  2217. maxdim, NETDATA_NV_CAP_VALUE);
  2218. maxdim = NETDATA_NV_CAP_VALUE;
  2219. }
  2220. maxdim /= 2;
  2221. if (!maxdim) {
  2222. info("The number of dimensions is too small (%u), we are setting it to minimum 2", network_viewer_opt.max_dim);
  2223. network_viewer_opt.max_dim = 1;
  2224. return;
  2225. }
  2226. network_viewer_opt.max_dim = (uint32_t)maxdim;
  2227. }
  2228. /**
  2229. * Parse Port Range
  2230. *
  2231. * Parse the port ranges given and create Network Viewer Port Structure
  2232. *
  2233. * @param ptr is a pointer with the text to parse.
  2234. */
  2235. static void parse_ports(char *ptr)
  2236. {
  2237. // No value
  2238. if (unlikely(!ptr))
  2239. return;
  2240. while (likely(ptr)) {
  2241. // Move forward until next valid character
  2242. while (isspace(*ptr)) ptr++;
  2243. // No valid value found
  2244. if (unlikely(!*ptr))
  2245. return;
  2246. // Find space that ends the list
  2247. char *end = strchr(ptr, ' ');
  2248. if (end) {
  2249. *end++ = '\0';
  2250. }
  2251. int neg = 0;
  2252. if (*ptr == '!') {
  2253. neg++;
  2254. ptr++;
  2255. }
  2256. if (isdigit(*ptr)) { // Parse port
  2257. parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
  2258. ptr);
  2259. } else if (isalpha(*ptr)) { // Parse service
  2260. parse_service_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
  2261. ptr);
  2262. } else if (*ptr == '*') { // All
  2263. parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
  2264. ptr);
  2265. }
  2266. ptr = end;
  2267. }
  2268. }
  2269. /**
  2270. * Link hostname
  2271. *
  2272. * @param out is the output link list
  2273. * @param in the hostname to add to list.
  2274. */
  2275. static void link_hostname(ebpf_network_viewer_hostname_list_t **out, ebpf_network_viewer_hostname_list_t *in)
  2276. {
  2277. if (likely(*out)) {
  2278. ebpf_network_viewer_hostname_list_t *move = *out;
  2279. for (; move->next ; move = move->next ) {
  2280. if (move->hash == in->hash && !strcmp(move->value, in->value)) {
  2281. info("The hostname %s was already inserted, it will be ignored.", in->value);
  2282. freez(in->value);
  2283. simple_pattern_free(in->value_pattern);
  2284. freez(in);
  2285. return;
  2286. }
  2287. }
  2288. move->next = in;
  2289. } else {
  2290. *out = in;
  2291. }
  2292. #ifdef NETDATA_INTERNAL_CHECKS
  2293. info("Adding value %s to %s hostname list used on network viewer",
  2294. in->value,
  2295. (*out == network_viewer_opt.included_hostnames)?"included":"excluded");
  2296. #endif
  2297. }
  2298. /**
  2299. * Link Hostnames
  2300. *
  2301. * Parse the list of hostnames to create the link list.
  2302. * This is not associated with the IP, because simple patterns like *example* cannot be resolved to IP.
  2303. *
  2304. * @param out is the output link list
  2305. * @param parse is a pointer with the text to parser.
  2306. */
  2307. static void link_hostnames(char *parse)
  2308. {
  2309. // No value
  2310. if (unlikely(!parse))
  2311. return;
  2312. while (likely(parse)) {
  2313. // Find the first valid value
  2314. while (isspace(*parse)) parse++;
  2315. // No valid value found
  2316. if (unlikely(!*parse))
  2317. return;
  2318. // Find space that ends the list
  2319. char *end = strchr(parse, ' ');
  2320. if (end) {
  2321. *end++ = '\0';
  2322. }
  2323. int neg = 0;
  2324. if (*parse == '!') {
  2325. neg++;
  2326. parse++;
  2327. }
  2328. ebpf_network_viewer_hostname_list_t *hostname = callocz(1 , sizeof(ebpf_network_viewer_hostname_list_t));
  2329. hostname->value = strdupz(parse);
  2330. hostname->hash = simple_hash(parse);
  2331. hostname->value_pattern = simple_pattern_create(parse, NULL, SIMPLE_PATTERN_EXACT);
  2332. link_hostname((!neg)?&network_viewer_opt.included_hostnames:&network_viewer_opt.excluded_hostnames,
  2333. hostname);
  2334. parse = end;
  2335. }
  2336. }
  2337. /**
  2338. * Parse network viewer section
  2339. *
  2340. * @param cfg the configuration structure
  2341. */
  2342. void parse_network_viewer_section(struct config *cfg)
  2343. {
  2344. read_max_dimension(cfg);
  2345. network_viewer_opt.hostname_resolution_enabled = appconfig_get_boolean(cfg,
  2346. EBPF_NETWORK_VIEWER_SECTION,
  2347. EBPF_CONFIG_RESOLVE_HOSTNAME,
  2348. CONFIG_BOOLEAN_NO);
  2349. network_viewer_opt.service_resolution_enabled = appconfig_get_boolean(cfg,
  2350. EBPF_NETWORK_VIEWER_SECTION,
  2351. EBPF_CONFIG_RESOLVE_SERVICE,
  2352. CONFIG_BOOLEAN_NO);
  2353. char *value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION, EBPF_CONFIG_PORTS, NULL);
  2354. parse_ports(value);
  2355. if (network_viewer_opt.hostname_resolution_enabled) {
  2356. value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION, EBPF_CONFIG_HOSTNAMES, NULL);
  2357. link_hostnames(value);
  2358. } else {
  2359. info("Name resolution is disabled, collector will not parser \"hostnames\" list.");
  2360. }
  2361. value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION,
  2362. "ips", "!127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 fc00::/7 !::1/128");
  2363. parse_ips(value);
  2364. }
  2365. /**
  2366. * Link dimension name
  2367. *
  2368. * Link user specified names inside a link list.
  2369. *
  2370. * @param port the port number associated to the dimension name.
  2371. * @param hash the calculated hash for the dimension name.
  2372. * @param name the dimension name.
  2373. */
  2374. static void link_dimension_name(char *port, uint32_t hash, char *value)
  2375. {
  2376. int test = str2i(port);
  2377. if (test < NETDATA_MINIMUM_PORT_VALUE || test > NETDATA_MAXIMUM_PORT_VALUE){
  2378. error("The dimension given (%s = %s) has an invalid value and it will be ignored.", port, value);
  2379. return;
  2380. }
  2381. ebpf_network_viewer_dim_name_t *w;
  2382. w = callocz(1, sizeof(ebpf_network_viewer_dim_name_t));
  2383. w->name = strdupz(value);
  2384. w->hash = hash;
  2385. w->port = (uint16_t) htons(test);
  2386. ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
  2387. if (unlikely(!names)) {
  2388. network_viewer_opt.names = w;
  2389. } else {
  2390. for (; names->next; names = names->next) {
  2391. if (names->port == w->port) {
  2392. info("Dupplicated definition for a service, the name %s will be ignored. ", names->name);
  2393. freez(names->name);
  2394. names->name = w->name;
  2395. names->hash = w->hash;
  2396. freez(w);
  2397. return;
  2398. }
  2399. }
  2400. names->next = w;
  2401. }
  2402. #ifdef NETDATA_INTERNAL_CHECKS
  2403. info("Adding values %s( %u) to dimension name list used on network viewer", w->name, htons(w->port));
  2404. #endif
  2405. }
  2406. /**
  2407. * Parse service Name section.
  2408. *
  2409. * This function gets the values that will be used to overwrite dimensions.
  2410. *
  2411. * @param cfg the configuration structure
  2412. */
  2413. void parse_service_name_section(struct config *cfg)
  2414. {
  2415. struct section *co = appconfig_get_section(cfg, EBPF_SERVICE_NAME_SECTION);
  2416. if (co) {
  2417. struct config_option *cv;
  2418. for (cv = co->values; cv ; cv = cv->next) {
  2419. link_dimension_name(cv->name, cv->hash, cv->value);
  2420. }
  2421. }
  2422. // Always associated the default port to Netdata
  2423. ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
  2424. if (names) {
  2425. uint16_t default_port = htons(19999);
  2426. while (names) {
  2427. if (names->port == default_port)
  2428. return;
  2429. names = names->next;
  2430. }
  2431. }
  2432. char *port_string = getenv("NETDATA_LISTEN_PORT");
  2433. if (port_string) {
  2434. // if variable has an invalid value, we assume netdata is using 19999
  2435. int default_port = str2i(port_string);
  2436. if (default_port > 0 && default_port < 65536)
  2437. link_dimension_name(port_string, simple_hash(port_string), "Netdata");
  2438. }
  2439. }
  2440. /**
  2441. * Socket thread
  2442. *
  2443. * Thread used to generate socket charts.
  2444. *
  2445. * @param ptr a pointer to `struct ebpf_module`
  2446. *
  2447. * @return It always return NULL
  2448. */
  2449. void *ebpf_socket_thread(void *ptr)
  2450. {
  2451. netdata_thread_cleanup_push(ebpf_socket_cleanup, ptr);
  2452. avl_init_lock(&inbound_vectors.tree, compare_sockets);
  2453. avl_init_lock(&outbound_vectors.tree, compare_sockets);
  2454. ebpf_module_t *em = (ebpf_module_t *)ptr;
  2455. fill_ebpf_data(&socket_data);
  2456. ebpf_update_module(em, &socket_config, NETDATA_NETWORK_CONFIG_FILE);
  2457. parse_network_viewer_section(&socket_config);
  2458. parse_service_name_section(&socket_config);
  2459. if (!em->enabled)
  2460. goto endsocket;
  2461. if (pthread_mutex_init(&nv_mutex, NULL)) {
  2462. error("Cannot initialize local mutex");
  2463. goto endsocket;
  2464. }
  2465. pthread_mutex_lock(&lock);
  2466. ebpf_socket_allocate_global_vectors(NETDATA_MAX_SOCKET_VECTOR);
  2467. initialize_inbound_outbound();
  2468. if (ebpf_update_kernel(&socket_data)) {
  2469. pthread_mutex_unlock(&lock);
  2470. goto endsocket;
  2471. }
  2472. set_local_pointers();
  2473. probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, socket_data.map_fd);
  2474. if (!probe_links) {
  2475. pthread_mutex_unlock(&lock);
  2476. goto endsocket;
  2477. }
  2478. int algorithms[NETDATA_MAX_SOCKET_VECTOR] = {
  2479. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
  2480. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
  2481. };
  2482. ebpf_global_labels(
  2483. socket_aggregated_data, socket_publish_aggregated, socket_dimension_names, socket_id_names,
  2484. algorithms, NETDATA_MAX_SOCKET_VECTOR);
  2485. ebpf_create_global_charts(em);
  2486. finalized_threads = 0;
  2487. pthread_mutex_unlock(&lock);
  2488. socket_collector((usec_t)(em->update_time * USEC_PER_SEC), em);
  2489. endsocket:
  2490. netdata_thread_cleanup_pop(1);
  2491. return NULL;
  2492. }