[DTrace-devel] [PATCH v2] Implement the pcap action
Kris Van Hees
kris.van.hees at oracle.com
Tue Nov 7 06:59:44 UTC 2023
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_cg.c | 154 +++++++++++++++---
libdtrace/dt_consume.c | 53 +++---
libdtrace/dt_open.c | 5 +
libdtrace/pcap.d | 4 +-
.../err.D_PROTO_ARG.pcap_non_scalar_arg1.d | 27 +++
.../err.D_PROTO_ARG.pcap_non_scalar_arg1.r | 4 +
.../err.D_PROTO_ARG.pcap_non_scalar_arg2.d | 23 +++
.../err.D_PROTO_ARG.pcap_non_scalar_arg2.r | 4 +
.../pcap/err.D_PROTO_LEN.pcap_missing_arg.d | 23 +++
.../pcap/err.D_PROTO_LEN.pcap_missing_arg.r | 2 +
.../pcap/err.D_PROTO_LEN.pcap_too_few_args.d | 23 +++
.../pcap/err.D_PROTO_LEN.pcap_too_few_args.r | 2 +
.../pcap/err.D_PROTO_LEN.pcap_too_many_args.d | 23 +++
.../pcap/err.D_PROTO_LEN.pcap_too_many_args.r | 2 +
test/unittest/pcap/tst.pcap.file.sh | 1 -
test/unittest/pcap/tst.pcap.regleak.d | 38 +++++
.../pcap/tst.pcap.stdout-fork-error.sh | 2 -
test/unittest/pcap/tst.pcap.stdout.sh | 2 -
test/unittest/pcap/tst.pcap.tshark.sh | 1 -
19 files changed, 337 insertions(+), 56 deletions(-)
create mode 100644 test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.d
create mode 100644 test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.r
create mode 100644 test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.d
create mode 100644 test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.r
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.d
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.r
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.d
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.r
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.d
create mode 100644 test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.r
create mode 100644 test/unittest/pcap/tst.pcap.regleak.d
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 86ee6908..42be1389 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1632,6 +1632,29 @@ dt_cg_clsflags(dt_pcb_t *pcb, dtrace_actkind_t kind, const dt_node_t *dnp)
*cfp |= DT_CLSFLAG_DATAREC;
}
+/*
+ * Get offsetof(structname, membername) information from CTF.
+ * Optionally, also get member size.
+ */
+static int
+dt_cg_ctf_offsetof(const char *structname, const char *membername, size_t *sizep)
+{
+ ctf_file_t *cfp = yypcb->pcb_hdl->dt_shared_ctf;
+ ctf_id_t type;
+ ctf_membinfo_t ctm;
+
+ if (!cfp)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+ type = ctf_lookup_by_name(cfp, structname);
+ if (type == CTF_ERR)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+ if (ctf_member_info(cfp, type, membername, &ctm) == CTF_ERR)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+ if (sizep)
+ *sizep = ctf_type_size(cfp, ctm.ctm_type);
+ return (ctm.ctm_offset / NBBY);
+}
+
static void
dt_cg_act_breakpoint(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
{
@@ -1882,8 +1905,112 @@ dt_cg_act_panic(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
static void
dt_cg_act_pcap(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
{
- dnerror(dnp, D_UNKNOWN, "pcap() is not implemented (yet)\n");
- /* FIXME: Needs implementation */
+ dtrace_hdl_t *dtp = pcb->pcb_hdl;
+ dt_regset_t *drp = pcb->pcb_regs;
+ dt_irlist_t *dlp = &pcb->pcb_ir;
+ dt_node_t *addr = dnp->dn_args;
+ dt_node_t *proto = addr->dn_list;
+ uint_t time_off, size_off, data_off, off;
+ uint_t lbl_lenok = dt_irlist_label(dlp);
+ uint64_t pcapsz = dtp->dt_options[DTRACEOPT_PCAPSIZE];
+ int lenreg;
+
+ TRACE_REGSET("pcap(): Begin ");
+
+ /*
+ * Create records for timestamp, size, protocol id, and packet data.
+ * The protocol id is stored immediately from the passed in argument.
+ */
+ time_off = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_PCAP,
+ sizeof(uint64_t), sizeof(uint64_t), NULL, 0);
+ size_off = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_PCAP,
+ sizeof(uint32_t), sizeof(uint32_t), NULL, 0);
+ dt_cg_store_val(pcb, proto, DTRACEACT_PCAP, NULL, 0);
+ data_off = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_PCAP,
+ dtp->dt_options[DTRACEOPT_PCAPSIZE], 1, NULL, 0);
+
+ /* Store timestamp (ns since boot time). */
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(BPF_FUNC_ktime_get_ns));
+ dt_regset_free_args(drp);
+ emit(dlp, BPF_STORE(BPF_DW, BPF_REG_9, time_off, BPF_REG_0));
+ dt_regset_free(drp, BPF_REG_0);
+
+ /*
+ * Determine and store the packet data size.
+ * The size of the data to be copied (and reported as size of the
+ * packet capture) is the lesser of the linear data size
+ * (skb->len - skb->data_len) and the capture size.
+ */
+ dt_cg_node(addr, dlp, drp);
+
+ off = dt_cg_ctf_offsetof("struct sk_buff", "len", NULL);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, addr->dn_reg));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, off));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint32_t)));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+ dt_regset_free(drp, BPF_REG_0);
+ dt_regset_free_args(drp);
+
+ if ((lenreg = dt_regset_alloc(drp)) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_LOAD(BPF_DW, lenreg, BPF_REG_FP, DT_STK_SP));
+ emit(dlp, BPF_LOAD(BPF_W, lenreg, lenreg, 0));
+
+ off = dt_cg_ctf_offsetof("struct sk_buff", "data_len", NULL);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, addr->dn_reg));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, off));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint32_t)));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_STK_SP));
+ emit(dlp, BPF_LOAD(BPF_W, BPF_REG_0, BPF_REG_0, 0));
+ dt_regset_free(drp, BPF_REG_0);
+ dt_regset_free_args(drp);
+
+ emit(dlp, BPF_ALU64_REG(BPF_SUB, lenreg, BPF_REG_0));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JLE, lenreg, pcapsz, lbl_lenok));
+ emit(dlp, BPF_MOV_IMM(lenreg, pcapsz));
+ emitl(dlp, lbl_lenok,
+ BPF_STORE(BPF_W, BPF_REG_9, size_off, lenreg));
+
+ /* Copy the packet data to the output buffer. */
+ off = dt_cg_ctf_offsetof("struct sk_buff", "data", NULL);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, addr->dn_reg));
+ dt_regset_free(drp, addr->dn_reg);
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, off));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint64_t)));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_FP, DT_STK_SP));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_3, 0));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, lenreg));
+ dt_regset_free(drp, lenreg);
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, data_off));
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+ dt_regset_free_args(drp);
+ dt_regset_free(drp, BPF_REG_0);
+
+ TRACE_REGSET("pcap(): End ");
}
static void
@@ -4276,29 +4403,6 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
}
}
-/*
- * Get offsetof(structname, membername) information from CTF.
- * Optionally, also get member size.
- */
-static int
-dt_cg_ctf_offsetof(const char *structname, const char *membername, size_t *sizep)
-{
- ctf_file_t *cfp = yypcb->pcb_hdl->dt_shared_ctf;
- ctf_id_t type;
- ctf_membinfo_t ctm;
-
- if (!cfp)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
- type = ctf_lookup_by_name(cfp, structname);
- if (type == CTF_ERR)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
- if (ctf_member_info(cfp, type, membername, &ctm) == CTF_ERR)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
- if (sizep)
- *sizep = ctf_type_size(cfp, ctm.ctm_type);
- return (ctm.ctm_offset / NBBY);
-}
-
static void
dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index 1edca292..2f45d9d3 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -1427,28 +1427,26 @@ dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
}
int
-dt_print_pcap(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
+dt_print_pcap(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec, uint_t nrecs,
const caddr_t buf)
{
- caddr_t addr;
- uint64_t time, proto, pktlen, maxlen;
- const char *filename;
+ caddr_t data;
+ uint64_t time, proto, pktlen;
+ uint64_t maxlen = dtp->dt_options[DTRACEOPT_PCAPSIZE];
+ const char *filename;
- addr = (caddr_t)buf + rec->dtrd_offset;
+ if (nrecs < 4)
+ return dt_set_errno(dtp, EDT_PCAP);
if (dt_read_scalar(buf, rec, &time) < 0 ||
- dt_read_scalar(buf + sizeof(uint64_t), rec, &pktlen) < 0)
+ dt_read_scalar(buf, rec + 1, &pktlen) < 0)
return dt_set_errno(dtp, EDT_PCAP);
- if (pktlen == 0) {
- /*
- * skb must have been NULL, skip without capturing.
- */
+ /* If pktlen is 0, the skb must have been ULL, so don't capture it. */
+ if (pktlen == 0)
return 0;
- }
- maxlen = DT_PCAPSIZE(dtp->dt_options[DTRACEOPT_PCAPSIZE]);
- if (dt_read_scalar(buf, rec + 1, &proto) < 0)
+ if (dt_read_scalar(buf, rec + 2, &proto) < 0)
return dt_set_errno(dtp, EDT_PCAP);
/*
@@ -1456,17 +1454,16 @@ dt_print_pcap(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
* specified or if we have been able to connect a pipe to tshark,
* otherwise print tracemem-like output.
*/
+ data = buf + (rec + 3)->dtrd_offset;
filename = dt_pcap_filename(dtp, fp);
- if (filename != NULL) {
- dt_pcap_dump(dtp, filename, proto, time,
- addr + (2 * sizeof(uint64_t)), (uint32_t)pktlen,
- (uint32_t)maxlen);
- } else {
- if (dt_print_rawbytes(dtp, fp, addr + (2 * sizeof(uint64_t)),
- pktlen > maxlen ? maxlen : pktlen) < 0)
- return -1;
- }
- return 0;
+ if (filename != NULL)
+ dt_pcap_dump(dtp, filename, proto, time, data,
+ (uint32_t)pktlen, (uint32_t)maxlen);
+ else if (dt_print_rawbytes(dtp, fp, data,
+ pktlen > maxlen ? maxlen : pktlen) < 0)
+ return -1;
+
+ return 4;
}
/*
@@ -2508,6 +2505,16 @@ dt_consume_one_probe(dtrace_hdl_t *dtp, FILE *fp, char *data, uint32_t size,
i += n - 1;
continue;
}
+ case DTRACEACT_PCAP: {
+ int nrecs;
+
+ nrecs = epd->dtdd_nrecs - i;
+ n = dt_print_pcap(dtp, fp, rec, nrecs, data);
+ if (n < 0)
+ return -1;
+ i += n - 1;
+ continue;
+ }
case DTRACEACT_PRINTF:
func = dtrace_fprintf;
break;
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index a2d8ebd3..df694f0e 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -798,6 +798,11 @@ dt_vopen(int version, int flags, int *errp,
return set_open_errno(dtp, errp, EDT_READMAXSTACK);
fclose(fd);
+ /*
+ * Set the default pcap capture size.
+ */
+ dtp->dt_options[DTRACEOPT_PCAPSIZE] = DT_PCAP_DEF_PKTSIZE;
+
/*
* Set the default data rates.
*/
diff --git a/libdtrace/pcap.d b/libdtrace/pcap.d
index 5d0dc90d..21a8e74a 100644
--- a/libdtrace/pcap.d
+++ b/libdtrace/pcap.d
@@ -1,12 +1,12 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
#pragma D depends_on module vmlinux
-#pragma D depends_on provider tcp
+#pragma D depends_on provider ip
/*
* In general, PCAP_<type> names are chosen to match DL_<type> DLPI
diff --git a/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.d b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.d
new file mode 100644
index 00000000..ecd6cf69
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.d
@@ -0,0 +1,27 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The first argument to pcap() should be a pointer.
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+struct {
+ int a;
+} arg;
+
+BEGIN
+{
+ pcap(arg, 0);
+ exit(0);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.r b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.r
new file mode 100644
index 00000000..0754e27d
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg1.d: [D_PROTO_ARG] line 20: pcap( ) argument #1 is incompatible with prototype:
+ prototype: void *
+ argument: struct
diff --git a/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.d b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.d
new file mode 100644
index 00000000..fed3c4a9
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The second argument to pcap() should be a scalar.
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+BEGIN
+{
+ pcap(0, "a");
+ exit(0);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.r b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.r
new file mode 100644
index 00000000..2c56503e
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/pcap/err.D_PROTO_ARG.pcap_non_scalar_arg2.d: [D_PROTO_ARG] line 16: pcap( ) argument #2 is incompatible with prototype:
+ prototype: int
+ argument: string
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.d b/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.d
new file mode 100644
index 00000000..3ab818a3
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: pcap() arguments
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+BEGIN
+{
+ pcap();
+ exit(0);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.r b/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.r
new file mode 100644
index 00000000..a51daa61
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/pcap/err.D_PROTO_LEN.pcap_missing_arg.d: [D_PROTO_LEN] line 16: pcap( ) prototype mismatch: 0 args passed, 2 expected
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.d b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.d
new file mode 100644
index 00000000..4f4f2eaf
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The pcap() subroutine requires 2 arguments.
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+BEGIN
+{
+ pcap(0);
+ exit(0);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.r b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.r
new file mode 100644
index 00000000..2951a6de
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/pcap/err.D_PROTO_LEN.pcap_too_few_args.d: [D_PROTO_LEN] line 16: pcap( ) prototype mismatch: 1 arg passed, 2 expected
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.d b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.d
new file mode 100644
index 00000000..e744df36
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The pcap() subroutine accepts no more than two arguments.
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+BEGIN
+{
+ pcap(1, 2, 3);
+ exit(0);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.r b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.r
new file mode 100644
index 00000000..7960c808
--- /dev/null
+++ b/test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/pcap/err.D_PROTO_LEN.pcap_too_many_args.d: [D_PROTO_LEN] line 16: pcap( ) prototype mismatch: 3 args passed, 2 expected
diff --git a/test/unittest/pcap/tst.pcap.file.sh b/test/unittest/pcap/tst.pcap.file.sh
index f3be6541..8973971a 100755
--- a/test/unittest/pcap/tst.pcap.file.sh
+++ b/test/unittest/pcap/tst.pcap.file.sh
@@ -4,7 +4,6 @@
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
-# @@xfail: dtv2
#
# Ensure pcap() action directed to file succeeds, and verify the content
diff --git a/test/unittest/pcap/tst.pcap.regleak.d b/test/unittest/pcap/tst.pcap.regleak.d
new file mode 100644
index 00000000..3eb3cbc7
--- /dev/null
+++ b/test/unittest/pcap/tst.pcap.regleak.d
@@ -0,0 +1,38 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: pcap() does not leak registers
+ *
+ * SECTION: Actions and Subroutines/pcap()
+ */
+
+/* @@runtest-opts: -e */
+
+BEGIN
+{
+ /*
+ * If pcap() leaks even a single register, ten invocations will most
+ * certainly result in a compiler error (due to register starvation).
+ */
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ pcap(0, PCAP_IP);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/pcap/tst.pcap.stdout-fork-error.sh b/test/unittest/pcap/tst.pcap.stdout-fork-error.sh
index 5681936a..9e7b92de 100755
--- a/test/unittest/pcap/tst.pcap.stdout-fork-error.sh
+++ b/test/unittest/pcap/tst.pcap.stdout-fork-error.sh
@@ -12,8 +12,6 @@
# skb->data.
#
-# @@xfail: need ip provider
-
if (( $# != 1 )); then
echo "expected one argument: <dtrace-path>" >&2
exit 2
diff --git a/test/unittest/pcap/tst.pcap.stdout.sh b/test/unittest/pcap/tst.pcap.stdout.sh
index bb0dc242..6ad322dc 100755
--- a/test/unittest/pcap/tst.pcap.stdout.sh
+++ b/test/unittest/pcap/tst.pcap.stdout.sh
@@ -11,8 +11,6 @@
# skb->data.
#
-# @@xfail: need ip provider
-
if (( $# != 1 )); then
echo "expected one argument: <dtrace-path>" >&2
exit 2
diff --git a/test/unittest/pcap/tst.pcap.tshark.sh b/test/unittest/pcap/tst.pcap.tshark.sh
index 1d8ebe5b..f3127d27 100755
--- a/test/unittest/pcap/tst.pcap.tshark.sh
+++ b/test/unittest/pcap/tst.pcap.tshark.sh
@@ -4,7 +4,6 @@
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
-# @@xfail: dtv2
#
# Ensure pcap() action in absence of freopen() results in tshark output
--
2.40.1
More information about the DTrace-devel
mailing list