[PATCH 1/2] net-test: packetdrill: implement open syscall

62 views
Skip to first unread message

Thadeu Lima de Souza Cascardo

unread,
Jul 1, 2016, 4:23:45 PM7/1/16
to packe...@googlegroups.com, ncar...@google.com
open system call is implement, as it makes it easier to use the sendfile system
call as well.

Signed-off-by: Thadeu Lima de Souza Cascardo <casc...@redhat.com>
---
gtests/net/packetdrill/run_system_call.c | 62 ++++++++++++++++++++++++++++----
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 8a88598..46b0fb2 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -628,18 +628,18 @@ static int to_live_fd(struct state *state, int script_fd, int *live_fd,
* Returns STATUS_OK on success; on failure returns STATUS_ERR and
* sets error message.
*/
-static int run_syscall_socket(struct state *state, int address_family,
- int protocol, int script_fd, int live_fd,
- char **error)
+static struct socket * insert_new_socket(struct state *state, int address_family,
+ int protocol, int script_fd, int live_fd,
+ char **error)
{
/* Validate fd values. */
if (script_fd < 0) {
asprintf(error, "invalid socket fd %d in script", script_fd);
- return STATUS_ERR;
+ return NULL;
}
if (live_fd < 0) {
asprintf(error, "invalid live socket fd %d", live_fd);
- return STATUS_ERR;
+ return NULL;
}

/* Look for sockets with conflicting fds. Should not happen if
@@ -647,11 +647,11 @@ static int run_syscall_socket(struct state *state, int address_family,
if (find_socket_by_script_fd(state, script_fd)) {
asprintf(error, "duplicate socket fd %d in script",
script_fd);
- return STATUS_ERR;
+ return NULL;;
}
if (find_socket_by_live_fd(state, live_fd)) {
asprintf(error, "duplicate live socket fd %d", live_fd);
- return STATUS_ERR;
+ return NULL;
}

/* These fd values are kosher, so store them. */
@@ -662,6 +662,19 @@ static int run_syscall_socket(struct state *state, int address_family,
socket->script.fd = script_fd;
socket->live.fd = live_fd;

+ return socket;
+}
+
+static int run_syscall_socket(struct state *state, int address_family,
+ int protocol, int script_fd, int live_fd,
+ char **error)
+{
+ struct socket *socket = insert_new_socket(state, address_family,
+ protocol, script_fd, live_fd,
+ error);
+ if (socket == NULL)
+ return STATUS_ERR;
+
/* Any later packets in the test script will now be mapped here. */
state->socket_under_test = socket;

@@ -1682,6 +1695,40 @@ error_out:
return status;
}

+static int syscall_open(struct state *state, struct syscall_spec *syscall,
+ struct expression_list *args, char **error)
+{
+ int script_fd, live_fd, result;
+ struct expression *val;
+ char *name;
+ int flags;
+
+ if (check_arg_count(args, 2, error))
+ return STATUS_ERR;
+ val = get_arg(args, 0, error);
+ if (check_type(val, EXPR_STRING, error))
+ return STATUS_ERR;
+ name = val->value.string;
+ if (s32_arg(args, 1, &flags, error))
+ return STATUS_ERR;
+
+ begin_syscall(state, syscall);
+ result = open(name, flags);
+ if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error))
+ return STATUS_ERR;
+
+ if (result >= 0) {
+ live_fd = result;
+ if (get_s32(syscall->result, &script_fd, error))
+ return STATUS_ERR;
+ if (!insert_new_socket(state, 0, 0,
+ script_fd, live_fd, error))
+ return STATUS_ERR;
+ }
+
+ return STATUS_OK;
+}
+
/* A dispatch table with all the system calls that we support... */
struct system_call_entry {
const char *name;
@@ -1713,6 +1760,7 @@ struct system_call_entry system_call_table[] = {
{"getsockopt", syscall_getsockopt},
{"setsockopt", syscall_setsockopt},
{"poll", syscall_poll},
+ {"open", syscall_open},
};

/* Evaluate the system call arguments and invoke the system call. */
--
2.7.4

Thadeu Lima de Souza Cascardo

unread,
Jul 1, 2016, 4:23:47 PM7/1/16
to packe...@googlegroups.com, ncar...@google.com
Implement the sendfile system call. Offset is treated as only an input
parameter, though still in brackets.

sendfile is useful when we want the stack to send non linear skbs, as this is
helpful for reproducing some bugs and scenarios.

Signed-off-by: Thadeu Lima de Souza Cascardo <casc...@redhat.com>
---
gtests/net/packetdrill/run_system_call.c | 37 ++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)

diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 46b0fb2..043a4c7 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1,5 +1,6 @@
/*
* Copyright 2013 Google Inc.
+ * Copyright 2016 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +40,7 @@
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>
+#include <sys/sendfile.h>
#include <time.h>
#include <unistd.h>
#include "logging.h"
@@ -1729,6 +1731,40 @@ static int syscall_open(struct state *state, struct syscall_spec *syscall,
return STATUS_OK;
}

+static int syscall_sendfile(struct state *state, struct syscall_spec *syscall,
+ struct expression_list *args, char **error)
+{
+ int live_outfd, script_outfd;
+ int live_infd, script_infd;
+ off_t live_offset, script_offset = 0;
+ int count;
+ int result;
+ if (check_arg_count(args, 4, error))
+ return STATUS_ERR;
+ if (s32_arg(args, 0, &script_outfd, error))
+ return STATUS_ERR;
+ if (to_live_fd(state, script_outfd, &live_outfd, error))
+ return STATUS_ERR;
+ if (s32_arg(args, 1, &script_infd, error))
+ return STATUS_ERR;
+ if (to_live_fd(state, script_infd, &live_infd, error))
+ return STATUS_ERR;
+ if (s32_bracketed_arg(args, 2, (int *) &script_offset, error))
+ return STATUS_ERR;
+ if (s32_arg(args, 3, &count, error))
+ return STATUS_ERR;
+
+ live_offset = script_offset;
+
+ begin_syscall(state, syscall);
+
+ result = sendfile(live_outfd, live_infd, &live_offset, count);
+
+ int status = end_syscall(state, syscall, CHECK_EXACT, result, error);
+
+ return status;
+}
+
/* A dispatch table with all the system calls that we support... */
struct system_call_entry {
const char *name;
@@ -1761,6 +1797,7 @@ struct system_call_entry system_call_table[] = {
{"setsockopt", syscall_setsockopt},
{"poll", syscall_poll},
{"open", syscall_open},
+ {"sendfile", syscall_sendfile},

Neal Cardwell

unread,
Jul 1, 2016, 10:08:01 PM7/1/16
to Thadeu Lima de Souza Cascardo, packetdrill
Hi Thadeu,

Thank you so much for sending these two patches. These look like they will be very useful. I would like to make a few cosmetic style/formatting changes, if that's OK with you (some of which are pointed out by the Linux scripts/checkpatch.pl script). I've attached proposed revisions. Do these versions of the patch look OK to you?

Thanks,
neal

0001-net-test-packetdrill-implement-open-syscall.patch
0002-net-test-packetdrill-implement-sendfile-syscall.patch

Thadeu Lima de Souza Cascardo

unread,
Jul 4, 2016, 8:58:46 AM7/4/16
to Neal Cardwell, packetdrill
On Fri, Jul 01, 2016 at 10:07:30PM -0400, 'Neal Cardwell' via packetdrill wrote:
> Hi Thadeu,
>
> Thank you so much for sending these two patches. These look like they will
> be very useful. I would like to make a few cosmetic style/formatting
> changes, if that's OK with you (some of which are pointed out by the Linux
> scripts/checkpatch.pl script). I've attached proposed revisions. Do these
> versions of the patch look OK to you?
>
> Thanks,
> neal
>

Hi, Neal.

The new versions look fine to me. Thanks for reviewing and fixing them.

Cascardo.
> --
> You received this message because you are subscribed to the Google Groups "packetdrill" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to packetdrill...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



Neal Cardwell

unread,
Jul 7, 2016, 1:41:23 PM7/7/16
to Thadeu Lima de Souza Cascardo, packetdrill
Thanks! I have merged those two patches into the Google packetdrill github repo.

neal

Michael Tüxen

unread,
Jul 10, 2016, 3:12:32 PM7/10/16
to Neal Cardwell, Thadeu Lima de Souza Cascardo, packetdrill
> On 07 Jul 2016, at 19:40, 'Neal Cardwell' via packetdrill <packe...@googlegroups.com> wrote:
>
> Thanks! I have merged those two patches into the Google packetdrill github repo.
Dear all,

I added support of open() also to the fork at
https://github.com/nplab/packetdrill
I only added open to the list of the syscalls in the editor syntax files.
That seems to work on all platforms.

The implementation of sendfile() as provided in the patch only works on Linux.
FreeBSD's sendfile is different, therefore the code doesn't even on FreeBSD.
Neither NetBSD nor OpenBSD support sendfile.
I added support for FreeBSD's version and ifdefed it such that it also
compiles on NetBSD and OpenBSD.
sendfile has also been added to the syntax files for the editors.

With these modifications the following testscript runs on Linux and FreeBSD
(please note the the #ifdef stuff is an extension in the fork to deal with
platform specific script files):

0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.005 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.005 bind(3, ..., ...) = 0
+0.005 listen(3, 1) = 0
// Establish a TCP connection.
+0.035 < S 0:0(0) win 65535 <mss 1460>
+0.000 > S. 0:0(0) ack 1 <...>
+0.000 < . 1:1(0) ack 1 win 65535
+0.000 accept(3, ..., ...) = 4
+0.000 close(3) = 0
// Open file, send it and close it
// testfile MUST contain exactly 10 bytes of value 0
+0.000 open("testfile", O_RDONLY) = 5
#ifdef linux
+0.000 sendfile(4, 5, [0], 10) = 10
#endif
#ifdef FreeBSD
+0.000 sendfile(5, 4, 0, 0, {headers(2)=[{..., 10}, {..., 5}],
trailers(2)=[{..., 10}, {..., 5}]}, [40], 0) = 0
#endif
+0.000 close(5) = 0
#ifdef linux
+0.000 > P. 1:11(10) ack 1
+0.000 < . 1:1(0) ack 11 win 65535
// Terminate the TCP connection
+0.000 close(4) = 0
+0.000 > F. 11:11(0) ack 1
+0.000 < F. 1:1(0) ack 12 win 65535
+0.000 > . 12:12(0) ack 2
#endif
#ifdef FreeBSD
+0.000 > P. 1:26(25) ack 1
+0.000 < . 1:1(0) ack 26 win 65535
+0.000 > P. 26:41(15) ack 1
+0.000 < . 1:1(0) ack 41 win 65535
// Terminate the TCP connection
+0.000 close(4) = 0
+0.000 > F. 41:41(0) ack 1
+0.000 < F. 1:1(0) ack 42 win 65535
+0.000 > . 42:42(0) ack 2
#endif

Please note that sendfile() only works if the file only contains 0's. When
it contains other bytes, packetdrill will complain and abort the script.

Best regards
Michael
Reply all
Reply to author
Forward
0 new messages