diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index e37fc26c9..23a2288c8 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -53,7 +53,12 @@ static int entry(void *ctx) bpf_map_update_elem(&starts, &pid, &nsec, BPF_ANY); return 0; } - +SEC("fentry/dummy_fentry") +int BPF_PROG(dummy_fentry) +{ + entry(ctx); + return 0; +} SEC("kprobe/dummy_kprobe") int BPF_KPROBE(dummy_kprobe) { @@ -64,8 +69,7 @@ int BPF_KPROBE(dummy_kprobe) static int exit(void *ctx) { CHECK_ACTIVE; - u32 pid = bpf_get_current_pid_tgid() >> 32; - + u32 pid = bpf_get_current_pid_tgid() >> 32; u64 *start = bpf_map_lookup_elem(&starts, &pid); if (!start) return 0; @@ -87,6 +91,14 @@ static int exit(void *ctx) return 0; } +SEC("fexit/dummy_fexit") +int BPF_PROG(dummy_fexit) +{ + exit(ctx); + return 0; +} + + SEC("kretprobe/dummy_kretprobe") int BPF_KRETPROBE(dummy_kretprobe) { @@ -94,7 +106,6 @@ int BPF_KRETPROBE(dummy_kretprobe) return 0; } - static int handleCounts(void *ctx) { CHECK_ACTIVE; diff --git a/eBPF_Supermarket/Stack_Analyser/grafana_stack_analyzer_dashboard.json b/eBPF_Supermarket/Stack_Analyser/grafana_stack_analyzer_dashboard.json new file mode 100644 index 000000000..dfe7e0cab --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/grafana_stack_analyzer_dashboard.json @@ -0,0 +1,1362 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 3, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 6, + "panels": [], + "title": "cpu", + "type": "row" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "OnCPUTime:OnCPUTime:nanoseconds::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "cpu metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 2, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "OnCPUTime:OnCPUTime:nanoseconds::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "cpu profile", + "type": "flamegraph" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 5, + "panels": [], + "title": "block", + "type": "row" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "OffCPUTime:OffCPUTime:nanoseconds::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "block time metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 4, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "OffCPUTime:OffCPUTime:nanoseconds::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "block time profile", + "type": "flamegraph" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 7, + "panels": [], + "title": "memory inuse", + "type": "row" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "LeakedSize:LeakedSize:bytes::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "memory-inuse_space metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 9, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "LeakedSize:LeakedSize:bytes::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "memory-inuse_space profile", + "type": "flamegraph" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "LeakedCount:LeakedCount:counts::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "memory-inuse_alloc metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 12, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "LeakedCount:LeakedCount:counts::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "memory-inuse_alloc profile", + "type": "flamegraph" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 13, + "panels": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "IOSize:IOSize:bytes::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "IO size metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 20, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "IOSize:IOSize:bytes::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "io size profile", + "type": "flamegraph" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "IOCount:IOCount:counts::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "IO count metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 17, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "IOCount:IOCount:counts::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "io count profile", + "type": "flamegraph" + } + ], + "title": "IO", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 18, + "panels": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "UnusedReadaheadPages:UnusedReadaheadPages:pages::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "readahead unused metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 25, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "UnusedReadaheadPages:UnusedReadaheadPages:pages::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "readahead unused profile", + "type": "flamegraph" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "UsedReadaheadPages:UsedReadaheadPages:pages::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "readahead used metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 22, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "UsedReadaheadPages:UsedReadaheadPages:pages::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "readahead used profile", + "type": "flamegraph" + } + ], + "title": "readahead", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 23, + "panels": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "vfs_openCount:vfs_openCount:counts::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "vfs_open count metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 15, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "vfs_openCount:vfs_openCount:counts::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "vfs_open count profile", + "type": "flamegraph" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "vfs_openTime:vfs_openTime:nanoseconds::", + "queryType": "metrics", + "refId": "A", + "spanSelector": [] + } + ], + "title": "vfs_open time metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 27, + "targets": [ + { + "datasource": { + "type": "grafana-pyroscope-datasource", + "uid": "ddlp0mnbltkw0c" + }, + "groupBy": [], + "labelSelector": "{}", + "profileTypeId": "vfs_openTime:vfs_openTime:nanoseconds::", + "queryType": "profile", + "refId": "A", + "spanSelector": [] + } + ], + "title": "vfs_open time profile", + "type": "flamegraph" + } + ], + "title": "vfs_open", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "stack_analyzer_dashboard", + "uid": "fdlqh6mke9hq8e", + "version": 6, + "weekStart": "" +} \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp index d4db31cac..db883abbb 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp @@ -21,7 +21,23 @@ #include "uprobe_helpers.h" // ========== implement virtual func ========== - +bool tryf; +std::vector strList; +std::string func; +void splitStr(std::string symbol, const char split, std::vector &res) +{ + if (symbol == "") + return; + std::string strs = symbol + split; + size_t pos = strs.find(split); + while (pos != strs.npos) + { + std::string temp = strs.substr(0, pos); + res.push_back(temp); + strs = strs.substr(pos + 1, strs.size()); + pos = strs.find(split); + } +} uint64_t *ProbeStackCollector::count_values(void *data) { time_tuple *p = (time_tuple *)data; @@ -34,31 +50,67 @@ uint64_t *ProbeStackCollector::count_values(void *data) void ProbeStackCollector::setScale(std::string probe) { this->probe = probe; + splitStr(probe, ':', strList); + func = probe; for (int i = 0; i < scale_num; i++) scales[i].Type = probe + scales[i].Type; }; -int ProbeStackCollector::load(void) +static bool try_fentry(struct probe_bpf *skel, std::string func) { - EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); - return 0; -}; + long err; -void splitStr(std::string symbol, const char split, std::vector &res) -{ - if (symbol == "") - return; - std::string strs = symbol + split; - size_t pos = strs.find(split); - while (pos != strs.npos) + if (!fentry_can_attach(func.c_str(), NULL)) { - std::string temp = strs.substr(0, pos); - res.push_back(temp); - strs = strs.substr(pos + 1, strs.size()); - pos = strs.find(split); + return false; } + err = bpf_program__set_attach_target(skel->progs.dummy_fentry, 0, func.c_str()); + if (err) + { + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + return false; + } + err = bpf_program__set_attach_target(skel->progs.dummy_fexit, 0, func.c_str()); + if (err) + { + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + + return false; + } + + bpf_program__set_autoload(skel->progs.dummy_kprobe, false); + bpf_program__set_autoload(skel->progs.dummy_kretprobe, false); + return true; } +int ProbeStackCollector::load(void) +{ + std::string str = func; + skel = skel->open(NULL); + CHECK_ERR(!skel, "Fail to open BPF skeleton"); + if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") + str = strList[2]; + if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")){ + tryf = try_fentry(skel, str); + }else{ + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + } + skel->rodata->target_pid = pid; + skel->rodata->trace_user = ustack; + skel->rodata->trace_kernel = kstack; + skel->rodata->self_pid = self_pid; + skel->rodata->target_tgid = tgid; + skel->rodata->target_cgroupid = cgroup; + skel->rodata->freq = freq; + err = skel->load(skel); + CHECK_ERR(err, "Fail to load BPF skeleton"); + obj = skel->obj; + return 0; +}; + static int get_binpath(char *path, int pid) { char mode[16], line[128], buf[64]; @@ -97,6 +149,16 @@ static int attach_kprobes(struct probe_bpf *skel, std::string func) CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach ketprobe"); return 0; } +static int attach_fentry(struct probe_bpf *skel) +{ + skel->links.dummy_fentry = + bpf_program__attach(skel->progs.dummy_fentry); + CHECK_ERR(!skel->links.dummy_fentry, "Fail to attach fentry"); + skel->links.dummy_fexit = + bpf_program__attach(skel->progs.dummy_fexit); + CHECK_ERR(!skel->links.dummy_fexit, "Fail to attach fexit"); + return 0; +} static int attach_uprobes(struct probe_bpf *skel, std::string probe, int pid) { char *binary, *function; @@ -149,16 +211,24 @@ static int attach_usdt(struct probe_bpf *skel, std::string func, int pid) int ProbeStackCollector::attach(void) { // dynamic mounting - std::vector strList; - splitStr(probe, ':', strList); - std::string func = probe; + // std::vector strList; + // splitStr(probe, ':', strList); + // std::string func = probe; int err = 0; - if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") func = strList[2]; if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")) { - err = attach_kprobes(skel, func); + if (!tryf) + { + err = attach_kprobes(skel, func); + return 0; + } + else + { + err = attach_fentry(skel); + return 0; + } } else if (strList.size() == 3 && strList[0] == "t") { diff --git a/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md b/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md index 72d9a8034..65f954df8 100644 --- a/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md +++ b/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md @@ -48,7 +48,7 @@ ## 示例输出 4391为主机上的虚拟机进程,4508、4509、4510...分别是虚拟机中的vcpu子进程,每隔两秒输出虚拟机中产生的exit事件及其处理延时等信息。 - +结果会以进程号(VM的唯一标识)以及线程号(VM中每个VCPU的唯一标识)的优先级依次从小到大的顺序输出。 ``` ubuntu@rd350x:~/nans/lmp/eBPF_Supermarket/kvm_watcher$ sudo ./kvm_watcher -e diff --git a/eBPF_Supermarket/kvm_watcher/include/bpf/kvm_hypercall.h b/eBPF_Supermarket/kvm_watcher/include/bpf/kvm_hypercall.h index b4768d720..723200827 100644 --- a/eBPF_Supermarket/kvm_watcher/include/bpf/kvm_hypercall.h +++ b/eBPF_Supermarket/kvm_watcher/include/bpf/kvm_hypercall.h @@ -53,7 +53,7 @@ struct { __type(value, u32); } hc_count SEC(".maps"); -static int entry_emulate_hypercall(struct kvm_vcpu *vcpu, void *rb, +static int trace_emulate_hypercall(struct kvm_vcpu *vcpu, void *rb, struct common_event *e) { u32 pid = bpf_get_current_pid_tgid() >> 32; u64 nr, a0, a1, a2, a3; diff --git a/eBPF_Supermarket/kvm_watcher/include/common.h b/eBPF_Supermarket/kvm_watcher/include/common.h index d9435e584..8c5f89006 100644 --- a/eBPF_Supermarket/kvm_watcher/include/common.h +++ b/eBPF_Supermarket/kvm_watcher/include/common.h @@ -19,6 +19,16 @@ #ifndef __KVM_WATCHER_H #define __KVM_WATCHER_H +#define SET_KP_OR_FENTRY_LOAD(function_name, module_name) \ + do { \ + if (fentry_can_attach(#function_name, #module_name)) { \ + bpf_program__set_autoload(skel->progs.fentry_##function_name, \ + true); \ + } else { \ + bpf_program__set_autoload(skel->progs.kp_##function_name, true); \ + } \ + } while (0) + static const char binary_path[] = "/bin/qemu-system-x86_64"; #define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ do { \ diff --git a/eBPF_Supermarket/kvm_watcher/src/helpers/trace_helpers.c b/eBPF_Supermarket/kvm_watcher/src/helpers/trace_helpers.c index c84ed19a0..72b78524b 100644 --- a/eBPF_Supermarket/kvm_watcher/src/helpers/trace_helpers.c +++ b/eBPF_Supermarket/kvm_watcher/src/helpers/trace_helpers.c @@ -976,7 +976,7 @@ bool is_kernel_module(const char *name) { return found; } -static bool fentry_try_attach(int id) { +bool fentry_try_attach(int id) { int prog_fd, attach_fd; char error[4096]; struct bpf_insn insns[] = { @@ -1023,7 +1023,7 @@ bool fentry_can_attach(const char *name, const char *mod) { btf__free(module_btf); btf__free(vmlinux_btf); - return id > 0 && fentry_try_attach(id); + return id > 0; } #define DEBUGFS "/sys/kernel/debug/tracing" diff --git a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c index 54352b8de..8e57cb7ae 100644 --- a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c +++ b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c @@ -45,6 +45,13 @@ int BPF_PROG(fentry_kvm_vcpu_halt, struct kvm_vcpu *vcpu) { CHECK_PID(vm_pid); return trace_kvm_vcpu_halt(vcpu); } + +SEC("kprobe/kvm_vcpu_halt") +int BPF_KPROBE(kp_kvm_vcpu_halt, struct kvm_vcpu *vcpu) { + CHECK_PID(vm_pid); + return trace_kvm_vcpu_halt(vcpu); +} + // 追踪vcpu运行信息 SEC("tp/kvm/kvm_vcpu_wakeup") int tp_vcpu_wakeup(struct vcpu_wakeup *ctx) { @@ -67,6 +74,7 @@ SEC("tp/kvm/kvm_entry") int tp_entry(struct exit *ctx) { return trace_kvm_entry(); } + // 记录VCPU调度的信息--进入 SEC("fentry/vmx_vcpu_load") int BPF_PROG(fentry_vmx_vcpu_load, struct kvm_vcpu *vcpu, int cpu) { @@ -74,12 +82,23 @@ int BPF_PROG(fentry_vmx_vcpu_load, struct kvm_vcpu *vcpu, int cpu) { return trace_vmx_vcpu_load(vcpu, cpu); } +SEC("kprobe/vmx_vcpu_load") +int BPF_KPROBE(kp_vmx_vcpu_load, struct kvm_vcpu *vcpu, int cpu) { + CHECK_PID(vm_pid); + return trace_vmx_vcpu_load(vcpu, cpu); +} + // 记录VCPU调度的信息--退出 SEC("fentry/vmx_vcpu_put") int BPF_PROG(fentry_vmx_vcpu_put) { return trace_vmx_vcpu_put(); } +SEC("kprobe/vmx_vcpu_put") +int BPF_KPROBE(kp_vmx_vcpu_put) { + return trace_vmx_vcpu_put(); +} + SEC("fentry/mark_page_dirty_in_slot") int BPF_PROG(fentry_mark_page_dirty_in_slot, struct kvm *kvm, const struct kvm_memory_slot *memslot, gfn_t gfn) { @@ -87,6 +106,13 @@ int BPF_PROG(fentry_mark_page_dirty_in_slot, struct kvm *kvm, return trace_mark_page_dirty_in_slot(kvm, memslot, gfn, &rb, e); } +SEC("kprobe/mark_page_dirty_in_slot") +int BPF_KPROBE(kp_mark_page_dirty_in_slot, struct kvm *kvm, + const struct kvm_memory_slot *memslot, gfn_t gfn) { + CHECK_PID(vm_pid); + return trace_mark_page_dirty_in_slot(kvm, memslot, gfn, &rb, e); +} + SEC("tp/kvm/kvm_page_fault") int tp_page_fault(struct page_fault *ctx) { CHECK_PID(vm_pid); @@ -164,9 +190,15 @@ int BPF_PROG(fexit_vmx_inject_irq, struct kvm_vcpu *vcpu, bool reinjected) { } SEC("fentry/kvm_emulate_hypercall") -int BPF_PROG(fentry_emulate_hypercall, struct kvm_vcpu *vcpu) { +int BPF_PROG(fentry_kvm_emulate_hypercall, struct kvm_vcpu *vcpu) { CHECK_PID(vm_pid); - return entry_emulate_hypercall(vcpu, &rb, e); + return trace_emulate_hypercall(vcpu, &rb, e); +} + +SEC("kprobe/kvm_emulate_hypercall") +int BPF_KPROBE(kp_kvm_emulate_hypercall, struct kvm_vcpu *vcpu) { + CHECK_PID(vm_pid); + return trace_emulate_hypercall(vcpu, &rb, e); } SEC("tp/syscalls/sys_enter_ioctl") @@ -194,8 +226,20 @@ int BPF_PROG(fentry_start_hv_timer, struct kvm_lapic *apic) { return trace_start_hv_timer(apic); } +SEC("kprobe/start_hv_timer") +int BPF_KPROBE(kp_start_hv_timer, struct kvm_lapic *apic) { + CHECK_PID(vm_pid); + return trace_start_hv_timer(apic); +} + SEC("fentry/start_sw_timer") int BPF_PROG(fentry_start_sw_timer, struct kvm_lapic *apic) { CHECK_PID(vm_pid); return trace_start_sw_timer(apic); } + +SEC("kprobe/start_sw_timer") +int BPF_KPROBE(kp_start_sw_timer, struct kvm_lapic *apic) { + CHECK_PID(vm_pid); + return trace_start_sw_timer(apic); +} diff --git a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c index cc931f9c3..21301c4b3 100644 --- a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c +++ b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c @@ -793,16 +793,43 @@ static int print_event_head(struct env *env) { return 0; } -/*通过env结构体的属性真值来判断是否加载某个挂载函数*/ static void set_disable_load(struct kvm_watcher_bpf *skel) { + bpf_program__set_autoload(skel->progs.fentry_vmx_vcpu_load, false); + bpf_program__set_autoload(skel->progs.kp_vmx_vcpu_load, false); + bpf_program__set_autoload(skel->progs.fentry_vmx_vcpu_put, false); + bpf_program__set_autoload(skel->progs.kp_vmx_vcpu_put, false); + bpf_program__set_autoload(skel->progs.fentry_kvm_vcpu_halt, false); + bpf_program__set_autoload(skel->progs.kp_kvm_vcpu_halt, false); + bpf_program__set_autoload(skel->progs.fentry_mark_page_dirty_in_slot, + false); + bpf_program__set_autoload(skel->progs.kp_mark_page_dirty_in_slot, false); + bpf_program__set_autoload(skel->progs.fentry_kvm_emulate_hypercall, false); + bpf_program__set_autoload(skel->progs.kp_kvm_emulate_hypercall, false); + bpf_program__set_autoload(skel->progs.fentry_start_hv_timer, false); + bpf_program__set_autoload(skel->progs.kp_start_hv_timer, false); + bpf_program__set_autoload(skel->progs.fentry_start_sw_timer, false); + bpf_program__set_autoload(skel->progs.kp_start_sw_timer, false); + + if (env.execute_vcpu_load) { + SET_KP_OR_FENTRY_LOAD(vmx_vcpu_load, kvm_intel); + SET_KP_OR_FENTRY_LOAD(vmx_vcpu_put, kvm_intel); + } + if (env.execute_vcpu_wakeup) { + SET_KP_OR_FENTRY_LOAD(kvm_vcpu_halt, kvm); + } + if (env.execute_mark_page_dirty) { + SET_KP_OR_FENTRY_LOAD(mark_page_dirty_in_slot, kvm); + } + if (env.execute_timer) { + SET_KP_OR_FENTRY_LOAD(start_hv_timer, kvm); + SET_KP_OR_FENTRY_LOAD(start_sw_timer, kvm); + } + if (env.execute_hypercall) { + SET_KP_OR_FENTRY_LOAD(kvm_emulate_hypercall, kvm); + } + bpf_program__set_autoload(skel->progs.tp_vcpu_wakeup, env.execute_vcpu_wakeup ? true : false); - bpf_program__set_autoload(skel->progs.fentry_vmx_vcpu_load, - env.execute_vcpu_load ? true : false); - bpf_program__set_autoload(skel->progs.fentry_vmx_vcpu_put, - env.execute_vcpu_load ? true : false); - bpf_program__set_autoload(skel->progs.fentry_kvm_vcpu_halt, - env.execute_vcpu_wakeup ? true : false); bpf_program__set_autoload(skel->progs.tp_exit, env.execute_exit ? true : false); bpf_program__set_autoload(skel->progs.tp_entry, @@ -813,8 +840,6 @@ static void set_disable_load(struct kvm_watcher_bpf *skel) { env.execute_exit ? true : false); bpf_program__set_autoload(skel->progs.tp_kvm_halt_poll_ns, env.execute_halt_poll_ns ? true : false); - bpf_program__set_autoload(skel->progs.fentry_mark_page_dirty_in_slot, - env.execute_mark_page_dirty ? true : false); bpf_program__set_autoload(skel->progs.tp_page_fault, env.execute_page_fault ? true : false); bpf_program__set_autoload(skel->progs.fexit_tdp_page_fault, @@ -839,14 +864,8 @@ static void set_disable_load(struct kvm_watcher_bpf *skel) { env.execute_irq_inject ? true : false); bpf_program__set_autoload(skel->progs.fexit_vmx_inject_irq, env.execute_irq_inject ? true : false); - bpf_program__set_autoload(skel->progs.fentry_emulate_hypercall, - env.execute_hypercall ? true : false); bpf_program__set_autoload(skel->progs.tp_ioctl, env.execute_ioctl ? true : false); - bpf_program__set_autoload(skel->progs.fentry_start_hv_timer, - env.execute_timer ? true : false); - bpf_program__set_autoload(skel->progs.fentry_start_sw_timer, - env.execute_timer ? true : false); } // 函数不接受参数,返回一个静态分配的字符串 @@ -870,28 +889,15 @@ int sort_by_key(int fd, struct exit_key *keys, struct exit_value *values) { struct exit_key lookup_key = {}; struct exit_key next_key = {}; struct exit_value exit_value; - int first = 1; - int i = 0, j; - int count = 0; + int i = 0, j = 0, count = 0; while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { - count++; - if (first) { - first = 0; - bpf_map_lookup_elem(fd, &next_key, &exit_value); - keys[0] = next_key; - values[0] = exit_value; - i++; - lookup_key = next_key; - continue; - } + j = i - 1; + struct exit_key temp_key = next_key; err = bpf_map_lookup_elem(fd, &next_key, &exit_value); if (err < 0) { fprintf(stderr, "failed to lookup exit_value: %d\n", err); return -1; } - // insert sort - j = i - 1; - struct exit_key temp_key = next_key; struct exit_value temp_value = exit_value; while (j >= 0 && (keys[j].pid > temp_key.pid || (keys[j].tid > temp_key.tid))) { @@ -899,11 +905,11 @@ int sort_by_key(int fd, struct exit_key *keys, struct exit_value *values) { values[j + 1] = values[j]; j--; } - i++; - keys[j + 1] = next_key; + keys[j + 1] = temp_key; values[j + 1] = temp_value; - // Move to the next key lookup_key = next_key; + count++; + i++; } return count; }