From f645aba3e82833721b267ec645c1400a8f7337eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C4=83zvan=20Crainea?= Date: Fri, 8 Jun 2012 20:01:44 +0300 Subject: [PATCH] doc: added implementation tests: more results --- doc/paper.tex | 1 + doc/src/design.tex | 6 +- doc/src/implementation.tex | 167 ++++++++++++++++++++++++++++++++++++- sendfile/results | 12 +-- sendfile/test.sh | 2 + test/results | 12 +-- 6 files changed, 183 insertions(+), 17 deletions(-) diff --git a/doc/paper.tex b/doc/paper.tex index 4e80106..2ff1588 100644 --- a/doc/paper.tex +++ b/doc/paper.tex @@ -2,6 +2,7 @@ \usepackage{listings} \usepackage[utf8]{inputenc} \usepackage{graphicx} +\usepackage{subcaption} % paper info diff --git a/doc/src/design.tex b/doc/src/design.tex index 92e0fda..5944423 100644 --- a/doc/src/design.tex +++ b/doc/src/design.tex @@ -36,8 +36,8 @@ or the status of the operation. \begin{figure}[h!] \centering \includegraphics[scale=0.5]{img/architecture.png} - \label{fig:arch} \caption{P2PKP Module Architecture} + \label{fig:arch} \end{figure} Our implementation uses datagrams to send and receive information over @@ -60,7 +60,7 @@ space and deliver/receive them through the network. Section \ref{sec:implementation} describes the interactions between all these components and how they are linked together in order to provide the desired behavior. -\subsection{P2PKP Sender} +\subsection{Sender User} \label{subsec:sender} The sender module uses the UNIX socket interface in order to communicate from @@ -89,7 +89,7 @@ to one or multiple destinations. The total number of system calls used to transfer the files to each peer is equal to the number of files transferred plus the total number of recipients. -\subsection{P2PKP Received} +\subsection{Receiver User} \label{subsec:receiver} The receiver part of the module is also implemented in kernel module. The diff --git a/doc/src/implementation.tex b/doc/src/implementation.tex index aebd31e..90a812b 100644 --- a/doc/src/implementation.tex +++ b/doc/src/implementation.tex @@ -1,6 +1,169 @@ \section{Implementation} \label{sec:implementation} -How this protocol is implemented in kernel space - perhaps split it in -multiple subsections - sending/receiving. +As stated in the previous sections, and as Figure \ref{fig:arch} points out, +the whole implementation of the SWIFT protocol resides as a kernel module. +From the user's perspective, an application only has to use the generic socket +interface. It's implementation is described in Section \ref{subsec:sock}. +Based on the scenario, the application can act as file content distributor, or +receiver, (or perhaps both). Each behavior is largely presented in Section +\ref{subsec:psender} and \ref{subsec:preceiver}. +\subsection{P2PKP Socket Interface} +\label{subsec:sock} +This module advertises a new family socket in order to be used from user space +applications. Listing \ref{lst:protocol} presents the necessary registered +structures in order to create a new protocol in UNIX. There are three steps +that must be followed: + +\renewcommand{\figurename}{Listing} +\begin{figure}[h!] + \begin{minipage}[h]{.5\linewidth} + \lstset{language=C,captionpos=b,label=snip:familyops} + \begin{lstlisting} + +static struct proto p2pkp_proto = { + .name = P2PKP_PROTO_NAME, + .owner = THIS_MODULE, + .obj_size = sizeof(struct p2pkp_sock), +}; + \end{lstlisting} + \subcaption{Protocol Specification}\label{subfig1} + \end{minipage} \\ + \begin{minipage}[h]{.5\linewidth} + \lstset{language=C,captionpos=b,label=snip:familyops} + \begin{lstlisting} + +static const struct net_proto_family p2pkp_family_ops = { + .family = PF_P2PKP, + .create = p2pkp_create, + .owner = THIS_MODULE, +}; + \end{lstlisting} + \subcaption{Protocol Family}\label{subfig2} + \end{minipage} \\ + \begin{minipage}[h]{.5\linewidth} + \lstset{language=C,captionpos=b,label=snip:familyops} + \begin{lstlisting} + +static const struct proto_ops p2pkp_ops = { + .family = PF_P2PKP, + .owner = THIS_MODULE, + .release = p2pkp_release, + .bind = p2pkp_bind, + .connect = p2pkp_connect, + .sendmsg = p2pkp_sendmsg, + .recvmsg = p2pkp_recvmsg, + ... +}; + \end{lstlisting} + \subcaption{Protocol Operations}\label{subfig3} + \end{minipage} + \caption{Protocol specification} + \label{lst:protocol} +\end{figure} + +\begin{itemize} + \item Register the protocol - the structure needed to register a protocol + is presented in Listing \ref{subfig1}. It specifies the + protocol as it is seen in \\ + \texttt{/proc/net/protocols} + \item Register a new protocol family - Listing \ref{subfig2} is presenting + the structure needed to register a new protocol family. The + \texttt{p2pkp\_create} function initializes the kernel socket structures + when the \texttt{socket} system call is called. + \item Specify the protocol operations - the structure from Listing + \ref{subfig3} advertises the functions called by the Linux socket + interface from the \texttt{write}, \texttt{read}, \texttt{bind}, etc. + wrappers. Their implementation will be largely presented in the next + sections. +\end{itemize} + +In order to use the protocol provided by this module, all senders and +receivers have to open a socket. Then, based on their profile, they must +implement one of the following scenarios. + +\subsection{P2PKP Sender} +\label{subsec:psender} +As already described in Section \ref{subsec:sender}, after opening the socket, +the user space application has to specify all of the peers that wants to +distribute the file content to. Therefore it calls multiple times the +\texttt{connect} function, which is translated by the Linux socket interface +to the \texttt{p2pkp\_connect} function call. This function only links the +destination to a specific list attached to each socket. As this protocol is +built over UDP, there is no need of establishing a real connection to the +other peer. + +The next step the user space application has to do is to call the +\texttt{write} system call with the desired filename for distribution. This +system call maps to the \texttt{p2pkp\_sendmsg} function, and has the behavior +described in Listing \ref{lst:sender}. This is the main logic of the +multiparty sender. After some parameters checks are +performed, the input files are iterated and opened using the VFS \texttt{open} +call. If no files exist, the function exits with a \texttt{ENOENT} +\texttt{errno} set. Then, the content of the file is sent to each peer +previously connected. This is done using the Linux NET layer, using the +\texttt{kernel\_sendmsg} function. If the function succeeds, the total number +of files distributed is returned to the application. Otherwise, if one of the +Linux VFS or NET layer fail, the proper error is returned. + +The file's data is not read all at once in a single chunk, but rather +iteratively in chunks of 8192 bytes. After loading the data in buffer, it is +directly transmitted to all peers using the Linux NET layer. Therefore any +latency caused by the network, or hard disks are not to be assigned to the P2PKP +module, as it is a simple user of these mechanisms. + +After sending all the files to all the peers, the file is closed and the +structures are cleaned up. At this point, the user might start sending some +different files, or close the socket, using \texttt{close}. In this case, the +\texttt{p2pkp\_release} function is called that frees all the allocated data, +closes the UDP socket and cleans up the kernel structures. + +\addtocounter{lstlisting}{2} +\lstset{language=C,captionpos=b,label=lst:sender,caption={\texttt{p2pkp\_sendmsg} + pseudo code},tabsize=4,morekeywords={foreach}} +\begin{lstlisting} +foreach file + f = open(file, O_RDONLY) + do + read(f, buffer, chunk_size) + foreach peer + send(peer, buffer, chunk_size) + while f has more data + close(f) + +\end{lstlisting} + +\subsection{P2PKP Receiver} +\label{subsec:preceiver} +In order to receive files using the P2PKP module, a receiver application has +to bind a socket to an interface. As in any other protocol, this is done using +the \texttt{bind} system call, which is translated to \texttt{p2pkp\_bind} +function. In this function we create a new UDP socket, and we bind it to the +specified interface. + +Next, the application has to call the \texttt{read} function in order to +receive a file. The pseudo code of this function is presented in Listing +\ref{lst:receiver}. Basically, this function reads data from network and dumps +them into a file. First, a new file is opened for writing this time. If the +file exists, it is truncated to 0, otherwise it is created. + +Then the module enters in a loop, where it waits for data coming from the +peers through the Linux NET layer. Similar to the sender's behavior data is +received in chunks of 8192 each. After the transfer is completed, the cleanup +is done similarly to the receiver from the previous section. + +\lstset{language=C,captionpos=b,label=lst:receiver,caption={\texttt{p2pkp\_recvmsg} + pseudo code},tabsize=4,morekeywords={foreach}} +\begin{lstlisting} +f = open(file, O_WRONLY|O_CREAT|O_TRUNC); +while more data on socket + recv(sock, buffer, chunk_size) + write(f, buffer, chunk_size) +close(f) + +\end{lstlisting} + +Having presented the internal implementation of our module, we will proceed to +describing the testing scenarios we have performed in order to test our module +efficiency. diff --git a/sendfile/results b/sendfile/results index f62e2da..e406710 100644 --- a/sendfile/results +++ b/sendfile/results @@ -1,6 +1,6 @@ -send (B/MB) receive (B/KB) t(s) 2p 3p 6p ------------------------------------------------------------------------ -33554432/32 344232/337 4 10 18 49 -67108864/64 368820/361 10 20 35 80 -134217728/128 434388/425 20 42 58 226 -268435456/256 1901472/1946 41 75 129 385 +send (B/MB) receive (B/KB) t(s) 2p 3p 6p 8p +------------------------------------------------------------------------------- +33554432/32 344232/337 4 10 18 49 61 +67108864/64 368820/361 10 20 35 80 115 +134217728/128 434388/425 20 42 58 226 214 +268435456/256 1901472/1946 41 75 129 385 439 diff --git a/sendfile/test.sh b/sendfile/test.sh index 7f9bc2b..cb06891 100755 --- a/sendfile/test.sh +++ b/sendfile/test.sh @@ -16,6 +16,8 @@ LISTENERS_PORTS=( 50003 50004 50005 + 50006 + 50007 ) #use nc.traditional diff --git a/test/results b/test/results index 45549fd..100a529 100644 --- a/test/results +++ b/test/results @@ -1,6 +1,6 @@ -send (B/MB) receive (B/MB) t(s) 2p 3p 6p ------------------------------------------------------------------------ -33554432/32 8388608/8 13 29 35 45 -67108864/64 18874368/18 34 53 67 103 -134217728/128 40894464/39 66 118 142 167 -268435456/256 57671680/55 121 223 277 378 +send (B/MB) receive (B/MB) t(s) 2p 3p 6p 8p +------------------------------------------------------------------------------- +33554432/32 8388608/8 13 29 35 20 21 +67108864/64 18874368/18 34 53 67 35 41 +134217728/128 40894464/39 66 118 142 72 91 +268435456/256 57671680/55 121 223 277 115 159 -- 2.20.1