doc: added implementation
[p2p-kernel-protocol.git] / doc / src / implementation.tex
index aebd31e..90a812b 100644 (file)
@@ -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.