eBPF plugin
Change eBPF plugin internal organization.
thiagoftsm committed
Mar 18, 2021 at 13:39 UTC
3b5a69c2a29817f4fe114c09107f7e57e5a4d26d
22 files changed
+1385
-1030
collectors/ebpf.plugin/Makefile.am
+16
-2
@@ -10,6 +10,12 @@ CLEANFILES = \
10
include $(top_srcdir)/build/subst.inc
11
SUFFIXES = .in
12
13
+userebpfconfigdir=$(configdir)/ebpf.d
14
+
15
+# Explicitly install directories to avoid permission issues due to umask
16
+install-exec-local:
17
+ $(INSTALL) -d $(DESTDIR)$(userebpfconfigdir)
18
+
19
dist_plugins_SCRIPTS = \
20
reset_netdata_trace.sh \
21
$(NULL)
@@ -19,7 +25,15 @@ dist_noinst_DATA = \
25
README.md \
26
$(NULL)
27
28
+ebpfconfigdir=$(libconfigdir)/ebpf.d
29
dist_libconfig_DATA = \
23
- ebpf.conf \
24
- ebpf_kernel_reject_list.txt \
30
+ ebpf.d.conf \
31
+ $(NULL)
32
+
33
+dist_ebpfconfig_DATA = \
34
+ ebpf.d/ebpf_kernel_reject_list.txt \
35
+ ebpf.d/cachestat.conf \
36
+ ebpf.d/network.conf \
37
+ ebpf.d/process.conf \
38
+ ebpf.d/sync.conf \
39
$(NULL)
collectors/ebpf.plugin/README.md
+30
-2
@@ -148,6 +148,7 @@ accepts the following values:
148
- `return`: In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
149
new charts for the return of these functions, such as errors. Monitoring function returns can help in debugging
150
software, such as failing to close file descriptors or creating zombie processes.
151
+- `update every`: Number of seconds used for eBPF to send data for Netdata.
152
153
#### Integration with `apps.plugin`
154
@@ -186,17 +187,44 @@ If you want to _disable_ the integration with `apps.plugin` along with the above
187
apps = yes
188
```
189
189
-### `[ebpf programs]`
190
+#### `[ebpf programs]`
191
192
The eBPF collector enables and runs the following eBPF programs by default:
193
194
+- `cachestat`: Netdata's eBPF data collector creates charts about the memory page cache. When the integration with
195
+ [`apps.plugin`](/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
196
+ for each application.
197
- `process`: This eBPF program creates charts that show information about process creation, VFS IO, and files removed.
198
When in `return` mode, it also creates charts showing errors when these operations are executed.
199
- `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
200
bandwidth consumed by each.
201
- `sync`: Montitor calls for syscall sync(2).
202
199
-### `[network connections]`
203
+## Thread configuration
204
+
205
+You can configure each thread of the eBPF data collector by editing either the `cachestat.conf`, `process.conf`,
206
+or `network.conf` files. Use [`edit-config`](/docs/configure/nodes.md) from your Netdata config directory:
207
+
208
+```bash
209
+cd /etc/netdata/ # Replace with your Netdata configuration directory, if not /etc/netdata/
210
+./edit-config ebpf.d/process.conf
211
+```
212
+
213
+### Configuration files
214
+
215
+The following configuration files are available:
216
+
217
+- `cachestat.conf`: Configuration for the `cachestat` thread.
218
+- `process.conf`: Configuration for the `process` thread.
219
+- `network.conf`: Configuration for the `network viewer` thread. This config file overwrites the global options and
220
+ also lets you specify which network the eBPF collector monitors.
221
+
222
+### Network configuration
223
+
224
+The network configuration has specific options to configure which network(s) the eBPF collector monitors. These options
225
+are divided in the following sections:
226
+
227
+#### `[network connections]`
228
229
You can configure the information shown on `outbound` and `inbound` charts with the settings in this section.
230
collectors/ebpf.plugin/ebpf.c
+45
-930
@@ -52,8 +52,6 @@ void netdata_cleanup_and_exit(int ret)
52
*****************************************************************/
53
54
char *ebpf_plugin_dir = PLUGINS_DIR;
55
-char *ebpf_user_config_dir = CONFIG_DIR;
56
-char *ebpf_stock_config_dir = LIBCONFIG_DIR;
55
static char *ebpf_configured_log_dir = LOG_DIR;
56
57
char *ebpf_algorithms[] = {"absolute", "incremental"};
@@ -106,58 +104,6 @@ ebpf_network_viewer_options_t network_viewer_opt;
104
*
105
*****************************************************************/
106
109
-/**
110
- * Cleanup publish syscall
111
- *
112
- * @param nps list of structures to clean
113
- */
114
-void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
115
-{
116
- while (nps) {
117
- freez(nps->algorithm);
118
- nps = nps->next;
119
- }
120
-}
121
-
122
-/**
123
- * Clean port Structure
124
- *
125
- * Clean the allocated list.
126
- *
127
- * @param clean the list that will be cleaned
128
- */
129
-void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
130
-{
131
- ebpf_network_viewer_port_list_t *move = *clean;
132
- while (move) {
133
- ebpf_network_viewer_port_list_t *next = move->next;
134
- freez(move->value);
135
- freez(move);
136
-
137
- move = next;
138
- }
139
- *clean = NULL;
140
-}
141
-
142
-/**
143
- * Clean IP structure
144
- *
145
- * Clean the allocated list.
146
- *
147
- * @param clean the list that will be cleaned
148
- */
149
-static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
150
-{
151
- ebpf_network_viewer_ip_list_t *move = *clean;
152
- while (move) {
153
- ebpf_network_viewer_ip_list_t *next = move->next;
154
- freez(move);
155
-
156
- move = next;
157
- }
158
- *clean = NULL;
159
-}
160
-
107
/**
108
* Clean Loaded Events
109
*
@@ -426,15 +372,17 @@ void ebpf_create_global_dimension(void *ptr, int end)
372
/**
373
* Call write_chart_cmd to create the charts
374
*
429
- * @param type chart type
430
- * @param id chart id
431
- * @param units axis label
432
- * @param family group name used to attach the chart on dashaboard
433
- * @param order order number of the specified chart
434
- * @param context chart context
435
- * @param ncd a pointer to a function called to create dimensions
436
- * @param move a pointer for a structure that has the dimensions
437
- * @param end number of dimensions for the chart created
375
+ * @param type chart type
376
+ * @param id chart id
377
+ * @param title chart title
378
+ * @param units axis label
379
+ * @param family group name used to attach the chart on dashaboard
380
+ * @param context chart context
381
+ * @param charttype chart type
382
+ * @param order order number of the specified chart
383
+ * @param ncd a pointer to a function called to create dimensions
384
+ * @param move a pointer for a structure that has the dimensions
385
+ * @param end number of dimensions for the chart created
386
*/
387
void ebpf_create_chart(char *type,
388
char *id,
@@ -442,12 +390,13 @@ void ebpf_create_chart(char *type,
390
char *units,
391
char *family,
392
char *context,
393
+ char *charttype,
394
int order,
395
void (*ncd)(void *, int),
396
void *move,
397
int end)
398
{
450
- ebpf_write_chart_cmd(type, id, title, units, family, "line", context, order);
399
+ ebpf_write_chart_cmd(type, id, title, units, family, charttype, context, order);
400
401
ncd(move, end);
402
}
@@ -459,15 +408,16 @@ void ebpf_create_chart(char *type,
408
* @param title the value displayed on vertical axis.
409
* @param units the value displayed on vertical axis.
410
* @param family Submenu that the chart will be attached on dashboard.
411
+ * @param charttype chart type
412
* @param order the chart order
413
* @param algorithm the algorithm used by dimension
414
* @param root structure used to create the dimensions.
415
*/
466
-void ebpf_create_charts_on_apps(char *id, char *title, char *units, char *family, int order,
416
+void ebpf_create_charts_on_apps(char *id, char *title, char *units, char *family, char *charttype, int order,
417
char *algorithm, struct target *root)
418
{
419
struct target *w;
470
- ebpf_write_chart_cmd(NETDATA_APPS_FAMILY, id, title, units, family, "stacked", NULL, order);
420
+ ebpf_write_chart_cmd(NETDATA_APPS_FAMILY, id, title, units, family, charttype, NULL, order);
421
422
for (w = root; w; w = w->next) {
423
if (unlikely(w->exposed))
@@ -640,87 +590,6 @@ void ebpf_print_help()
590
*
591
*****************************************************************/
592
643
-/**
644
- * Is ip inside the range
645
- *
646
- * Check if the ip is inside a IP range
647
- *
648
- * @param rfirst the first ip address of the range
649
- * @param rlast the last ip address of the range
650
- * @param cmpfirst the first ip to compare
651
- * @param cmplast the last ip to compare
652
- * @param family the IP family
653
- *
654
- * @return It returns 1 if the IP is inside the range and 0 otherwise
655
- */
656
-static int is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rlast,
657
- union netdata_ip_t *cmpfirst, union netdata_ip_t *cmplast, int family)
658
-{
659
- if (family == AF_INET) {
660
- if (ntohl(rfirst->addr32[0]) <= ntohl(cmpfirst->addr32[0]) &&
661
- ntohl(rlast->addr32[0]) >= ntohl(cmplast->addr32[0]))
662
- return 1;
663
- } else {
664
- if (memcmp(rfirst->addr8, cmpfirst->addr8, sizeof(union netdata_ip_t)) <= 0 &&
665
- memcmp(rlast->addr8, cmplast->addr8, sizeof(union netdata_ip_t)) >= 0) {
666
- return 1;
667
- }
668
-
669
- }
670
- return 0;
671
-}
672
-
673
-
674
-/**
675
- * Fill IP list
676
- *
677
- * @param out a pointer to the link list.
678
- * @param in the structure that will be linked.
679
- */
680
-static inline void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table)
681
-{
682
-#ifndef NETDATA_INTERNAL_CHECKS
683
- UNUSED(table);
684
-#endif
685
- if (likely(*out)) {
686
- ebpf_network_viewer_ip_list_t *move = *out, *store = *out;
687
- while (move) {
688
- if (in->ver == move->ver && is_ip_inside_range(&move->first, &move->last, &in->first, &in->last, in->ver)) {
689
- info("The range/value (%s) is inside the range/value (%s) already inserted, it will be ignored.",
690
- in->value, move->value);
691
- freez(in->value);
692
- freez(in);
693
- return;
694
- }
695
- store = move;
696
- move = move->next;
697
- }
698
-
699
- store->next = in;
700
- } else {
701
- *out = in;
702
- }
703
-
704
-#ifdef NETDATA_INTERNAL_CHECKS
705
- char first[512], last[512];
706
- if (in->ver == AF_INET) {
707
- if (inet_ntop(AF_INET, in->first.addr8, first, INET_ADDRSTRLEN) &&
708
- inet_ntop(AF_INET, in->last.addr8, last, INET_ADDRSTRLEN))
709
- info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
710
- first, last,
711
- (*out == network_viewer_opt.included_ips)?"included":"excluded",
712
- table);
713
- } else {
714
- if (inet_ntop(AF_INET6, in->first.addr8, first, INET6_ADDRSTRLEN) &&
715
- inet_ntop(AF_INET6, in->last.addr8, last, INET6_ADDRSTRLEN))
716
- info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
717
- first, last,
718
- (*out == network_viewer_opt.included_ips)?"included":"excluded",
719
- table);
720
- }
721
-#endif
722
-}
723
-
593
/**
594
* Read Local Ports
595
*
@@ -872,789 +741,26 @@ void fill_ebpf_data(ebpf_data_t *ef)
741
*/
742
static inline void how_to_load(char *ptr)
743
{
875
- if (!strcasecmp(ptr, "return"))
744
+ if (!strcasecmp(ptr, EBPF_CFG_LOAD_MODE_RETURN))
745
ebpf_set_thread_mode(MODE_RETURN);
877
- else if (!strcasecmp(ptr, "entry"))
746
+ else if (!strcasecmp(ptr, EBPF_CFG_LOAD_MODE_DEFAULT))
747
ebpf_set_thread_mode(MODE_ENTRY);
748
else
749
error("the option %s for \"ebpf load mode\" is not a valid option.", ptr);
750
}
751
752
/**
884
- * Fill Port list
885
- *
886
- * @param out a pointer to the link list.
887
- * @param in the structure that will be linked.
888
- */
889
-static inline void fill_port_list(ebpf_network_viewer_port_list_t **out, ebpf_network_viewer_port_list_t *in)
890
-{
891
- if (likely(*out)) {
892
- ebpf_network_viewer_port_list_t *move = *out, *store = *out;
893
- uint16_t first = ntohs(in->first);
894
- uint16_t last = ntohs(in->last);
895
- while (move) {
896
- uint16_t cmp_first = ntohs(move->first);
897
- uint16_t cmp_last = ntohs(move->last);
898
- if (cmp_first <= first && first <= cmp_last &&
899
- cmp_first <= last && last <= cmp_last ) {
900
- info("The range/value (%u, %u) is inside the range/value (%u, %u) already inserted, it will be ignored.",
901
- first, last, cmp_first, cmp_last);
902
- freez(in->value);
903
- freez(in);
904
- return;
905
- } else if (first <= cmp_first && cmp_first <= last &&
906
- first <= cmp_last && cmp_last <= last) {
907
- info("The range (%u, %u) is bigger than previous range (%u, %u) already inserted, the previous will be ignored.",
908
- first, last, cmp_first, cmp_last);
909
- freez(move->value);
910
- move->value = in->value;
911
- move->first = in->first;
912
- move->last = in->last;
913
- freez(in);
914
- return;
915
- }
916
-
917
- store = move;
918
- move = move->next;
919
- }
920
-
921
- store->next = in;
922
- } else {
923
- *out = in;
924
- }
925
-
926
-#ifdef NETDATA_INTERNAL_CHECKS
927
- info("Adding values %s( %u, %u) to %s port list used on network viewer",
928
- in->value, ntohs(in->first), ntohs(in->last),
929
- (*out == network_viewer_opt.included_port)?"included":"excluded");
930
-#endif
931
-}
932
-
933
-/**
934
- * Fill port list
935
- *
936
- * Fill an allocated port list with the range given
937
- *
938
- * @param out a pointer to store the link list
939
- * @param range the informed range for the user.
940
- */
941
-static void parse_port_list(void **out, char *range)
942
-{
943
- int first, last;
944
- ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
945
-
946
- char *copied = strdupz(range);
947
- if (*range == '*' && *(range+1) == '\0') {
948
- first = 1;
949
- last = 65535;
950
-
951
- clean_port_structure(list);
952
- goto fillenvpl;
953
- }
954
-
955
- char *end = range;
956
- //Move while I cannot find a separator
957
- while (*end && *end != ':' && *end != '-') end++;
958
-
959
- //It has a range
960
- if (likely(*end)) {
961
- *end++ = '\0';
962
- if (*end == '!') {
963
- info("The exclusion cannot be in the second part of the range, the range %s will be ignored.", copied);
964
- freez(copied);
965
- return;
966
- }
967
- last = str2i((const char *)end);
968
- } else {
969
- last = 0;
970
- }
971
-
972
- first = str2i((const char *)range);
973
- if (first < NETDATA_MINIMUM_PORT_VALUE || first > NETDATA_MAXIMUM_PORT_VALUE) {
974
- info("The first port %d of the range \"%s\" is invalid and it will be ignored!", first, copied);
975
- freez(copied);
976
- return;
977
- }
978
-
979
- if (!last)
980
- last = first;
981
-
982
- if (last < NETDATA_MINIMUM_PORT_VALUE || last > NETDATA_MAXIMUM_PORT_VALUE) {
983
- info("The second port %d of the range \"%s\" is invalid and the whole range will be ignored!", last, copied);
984
- freez(copied);
985
- return;
986
- }
987
-
988
- if (first > last) {
989
- info("The specified order %s is wrong, the smallest value is always the first, it will be ignored!", copied);
990
- freez(copied);
991
- return;
992
- }
993
-
994
- ebpf_network_viewer_port_list_t *w;
995
-fillenvpl:
996
- w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
997
- w->value = copied;
998
- w->hash = simple_hash(copied);
999
- w->first = (uint16_t)htons((uint16_t)first);
1000
- w->last = (uint16_t)htons((uint16_t)last);
1001
- w->cmp_first = (uint16_t)first;
1002
- w->cmp_last = (uint16_t)last;
1003
-
1004
- fill_port_list(list, w);
1005
-}
1006
-
1007
-/**
1008
- * Parse Service List
1009
- *
1010
- * @param out a pointer to store the link list
1011
- * @param service the service used to create the structure that will be linked.
1012
- */
1013
-static void parse_service_list(void **out, char *service)
1014
-{
1015
- ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
1016
- struct servent *serv = getservbyname((const char *)service, "tcp");
1017
- if (!serv)
1018
- serv = getservbyname((const char *)service, "udp");
1019
-
1020
- if (!serv) {
1021
- info("Cannot resolv the service '%s' with protocols TCP and UDP, it will be ignored", service);
1022
- return;
1023
- }
1024
-
1025
- ebpf_network_viewer_port_list_t *w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
1026
- w->value = strdupz(service);
1027
- w->hash = simple_hash(service);
1028
-
1029
- w->first = w->last = (uint16_t)serv->s_port;
1030
-
1031
- fill_port_list(list, w);
1032
-}
1033
-
1034
-/**
1035
- * Netmask
1036
- *
1037
- * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
1038
- *
1039
- * @param prefix create the netmask based in the CIDR value.
1040
- *
1041
- * @return
1042
- */
1043
-static inline in_addr_t netmask(int prefix) {
1044
-
1045
- if (prefix == 0)
1046
- return (~((in_addr_t) - 1));
1047
- else
1048
- return (in_addr_t)(~((1 << (32 - prefix)) - 1));
1049
-
1050
-}
1051
-
1052
-/**
1053
- * Broadcast
753
+ * Update interval
754
*
1055
- * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
1056
- *
1057
- * @param addr is the ip address
1058
- * @param prefix is the CIDR value.
1059
- *
1060
- * @return It returns the last address of the range
755
+ * Update default interval with value from user
756
*/
1062
-static inline in_addr_t broadcast(in_addr_t addr, int prefix)
757
+static void ebpf_update_interval()
758
{
1064
- return (addr | ~netmask(prefix));
1065
-}
1066
-
1067
-/**
1068
- * Network
1069
- *
1070
- * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
1071
- *
1072
- * @param addr is the ip address
1073
- * @param prefix is the CIDR value.
1074
- *
1075
- * @return It returns the first address of the range.
1076
- */
1077
-static inline in_addr_t ipv4_network(in_addr_t addr, int prefix)
1078
-{
1079
- return (addr & netmask(prefix));
1080
-}
1081
-
1082
-/**
1083
- * IP to network long
1084
- *
1085
- * @param dst the vector to store the result
1086
- * @param ip the source ip given by our users.
1087
- * @param domain the ip domain (IPV4 or IPV6)
1088
- * @param source the original string
1089
- *
1090
- * @return it returns 0 on success and -1 otherwise.
1091
- */
1092
-static inline int ip2nl(uint8_t *dst, char *ip, int domain, char *source)
1093
-{
1094
- if (inet_pton(domain, ip, dst) <= 0) {
1095
- error("The address specified (%s) is invalid ", source);
1096
- return -1;
1097
- }
1098
-
1099
- return 0;
1100
-}
1101
-
1102
-/**
1103
- * Get IPV6 Last Address
1104
- *
1105
- * @param out the address to store the last address.
1106
- * @param in the address used to do the math.
1107
- * @param prefix number of bits used to calculate the address
1108
- */
1109
-static void get_ipv6_last_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
1110
-{
1111
- uint64_t mask,tmp;
1112
- uint64_t ret[2];
1113
- memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
1114
-
1115
- if (prefix == 128) {
1116
- memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
1117
- return;
1118
- } else if (!prefix) {
1119
- ret[0] = ret[1] = 0xFFFFFFFFFFFFFFFF;
1120
- memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
1121
- return;
1122
- } else if (prefix <= 64) {
1123
- ret[1] = 0xFFFFFFFFFFFFFFFFULL;
1124
-
1125
- tmp = be64toh(ret[0]);
1126
- if (prefix > 0) {
1127
- mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
1128
- tmp |= ~mask;
1129
- }
1130
- ret[0] = htobe64(tmp);
1131
- } else {
1132
- mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
1133
- tmp = be64toh(ret[1]);
1134
- tmp |= ~mask;
1135
- ret[1] = htobe64(tmp);
1136
- }
1137
-
1138
- memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
1139
-}
1140
-
1141
-/**
1142
- * Calculate ipv6 first address
1143
- *
1144
- * @param out the address to store the first address.
1145
- * @param in the address used to do the math.
1146
- * @param prefix number of bits used to calculate the address
1147
- */
1148
-static void get_ipv6_first_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
1149
-{
1150
- uint64_t mask,tmp;
1151
- uint64_t ret[2];
1152
-
1153
- memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
1154
-
1155
- if (prefix == 128) {
1156
- memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
1157
- return;
1158
- } else if (!prefix) {
1159
- ret[0] = ret[1] = 0;
1160
- memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
1161
- return;
1162
- } else if (prefix <= 64) {
1163
- ret[1] = 0ULL;
1164
-
1165
- tmp = be64toh(ret[0]);
1166
- if (prefix > 0) {
1167
- mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
1168
- tmp &= mask;
1169
- }
1170
- ret[0] = htobe64(tmp);
1171
- } else {
1172
- mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
1173
- tmp = be64toh(ret[1]);
1174
- tmp &= mask;
1175
- ret[1] = htobe64(tmp);
1176
- }
1177
-
1178
- memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
1179
-}
1180
-
1181
-/**
1182
- * Parse IP List
1183
- *
1184
- * Parse IP list and link it.
1185
- *
1186
- * @param out a pointer to store the link list
1187
- * @param ip the value given as parameter
1188
- */
1189
-static void parse_ip_list(void **out, char *ip)
1190
-{
1191
- ebpf_network_viewer_ip_list_t **list = (ebpf_network_viewer_ip_list_t **)out;
1192
-
1193
- char *ipdup = strdupz(ip);
1194
- union netdata_ip_t first = { };
1195
- union netdata_ip_t last = { };
1196
- char *is_ipv6;
1197
- if (*ip == '*' && *(ip+1) == '\0') {
1198
- memset(first.addr8, 0, sizeof(first.addr8));
1199
- memset(last.addr8, 0xFF, sizeof(last.addr8));
1200
-
1201
- is_ipv6 = ip;
1202
-
1203
- clean_ip_structure(list);
1204
- goto storethisip;
1205
- }
1206
-
1207
- char *end = ip;
1208
- // Move while I cannot find a separator
1209
- while (*end && *end != '/' && *end != '-') end++;
1210
-
1211
- // We will use only the classic IPV6 for while, but we could consider the base 85 in a near future
1212
- // https://tools.ietf.org/html/rfc1924
1213
- is_ipv6 = strchr(ip, ':');
1214
-
1215
- int select;
1216
- if (*end && !is_ipv6) { // IPV4 range
1217
- select = (*end == '/') ? 0 : 1;
1218
- *end++ = '\0';
1219
- if (*end == '!') {
1220
- info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
1221
- goto cleanipdup;
1222
- }
1223
-
1224
- if (!select) { // CIDR
1225
- select = ip2nl(first.addr8, ip, AF_INET, ipdup);
1226
- if (select)
1227
- goto cleanipdup;
1228
-
1229
- select = (int) str2i(end);
1230
- if (select < NETDATA_MINIMUM_IPV4_CIDR || select > NETDATA_MAXIMUM_IPV4_CIDR) {
1231
- info("The specified CIDR %s is not valid, the IP %s will be ignored.", end, ip);
1232
- goto cleanipdup;
1233
- }
1234
-
1235
- last.addr32[0] = htonl(broadcast(ntohl(first.addr32[0]), select));
1236
- // This was added to remove
1237
- // https://app.codacy.com/manual/netdata/netdata/pullRequest?prid=5810941&bid=19021977
1238
- UNUSED(last.addr32[0]);
1239
-
1240
- uint32_t ipv4_test = htonl(ipv4_network(ntohl(first.addr32[0]), select));
1241
- if (first.addr32[0] != ipv4_test) {
1242
- first.addr32[0] = ipv4_test;
1243
- struct in_addr ipv4_convert;
1244
- ipv4_convert.s_addr = ipv4_test;
1245
- char ipv4_msg[INET_ADDRSTRLEN];
1246
- if(inet_ntop(AF_INET, &ipv4_convert, ipv4_msg, INET_ADDRSTRLEN))
1247
- info("The network value of CIDR %s was updated for %s .", ipdup, ipv4_msg);
1248
- }
1249
- } else { // Range
1250
- select = ip2nl(first.addr8, ip, AF_INET, ipdup);
1251
- if (select)
1252
- goto cleanipdup;
1253
-
1254
- select = ip2nl(last.addr8, end, AF_INET, ipdup);
1255
- if (select)
1256
- goto cleanipdup;
1257
- }
1258
-
1259
- if (htonl(first.addr32[0]) > htonl(last.addr32[0])) {
1260
- info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
1261
- ipdup);
1262
- goto cleanipdup;
1263
- }
1264
- } else if (is_ipv6) { // IPV6
1265
- if (!*end) { // Unique
1266
- select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
1267
- if (select)
1268
- goto cleanipdup;
1269
-
1270
- memcpy(last.addr8, first.addr8, sizeof(first.addr8));
1271
- } else if (*end == '-') {
1272
- *end++ = 0x00;
1273
- if (*end == '!') {
1274
- info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
1275
- goto cleanipdup;
1276
- }
1277
-
1278
- select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
1279
- if (select)
1280
- goto cleanipdup;
1281
-
1282
- select = ip2nl(last.addr8, end, AF_INET6, ipdup);
1283
- if (select)
1284
- goto cleanipdup;
1285
- } else { // CIDR
1286
- *end++ = 0x00;
1287
- if (*end == '!') {
1288
- info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
1289
- goto cleanipdup;
1290
- }
1291
-
1292
- select = str2i(end);
1293
- if (select < 0 || select > 128) {
1294
- info("The CIDR %s is not valid, the address %s will be ignored.", end, ip);
1295
- goto cleanipdup;
1296
- }
1297
-
1298
- uint64_t prefix = (uint64_t)select;
1299
- select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
1300
- if (select)
1301
- goto cleanipdup;
1302
-
1303
- get_ipv6_last_addr(&last, &first, prefix);
1304
-
1305
- union netdata_ip_t ipv6_test;
1306
- get_ipv6_first_addr(&ipv6_test, &first, prefix);
1307
-
1308
- if (memcmp(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t)) != 0) {
1309
- memcpy(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t));
1310
-
1311
- struct in6_addr ipv6_convert;
1312
- memcpy(ipv6_convert.s6_addr, ipv6_test.addr8, sizeof(union netdata_ip_t));
1313
-
1314
- char ipv6_msg[INET6_ADDRSTRLEN];
1315
- if(inet_ntop(AF_INET6, &ipv6_convert, ipv6_msg, INET6_ADDRSTRLEN))
1316
- info("The network value of CIDR %s was updated for %s .", ipdup, ipv6_msg);
1317
- }
1318
- }
1319
-
1320
- if ((be64toh(*(uint64_t *)&first.addr32[2]) > be64toh(*(uint64_t *)&last.addr32[2]) &&
1321
- !memcmp(first.addr32, last.addr32, 2*sizeof(uint32_t))) ||
1322
- (be64toh(*(uint64_t *)&first.addr32) > be64toh(*(uint64_t *)&last.addr32)) ) {
1323
- info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
1324
- ipdup);
1325
- goto cleanipdup;
1326
- }
1327
- } else { // Unique ip
1328
- select = ip2nl(first.addr8, ip, AF_INET, ipdup);
1329
- if (select)
1330
- goto cleanipdup;
1331
-
1332
- memcpy(last.addr8, first.addr8, sizeof(first.addr8));
1333
- }
1334
-
1335
- ebpf_network_viewer_ip_list_t *store;
1336
-
1337
-storethisip:
1338
- store = callocz(1, sizeof(ebpf_network_viewer_ip_list_t));
1339
- store->value = ipdup;
1340
- store->hash = simple_hash(ipdup);
1341
- store->ver = (uint8_t)(!is_ipv6)?AF_INET:AF_INET6;
1342
- memcpy(store->first.addr8, first.addr8, sizeof(first.addr8));
1343
- memcpy(store->last.addr8, last.addr8, sizeof(last.addr8));
1344
-
1345
- fill_ip_list(list, store, "socket");
1346
- return;
1347
-
1348
-cleanipdup:
1349
- freez(ipdup);
1350
-}
1351
-
1352
-/**
1353
- * Parse IP Range
1354
- *
1355
- * Parse the IP ranges given and create Network Viewer IP Structure
1356
- *
1357
- * @param ptr is a pointer with the text to parse.
1358
- */
1359
-static void parse_ips(char *ptr)
1360
-{
1361
- // No value
1362
- if (unlikely(!ptr))
1363
- return;
1364
-
1365
- while (likely(ptr)) {
1366
- // Move forward until next valid character
1367
- while (isspace(*ptr)) ptr++;
1368
-
1369
- // No valid value found
1370
- if (unlikely(!*ptr))
1371
- return;
1372
-
1373
- // Find space that ends the list
1374
- char *end = strchr(ptr, ' ');
1375
- if (end) {
1376
- *end++ = '\0';
1377
- }
1378
-
1379
- int neg = 0;
1380
- if (*ptr == '!') {
1381
- neg++;
1382
- ptr++;
1383
- }
1384
-
1385
- if (isascii(*ptr)) { // Parse port
1386
- parse_ip_list((!neg)?(void **)&network_viewer_opt.included_ips:(void **)&network_viewer_opt.excluded_ips,
1387
- ptr);
1388
- }
1389
-
1390
- ptr = end;
1391
- }
1392
-}
1393
-
1394
-
1395
-/**
1396
- * Parse Port Range
1397
- *
1398
- * Parse the port ranges given and create Network Viewer Port Structure
1399
- *
1400
- * @param ptr is a pointer with the text to parse.
1401
- */
1402
-static void parse_ports(char *ptr)
1403
-{
1404
- // No value
1405
- if (unlikely(!ptr))
1406
- return;
1407
-
1408
- while (likely(ptr)) {
1409
- // Move forward until next valid character
1410
- while (isspace(*ptr)) ptr++;
1411
-
1412
- // No valid value found
1413
- if (unlikely(!*ptr))
1414
- return;
1415
-
1416
- // Find space that ends the list
1417
- char *end = strchr(ptr, ' ');
1418
- if (end) {
1419
- *end++ = '\0';
1420
- }
1421
-
1422
- int neg = 0;
1423
- if (*ptr == '!') {
1424
- neg++;
1425
- ptr++;
1426
- }
1427
-
1428
- if (isdigit(*ptr)) { // Parse port
1429
- parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
1430
- ptr);
1431
- } else if (isalpha(*ptr)) { // Parse service
1432
- parse_service_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
1433
- ptr);
1434
- } else if (*ptr == '*') { // All
1435
- parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
1436
- ptr);
1437
- }
1438
-
1439
- ptr = end;
1440
- }
1441
-}
1442
-
1443
-/**
1444
- * Link hostname
1445
- *
1446
- * @param out is the output link list
1447
- * @param in the hostname to add to list.
1448
- */
1449
-static void link_hostname(ebpf_network_viewer_hostname_list_t **out, ebpf_network_viewer_hostname_list_t *in)
1450
-{
1451
- if (likely(*out)) {
1452
- ebpf_network_viewer_hostname_list_t *move = *out;
1453
- for (; move->next ; move = move->next ) {
1454
- if (move->hash == in->hash && !strcmp(move->value, in->value)) {
1455
- info("The hostname %s was already inserted, it will be ignored.", in->value);
1456
- freez(in->value);
1457
- simple_pattern_free(in->value_pattern);
1458
- freez(in);
1459
- return;
1460
- }
1461
- }
1462
-
1463
- move->next = in;
1464
- } else {
1465
- *out = in;
1466
- }
1467
-#ifdef NETDATA_INTERNAL_CHECKS
1468
- info("Adding value %s to %s hostname list used on network viewer",
1469
- in->value,
1470
- (*out == network_viewer_opt.included_hostnames)?"included":"excluded");
1471
-#endif
1472
-}
1473
-
1474
-/**
1475
- * Link Hostnames
1476
- *
1477
- * Parse the list of hostnames to create the link list.
1478
- * This is not associated with the IP, because simple patterns like *example* cannot be resolved to IP.
1479
- *
1480
- * @param out is the output link list
1481
- * @param parse is a pointer with the text to parser.
1482
- */
1483
-static void link_hostnames(char *parse)
1484
-{
1485
- // No value
1486
- if (unlikely(!parse))
1487
- return;
1488
-
1489
- while (likely(parse)) {
1490
- // Find the first valid value
1491
- while (isspace(*parse)) parse++;
1492
-
1493
- // No valid value found
1494
- if (unlikely(!*parse))
1495
- return;
1496
-
1497
- // Find space that ends the list
1498
- char *end = strchr(parse, ' ');
1499
- if (end) {
1500
- *end++ = '\0';
1501
- }
1502
-
1503
- int neg = 0;
1504
- if (*parse == '!') {
1505
- neg++;
1506
- parse++;
1507
- }
1508
-
1509
- ebpf_network_viewer_hostname_list_t *hostname = callocz(1 , sizeof(ebpf_network_viewer_hostname_list_t));
1510
- hostname->value = strdupz(parse);
1511
- hostname->hash = simple_hash(parse);
1512
- hostname->value_pattern = simple_pattern_create(parse, NULL, SIMPLE_PATTERN_EXACT);
1513
-
1514
- link_hostname((!neg)?&network_viewer_opt.included_hostnames:&network_viewer_opt.excluded_hostnames,
1515
- hostname);
1516
-
1517
- parse = end;
1518
- }
1519
-}
1520
-
1521
-/**
1522
- * Read max dimension.
1523
- *
1524
- * Netdata plot two dimensions per connection, so it is necessary to adjust the values.
1525
- */
1526
-static void read_max_dimension()
1527
-{
1528
- int maxdim ;
1529
- maxdim = (int) appconfig_get_number(&collector_config,
1530
- EBPF_NETWORK_VIEWER_SECTION,
1531
- "maximum dimensions",
1532
- NETDATA_NV_CAP_VALUE);
1533
- if (maxdim < 0) {
1534
- error("'maximum dimensions = %d' must be a positive number, Netdata will change for default value %ld.",
1535
- maxdim, NETDATA_NV_CAP_VALUE);
1536
- maxdim = NETDATA_NV_CAP_VALUE;
1537
- }
1538
-
1539
- maxdim /= 2;
1540
- if (!maxdim) {
1541
- info("The number of dimensions is too small (%u), we are setting it to minimum 2", network_viewer_opt.max_dim);
1542
- network_viewer_opt.max_dim = 1;
1543
- }
1544
-
1545
- network_viewer_opt.max_dim = (uint32_t)maxdim;
1546
-}
1547
-
1548
-/**
1549
- * Parse network viewer section
1550
- */
1551
-static void parse_network_viewer_section()
1552
-{
1553
- read_max_dimension();
1554
-
1555
- network_viewer_opt.hostname_resolution_enabled = appconfig_get_boolean(&collector_config,
1556
- EBPF_NETWORK_VIEWER_SECTION,
1557
- "resolve hostnames",
1558
- CONFIG_BOOLEAN_NO);
1559
-
1560
- network_viewer_opt.service_resolution_enabled = appconfig_get_boolean(&collector_config,
1561
- EBPF_NETWORK_VIEWER_SECTION,
1562
- "resolve service names",
1563
- CONFIG_BOOLEAN_NO);
1564
-
1565
- char *value = appconfig_get(&collector_config, EBPF_NETWORK_VIEWER_SECTION,
1566
- "ports", NULL);
1567
- parse_ports(value);
1568
-
1569
- if (network_viewer_opt.hostname_resolution_enabled) {
1570
- value = appconfig_get(&collector_config, EBPF_NETWORK_VIEWER_SECTION, "hostnames", NULL);
1571
- link_hostnames(value);
1572
- } else {
1573
- info("Name resolution is disabled, collector will not parser \"hostnames\" list.");
1574
- }
1575
-
1576
- value = appconfig_get(&collector_config, EBPF_NETWORK_VIEWER_SECTION,
1577
- "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");
1578
- parse_ips(value);
1579
-}
1580
-
1581
-/**
1582
- * Link dimension name
1583
- *
1584
- * Link user specified names inside a link list.
1585
- *
1586
- * @param port the port number associated to the dimension name.
1587
- * @param hash the calculated hash for the dimension name.
1588
- * @param name the dimension name.
1589
- */
1590
-static void link_dimension_name(char *port, uint32_t hash, char *value)
1591
-{
1592
- int test = str2i(port);
1593
- if (test < NETDATA_MINIMUM_PORT_VALUE || test > NETDATA_MAXIMUM_PORT_VALUE){
1594
- error("The dimension given (%s = %s) has an invalid value and it will be ignored.", port, value);
1595
- return;
1596
- }
1597
-
1598
- ebpf_network_viewer_dim_name_t *w;
1599
- w = callocz(1, sizeof(ebpf_network_viewer_dim_name_t));
1600
-
1601
- w->name = strdupz(value);
1602
- w->hash = hash;
1603
-
1604
- w->port = (uint16_t) htons(test);
1605
-
1606
- ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
1607
- if (unlikely(!names)) {
1608
- network_viewer_opt.names = w;
1609
- } else {
1610
- for (; names->next; names = names->next) {
1611
- if (names->port == w->port) {
1612
- info("Dupplicated definition for a service, the name %s will be ignored. ", names->name);
1613
- freez(names->name);
1614
- names->name = w->name;
1615
- names->hash = w->hash;
1616
- freez(w);
1617
- return;
1618
- }
1619
- }
1620
- names->next = w;
1621
- }
1622
-
1623
-#ifdef NETDATA_INTERNAL_CHECKS
1624
- info("Adding values %s( %u) to dimension name list used on network viewer", w->name, htons(w->port));
1625
-#endif
1626
-}
1627
-
1628
-/**
1629
- * Parse service Name section.
1630
- *
1631
- * This function gets the values that will be used to overwrite dimensions.
1632
- */
1633
-static void parse_service_name_section()
1634
-{
1635
- struct section *co = appconfig_get_section(&collector_config, EBPF_SERVICE_NAME_SECTION);
1636
- if (co) {
1637
- struct config_option *cv;
1638
- for (cv = co->values; cv ; cv = cv->next) {
1639
- link_dimension_name(cv->name, cv->hash, cv->value);
1640
- }
1641
- }
1642
-
1643
- // Always associated the default port to Netdata
1644
- ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
1645
- if (names) {
1646
- uint16_t default_port = htons(19999);
1647
- while (names) {
1648
- if (names->port == default_port)
1649
- return;
1650
-
1651
- names = names->next;
1652
- }
759
+ int i;
760
+ int value = (int) appconfig_get_number(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_UPDATE_EVERY, 1);
761
+ for (i = 0; ebpf_modules[i].thread_name; i++) {
762
+ ebpf_modules[i].update_time = value;
763
}
1654
-
1655
- char *port_string = getenv("NETDATA_LISTEN_PORT");
1656
- if (port_string)
1657
- link_dimension_name(port_string, simple_hash(port_string), "Netdata");
764
}
765
766
/**
@@ -1667,18 +773,22 @@ static void read_collector_values(int *disable_apps)
773
// Read global section
774
char *value;
775
if (appconfig_exists(&collector_config, EBPF_GLOBAL_SECTION, "load")) // Backward compatibility
1670
- value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, "load", "entry");
776
+ value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, "load",
777
+ EBPF_CFG_LOAD_MODE_DEFAULT);
778
else
1672
- value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, "ebpf load mode", "entry");
779
+ value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE,
780
+ EBPF_CFG_LOAD_MODE_DEFAULT);
781
782
how_to_load(value);
783
784
+ ebpf_update_interval();
785
+
786
// This is kept to keep compatibility
787
uint32_t enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, "disable apps",
788
CONFIG_BOOLEAN_NO);
789
if (!enabled) {
790
// Apps is a positive sentence, so we need to invert the values to disable apps.
1681
- enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, "apps",
791
+ enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION,
792
CONFIG_BOOLEAN_YES);
793
enabled = (enabled == CONFIG_BOOLEAN_NO)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_NO;
794
}
@@ -1704,8 +814,9 @@ static void read_collector_values(int *disable_apps)
814
if (enabled) {
815
ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps);
816
// Read network viewer section if network viewer is enabled
1707
- parse_network_viewer_section();
1708
- parse_service_name_section();
817
+ // This is kept here to keep backward compatibility
818
+ parse_network_viewer_section(&collector_config);
819
+ parse_service_name_section(&collector_config);
820
started++;
821
}
822
@@ -1736,8 +847,9 @@ static void read_collector_values(int *disable_apps)
847
if (!started){
848
ebpf_enable_all_charts(*disable_apps);
849
// Read network viewer section
1739
- parse_network_viewer_section();
1740
- parse_service_name_section();
850
+ // This is kept here to keep backward compatibility
851
+ parse_network_viewer_section(&collector_config);
852
+ parse_service_name_section(&collector_config);
853
}
854
}
855
@@ -1753,10 +865,13 @@ static int load_collector_config(char *path, int *disable_apps)
865
{
866
char lpath[4096];
867
1756
- snprintf(lpath, 4095, "%s/%s", path, "ebpf.conf");
1757
-
1758
- if (!appconfig_load(&collector_config, lpath, 0, NULL))
1759
- return -1;
868
+ snprintf(lpath, 4095, "%s/%s", path, NETDATA_EBPF_CONFIG_FILE);
869
+ if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
870
+ snprintf(lpath, 4095, "%s/%s", path, NETDATA_EBPF_OLD_CONFIG_FILE);
871
+ if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
872
+ return -1;
873
+ }
874
+ }
875
876
read_collector_values(disable_apps);
877
collectors/ebpf.plugin/ebpf.d.conf
renamed
+2
-15
@@ -10,9 +10,11 @@
10
# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
11
# 'no'.
12
#
13
+# The `update every` option defines the number of seconds used to read data from kernel and send to netdata
14
[global]
15
ebpf load mode = entry
16
apps = yes
17
+ update every = 1
18
19
#
20
# eBPF Programs
@@ -32,18 +34,3 @@
34
sync = yes
35
network connections = no
36
35
-#
36
-# Network Connection
37
-#
38
-# This is a feature with status WIP(Work in Progress)
39
-#
40
-[network connections]
41
- maximum dimensions = 50
42
- resolve hostnames = no
43
- resolve service names = no
44
- ports = *
45
- 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
46
- hostnames = *
47
-
48
-[service name]
49
- 19999 = Netdata
collectors/ebpf.plugin/ebpf.d/cachestat.conf
new
+14
@@ -0,0 +1,14 @@
1
+# The `ebpf load mode` option accepts the following values :
2
+# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3
+# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4
+# new charts for the return of these functions, such as errors.
5
+#
6
+# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7
+# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8
+# 'no'.
9
+#
10
+#
11
+[global]
12
+ ebpf load mode = entry
13
+ apps = yes
14
+ update every = 2
collectors/ebpf.plugin/ebpf.d/ebpf_kernel_reject_list.txt
renamed
collectors/ebpf.plugin/ebpf.d/network.conf
new
+30
@@ -0,0 +1,30 @@
1
+# The `ebpf load mode` option accepts the following values :
2
+# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3
+# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4
+# new charts for the return of these functions, such as errors.
5
+#
6
+# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7
+# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8
+# 'no'.
9
+#
10
+#
11
+[global]
12
+ ebpf load mode = entry
13
+ apps = yes
14
+ update every = 1
15
+
16
+#
17
+# Network Connection
18
+#
19
+# This is a feature with status WIP(Work in Progress)
20
+#
21
+[network connections]
22
+ maximum dimensions = 50
23
+ resolve hostnames = no
24
+ resolve service names = no
25
+ ports = *
26
+ 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
27
+ hostnames = *
28
+
29
+[service name]
30
+ 19999 = Netdata
collectors/ebpf.plugin/ebpf.d/process.conf
new
+14
@@ -0,0 +1,14 @@
1
+# The `ebpf load mode` option accepts the following values :
2
+# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3
+# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4
+# new charts for the return of these functions, such as errors.
5
+#
6
+# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7
+# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8
+# 'no'.
9
+#
10
+#
11
+[global]
12
+ ebpf load mode = entry
13
+ apps = yes
14
+ update every = 1
collectors/ebpf.plugin/ebpf.d/sync.conf
new
+14
@@ -0,0 +1,14 @@
1
+# The `ebpf load mode` option accepts the following values :
2
+# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3
+# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4
+# new charts for the return of these functions, such as errors.
5
+#
6
+# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7
+# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8
+# 'no'.
9
+#
10
+#
11
+[global]
12
+ ebpf load mode = entry
13
+ apps = yes
14
+ update every = 2
collectors/ebpf.plugin/ebpf.h
+13
-10
@@ -31,6 +31,9 @@
31
32
#include "ebpf_apps.h"
33
34
+#define NETDATA_EBPF_OLD_CONFIG_FILE "ebpf.conf"
35
+#define NETDATA_EBPF_CONFIG_FILE "ebpf.d.conf"
36
+
37
typedef struct netdata_syscall_stat {
38
unsigned long bytes; // total number of bytes
39
uint64_t call; // total number of calls
@@ -88,6 +91,8 @@ enum ebpf_module_indexes {
91
92
// Chart defintions
93
#define NETDATA_EBPF_FAMILY "ebpf"
94
+#define NETDATA_EBPF_CHART_TYPE_LINE "line"
95
+#define NETDATA_EBPF_CHART_TYPE_STACKED "stacked"
96
#define NETDATA_EBPF_MEMORY_GROUP "mem"
97
98
// Log file
@@ -151,6 +156,7 @@ extern void ebpf_create_chart(char *type,
156
char *units,
157
char *family,
158
char *context,
159
+ char *charttype,
160
int order,
161
void (*ncd)(void *, int),
162
void *move,
@@ -173,6 +179,7 @@ extern void ebpf_create_charts_on_apps(char *name,
179
char *title,
180
char *units,
181
char *family,
182
+ char *charttype,
183
int order,
184
char *algorithm,
185
struct target *root);
@@ -181,10 +188,7 @@ extern void write_end_chart();
188
189
extern void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps);
190
184
-#define EBPF_GLOBAL_SECTION "global"
191
#define EBPF_PROGRAMS_SECTION "ebpf programs"
186
-#define EBPF_NETWORK_VIEWER_SECTION "network connections"
187
-#define EBPF_SERVICE_NAME_SECTION "service name"
192
193
#define EBPF_COMMON_DIMENSION_PERCENTAGE "%"
194
#define EBPF_COMMON_DIMENSION_CALL "calls/s"
@@ -194,11 +198,15 @@ extern void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps);
198
#define EBPF_COMMON_DIMENSION_PACKETS "packets"
199
200
// Common variables
197
-extern char *ebpf_user_config_dir;
198
-extern char *ebpf_stock_config_dir;
201
extern int debug_enabled;
202
extern struct pid_stat *root_of_pids;
203
extern char *ebpf_algorithms[];
204
+extern struct config collector_config;
205
+extern struct pid_stat *root_of_pids;
206
+extern ebpf_process_stat_t *global_process_stat;
207
+extern size_t all_pids_count;
208
+extern int update_every;
209
+extern uint32_t finalized_threads;
210
211
// Socket functions and variables
212
// Common functions
@@ -207,11 +215,6 @@ extern void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr);
215
extern void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *root);
216
extern void ebpf_one_dimension_write_charts(char *family, char *chart, char *dim, long long v1);
217
extern collected_number get_value_from_structure(char *basis, size_t offset);
210
-extern struct pid_stat *root_of_pids;
211
-extern ebpf_process_stat_t *global_process_stat;
212
-extern size_t all_pids_count;
213
-extern int update_every;
214
-extern uint32_t finalized_threads;
218
219
#define EBPF_MAX_SYNCHRONIZATION_TIME 300
220
collectors/ebpf.plugin/ebpf_apps.h
+5
-5
@@ -11,11 +11,11 @@
11
#include "libnetdata/ebpf/ebpf.h"
12
13
#define NETDATA_APPS_FAMILY "apps"
14
-#define NETDATA_APPS_FILE_GROUP "ebpf file"
15
-#define NETDATA_APPS_VFS_GROUP "ebpf vfs"
16
-#define NETDATA_APPS_PROCESS_GROUP "ebpf process"
17
-#define NETDATA_APPS_NET_GROUP "ebpf net"
18
-#define NETDATA_APPS_CACHESTAT_GROUP "ebpf cachestat"
14
+#define NETDATA_APPS_FILE_GROUP "file (eBPF)"
15
+#define NETDATA_APPS_VFS_GROUP "vfs (eBPF)"
16
+#define NETDATA_APPS_PROCESS_GROUP "process (eBPF)"
17
+#define NETDATA_APPS_NET_GROUP "net (eBPF)"
18
+#define NETDATA_APPS_CACHESTAT_GROUP "page cache (eBPF)"
19
20
#include "ebpf_process.h"
21
#include "ebpf_cachestat.h"
collectors/ebpf.plugin/ebpf_cachestat.c
+21
-7
@@ -11,8 +11,8 @@ static struct bpf_object *objects = NULL;
11
12
static char *cachestat_counter_dimension_name[NETDATA_CACHESTAT_END] = { "ratio", "dirty", "hit",
13
"miss" };
14
-static netdata_syscall_stat_t *cachestat_counter_aggregated_data = NULL;
15
-static netdata_publish_syscall_t *cachestat_counter_publish_aggregated = NULL;
14
+static netdata_syscall_stat_t cachestat_counter_aggregated_data[NETDATA_CACHESTAT_END];
15
+static netdata_publish_syscall_t cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_END];
16
17
netdata_cachestat_pid_t *cachestat_vector = NULL;
18
@@ -26,6 +26,12 @@ struct netdata_static_thread cachestat_threads = {"CACHESTAT KERNEL",
26
27
static int *map_fd = NULL;
28
29
+struct config cachestat_config = { .first_section = NULL,
30
+ .last_section = NULL,
31
+ .mutex = NETDATA_MUTEX_INITIALIZER,
32
+ .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
33
+ .rwlock = AVL_LOCK_INITIALIZER } };
34
+
35
/*****************************************************************
36
*
37
* FUNCTIONS TO CLOSE THE THREAD
@@ -68,9 +74,7 @@ static void ebpf_cachestat_cleanup(void *ptr)
74
clean_pid_structures();
75
freez(cachestat_pid);
76
71
- freez(cachestat_counter_aggregated_data);
77
ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
73
- freez(cachestat_counter_publish_aggregated);
78
79
freez(cachestat_vector);
80
freez(cachestat_hash_values);
@@ -278,6 +282,7 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
282
"The ratio is calculated dividing the Hit pages per total cache accesses without counting dirties.",
283
EBPF_COMMON_DIMENSION_PERCENTAGE,
284
NETDATA_APPS_CACHESTAT_GROUP,
285
+ NETDATA_EBPF_CHART_TYPE_STACKED,
286
20090,
287
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
288
root);
@@ -286,6 +291,7 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
291
"Number of pages marked as dirty. When a page is called dirty, this means that the data stored inside the page needs to be written to devices.",
292
EBPF_CACHESTAT_DIMENSION_PAGE,
293
NETDATA_APPS_CACHESTAT_GROUP,
294
+ NETDATA_EBPF_CHART_TYPE_STACKED,
295
20091,
296
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
297
root);
@@ -294,6 +300,7 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
300
"Number of cache access without counting dirty pages and page additions.",
301
EBPF_CACHESTAT_DIMENSION_HITS,
302
NETDATA_APPS_CACHESTAT_GROUP,
303
+ NETDATA_EBPF_CHART_TYPE_STACKED,
304
20092,
305
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
306
root);
@@ -302,6 +309,7 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
309
"Page caches added without counting dirty pages",
310
EBPF_CACHESTAT_DIMENSION_MISSES,
311
NETDATA_APPS_CACHESTAT_GROUP,
312
+ NETDATA_EBPF_CHART_TYPE_STACKED,
313
20093,
314
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
315
root);
@@ -348,10 +356,10 @@ void *ebpf_cachestat_read_hash(void *ptr)
356
357
heartbeat_t hb;
358
heartbeat_init(&hb);
351
- usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS;
359
360
ebpf_module_t *em = (ebpf_module_t *)ptr;
361
362
+ usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_time;
363
int apps = em->apps_charts;
364
while (!close_ebpf_plugin) {
365
usec_t dt = heartbeat_next(&hb, step);
@@ -533,6 +541,7 @@ static void ebpf_create_memory_charts()
541
"Hit is calculating using total cache added without dirties per total added because of red misses.",
542
EBPF_CACHESTAT_DIMENSION_HITS, NETDATA_CACHESTAT_SUBMENU,
543
NULL,
544
+ NETDATA_EBPF_CHART_TYPE_LINE,
545
21100,
546
ebpf_create_global_dimension,
547
cachestat_counter_publish_aggregated, 1);
@@ -541,6 +550,7 @@ static void ebpf_create_memory_charts()
550
"Number of dirty pages added to the page cache.",
551
EBPF_CACHESTAT_DIMENSION_PAGE, NETDATA_CACHESTAT_SUBMENU,
552
NULL,
553
+ NETDATA_EBPF_CHART_TYPE_LINE,
554
21101,
555
ebpf_create_global_dimension,
556
&cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_DIRTY], 1);
@@ -549,6 +559,7 @@ static void ebpf_create_memory_charts()
559
"Hits are function calls that Netdata counts.",
560
EBPF_CACHESTAT_DIMENSION_HITS, NETDATA_CACHESTAT_SUBMENU,
561
NULL,
562
+ NETDATA_EBPF_CHART_TYPE_LINE,
563
21102,
564
ebpf_create_global_dimension,
565
&cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_HIT], 1);
@@ -557,6 +568,7 @@ static void ebpf_create_memory_charts()
568
"Misses are function calls that Netdata counts.",
569
EBPF_CACHESTAT_DIMENSION_MISSES, NETDATA_CACHESTAT_SUBMENU,
570
NULL,
571
+ NETDATA_EBPF_CHART_TYPE_LINE,
572
21103,
573
ebpf_create_global_dimension,
574
&cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_MISS], 1);
@@ -579,8 +591,8 @@ static void ebpf_cachestat_allocate_global_vectors(size_t length)
591
592
cachestat_hash_values = callocz(length, sizeof(netdata_idx_t));
593
582
- cachestat_counter_aggregated_data = callocz(length, sizeof(netdata_syscall_stat_t));
583
- cachestat_counter_publish_aggregated = callocz(length, sizeof(netdata_publish_syscall_t));
594
+ memset(cachestat_counter_aggregated_data, 0, length * sizeof(netdata_syscall_stat_t));
595
+ memset(cachestat_counter_publish_aggregated, 0, length * sizeof(netdata_publish_syscall_t));
596
}
597
598
/*****************************************************************
@@ -605,6 +617,8 @@ void *ebpf_cachestat_thread(void *ptr)
617
ebpf_module_t *em = (ebpf_module_t *)ptr;
618
fill_ebpf_data(&cachestat_data);
619
620
+ ebpf_update_module(em, &cachestat_config, NETDATA_CACHESTAT_CONFIG_FILE);
621
+
622
if (!em->enabled)
623
goto endcachestat;
624
collectors/ebpf.plugin/ebpf_cachestat.h
+4
-1
@@ -9,7 +9,7 @@
9
#define NETDATA_CACHESTAT_HIT_CHART "cachestat_hits"
10
#define NETDATA_CACHESTAT_MISSES_CHART "cachestat_misses"
11
12
-#define NETDATA_CACHESTAT_SUBMENU "page cache"
12
+#define NETDATA_CACHESTAT_SUBMENU "page cache (eBPF)"
13
14
#define EBPF_CACHESTAT_DIMENSION_PAGE "pages/s"
15
#define EBPF_CACHESTAT_DIMENSION_HITS "hits/s"
@@ -17,6 +17,9 @@
17
18
#define NETDATA_LATENCY_CACHESTAT_SLEEP_MS 600000ULL
19
20
+// configuration file
21
+#define NETDATA_CACHESTAT_CONFIG_FILE "cachestat.conf"
22
+
23
// variables
24
enum cachestat_counters {
25
NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU,
collectors/ebpf.plugin/ebpf_process.c
+37
-9
@@ -19,8 +19,8 @@ static char *process_id_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "do_sys_open"
19
static char *status[] = { "process", "zombie" };
20
21
static netdata_idx_t *process_hash_values = NULL;
22
-static netdata_syscall_stat_t *process_aggregated_data = NULL;
23
-static netdata_publish_syscall_t *process_publish_aggregated = NULL;
22
+static netdata_syscall_stat_t process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_END];
23
+static netdata_publish_syscall_t process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_END];
24
25
static ebpf_data_t process_data;
26
@@ -33,6 +33,12 @@ static int *map_fd = NULL;
33
static struct bpf_object *objects = NULL;
34
static struct bpf_link **probe_links = NULL;
35
36
+struct config process_config = { .first_section = NULL,
37
+ .last_section = NULL,
38
+ .mutex = NETDATA_MUTEX_INITIALIZER,
39
+ .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
40
+ .rwlock = AVL_LOCK_INITIALIZER } };
41
+
42
/*****************************************************************
43
*
44
* PROCESS DATA AND SEND TO NETDATA
@@ -521,6 +527,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
527
EBPF_COMMON_DIMENSION_CALL,
528
NETDATA_FILE_GROUP,
529
NULL,
530
+ NETDATA_EBPF_CHART_TYPE_LINE,
531
21000,
532
ebpf_create_global_dimension,
533
process_publish_aggregated,
@@ -533,6 +540,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
540
EBPF_COMMON_DIMENSION_CALL,
541
NETDATA_FILE_GROUP,
542
NULL,
543
+ NETDATA_EBPF_CHART_TYPE_LINE,
544
21001,
545
ebpf_create_global_dimension,
546
process_publish_aggregated,
@@ -545,6 +553,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
553
EBPF_COMMON_DIMENSION_CALL,
554
NETDATA_VFS_GROUP,
555
NULL,
556
+ NETDATA_EBPF_CHART_TYPE_LINE,
557
21002,
558
ebpf_create_global_dimension,
559
&process_publish_aggregated[NETDATA_DEL_START],
@@ -556,6 +565,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
565
EBPF_COMMON_DIMENSION_CALL,
566
NETDATA_VFS_GROUP,
567
NULL,
568
+ NETDATA_EBPF_CHART_TYPE_LINE,
569
21003,
570
ebpf_create_global_dimension,
571
&process_publish_aggregated[NETDATA_IN_START_BYTE],
@@ -574,6 +584,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
584
EBPF_COMMON_DIMENSION_CALL,
585
NETDATA_VFS_GROUP,
586
NULL,
587
+ NETDATA_EBPF_CHART_TYPE_LINE,
588
21005,
589
ebpf_create_global_dimension,
590
&process_publish_aggregated[2],
@@ -586,6 +597,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
597
EBPF_COMMON_DIMENSION_CALL,
598
NETDATA_PROCESS_GROUP,
599
NULL,
600
+ NETDATA_EBPF_CHART_TYPE_LINE,
601
21006,
602
ebpf_create_global_dimension,
603
&process_publish_aggregated[NETDATA_PROCESS_START],
@@ -597,6 +609,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
609
EBPF_COMMON_DIMENSION_CALL,
610
NETDATA_PROCESS_GROUP,
611
NULL,
612
+ NETDATA_EBPF_CHART_TYPE_LINE,
613
21007,
614
ebpf_create_global_dimension,
615
&process_publish_aggregated[NETDATA_EXIT_START],
@@ -616,6 +629,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
629
EBPF_COMMON_DIMENSION_CALL,
630
NETDATA_PROCESS_GROUP,
631
NULL,
632
+ NETDATA_EBPF_CHART_TYPE_LINE,
633
21009,
634
ebpf_create_global_dimension,
635
&process_publish_aggregated[NETDATA_PROCESS_START],
@@ -638,6 +652,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
652
"Number of open files",
653
EBPF_COMMON_DIMENSION_CALL,
654
NETDATA_APPS_FILE_GROUP,
655
+ NETDATA_EBPF_CHART_TYPE_STACKED,
656
20061,
657
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
658
root);
@@ -647,6 +662,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
662
"Fails to open files",
663
EBPF_COMMON_DIMENSION_CALL,
664
NETDATA_APPS_FILE_GROUP,
665
+ NETDATA_EBPF_CHART_TYPE_STACKED,
666
20062,
667
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
668
root);
@@ -656,6 +672,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
672
"Files closed",
673
EBPF_COMMON_DIMENSION_CALL,
674
NETDATA_APPS_FILE_GROUP,
675
+ NETDATA_EBPF_CHART_TYPE_STACKED,
676
20063,
677
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
678
root);
@@ -665,6 +682,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
682
"Fails to close files",
683
EBPF_COMMON_DIMENSION_CALL,
684
NETDATA_APPS_FILE_GROUP,
685
+ NETDATA_EBPF_CHART_TYPE_STACKED,
686
20064,
687
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
688
root);
@@ -674,6 +692,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
692
"Files deleted",
693
EBPF_COMMON_DIMENSION_CALL,
694
NETDATA_APPS_VFS_GROUP,
695
+ NETDATA_EBPF_CHART_TYPE_STACKED,
696
20065,
697
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
698
root);
@@ -682,6 +701,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
701
"Write to disk",
702
EBPF_COMMON_DIMENSION_CALL,
703
NETDATA_APPS_VFS_GROUP,
704
+ NETDATA_EBPF_CHART_TYPE_STACKED,
705
20066,
706
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
707
apps_groups_root_target);
@@ -691,6 +711,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
711
"Fails to write",
712
EBPF_COMMON_DIMENSION_CALL,
713
NETDATA_APPS_VFS_GROUP,
714
+ NETDATA_EBPF_CHART_TYPE_STACKED,
715
20067,
716
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
717
root);
@@ -700,6 +721,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
721
"Read from disk",
722
EBPF_COMMON_DIMENSION_CALL,
723
NETDATA_APPS_VFS_GROUP,
724
+ NETDATA_EBPF_CHART_TYPE_STACKED,
725
20068,
726
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
727
root);
@@ -709,6 +731,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
731
"Fails to read",
732
EBPF_COMMON_DIMENSION_CALL,
733
NETDATA_APPS_VFS_GROUP,
734
+ NETDATA_EBPF_CHART_TYPE_STACKED,
735
20069,
736
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
737
root);
@@ -717,6 +740,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
740
ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
741
"Bytes written on disk", EBPF_COMMON_DIMENSION_BYTES,
742
NETDATA_APPS_VFS_GROUP,
743
+ NETDATA_EBPF_CHART_TYPE_STACKED,
744
20070,
745
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
746
root);
@@ -724,6 +748,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
748
ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
749
"Bytes read from disk", EBPF_COMMON_DIMENSION_BYTES,
750
NETDATA_APPS_VFS_GROUP,
751
+ NETDATA_EBPF_CHART_TYPE_STACKED,
752
20071,
753
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
754
root);
@@ -732,6 +757,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
757
"Process started",
758
EBPF_COMMON_DIMENSION_CALL,
759
NETDATA_APPS_PROCESS_GROUP,
760
+ NETDATA_EBPF_CHART_TYPE_STACKED,
761
20072,
762
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
763
root);
@@ -740,6 +766,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
766
"Threads started",
767
EBPF_COMMON_DIMENSION_CALL,
768
NETDATA_APPS_PROCESS_GROUP,
769
+ NETDATA_EBPF_CHART_TYPE_STACKED,
770
20073,
771
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
772
root);
@@ -748,6 +775,7 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
775
"Tasks closed",
776
EBPF_COMMON_DIMENSION_CALL,
777
NETDATA_APPS_PROCESS_GROUP,
778
+ NETDATA_EBPF_CHART_TYPE_STACKED,
779
20074,
780
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
781
root);
@@ -798,7 +826,7 @@ static void ebpf_create_apps_charts(ebpf_module_t *em, struct target *root)
826
int counter;
827
for (counter = 0; ebpf_modules[counter].thread_name; counter++) {
828
ebpf_module_t *current = &ebpf_modules[counter];
801
- if (current->apps_charts && current->apps_routine)
829
+ if (current->enabled && current->apps_charts && current->apps_routine)
830
current->apps_routine(em, root);
831
}
832
}
@@ -914,9 +942,7 @@ static void ebpf_process_cleanup(void *ptr)
942
UNUSED(dt);
943
}
944
917
- freez(process_aggregated_data);
945
ebpf_cleanup_publish_syscall(process_publish_aggregated);
919
- freez(process_publish_aggregated);
946
freez(process_hash_values);
947
948
clean_global_memory();
@@ -950,8 +976,8 @@ static void ebpf_process_cleanup(void *ptr)
976
*/
977
static void ebpf_process_allocate_global_vectors(size_t length)
978
{
953
- process_aggregated_data = callocz(length, sizeof(netdata_syscall_stat_t));
954
- process_publish_aggregated = callocz(length, sizeof(netdata_publish_syscall_t));
979
+ memset(process_aggregated_data, 0, length * sizeof(netdata_syscall_stat_t));
980
+ memset(process_publish_aggregated, 0, length * sizeof(netdata_publish_syscall_t));
981
process_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
982
983
global_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
@@ -1028,13 +1054,15 @@ void *ebpf_process_thread(void *ptr)
1054
fill_ebpf_data(&process_data);
1055
1056
pthread_mutex_lock(&lock);
1031
- ebpf_process_allocate_global_vectors(NETDATA_MAX_MONITOR_VECTOR);
1057
+ ebpf_process_allocate_global_vectors(NETDATA_KEY_PUBLISH_PROCESS_END);
1058
1059
if (ebpf_update_kernel(&process_data)) {
1060
pthread_mutex_unlock(&lock);
1061
goto endprocess;
1062
}
1063
1064
+ ebpf_update_module(em, &process_config, NETDATA_PROCESS_CONFIG_FILE);
1065
+
1066
set_local_pointers();
1067
probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, process_data.map_fd);
1068
if (!probe_links) {
@@ -1050,7 +1078,7 @@ void *ebpf_process_thread(void *ptr)
1078
1079
ebpf_global_labels(
1080
process_aggregated_data, process_publish_aggregated, process_dimension_names, process_id_names,
1053
- algorithms, NETDATA_MAX_MONITOR_VECTOR);
1081
+ algorithms, NETDATA_KEY_PUBLISH_PROCESS_END);
1082
1083
if (process_enabled) {
1084
ebpf_create_global_charts(em);
collectors/ebpf.plugin/ebpf_process.h
+3
-1
@@ -10,7 +10,6 @@
10
11
// Internal constants
12
#define NETDATA_GLOBAL_VECTOR 24
13
-#define NETDATA_MAX_MONITOR_VECTOR 9
13
#define NETDATA_VFS_ERRORS 3
14
15
// Map index
@@ -52,6 +51,9 @@
51
#define NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR "vfs_write_error"
52
#define NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR "vfs_read_error"
53
54
+// Process configuration name
55
+#define NETDATA_PROCESS_CONFIG_FILE "process.conf"
56
+
57
// Index from kernel
58
typedef enum ebpf_process_index {
59
NETDATA_KEY_CALLS_DO_SYS_OPEN,
collectors/ebpf.plugin/ebpf_socket.c
+978
-32
@@ -17,8 +17,8 @@ static char *socket_id_names[NETDATA_MAX_SOCKET_VECTOR] = { "tcp_sendmsg", "tcp_
17
"udp_sendmsg", "udp_recvmsg", "tcp_retransmit_skb" };
18
19
static netdata_idx_t *socket_hash_values = NULL;
20
-static netdata_syscall_stat_t *socket_aggregated_data = NULL;
21
-static netdata_publish_syscall_t *socket_publish_aggregated = NULL;
20
+static netdata_syscall_stat_t socket_aggregated_data[NETDATA_MAX_SOCKET_VECTOR];
21
+static netdata_publish_syscall_t socket_publish_aggregated[NETDATA_MAX_SOCKET_VECTOR];
22
23
static ebpf_data_t socket_data;
24
@@ -40,6 +40,12 @@ static int *map_fd = NULL;
40
static struct bpf_object *objects = NULL;
41
static struct bpf_link **probe_links = NULL;
42
43
+struct config socket_config = { .first_section = NULL,
44
+ .last_section = NULL,
45
+ .mutex = NETDATA_MUTEX_INITIALIZER,
46
+ .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
47
+ .rwlock = AVL_LOCK_INITIALIZER } };
48
+
49
/*****************************************************************
50
*
51
* PROCESS DATA AND SEND TO NETDATA
@@ -279,17 +285,20 @@ static void ebpf_socket_send_data(ebpf_module_t *em)
285
NETDATA_TCP_FUNCTION_ERROR, NETDATA_EBPF_FAMILY, socket_publish_aggregated, 2);
286
}
287
write_count_chart(
282
- NETDATA_TCP_RETRANSMIT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_RETRANSMIT_START], 1);
288
+ NETDATA_TCP_RETRANSMIT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT],
289
+ 1);
290
291
write_count_chart(
285
- NETDATA_UDP_FUNCTION_COUNT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_UDP_START], 2);
292
+ NETDATA_UDP_FUNCTION_COUNT, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
293
+ 2);
294
write_io_chart(
295
NETDATA_UDP_FUNCTION_BITS, NETDATA_EBPF_FAMILY,
296
socket_id_names[3],(long long)common_udp.write*8/100,
297
socket_id_names[4], (long long)common_udp.read*8/1000);
298
if (em->mode < MODE_ENTRY) {
299
write_err_chart(
292
- NETDATA_UDP_FUNCTION_ERROR, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_UDP_START], 2);
300
+ NETDATA_UDP_FUNCTION_ERROR, NETDATA_EBPF_FAMILY, &socket_publish_aggregated[NETDATA_UDP_START],
301
+ 2);
302
}
303
}
304
@@ -428,6 +437,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
437
EBPF_COMMON_DIMENSION_CALL,
438
NETDATA_SOCKET_GROUP,
439
NULL,
440
+ NETDATA_EBPF_CHART_TYPE_LINE,
441
21070,
442
ebpf_create_global_dimension,
443
socket_publish_aggregated,
@@ -437,6 +447,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
447
"TCP bandwidth", EBPF_COMMON_DIMENSION_BITS,
448
NETDATA_SOCKET_GROUP,
449
NULL,
450
+ NETDATA_EBPF_CHART_TYPE_LINE,
451
21071,
452
ebpf_create_global_dimension,
453
socket_publish_aggregated,
@@ -449,6 +460,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
460
EBPF_COMMON_DIMENSION_CALL,
461
NETDATA_SOCKET_GROUP,
462
NULL,
463
+ NETDATA_EBPF_CHART_TYPE_LINE,
464
21072,
465
ebpf_create_global_dimension,
466
socket_publish_aggregated,
@@ -461,9 +473,10 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
473
EBPF_COMMON_DIMENSION_CALL,
474
NETDATA_SOCKET_GROUP,
475
NULL,
476
+ NETDATA_EBPF_CHART_TYPE_LINE,
477
21073,
478
ebpf_create_global_dimension,
466
- &socket_publish_aggregated[NETDATA_RETRANSMIT_START],
479
+ &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT],
480
1);
481
482
ebpf_create_chart(NETDATA_EBPF_FAMILY,
@@ -472,18 +485,20 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
485
EBPF_COMMON_DIMENSION_CALL,
486
NETDATA_SOCKET_GROUP,
487
NULL,
488
+ NETDATA_EBPF_CHART_TYPE_LINE,
489
21074,
490
ebpf_create_global_dimension,
477
- &socket_publish_aggregated[NETDATA_UDP_START],
491
+ &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
492
2);
493
494
ebpf_create_chart(NETDATA_EBPF_FAMILY, NETDATA_UDP_FUNCTION_BITS,
495
"UDP bandwidth", EBPF_COMMON_DIMENSION_BITS,
496
NETDATA_SOCKET_GROUP,
497
NULL,
498
+ NETDATA_EBPF_CHART_TYPE_LINE,
499
21075,
500
ebpf_create_global_dimension,
486
- &socket_publish_aggregated[NETDATA_UDP_START],
501
+ &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
502
2);
503
504
if (em->mode < MODE_ENTRY) {
@@ -493,9 +508,10 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
508
EBPF_COMMON_DIMENSION_CALL,
509
NETDATA_SOCKET_GROUP,
510
NULL,
511
+ NETDATA_EBPF_CHART_TYPE_LINE,
512
21076,
513
ebpf_create_global_dimension,
498
- &socket_publish_aggregated[NETDATA_UDP_START],
514
+ &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
515
2);
516
}
517
}
@@ -515,6 +531,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
531
ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_SENT,
532
"Bytes sent", EBPF_COMMON_DIMENSION_BITS,
533
NETDATA_APPS_NET_GROUP,
534
+ NETDATA_EBPF_CHART_TYPE_STACKED,
535
20080,
536
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
537
root);
@@ -522,6 +539,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
539
ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_RECV,
540
"bytes received", EBPF_COMMON_DIMENSION_BITS,
541
NETDATA_APPS_NET_GROUP,
542
+ NETDATA_EBPF_CHART_TYPE_STACKED,
543
20081,
544
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
545
root);
@@ -530,6 +548,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
548
"Calls for tcp_sendmsg",
549
EBPF_COMMON_DIMENSION_CALL,
550
NETDATA_APPS_NET_GROUP,
551
+ NETDATA_EBPF_CHART_TYPE_STACKED,
552
20082,
553
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
554
root);
@@ -538,6 +557,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
557
"Calls for tcp_cleanup_rbuf",
558
EBPF_COMMON_DIMENSION_CALL,
559
NETDATA_APPS_NET_GROUP,
560
+ NETDATA_EBPF_CHART_TYPE_STACKED,
561
20083,
562
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
563
root);
@@ -546,6 +566,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
566
"Calls for tcp_retransmit",
567
EBPF_COMMON_DIMENSION_CALL,
568
NETDATA_APPS_NET_GROUP,
569
+ NETDATA_EBPF_CHART_TYPE_STACKED,
570
20084,
571
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
572
root);
@@ -554,6 +575,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
575
"Calls for udp_sendmsg",
576
EBPF_COMMON_DIMENSION_CALL,
577
NETDATA_APPS_NET_GROUP,
578
+ NETDATA_EBPF_CHART_TYPE_STACKED,
579
20085,
580
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
581
root);
@@ -562,6 +584,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
584
"Calls for udp_recvmsg",
585
EBPF_COMMON_DIMENSION_CALL,
586
NETDATA_APPS_NET_GROUP,
587
+ NETDATA_EBPF_CHART_TYPE_STACKED,
588
20086,
589
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
590
root);
@@ -589,7 +612,7 @@ static void ebpf_socket_create_nv_chart(char *id, char *title, char *units,
612
title,
613
units,
614
family,
592
- "stacked",
615
+ NETDATA_EBPF_CHART_TYPE_STACKED,
616
NULL,
617
order);
618
@@ -626,7 +649,7 @@ static void ebpf_socket_create_nv_retransmit(char *id, char *title, char *units,
649
title,
650
units,
651
family,
629
- "stacked",
652
+ NETDATA_EBPF_CHART_TYPE_STACKED,
653
NULL,
654
order);
655
@@ -1438,7 +1461,7 @@ void *ebpf_socket_read_hash(void *ptr)
1461
read_thread_closed = 0;
1462
heartbeat_t hb;
1463
heartbeat_init(&hb);
1441
- usec_t step = NETDATA_SOCKET_READ_SLEEP_MS;
1464
+ usec_t step = NETDATA_SOCKET_READ_SLEEP_MS * em->update_time;
1465
int fd_ipv4 = map_fd[NETDATA_SOCKET_IPV4_HASH_TABLE];
1466
int fd_ipv6 = map_fd[NETDATA_SOCKET_IPV6_HASH_TABLE];
1467
int network_connection = em->optional;
@@ -1482,22 +1505,22 @@ static void read_hash_global_tables()
1505
}
1506
}
1507
1485
- socket_aggregated_data[0].call = res[NETDATA_KEY_CALLS_TCP_SENDMSG];
1486
- socket_aggregated_data[1].call = res[NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF];
1487
- socket_aggregated_data[2].call = res[NETDATA_KEY_CALLS_TCP_CLOSE];
1488
- socket_aggregated_data[3].call = res[NETDATA_KEY_CALLS_UDP_RECVMSG];
1489
- socket_aggregated_data[4].call = res[NETDATA_KEY_CALLS_UDP_SENDMSG];
1490
- socket_aggregated_data[5].call = res[NETDATA_KEY_TCP_RETRANSMIT];
1491
-
1492
- socket_aggregated_data[0].ecall = res[NETDATA_KEY_ERROR_TCP_SENDMSG];
1493
- socket_aggregated_data[1].ecall = res[NETDATA_KEY_ERROR_TCP_CLEANUP_RBUF];
1494
- socket_aggregated_data[3].ecall = res[NETDATA_KEY_ERROR_UDP_RECVMSG];
1495
- socket_aggregated_data[4].ecall = res[NETDATA_KEY_ERROR_UDP_SENDMSG];
1496
-
1497
- socket_aggregated_data[0].bytes = res[NETDATA_KEY_BYTES_TCP_SENDMSG];
1498
- socket_aggregated_data[1].bytes = res[NETDATA_KEY_BYTES_TCP_CLEANUP_RBUF];
1499
- socket_aggregated_data[3].bytes = res[NETDATA_KEY_BYTES_UDP_RECVMSG];
1500
- socket_aggregated_data[4].bytes = res[NETDATA_KEY_BYTES_UDP_SENDMSG];
1508
+ socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].call = res[NETDATA_KEY_CALLS_TCP_SENDMSG];
1509
+ socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].call = res[NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF];
1510
+ socket_aggregated_data[NETDATA_IDX_TCP_CLOSE].call = res[NETDATA_KEY_CALLS_TCP_CLOSE];
1511
+ socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].call = res[NETDATA_KEY_CALLS_UDP_RECVMSG];
1512
+ socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].call = res[NETDATA_KEY_CALLS_UDP_SENDMSG];
1513
+ socket_aggregated_data[NETDATA_IDX_TCP_RETRANSMIT].call = res[NETDATA_KEY_TCP_RETRANSMIT];
1514
+
1515
+ socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_TCP_SENDMSG];
1516
+ socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].ecall = res[NETDATA_KEY_ERROR_TCP_CLEANUP_RBUF];
1517
+ socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].ecall = res[NETDATA_KEY_ERROR_UDP_RECVMSG];
1518
+ socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_UDP_SENDMSG];
1519
+
1520
+ socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_TCP_SENDMSG];
1521
+ socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].bytes = res[NETDATA_KEY_BYTES_TCP_CLEANUP_RBUF];
1522
+ socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].bytes = res[NETDATA_KEY_BYTES_UDP_RECVMSG];
1523
+ socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_UDP_SENDMSG];
1524
}
1525
1526
/**
@@ -1755,6 +1778,59 @@ void clean_thread_structures() {
1778
}
1779
}
1780
1781
+/**
1782
+ * Cleanup publish syscall
1783
+ *
1784
+ * @param nps list of structures to clean
1785
+ */
1786
+void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
1787
+{
1788
+ while (nps) {
1789
+ freez(nps->algorithm);
1790
+ nps = nps->next;
1791
+ }
1792
+}
1793
+
1794
+/**
1795
+ * Clean port Structure
1796
+ *
1797
+ * Clean the allocated list.
1798
+ *
1799
+ * @param clean the list that will be cleaned
1800
+ */
1801
+void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
1802
+{
1803
+ ebpf_network_viewer_port_list_t *move = *clean;
1804
+ while (move) {
1805
+ ebpf_network_viewer_port_list_t *next = move->next;
1806
+ freez(move->value);
1807
+ freez(move);
1808
+
1809
+ move = next;
1810
+ }
1811
+ *clean = NULL;
1812
+}
1813
+
1814
+/**
1815
+ * Clean IP structure
1816
+ *
1817
+ * Clean the allocated list.
1818
+ *
1819
+ * @param clean the list that will be cleaned
1820
+ */
1821
+static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
1822
+{
1823
+ ebpf_network_viewer_ip_list_t *move = *clean;
1824
+ while (move) {
1825
+ ebpf_network_viewer_ip_list_t *next = move->next;
1826
+ freez(move->value);
1827
+ freez(move);
1828
+
1829
+ move = next;
1830
+ }
1831
+ *clean = NULL;
1832
+}
1833
+
1834
/**
1835
* Clean up the main thread.
1836
*
@@ -1774,9 +1850,7 @@ static void ebpf_socket_cleanup(void *ptr)
1850
UNUSED(dt);
1851
}
1852
1777
- freez(socket_aggregated_data);
1853
ebpf_cleanup_publish_syscall(socket_publish_aggregated);
1779
- freez(socket_publish_aggregated);
1854
freez(socket_hash_values);
1855
1856
clean_thread_structures();
@@ -1828,8 +1902,8 @@ static void ebpf_socket_cleanup(void *ptr)
1902
*/
1903
static void ebpf_socket_allocate_global_vectors(size_t length)
1904
{
1831
- socket_aggregated_data = callocz(length, sizeof(netdata_syscall_stat_t));
1832
- socket_publish_aggregated = callocz(length, sizeof(netdata_publish_syscall_t));
1905
+ memset(socket_aggregated_data, 0 ,length * sizeof(netdata_syscall_stat_t));
1906
+ memset(socket_publish_aggregated, 0 ,length * sizeof(netdata_publish_syscall_t));
1907
socket_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
1908
1909
socket_bandwidth_curr = callocz((size_t)pid_max, sizeof(ebpf_socket_publish_apps_t *));
@@ -1867,6 +1941,874 @@ static void initialize_inbound_outbound()
1941
*
1942
*****************************************************************/
1943
1944
+/**
1945
+ * Fill Port list
1946
+ *
1947
+ * @param out a pointer to the link list.
1948
+ * @param in the structure that will be linked.
1949
+ */
1950
+static inline void fill_port_list(ebpf_network_viewer_port_list_t **out, ebpf_network_viewer_port_list_t *in)
1951
+{
1952
+ if (likely(*out)) {
1953
+ ebpf_network_viewer_port_list_t *move = *out, *store = *out;
1954
+ uint16_t first = ntohs(in->first);
1955
+ uint16_t last = ntohs(in->last);
1956
+ while (move) {
1957
+ uint16_t cmp_first = ntohs(move->first);
1958
+ uint16_t cmp_last = ntohs(move->last);
1959
+ if (cmp_first <= first && first <= cmp_last &&
1960
+ cmp_first <= last && last <= cmp_last ) {
1961
+ info("The range/value (%u, %u) is inside the range/value (%u, %u) already inserted, it will be ignored.",
1962
+ first, last, cmp_first, cmp_last);
1963
+ freez(in->value);
1964
+ freez(in);
1965
+ return;
1966
+ } else if (first <= cmp_first && cmp_first <= last &&
1967
+ first <= cmp_last && cmp_last <= last) {
1968
+ info("The range (%u, %u) is bigger than previous range (%u, %u) already inserted, the previous will be ignored.",
1969
+ first, last, cmp_first, cmp_last);
1970
+ freez(move->value);
1971
+ move->value = in->value;
1972
+ move->first = in->first;
1973
+ move->last = in->last;
1974
+ freez(in);
1975
+ return;
1976
+ }
1977
+
1978
+ store = move;
1979
+ move = move->next;
1980
+ }
1981
+
1982
+ store->next = in;
1983
+ } else {
1984
+ *out = in;
1985
+ }
1986
+
1987
+#ifdef NETDATA_INTERNAL_CHECKS
1988
+ info("Adding values %s( %u, %u) to %s port list used on network viewer",
1989
+ in->value, ntohs(in->first), ntohs(in->last),
1990
+ (*out == network_viewer_opt.included_port)?"included":"excluded");
1991
+#endif
1992
+}
1993
+
1994
+/**
1995
+ * Parse Service List
1996
+ *
1997
+ * @param out a pointer to store the link list
1998
+ * @param service the service used to create the structure that will be linked.
1999
+ */
2000
+static void parse_service_list(void **out, char *service)
2001
+{
2002
+ ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
2003
+ struct servent *serv = getservbyname((const char *)service, "tcp");
2004
+ if (!serv)
2005
+ serv = getservbyname((const char *)service, "udp");
2006
+
2007
+ if (!serv) {
2008
+ info("Cannot resolv the service '%s' with protocols TCP and UDP, it will be ignored", service);
2009
+ return;
2010
+ }
2011
+
2012
+ ebpf_network_viewer_port_list_t *w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
2013
+ w->value = strdupz(service);
2014
+ w->hash = simple_hash(service);
2015
+
2016
+ w->first = w->last = (uint16_t)serv->s_port;
2017
+
2018
+ fill_port_list(list, w);
2019
+}
2020
+
2021
+/**
2022
+ * Netmask
2023
+ *
2024
+ * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
2025
+ *
2026
+ * @param prefix create the netmask based in the CIDR value.
2027
+ *
2028
+ * @return
2029
+ */
2030
+static inline in_addr_t netmask(int prefix) {
2031
+
2032
+ if (prefix == 0)
2033
+ return (~((in_addr_t) - 1));
2034
+ else
2035
+ return (in_addr_t)(~((1 << (32 - prefix)) - 1));
2036
+
2037
+}
2038
+
2039
+/**
2040
+ * Broadcast
2041
+ *
2042
+ * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
2043
+ *
2044
+ * @param addr is the ip address
2045
+ * @param prefix is the CIDR value.
2046
+ *
2047
+ * @return It returns the last address of the range
2048
+ */
2049
+static inline in_addr_t broadcast(in_addr_t addr, int prefix)
2050
+{
2051
+ return (addr | ~netmask(prefix));
2052
+}
2053
+
2054
+/**
2055
+ * Network
2056
+ *
2057
+ * Copied from iprange (https://github.com/firehol/iprange/blob/master/iprange.h)
2058
+ *
2059
+ * @param addr is the ip address
2060
+ * @param prefix is the CIDR value.
2061
+ *
2062
+ * @return It returns the first address of the range.
2063
+ */
2064
+static inline in_addr_t ipv4_network(in_addr_t addr, int prefix)
2065
+{
2066
+ return (addr & netmask(prefix));
2067
+}
2068
+
2069
+/**
2070
+ * IP to network long
2071
+ *
2072
+ * @param dst the vector to store the result
2073
+ * @param ip the source ip given by our users.
2074
+ * @param domain the ip domain (IPV4 or IPV6)
2075
+ * @param source the original string
2076
+ *
2077
+ * @return it returns 0 on success and -1 otherwise.
2078
+ */
2079
+static inline int ip2nl(uint8_t *dst, char *ip, int domain, char *source)
2080
+{
2081
+ if (inet_pton(domain, ip, dst) <= 0) {
2082
+ error("The address specified (%s) is invalid ", source);
2083
+ return -1;
2084
+ }
2085
+
2086
+ return 0;
2087
+}
2088
+
2089
+/**
2090
+ * Get IPV6 Last Address
2091
+ *
2092
+ * @param out the address to store the last address.
2093
+ * @param in the address used to do the math.
2094
+ * @param prefix number of bits used to calculate the address
2095
+ */
2096
+static void get_ipv6_last_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
2097
+{
2098
+ uint64_t mask,tmp;
2099
+ uint64_t ret[2];
2100
+ memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
2101
+
2102
+ if (prefix == 128) {
2103
+ memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
2104
+ return;
2105
+ } else if (!prefix) {
2106
+ ret[0] = ret[1] = 0xFFFFFFFFFFFFFFFF;
2107
+ memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
2108
+ return;
2109
+ } else if (prefix <= 64) {
2110
+ ret[1] = 0xFFFFFFFFFFFFFFFFULL;
2111
+
2112
+ tmp = be64toh(ret[0]);
2113
+ if (prefix > 0) {
2114
+ mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
2115
+ tmp |= ~mask;
2116
+ }
2117
+ ret[0] = htobe64(tmp);
2118
+ } else {
2119
+ mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
2120
+ tmp = be64toh(ret[1]);
2121
+ tmp |= ~mask;
2122
+ ret[1] = htobe64(tmp);
2123
+ }
2124
+
2125
+ memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
2126
+}
2127
+
2128
+/**
2129
+ * Calculate ipv6 first address
2130
+ *
2131
+ * @param out the address to store the first address.
2132
+ * @param in the address used to do the math.
2133
+ * @param prefix number of bits used to calculate the address
2134
+ */
2135
+static void get_ipv6_first_addr(union netdata_ip_t *out, union netdata_ip_t *in, uint64_t prefix)
2136
+{
2137
+ uint64_t mask,tmp;
2138
+ uint64_t ret[2];
2139
+
2140
+ memcpy(ret, in->addr32, sizeof(union netdata_ip_t));
2141
+
2142
+ if (prefix == 128) {
2143
+ memcpy(out->addr32, in->addr32, sizeof(union netdata_ip_t));
2144
+ return;
2145
+ } else if (!prefix) {
2146
+ ret[0] = ret[1] = 0;
2147
+ memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
2148
+ return;
2149
+ } else if (prefix <= 64) {
2150
+ ret[1] = 0ULL;
2151
+
2152
+ tmp = be64toh(ret[0]);
2153
+ if (prefix > 0) {
2154
+ mask = 0xFFFFFFFFFFFFFFFFULL << (64 - prefix);
2155
+ tmp &= mask;
2156
+ }
2157
+ ret[0] = htobe64(tmp);
2158
+ } else {
2159
+ mask = 0xFFFFFFFFFFFFFFFFULL << (128 - prefix);
2160
+ tmp = be64toh(ret[1]);
2161
+ tmp &= mask;
2162
+ ret[1] = htobe64(tmp);
2163
+ }
2164
+
2165
+ memcpy(out->addr32, ret, sizeof(union netdata_ip_t));
2166
+}
2167
+
2168
+/**
2169
+ * Is ip inside the range
2170
+ *
2171
+ * Check if the ip is inside a IP range
2172
+ *
2173
+ * @param rfirst the first ip address of the range
2174
+ * @param rlast the last ip address of the range
2175
+ * @param cmpfirst the first ip to compare
2176
+ * @param cmplast the last ip to compare
2177
+ * @param family the IP family
2178
+ *
2179
+ * @return It returns 1 if the IP is inside the range and 0 otherwise
2180
+ */
2181
+static int is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rlast,
2182
+ union netdata_ip_t *cmpfirst, union netdata_ip_t *cmplast, int family)
2183
+{
2184
+ if (family == AF_INET) {
2185
+ if (ntohl(rfirst->addr32[0]) <= ntohl(cmpfirst->addr32[0]) &&
2186
+ ntohl(rlast->addr32[0]) >= ntohl(cmplast->addr32[0]))
2187
+ return 1;
2188
+ } else {
2189
+ if (memcmp(rfirst->addr8, cmpfirst->addr8, sizeof(union netdata_ip_t)) <= 0 &&
2190
+ memcmp(rlast->addr8, cmplast->addr8, sizeof(union netdata_ip_t)) >= 0) {
2191
+ return 1;
2192
+ }
2193
+
2194
+ }
2195
+ return 0;
2196
+}
2197
+
2198
+/**
2199
+ * Fill IP list
2200
+ *
2201
+ * @param out a pointer to the link list.
2202
+ * @param in the structure that will be linked.
2203
+ */
2204
+void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table)
2205
+{
2206
+#ifndef NETDATA_INTERNAL_CHECKS
2207
+ UNUSED(table);
2208
+#endif
2209
+ if (likely(*out)) {
2210
+ ebpf_network_viewer_ip_list_t *move = *out, *store = *out;
2211
+ while (move) {
2212
+ if (in->ver == move->ver && is_ip_inside_range(&move->first, &move->last, &in->first, &in->last, in->ver)) {
2213
+ info("The range/value (%s) is inside the range/value (%s) already inserted, it will be ignored.",
2214
+ in->value, move->value);
2215
+ freez(in->value);
2216
+ freez(in);
2217
+ return;
2218
+ }
2219
+ store = move;
2220
+ move = move->next;
2221
+ }
2222
+
2223
+ store->next = in;
2224
+ } else {
2225
+ *out = in;
2226
+ }
2227
+
2228
+#ifdef NETDATA_INTERNAL_CHECKS
2229
+ char first[512], last[512];
2230
+ if (in->ver == AF_INET) {
2231
+ if (inet_ntop(AF_INET, in->first.addr8, first, INET_ADDRSTRLEN) &&
2232
+ inet_ntop(AF_INET, in->last.addr8, last, INET_ADDRSTRLEN))
2233
+ info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
2234
+ first, last,
2235
+ (*out == network_viewer_opt.included_ips)?"included":"excluded",
2236
+ table);
2237
+ } else {
2238
+ if (inet_ntop(AF_INET6, in->first.addr8, first, INET6_ADDRSTRLEN) &&
2239
+ inet_ntop(AF_INET6, in->last.addr8, last, INET6_ADDRSTRLEN))
2240
+ info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
2241
+ first, last,
2242
+ (*out == network_viewer_opt.included_ips)?"included":"excluded",
2243
+ table);
2244
+ }
2245
+#endif
2246
+}
2247
+
2248
+/**
2249
+ * Parse IP List
2250
+ *
2251
+ * Parse IP list and link it.
2252
+ *
2253
+ * @param out a pointer to store the link list
2254
+ * @param ip the value given as parameter
2255
+ */
2256
+static void parse_ip_list(void **out, char *ip)
2257
+{
2258
+ ebpf_network_viewer_ip_list_t **list = (ebpf_network_viewer_ip_list_t **)out;
2259
+
2260
+ char *ipdup = strdupz(ip);
2261
+ union netdata_ip_t first = { };
2262
+ union netdata_ip_t last = { };
2263
+ char *is_ipv6;
2264
+ if (*ip == '*' && *(ip+1) == '\0') {
2265
+ memset(first.addr8, 0, sizeof(first.addr8));
2266
+ memset(last.addr8, 0xFF, sizeof(last.addr8));
2267
+
2268
+ is_ipv6 = ip;
2269
+
2270
+ clean_ip_structure(list);
2271
+ goto storethisip;
2272
+ }
2273
+
2274
+ char *end = ip;
2275
+ // Move while I cannot find a separator
2276
+ while (*end && *end != '/' && *end != '-') end++;
2277
+
2278
+ // We will use only the classic IPV6 for while, but we could consider the base 85 in a near future
2279
+ // https://tools.ietf.org/html/rfc1924
2280
+ is_ipv6 = strchr(ip, ':');
2281
+
2282
+ int select;
2283
+ if (*end && !is_ipv6) { // IPV4 range
2284
+ select = (*end == '/') ? 0 : 1;
2285
+ *end++ = '\0';
2286
+ if (*end == '!') {
2287
+ info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
2288
+ goto cleanipdup;
2289
+ }
2290
+
2291
+ if (!select) { // CIDR
2292
+ select = ip2nl(first.addr8, ip, AF_INET, ipdup);
2293
+ if (select)
2294
+ goto cleanipdup;
2295
+
2296
+ select = (int) str2i(end);
2297
+ if (select < NETDATA_MINIMUM_IPV4_CIDR || select > NETDATA_MAXIMUM_IPV4_CIDR) {
2298
+ info("The specified CIDR %s is not valid, the IP %s will be ignored.", end, ip);
2299
+ goto cleanipdup;
2300
+ }
2301
+
2302
+ last.addr32[0] = htonl(broadcast(ntohl(first.addr32[0]), select));
2303
+ // This was added to remove
2304
+ // https://app.codacy.com/manual/netdata/netdata/pullRequest?prid=5810941&bid=19021977
2305
+ UNUSED(last.addr32[0]);
2306
+
2307
+ uint32_t ipv4_test = htonl(ipv4_network(ntohl(first.addr32[0]), select));
2308
+ if (first.addr32[0] != ipv4_test) {
2309
+ first.addr32[0] = ipv4_test;
2310
+ struct in_addr ipv4_convert;
2311
+ ipv4_convert.s_addr = ipv4_test;
2312
+ char ipv4_msg[INET_ADDRSTRLEN];
2313
+ if(inet_ntop(AF_INET, &ipv4_convert, ipv4_msg, INET_ADDRSTRLEN))
2314
+ info("The network value of CIDR %s was updated for %s .", ipdup, ipv4_msg);
2315
+ }
2316
+ } else { // Range
2317
+ select = ip2nl(first.addr8, ip, AF_INET, ipdup);
2318
+ if (select)
2319
+ goto cleanipdup;
2320
+
2321
+ select = ip2nl(last.addr8, end, AF_INET, ipdup);
2322
+ if (select)
2323
+ goto cleanipdup;
2324
+ }
2325
+
2326
+ if (htonl(first.addr32[0]) > htonl(last.addr32[0])) {
2327
+ info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
2328
+ ipdup);
2329
+ goto cleanipdup;
2330
+ }
2331
+ } else if (is_ipv6) { // IPV6
2332
+ if (!*end) { // Unique
2333
+ select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
2334
+ if (select)
2335
+ goto cleanipdup;
2336
+
2337
+ memcpy(last.addr8, first.addr8, sizeof(first.addr8));
2338
+ } else if (*end == '-') {
2339
+ *end++ = 0x00;
2340
+ if (*end == '!') {
2341
+ info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
2342
+ goto cleanipdup;
2343
+ }
2344
+
2345
+ select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
2346
+ if (select)
2347
+ goto cleanipdup;
2348
+
2349
+ select = ip2nl(last.addr8, end, AF_INET6, ipdup);
2350
+ if (select)
2351
+ goto cleanipdup;
2352
+ } else { // CIDR
2353
+ *end++ = 0x00;
2354
+ if (*end == '!') {
2355
+ info("The exclusion cannot be in the second part of the range %s, it will be ignored.", ipdup);
2356
+ goto cleanipdup;
2357
+ }
2358
+
2359
+ select = str2i(end);
2360
+ if (select < 0 || select > 128) {
2361
+ info("The CIDR %s is not valid, the address %s will be ignored.", end, ip);
2362
+ goto cleanipdup;
2363
+ }
2364
+
2365
+ uint64_t prefix = (uint64_t)select;
2366
+ select = ip2nl(first.addr8, ip, AF_INET6, ipdup);
2367
+ if (select)
2368
+ goto cleanipdup;
2369
+
2370
+ get_ipv6_last_addr(&last, &first, prefix);
2371
+
2372
+ union netdata_ip_t ipv6_test;
2373
+ get_ipv6_first_addr(&ipv6_test, &first, prefix);
2374
+
2375
+ if (memcmp(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t)) != 0) {
2376
+ memcpy(first.addr8, ipv6_test.addr8, sizeof(union netdata_ip_t));
2377
+
2378
+ struct in6_addr ipv6_convert;
2379
+ memcpy(ipv6_convert.s6_addr, ipv6_test.addr8, sizeof(union netdata_ip_t));
2380
+
2381
+ char ipv6_msg[INET6_ADDRSTRLEN];
2382
+ if(inet_ntop(AF_INET6, &ipv6_convert, ipv6_msg, INET6_ADDRSTRLEN))
2383
+ info("The network value of CIDR %s was updated for %s .", ipdup, ipv6_msg);
2384
+ }
2385
+ }
2386
+
2387
+ if ((be64toh(*(uint64_t *)&first.addr32[2]) > be64toh(*(uint64_t *)&last.addr32[2]) &&
2388
+ !memcmp(first.addr32, last.addr32, 2*sizeof(uint32_t))) ||
2389
+ (be64toh(*(uint64_t *)&first.addr32) > be64toh(*(uint64_t *)&last.addr32)) ) {
2390
+ info("The specified range %s is invalid, the second address is smallest than the first, it will be ignored.",
2391
+ ipdup);
2392
+ goto cleanipdup;
2393
+ }
2394
+ } else { // Unique ip
2395
+ select = ip2nl(first.addr8, ip, AF_INET, ipdup);
2396
+ if (select)
2397
+ goto cleanipdup;
2398
+
2399
+ memcpy(last.addr8, first.addr8, sizeof(first.addr8));
2400
+ }
2401
+
2402
+ ebpf_network_viewer_ip_list_t *store;
2403
+
2404
+ storethisip:
2405
+ store = callocz(1, sizeof(ebpf_network_viewer_ip_list_t));
2406
+ store->value = ipdup;
2407
+ store->hash = simple_hash(ipdup);
2408
+ store->ver = (uint8_t)(!is_ipv6)?AF_INET:AF_INET6;
2409
+ memcpy(store->first.addr8, first.addr8, sizeof(first.addr8));
2410
+ memcpy(store->last.addr8, last.addr8, sizeof(last.addr8));
2411
+
2412
+ fill_ip_list(list, store, "socket");
2413
+ return;
2414
+
2415
+cleanipdup:
2416
+ freez(ipdup);
2417
+}
2418
+
2419
+/**
2420
+ * Parse IP Range
2421
+ *
2422
+ * Parse the IP ranges given and create Network Viewer IP Structure
2423
+ *
2424
+ * @param ptr is a pointer with the text to parse.
2425
+ */
2426
+static void parse_ips(char *ptr)
2427
+{
2428
+ // No value
2429
+ if (unlikely(!ptr))
2430
+ return;
2431
+
2432
+ while (likely(ptr)) {
2433
+ // Move forward until next valid character
2434
+ while (isspace(*ptr)) ptr++;
2435
+
2436
+ // No valid value found
2437
+ if (unlikely(!*ptr))
2438
+ return;
2439
+
2440
+ // Find space that ends the list
2441
+ char *end = strchr(ptr, ' ');
2442
+ if (end) {
2443
+ *end++ = '\0';
2444
+ }
2445
+
2446
+ int neg = 0;
2447
+ if (*ptr == '!') {
2448
+ neg++;
2449
+ ptr++;
2450
+ }
2451
+
2452
+ if (isascii(*ptr)) { // Parse port
2453
+ parse_ip_list((!neg)?(void **)&network_viewer_opt.included_ips:(void **)&network_viewer_opt.excluded_ips,
2454
+ ptr);
2455
+ }
2456
+
2457
+ ptr = end;
2458
+ }
2459
+}
2460
+
2461
+
2462
+
2463
+/**
2464
+ * Parse port list
2465
+ *
2466
+ * Parse an allocated port list with the range given
2467
+ *
2468
+ * @param out a pointer to store the link list
2469
+ * @param range the informed range for the user.
2470
+ */
2471
+static void parse_port_list(void **out, char *range)
2472
+{
2473
+ int first, last;
2474
+ ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
2475
+
2476
+ char *copied = strdupz(range);
2477
+ if (*range == '*' && *(range+1) == '\0') {
2478
+ first = 1;
2479
+ last = 65535;
2480
+
2481
+ clean_port_structure(list);
2482
+ goto fillenvpl;
2483
+ }
2484
+
2485
+ char *end = range;
2486
+ //Move while I cannot find a separator
2487
+ while (*end && *end != ':' && *end != '-') end++;
2488
+
2489
+ //It has a range
2490
+ if (likely(*end)) {
2491
+ *end++ = '\0';
2492
+ if (*end == '!') {
2493
+ info("The exclusion cannot be in the second part of the range, the range %s will be ignored.", copied);
2494
+ freez(copied);
2495
+ return;
2496
+ }
2497
+ last = str2i((const char *)end);
2498
+ } else {
2499
+ last = 0;
2500
+ }
2501
+
2502
+ first = str2i((const char *)range);
2503
+ if (first < NETDATA_MINIMUM_PORT_VALUE || first > NETDATA_MAXIMUM_PORT_VALUE) {
2504
+ info("The first port %d of the range \"%s\" is invalid and it will be ignored!", first, copied);
2505
+ freez(copied);
2506
+ return;
2507
+ }
2508
+
2509
+ if (!last)
2510
+ last = first;
2511
+
2512
+ if (last < NETDATA_MINIMUM_PORT_VALUE || last > NETDATA_MAXIMUM_PORT_VALUE) {
2513
+ info("The second port %d of the range \"%s\" is invalid and the whole range will be ignored!", last, copied);
2514
+ freez(copied);
2515
+ return;
2516
+ }
2517
+
2518
+ if (first > last) {
2519
+ info("The specified order %s is wrong, the smallest value is always the first, it will be ignored!", copied);
2520
+ freez(copied);
2521
+ return;
2522
+ }
2523
+
2524
+ ebpf_network_viewer_port_list_t *w;
2525
+fillenvpl:
2526
+ w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
2527
+ w->value = copied;
2528
+ w->hash = simple_hash(copied);
2529
+ w->first = (uint16_t)htons((uint16_t)first);
2530
+ w->last = (uint16_t)htons((uint16_t)last);
2531
+ w->cmp_first = (uint16_t)first;
2532
+ w->cmp_last = (uint16_t)last;
2533
+
2534
+ fill_port_list(list, w);
2535
+}
2536
+
2537
+/**
2538
+ * Read max dimension.
2539
+ *
2540
+ * Netdata plot two dimensions per connection, so it is necessary to adjust the values.
2541
+ *
2542
+ * @param cfg the configuration structure
2543
+ */
2544
+static void read_max_dimension(struct config *cfg)
2545
+{
2546
+ int maxdim ;
2547
+ maxdim = (int) appconfig_get_number(cfg,
2548
+ EBPF_NETWORK_VIEWER_SECTION,
2549
+ EBPF_MAXIMUM_DIMENSIONS,
2550
+ NETDATA_NV_CAP_VALUE);
2551
+ if (maxdim < 0) {
2552
+ error("'maximum dimensions = %d' must be a positive number, Netdata will change for default value %ld.",
2553
+ maxdim, NETDATA_NV_CAP_VALUE);
2554
+ maxdim = NETDATA_NV_CAP_VALUE;
2555
+ }
2556
+
2557
+ maxdim /= 2;
2558
+ if (!maxdim) {
2559
+ info("The number of dimensions is too small (%u), we are setting it to minimum 2", network_viewer_opt.max_dim);
2560
+ network_viewer_opt.max_dim = 1;
2561
+ return;
2562
+ }
2563
+
2564
+ network_viewer_opt.max_dim = (uint32_t)maxdim;
2565
+}
2566
+
2567
+/**
2568
+ * Parse Port Range
2569
+ *
2570
+ * Parse the port ranges given and create Network Viewer Port Structure
2571
+ *
2572
+ * @param ptr is a pointer with the text to parse.
2573
+ */
2574
+static void parse_ports(char *ptr)
2575
+{
2576
+ // No value
2577
+ if (unlikely(!ptr))
2578
+ return;
2579
+
2580
+ while (likely(ptr)) {
2581
+ // Move forward until next valid character
2582
+ while (isspace(*ptr)) ptr++;
2583
+
2584
+ // No valid value found
2585
+ if (unlikely(!*ptr))
2586
+ return;
2587
+
2588
+ // Find space that ends the list
2589
+ char *end = strchr(ptr, ' ');
2590
+ if (end) {
2591
+ *end++ = '\0';
2592
+ }
2593
+
2594
+ int neg = 0;
2595
+ if (*ptr == '!') {
2596
+ neg++;
2597
+ ptr++;
2598
+ }
2599
+
2600
+ if (isdigit(*ptr)) { // Parse port
2601
+ parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
2602
+ ptr);
2603
+ } else if (isalpha(*ptr)) { // Parse service
2604
+ parse_service_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
2605
+ ptr);
2606
+ } else if (*ptr == '*') { // All
2607
+ parse_port_list((!neg)?(void **)&network_viewer_opt.included_port:(void **)&network_viewer_opt.excluded_port,
2608
+ ptr);
2609
+ }
2610
+
2611
+ ptr = end;
2612
+ }
2613
+}
2614
+
2615
+/**
2616
+ * Link hostname
2617
+ *
2618
+ * @param out is the output link list
2619
+ * @param in the hostname to add to list.
2620
+ */
2621
+static void link_hostname(ebpf_network_viewer_hostname_list_t **out, ebpf_network_viewer_hostname_list_t *in)
2622
+{
2623
+ if (likely(*out)) {
2624
+ ebpf_network_viewer_hostname_list_t *move = *out;
2625
+ for (; move->next ; move = move->next ) {
2626
+ if (move->hash == in->hash && !strcmp(move->value, in->value)) {
2627
+ info("The hostname %s was already inserted, it will be ignored.", in->value);
2628
+ freez(in->value);
2629
+ simple_pattern_free(in->value_pattern);
2630
+ freez(in);
2631
+ return;
2632
+ }
2633
+ }
2634
+
2635
+ move->next = in;
2636
+ } else {
2637
+ *out = in;
2638
+ }
2639
+#ifdef NETDATA_INTERNAL_CHECKS
2640
+ info("Adding value %s to %s hostname list used on network viewer",
2641
+ in->value,
2642
+ (*out == network_viewer_opt.included_hostnames)?"included":"excluded");
2643
+#endif
2644
+}
2645
+
2646
+/**
2647
+ * Link Hostnames
2648
+ *
2649
+ * Parse the list of hostnames to create the link list.
2650
+ * This is not associated with the IP, because simple patterns like *example* cannot be resolved to IP.
2651
+ *
2652
+ * @param out is the output link list
2653
+ * @param parse is a pointer with the text to parser.
2654
+ */
2655
+static void link_hostnames(char *parse)
2656
+{
2657
+ // No value
2658
+ if (unlikely(!parse))
2659
+ return;
2660
+
2661
+ while (likely(parse)) {
2662
+ // Find the first valid value
2663
+ while (isspace(*parse)) parse++;
2664
+
2665
+ // No valid value found
2666
+ if (unlikely(!*parse))
2667
+ return;
2668
+
2669
+ // Find space that ends the list
2670
+ char *end = strchr(parse, ' ');
2671
+ if (end) {
2672
+ *end++ = '\0';
2673
+ }
2674
+
2675
+ int neg = 0;
2676
+ if (*parse == '!') {
2677
+ neg++;
2678
+ parse++;
2679
+ }
2680
+
2681
+ ebpf_network_viewer_hostname_list_t *hostname = callocz(1 , sizeof(ebpf_network_viewer_hostname_list_t));
2682
+ hostname->value = strdupz(parse);
2683
+ hostname->hash = simple_hash(parse);
2684
+ hostname->value_pattern = simple_pattern_create(parse, NULL, SIMPLE_PATTERN_EXACT);
2685
+
2686
+ link_hostname((!neg)?&network_viewer_opt.included_hostnames:&network_viewer_opt.excluded_hostnames,
2687
+ hostname);
2688
+
2689
+ parse = end;
2690
+ }
2691
+}
2692
+
2693
+/**
2694
+ * Parse network viewer section
2695
+ *
2696
+ * @param cfg the configuration structure
2697
+ */
2698
+void parse_network_viewer_section(struct config *cfg)
2699
+{
2700
+ read_max_dimension(cfg);
2701
+
2702
+ network_viewer_opt.hostname_resolution_enabled = appconfig_get_boolean(cfg,
2703
+ EBPF_NETWORK_VIEWER_SECTION,
2704
+ EBPF_CONFIG_RESOLVE_HOSTNAME,
2705
+ CONFIG_BOOLEAN_NO);
2706
+
2707
+ network_viewer_opt.service_resolution_enabled = appconfig_get_boolean(cfg,
2708
+ EBPF_NETWORK_VIEWER_SECTION,
2709
+ EBPF_CONFIG_RESOLVE_SERVICE,
2710
+ CONFIG_BOOLEAN_NO);
2711
+
2712
+ char *value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION, EBPF_CONFIG_PORTS, NULL);
2713
+ parse_ports(value);
2714
+
2715
+ if (network_viewer_opt.hostname_resolution_enabled) {
2716
+ value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION, EBPF_CONFIG_HOSTNAMES, NULL);
2717
+ link_hostnames(value);
2718
+ } else {
2719
+ info("Name resolution is disabled, collector will not parser \"hostnames\" list.");
2720
+ }
2721
+
2722
+ value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION,
2723
+ "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");
2724
+ parse_ips(value);
2725
+}
2726
+
2727
+/**
2728
+ * Link dimension name
2729
+ *
2730
+ * Link user specified names inside a link list.
2731
+ *
2732
+ * @param port the port number associated to the dimension name.
2733
+ * @param hash the calculated hash for the dimension name.
2734
+ * @param name the dimension name.
2735
+ */
2736
+static void link_dimension_name(char *port, uint32_t hash, char *value)
2737
+{
2738
+ int test = str2i(port);
2739
+ if (test < NETDATA_MINIMUM_PORT_VALUE || test > NETDATA_MAXIMUM_PORT_VALUE){
2740
+ error("The dimension given (%s = %s) has an invalid value and it will be ignored.", port, value);
2741
+ return;
2742
+ }
2743
+
2744
+ ebpf_network_viewer_dim_name_t *w;
2745
+ w = callocz(1, sizeof(ebpf_network_viewer_dim_name_t));
2746
+
2747
+ w->name = strdupz(value);
2748
+ w->hash = hash;
2749
+
2750
+ w->port = (uint16_t) htons(test);
2751
+
2752
+ ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
2753
+ if (unlikely(!names)) {
2754
+ network_viewer_opt.names = w;
2755
+ } else {
2756
+ for (; names->next; names = names->next) {
2757
+ if (names->port == w->port) {
2758
+ info("Dupplicated definition for a service, the name %s will be ignored. ", names->name);
2759
+ freez(names->name);
2760
+ names->name = w->name;
2761
+ names->hash = w->hash;
2762
+ freez(w);
2763
+ return;
2764
+ }
2765
+ }
2766
+ names->next = w;
2767
+ }
2768
+
2769
+#ifdef NETDATA_INTERNAL_CHECKS
2770
+ info("Adding values %s( %u) to dimension name list used on network viewer", w->name, htons(w->port));
2771
+#endif
2772
+}
2773
+
2774
+/**
2775
+ * Parse service Name section.
2776
+ *
2777
+ * This function gets the values that will be used to overwrite dimensions.
2778
+ *
2779
+ * @param cfg the configuration structure
2780
+ */
2781
+void parse_service_name_section(struct config *cfg)
2782
+{
2783
+ struct section *co = appconfig_get_section(cfg, EBPF_SERVICE_NAME_SECTION);
2784
+ if (co) {
2785
+ struct config_option *cv;
2786
+ for (cv = co->values; cv ; cv = cv->next) {
2787
+ link_dimension_name(cv->name, cv->hash, cv->value);
2788
+ }
2789
+ }
2790
+
2791
+ // Always associated the default port to Netdata
2792
+ ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
2793
+ if (names) {
2794
+ uint16_t default_port = htons(19999);
2795
+ while (names) {
2796
+ if (names->port == default_port)
2797
+ return;
2798
+
2799
+ names = names->next;
2800
+ }
2801
+ }
2802
+
2803
+ char *port_string = getenv("NETDATA_LISTEN_PORT");
2804
+ if (port_string) {
2805
+ // if variable has an invalid value, we assume netdata is using 19999
2806
+ int default_port = str2i(port_string);
2807
+ if (default_port > 0 && default_port < 65536)
2808
+ link_dimension_name(port_string, simple_hash(port_string), "Netdata");
2809
+ }
2810
+}
2811
+
2812
/**
2813
* Socket thread
2814
*
@@ -1886,6 +2828,10 @@ void *ebpf_socket_thread(void *ptr)
2828
ebpf_module_t *em = (ebpf_module_t *)ptr;
2829
fill_ebpf_data(&socket_data);
2830
2831
+ ebpf_update_module(em, &socket_config, NETDATA_NETWORK_CONFIG_FILE);
2832
+ parse_network_viewer_section(&socket_config);
2833
+ parse_service_name_section(&socket_config);
2834
+
2835
if (!em->enabled)
2836
goto endsocket;
2837
collectors/ebpf.plugin/ebpf_socket.h
+26
-1
@@ -5,7 +5,6 @@
5
#include "libnetdata/avl/avl.h"
6
7
// Vector indexes
8
-#define NETDATA_MAX_SOCKET_VECTOR 6
8
#define NETDATA_UDP_START 3
9
#define NETDATA_RETRANSMIT_START 5
10
@@ -17,6 +16,28 @@
16
17
#define NETDATA_SOCKET_READ_SLEEP_MS 800000ULL
18
19
+// config file
20
+#define NETDATA_NETWORK_CONFIG_FILE "network.conf"
21
+#define EBPF_NETWORK_VIEWER_SECTION "network connections"
22
+#define EBPF_SERVICE_NAME_SECTION "service name"
23
+#define EBPF_CONFIG_RESOLVE_HOSTNAME "resolve hostnames"
24
+#define EBPF_CONFIG_RESOLVE_SERVICE "resolve service names"
25
+#define EBPF_CONFIG_PORTS "ports"
26
+#define EBPF_CONFIG_HOSTNAMES "hostnames"
27
+#define EBPF_MAXIMUM_DIMENSIONS "maximum dimensions"
28
+
29
+enum ebpf_socket_publish_index {
30
+ NETDATA_IDX_TCP_SENDMSG,
31
+ NETDATA_IDX_TCP_CLEANUP_RBUF,
32
+ NETDATA_IDX_TCP_CLOSE,
33
+ NETDATA_IDX_UDP_RECVBUF,
34
+ NETDATA_IDX_UDP_SENDMSG,
35
+ NETDATA_IDX_TCP_RETRANSMIT,
36
+
37
+ // Keep this as last and don't skip numbers as it is used as element counter
38
+ NETDATA_MAX_SOCKET_VECTOR
39
+};
40
+
41
typedef enum ebpf_socket_idx {
42
NETDATA_KEY_CALLS_TCP_SENDMSG,
43
NETDATA_KEY_ERROR_TCP_SENDMSG,
@@ -38,6 +59,7 @@ typedef enum ebpf_socket_idx {
59
60
NETDATA_KEY_TCP_RETRANSMIT,
61
62
+ // Keep this as last and don't skip numbers as it is used as element counter
63
NETDATA_SOCKET_COUNTER
64
} ebpf_socket_index_t;
65
@@ -269,6 +291,9 @@ typedef struct netdata_vector_plot {
291
extern void clean_port_structure(ebpf_network_viewer_port_list_t **clean);
292
extern ebpf_network_viewer_port_list_t *listen_ports;
293
extern void update_listen_table(uint16_t value, uint8_t proto);
294
+extern void parse_network_viewer_section(struct config *cfg);
295
+extern void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table);
296
+extern void parse_service_name_section(struct config *cfg);
297
298
extern ebpf_socket_publish_apps_t **socket_bandwidth_curr;
299
collectors/ebpf.plugin/ebpf_sync.c
+12
-3
@@ -20,6 +20,12 @@ static netdata_idx_t sync_hash_values = 0;
20
struct netdata_static_thread sync_threads = {"SYNC KERNEL", NULL, NULL, 1,
21
NULL, NULL, NULL};
22
23
+struct config sync_config = { .first_section = NULL,
24
+ .last_section = NULL,
25
+ .mutex = NETDATA_MUTEX_INITIALIZER,
26
+ .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
27
+ .rwlock = AVL_LOCK_INITIALIZER } };
28
+
29
/*****************************************************************
30
*
31
* DATA THREAD
@@ -53,12 +59,12 @@ static void read_global_table()
59
*/
60
void *ebpf_sync_read_hash(void *ptr)
61
{
56
- UNUSED(ptr);
62
+ ebpf_module_t *em = (ebpf_module_t *)ptr;
63
read_thread_closed = 0;
64
65
heartbeat_t hb;
66
heartbeat_init(&hb);
61
- usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS;
67
+ usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS * em->update_time;
68
69
while (!close_ebpf_plugin) {
70
usec_t dt = heartbeat_next(&hb, step);
@@ -160,7 +166,8 @@ static void ebpf_create_sync_charts()
166
{
167
ebpf_create_chart(NETDATA_EBPF_MEMORY_GROUP, NETDATA_EBPF_SYNC_CHART,
168
"Monitor calls for <a href=\"https://linux.die.net/man/2/sync\">sync(2)</a> syscall.",
163
- EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_SYNC_SUBMENU, NULL, 21300,
169
+ EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_SYNC_SUBMENU, NULL,
170
+ NETDATA_EBPF_CHART_TYPE_LINE, 21300,
171
ebpf_create_global_dimension, &sync_counter_publish_aggregated, 1);
172
}
173
@@ -180,6 +187,8 @@ void *ebpf_sync_thread(void *ptr)
187
ebpf_module_t *em = (ebpf_module_t *)ptr;
188
fill_ebpf_data(&sync_data);
189
190
+ ebpf_update_module(em, &sync_config, NETDATA_SYNC_CONFIG_FILE);
191
+
192
if (!em->enabled)
193
goto endsync;
194
collectors/ebpf.plugin/ebpf_sync.h
+4
-1
@@ -5,10 +5,13 @@
5
6
// charts
7
#define NETDATA_EBPF_SYNC_CHART "sync"
8
-#define NETDATA_EBPF_SYNC_SUBMENU "synchronization"
8
+#define NETDATA_EBPF_SYNC_SUBMENU "synchronization (eBPF)"
9
10
#define NETDATA_EBPF_SYNC_SLEEP_MS 800000ULL
11
12
+// configuration file
13
+#define NETDATA_SYNC_CONFIG_FILE "sync.conf"
14
+
15
enum netdata_sync_charts {
16
NETDATA_SYNC_CALL,
17
libnetdata/ebpf/ebpf.c
+69
-9
@@ -8,6 +8,9 @@
8
9
#include "../libnetdata.h"
10
11
+char *ebpf_user_config_dir = CONFIG_DIR;
12
+char *ebpf_stock_config_dir = LIBCONFIG_DIR;
13
+
14
/*
15
static int clean_kprobe_event(FILE *out, char *filename, char *father_pid, netdata_ebpf_events_t *ptr)
16
{
@@ -182,20 +185,26 @@ static int kernel_is_rejected()
185
}
186
187
char filename[FILENAME_MAX + 1];
185
- snprintfz(filename, FILENAME_MAX, "%s/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
188
+ snprintfz(filename, FILENAME_MAX, "%s/ebpf.d/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
189
FILE *kernel_reject_list = fopen(filename, "r");
190
191
if (!kernel_reject_list) {
189
- config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
190
- if (config_dir == NULL) {
191
- config_dir = LIBCONFIG_DIR;
192
- }
193
-
192
+ // Keep this to have compatibility with old versions
193
snprintfz(filename, FILENAME_MAX, "%s/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
194
kernel_reject_list = fopen(filename, "r");
195
197
- if (!kernel_reject_list)
198
- return 0;
196
+ if (!kernel_reject_list) {
197
+ config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
198
+ if (config_dir == NULL) {
199
+ config_dir = LIBCONFIG_DIR;
200
+ }
201
+
202
+ snprintfz(filename, FILENAME_MAX, "%s/ebpf.d/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
203
+ kernel_reject_list = fopen(filename, "r");
204
+
205
+ if (!kernel_reject_list)
206
+ return 0;
207
+ }
208
}
209
210
// Find if the kernel is in the reject list
@@ -296,7 +305,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *
305
if (test < 0 || test > 127)
306
return NULL;
307
299
- snprintf(lpath, 4096, "%s/%s", plugins_dir, lname);
308
+ snprintf(lpath, 4096, "%s/ebpf.d/%s", plugins_dir, lname);
309
// We are using BPF_PROG_TYPE_UNSPEC instead a specific type for bpf_prog_load to define the type
310
// according the eBPF program loaded
311
if (bpf_prog_load(lpath, BPF_PROG_TYPE_UNSPEC, obj, &prog_fd)) {
@@ -326,3 +335,54 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *
335
336
return links;
337
}
338
+
339
+//----------------------------------------------------------------------------------------------------------------------
340
+
341
+static netdata_run_mode_t ebpf_select_mode(char *mode)
342
+{
343
+ if (!strcasecmp(mode, "return"))
344
+ return MODE_RETURN;
345
+ else if (!strcasecmp(mode, "dev"))
346
+ return MODE_DEVMODE;
347
+
348
+ return MODE_ENTRY;
349
+}
350
+
351
+void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg)
352
+{
353
+ char *mode = appconfig_get(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, EBPF_CFG_LOAD_MODE_DEFAULT);
354
+ modules->mode = ebpf_select_mode(mode);
355
+
356
+ modules->update_time = (int)appconfig_get_number(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_UPDATE_EVERY, 1);
357
+
358
+ modules->apps_charts = appconfig_get_boolean(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION,
359
+ CONFIG_BOOLEAN_YES);
360
+}
361
+
362
+
363
+/**
364
+ * Update module
365
+ *
366
+ * When this function is called, it will load the configuration file and after this
367
+ * it updates the global information of ebpf_module.
368
+ * If the module has specific configuration, this function will load it, but it will not
369
+ * update the variables.
370
+ *
371
+ * @param em the module structure
372
+ * @param cfg the configuration structure
373
+ * @param cfg_file the filename to load
374
+ */
375
+void ebpf_update_module(ebpf_module_t *em, struct config *cfg, char *cfg_file)
376
+{
377
+ char filename[FILENAME_MAX+1];
378
+ ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, cfg_file);
379
+ if (!ebpf_load_config(cfg, filename)) {
380
+ ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, cfg_file);
381
+ if (!ebpf_load_config(cfg, filename)) {
382
+ error("Cannot load the ebpf configuration file %s", cfg_file);
383
+ return;
384
+ }
385
+ }
386
+
387
+ ebpf_update_module_using_config(em, cfg);
388
+}
libnetdata/ebpf/ebpf.h
+25
@@ -8,6 +8,15 @@
8
9
#define NETDATA_DEBUGFS "/sys/kernel/debug/tracing/"
10
11
+// Config files
12
+#define EBPF_GLOBAL_SECTION "global"
13
+#define EBPF_CFG_LOAD_MODE "ebpf load mode"
14
+#define EBPF_CFG_LOAD_MODE_DEFAULT "entry"
15
+#define EBPF_CFG_LOAD_MODE_RETURN "return"
16
+
17
+#define EBPF_CFG_UPDATE_EVERY "update every"
18
+#define EBPF_CFG_APPLICATION "apps"
19
+
20
/**
21
* The next magic number is got doing the following math:
22
* 294960 = 4*65536 + 11*256 + 0
@@ -69,6 +78,9 @@
78
#define VERSION_STRING_LEN 256
79
#define EBPF_KERNEL_REJECT_LIST_FILE "ebpf_kernel_reject_list.txt"
80
81
+extern char *ebpf_user_config_dir;
82
+extern char *ebpf_stock_config_dir;
83
+
84
typedef struct ebpf_data {
85
int *map_fd;
86
@@ -110,4 +122,17 @@ extern struct bpf_link **ebpf_load_program(char *plugins_dir,
122
struct bpf_object **obj,
123
int *map_fd);
124
125
+inline void ebpf_mount_config_name(char *filename, size_t length, char *path, char *config)
126
+{
127
+ snprintf(filename, length, "%s/ebpf.d/%s", path, config);
128
+}
129
+
130
+inline int ebpf_load_config(struct config *config, char *filename)
131
+{
132
+ return appconfig_load(config, filename, 0, NULL);
133
+}
134
+
135
+extern void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg);
136
+extern void ebpf_update_module(ebpf_module_t *em, struct config *cfg, char *cfg_file);
137
+
138
#endif /* NETDATA_EBPF_H */
netdata-installer.sh
+23
-2
@@ -1617,11 +1617,23 @@ remove_old_ebpf() {
1617
1618
# Added to remove eBPF programs with name pattern: NAME_VERSION.SUBVERSION.PATCH
1619
if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/pnetdata_ebpf_process.3.10.0.o" ]; then
1620
- echo >&2 "Removing old eBPF programs"
1620
+ echo >&2 "Removing old eBPF programs with patch."
1621
rm -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/rnetdata_ebpf"*.?.*.*.o
1622
rm -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/pnetdata_ebpf"*.?.*.*.o
1623
fi
1624
1625
+ # Remove old eBPF program to store new eBPF program inside subdirectory
1626
+ if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/pnetdata_ebpf_process.3.10.o" ]; then
1627
+ echo >&2 "Removing old eBPF programs installed in old directory."
1628
+ rm -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/rnetdata_ebpf"*.?.*.o
1629
+ rm -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/pnetdata_ebpf"*.?.*.o
1630
+ fi
1631
+
1632
+ # Remove old reject list from previous directory
1633
+ if [ -f "${NETDATA_PREFIX}/usr/lib/netdata/conf.d/ebpf_kernel_reject_list.txt" ]; then
1634
+ echo >&2 "Removing old ebpf_kernel_reject_list.txt."
1635
+ rm -f "${NETDATA_PREFIX}/usr/lib/netdata/conf.d/ebpf_kernel_reject_list.txt"
1636
+ fi
1637
}
1638
1639
install_ebpf() {
@@ -1658,7 +1670,16 @@ install_ebpf() {
1670
# chown everything to root:netdata before we start copying out of our package
1671
run chown -R root:netdata "${tmp}"
1672
1661
- run cp -a -v "${tmp}"/*netdata_ebpf_*.o "${NETDATA_PREFIX}"/usr/libexec/netdata/plugins.d
1673
+ if [ ! -d "${NETDATA_PREFIX}"/usr/libexec/netdata/plugins.d/ebpf.d ]; then
1674
+ mkdir "${NETDATA_PREFIX}"/usr/libexec/netdata/plugins.d/ebpf.d
1675
+ RET=$?
1676
+ if [ "${RET}" != "0" ]; then
1677
+ rm -rf "${tmp}"
1678
+ return 1
1679
+ fi
1680
+ fi
1681
+
1682
+ run cp -a -v "${tmp}"/*netdata_ebpf_*.o "${NETDATA_PREFIX}"/usr/libexec/netdata/plugins.d/ebpf.d
1683
1684
rm -rf "${tmp}"
1685