X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=blobdiff_plain;ds=sidebyside;f=doc%2Fsrc%2Fimplementation.tex;fp=doc%2Fsrc%2Fimplementation.tex;h=90a812be9eb6636fda42e109a7e7c30ec942f6d5;hb=f645aba3e82833721b267ec645c1400a8f7337eb;hp=aebd31e51317cbe95367817806a979ffee1008ea;hpb=bafe5cf4c62e2e972c2b98287cd98dca9f140013;p=p2p-kernel-protocol.git 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.