doc: added implementation
[p2p-kernel-protocol.git] / doc / src / implementation.tex
1 \section{Implementation}
2 \label{sec:implementation}
3
4 As stated in the previous sections, and as Figure \ref{fig:arch} points out,
5 the whole implementation of the SWIFT protocol resides as a kernel module.
6 From the user's perspective, an application only has to use the generic socket
7 interface. It's implementation is described in Section \ref{subsec:sock}.
8 Based on the scenario, the application can act as file content distributor, or
9 receiver, (or perhaps both). Each behavior is largely presented in Section
10 \ref{subsec:psender} and \ref{subsec:preceiver}.
11
12 \subsection{P2PKP Socket Interface}
13 \label{subsec:sock}
14 This module advertises a new family socket in order to be used from user space
15 applications. Listing \ref{lst:protocol} presents the necessary registered
16 structures in order to create a new protocol in UNIX. There are three steps
17 that must be followed:
18
19 \renewcommand{\figurename}{Listing}
20 \begin{figure}[h!]
21         \begin{minipage}[h]{.5\linewidth}
22                 \lstset{language=C,captionpos=b,label=snip:familyops}
23                 \begin{lstlisting}
24
25 static struct proto p2pkp_proto = {
26         .name           = P2PKP_PROTO_NAME,
27         .owner          = THIS_MODULE,
28         .obj_size       = sizeof(struct p2pkp_sock),
29 };
30                 \end{lstlisting}
31                 \subcaption{Protocol Specification}\label{subfig1}
32         \end{minipage} \\
33         \begin{minipage}[h]{.5\linewidth}
34                 \lstset{language=C,captionpos=b,label=snip:familyops}
35                 \begin{lstlisting}
36         
37 static const struct net_proto_family p2pkp_family_ops = {
38         .family         = PF_P2PKP,
39         .create         = p2pkp_create,
40         .owner          = THIS_MODULE,
41 };      
42                 \end{lstlisting}
43                 \subcaption{Protocol Family}\label{subfig2}
44         \end{minipage} \\
45         \begin{minipage}[h]{.5\linewidth}
46                 \lstset{language=C,captionpos=b,label=snip:familyops}
47                 \begin{lstlisting}
48
49 static const struct proto_ops p2pkp_ops = {
50         .family         = PF_P2PKP,
51         .owner          = THIS_MODULE,
52         .release        = p2pkp_release,
53         .bind           = p2pkp_bind,
54         .connect        = p2pkp_connect,
55         .sendmsg        = p2pkp_sendmsg,
56         .recvmsg        = p2pkp_recvmsg,
57         ...
58 };
59                 \end{lstlisting}
60                 \subcaption{Protocol Operations}\label{subfig3}
61         \end{minipage}
62         \caption{Protocol specification}
63         \label{lst:protocol}
64 \end{figure}
65
66 \begin{itemize}
67         \item Register the protocol - the structure needed to register a protocol
68         is presented in Listing \ref{subfig1}. It specifies the
69         protocol as it is seen in \\
70                 \texttt{/proc/net/protocols}
71         \item Register a new protocol family - Listing \ref{subfig2} is presenting
72         the structure needed to register a new protocol family. The
73         \texttt{p2pkp\_create} function initializes the kernel socket structures
74         when the \texttt{socket} system call is called.
75         \item Specify the protocol operations - the structure from Listing
76         \ref{subfig3} advertises the functions called by the Linux socket
77         interface from the \texttt{write}, \texttt{read}, \texttt{bind}, etc.
78         wrappers. Their implementation will be largely presented in the next
79         sections.
80 \end{itemize}
81
82 In order to use the protocol provided by this module, all senders and
83 receivers have to open a socket. Then, based on their profile, they must
84 implement one of the following scenarios.
85
86 \subsection{P2PKP Sender}
87 \label{subsec:psender}
88 As already described in Section \ref{subsec:sender}, after opening the socket,
89 the user space application has to specify all of the peers that wants to
90 distribute the file content to. Therefore it calls multiple times the
91 \texttt{connect} function, which is translated by the Linux socket interface
92 to the \texttt{p2pkp\_connect} function call. This function only links the
93 destination to a specific list attached to each socket. As this protocol is
94 built over UDP, there is no need of establishing a real connection to the
95 other peer.
96
97 The next step the user space application has to do is to call the
98 \texttt{write} system call with the desired filename for distribution. This
99 system call maps to the \texttt{p2pkp\_sendmsg} function, and has the behavior
100 described in Listing \ref{lst:sender}. This is the main logic of the
101 multiparty sender. After some parameters checks are
102 performed, the input files are iterated and opened using the VFS \texttt{open}
103 call. If no files exist, the function exits with a \texttt{ENOENT}
104 \texttt{errno} set. Then, the content of the file is sent to each peer
105 previously connected. This is done using the Linux NET layer, using the
106 \texttt{kernel\_sendmsg} function. If the function succeeds, the total number
107 of files distributed is returned to the application. Otherwise, if one of the
108 Linux VFS or NET layer fail, the proper error is returned.
109
110 The file's data is not read all at once in a single chunk, but rather
111 iteratively in chunks of 8192 bytes. After loading the data in buffer, it is
112 directly transmitted to all peers using the Linux NET layer. Therefore any
113 latency caused by the network, or hard disks are not to be assigned to the P2PKP
114 module, as it is a simple user of these mechanisms.
115
116 After sending all the files to all the peers, the file is closed and the
117 structures are cleaned up. At this point, the user might start sending some
118 different files, or close the socket, using \texttt{close}. In this case, the
119 \texttt{p2pkp\_release} function is called that frees all the allocated data,
120 closes the UDP socket and cleans up the kernel structures.
121
122 \addtocounter{lstlisting}{2}
123 \lstset{language=C,captionpos=b,label=lst:sender,caption={\texttt{p2pkp\_sendmsg}
124                 pseudo code},tabsize=4,morekeywords={foreach}}
125 \begin{lstlisting}
126 foreach file
127         f = open(file, O_RDONLY)
128         do
129                 read(f, buffer, chunk_size)
130                 foreach peer
131                         send(peer, buffer, chunk_size)
132         while f has more data
133         close(f)
134
135 \end{lstlisting}
136
137 \subsection{P2PKP Receiver}
138 \label{subsec:preceiver}
139 In order to receive files using the P2PKP module, a receiver application has
140 to bind a socket to an interface. As in any other protocol, this is done using
141 the \texttt{bind} system call, which is translated to \texttt{p2pkp\_bind}
142 function. In this function we create a new UDP socket, and we bind it to the
143 specified interface.
144
145 Next, the application has to call the \texttt{read} function in order to
146 receive a file. The pseudo code of this function is presented in Listing
147 \ref{lst:receiver}. Basically, this function reads data from network and dumps
148 them into a file. First, a new file is opened for writing this time. If the
149 file exists, it is truncated to 0, otherwise it is created.
150
151 Then the module enters in a loop, where it waits for data coming from the
152 peers through the Linux NET layer. Similar to the sender's behavior data is
153 received in chunks of 8192 each. After the transfer is completed, the cleanup
154 is done similarly to the receiver from the previous section.
155
156 \lstset{language=C,captionpos=b,label=lst:receiver,caption={\texttt{p2pkp\_recvmsg}
157                 pseudo code},tabsize=4,morekeywords={foreach}}
158 \begin{lstlisting}
159 f = open(file, O_WRONLY|O_CREAT|O_TRUNC);
160 while more data on socket
161         recv(sock, buffer, chunk_size)
162         write(f, buffer, chunk_size)
163 close(f)
164
165 \end{lstlisting}
166
167 Having presented the internal implementation of our module, we will proceed to
168 describing the testing scenarios we have performed in order to test our module
169 efficiency.