[DTrace-devel] [PATCH v3] Implement the pcap action

Kris Van Hees kris.van.hees at oracle.com
Wed Nov 8 16:31:17 UTC 2023


Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                             | 160 +++++++++++++++---
 libdtrace/dt_consume.c                        |  53 +++---
 libdtrace/dt_open.c                           |   5 +
 libdtrace/dt_pcap.h                           |   4 +-
 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           |   3 +-
 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         |   3 +-
 20 files changed, 346 insertions(+), 61 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..489da823 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,118 @@ 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,
+			      pcapsz, 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_args(drp);
+	dt_regset_free(drp, BPF_REG_0);
+
+	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]));
+	dt_regset_free_args(drp);
+	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));
+
+	emit(dlp,  BPF_ALU64_REG(BPF_SUB, lenreg, BPF_REG_0));
+	dt_regset_free(drp, 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]));
+	dt_regset_free_args(drp);
+	dt_regset_free(drp, BPF_REG_0);
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp,  BPF_MOV_REG(BPF_REG_2, lenreg));
+	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));
+	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));
+	dt_regset_xalloc(drp, BPF_REG_0);
+	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 +4409,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 f5dfc373..7e2b1005 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 NULL, 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 dd70df24..b521d887 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -799,6 +799,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/dt_pcap.h b/libdtrace/dt_pcap.h
index bf14d013..f4d08591 100644
--- a/libdtrace/dt_pcap.h
+++ b/libdtrace/dt_pcap.h
@@ -1,6 +1,6 @@
 /*
  * 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.
  */
@@ -20,8 +20,6 @@ extern "C" {
 struct dtrace_hdl;
 
 #define	DT_PCAP_DEF_PKTSIZE	1514
-#define	DT_PCAPSIZE(sz) \
-	((sz > 0 && sz < 65566) ? sz : DT_PCAP_DEF_PKTSIZE)
 
 typedef struct dt_global_pcap {
 	dt_list_t dt_pcaps;	/* pcap file info */
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..2985514a 100755
--- a/test/unittest/pcap/tst.pcap.file.sh
+++ b/test/unittest/pcap/tst.pcap.file.sh
@@ -1,10 +1,9 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 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.
-# @@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..f0baf071 100755
--- a/test/unittest/pcap/tst.pcap.tshark.sh
+++ b/test/unittest/pcap/tst.pcap.tshark.sh
@@ -1,10 +1,9 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 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.
-# @@xfail: dtv2
 
 #
 # Ensure pcap() action in absence of freopen() results in tshark output
-- 
2.40.1




More information about the DTrace-devel mailing list