]> rtime.felk.cvut.cz Git - canping.git/blob - doc/canping.xml
Second version of OCERA casestudies. This version fixes many errors, enhances the...
[canping.git] / doc / canping.xml
1 <?xml version="1.0" encoding="ISO-8859-2"?>
2 <!-- <?xml version="1.0" encoding="ISO-8859-2"?> -->
3 <!-- <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" -->
4 <!-- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ -->
5 <!-- <!ENTITY % canping_path "."> -->
6 <!-- <!ENTITY % canping_entities SYSTEM "canping.ent"> -->
7 <!-- %canping_entities; -->
8 <!-- ]> -->
9 <chapter>
10   <title>CANping &ndash; a simple LinCAN testing application</title>
11
12   <section>
13     <title>Introduction</title>
14
15     <para>This chapter describes a simple application called
16     <productname>canping</productname>. Its primary goal was to test the
17     LinCAN driver but it also nicely illustrates how to use LinCAN driver in
18     real applications. In addition, it shows some maliciousness of the LinCAN
19     driver.</para>
20
21     <para>Canping is a multithread application, which sends and receives
22     messages in parallel and thus can be used for stress testing of the LinCAN
23     driver. For basic usage, two running instances of canping, each one on a
24     different host, are needed. One instance sends messages and waits for
25     replies and the other instance waits for the sent messages and sends
26     replays with an ID incremented by one. Canping can also be run twice on
27     one host provided that we are either using a virtual CAN device or there
28     are multiple CAN cards/chips in the host.</para>
29   </section>
30
31   <section>
32     <title>CANping manual</title>
33
34     <refentry>
35       <refnamediv>
36         <refname>canping</refname>
37
38         <refpurpose>Multi-thread LinCAN testing utility</refpurpose>
39       </refnamediv>
40
41       <refsynopsisdiv>
42         <cmdsynopsis>
43           <command>canping</command>
44
45           <group>
46             <arg choice="req">-m <replaceable>num</replaceable></arg>
47
48             <arg choice="req">-s <replaceable>num</replaceable></arg>
49           </group>
50
51           <arg>-c <replaceable>count</replaceable></arg>
52
53           <arg>-d <replaceable>device</replaceable></arg>
54
55           <arg>-h</arg>
56
57           <arg>-i <replaceable>id</replaceable></arg>
58
59           <arg>-l <replaceable>length</replaceable></arg>
60
61           <arg>-o</arg>
62
63           <arg>-t <replaceable>timeout</replaceable></arg>
64
65           <arg>-y <replaceable>count</replaceable></arg>
66         </cmdsynopsis>
67       </refsynopsisdiv>
68
69       <refsect1>
70         <title>Options</title>
71
72         <variablelist>
73           <varlistentry>
74             <term><option>-m <replaceable>num</replaceable></option></term>
75
76             <listitem>
77               <para>Start in the master mode and run
78               <replaceable>num</replaceable> master threads in
79               parallel.</para>
80             </listitem>
81           </varlistentry>
82
83           <varlistentry>
84             <term><option>-s <replaceable>num</replaceable></option></term>
85
86             <listitem>
87               <para>Start in the slave mode and run
88               <replaceable>num</replaceable> slave threads in parallel.</para>
89             </listitem>
90           </varlistentry>
91
92           <varlistentry>
93             <term><option>-c <replaceable>count</replaceable></option></term>
94
95             <listitem>
96               <para>Every master thread will send only
97               <replaceable>count</replaceable> messages and then finishes.
98               Without this option messages are sent forever and CANping can be
99               terminated by a signal e.g. by pressing a <keycombo>
100                   <keysym>Ctrl+C</keysym>
101                 </keycombo> key.</para>
102             </listitem>
103           </varlistentry>
104
105           <varlistentry>
106             <term><option>-d <replaceable>device</replaceable></option></term>
107
108             <listitem>
109               <para>CAN device to be used. Default is
110               <filename>/dev/can0</filename>.</para>
111             </listitem>
112           </varlistentry>
113
114           <varlistentry>
115             <term><option>-i <replaceable>id</replaceable></option></term>
116
117             <listitem>
118               <para>Select ID of the lowest generated or responded message.
119               Default is 1000. CANping in the master mode will generate
120               messages with IDs <replaceable>id</replaceable>,
121               <replaceable>id</replaceable>+2,
122               <replaceable>id</replaceable>+4, etc. Each master thread will
123               generate different ID. The slave threads will listen to these
124               IDs and will answer with an ID increased by one.</para>
125             </listitem>
126           </varlistentry>
127
128           <varlistentry>
129             <term><option>-l <replaceable>len</replaceable></option></term>
130
131             <listitem>
132               <para>Specify a length of the messages. Default is 8 and
133               possible values are from 0 to 8.</para>
134             </listitem>
135           </varlistentry>
136
137           <varlistentry>
138             <term><option>-t <replaceable>sec</replaceable></option></term>
139
140             <listitem>
141               <para>A timeout in seconds; this option specifies how long the
142               master thread will wait for the response message from a slave.
143               If the response won't arrive in <replaceable>SEC</replaceable>
144               seconds, the message is considered as loosed.</para>
145             </listitem>
146           </varlistentry>
147
148           <varlistentry>
149             <term><option>-v</option></term>
150
151             <listitem>
152               <para>Increase verbosity. Without this option only summary
153               statistics are displayed just before the program finishes. One
154               -v means to display a global status (number of sent messages and
155               timeouts) during program execution. Two -v options display a
156               simple message for every packet in the format <emphasis
157               role="bold">ID:time</emphasis> where time is measured in
158               microseconds. Three -v options display more verbose information
159               about each packet.</para>
160             </listitem>
161           </varlistentry>
162
163           <varlistentry>
164             <term><option>-w <replaceable>msec</replaceable></option></term>
165
166             <listitem>
167               <para>Wait time in milliseconds before the master thread sends a
168               next message. Default value is 1000 ms.</para>
169             </listitem>
170           </varlistentry>
171
172           <varlistentry>
173             <term><option>-y</option></term>
174
175             <listitem>
176               <para>Synchronize the master threads before sending the first
177               message. When CANping is stared with the high number of master
178               threads, usually the first created thread will begin by sending
179               the messages before the last thread is created. Sometimes it may
180               be useful that every thread will wait before sending anything to
181               the other threads. Only when all threads are created and
182               prepared for sending, sending can start.</para>
183             </listitem>
184           </varlistentry>
185         </variablelist>
186       </refsect1>
187
188       <refsect1>
189         <title>Exit codes</title>
190
191         <para>The <productname>canping</productname> exit code depends on how
192         the program finishes. This feature can be used for (semi)automatic
193         testing of <productname>LinCAN</productname> driver. Exit codes are
194         listed in the table bellow.</para>
195
196         <informaltable frame="none" pgwide="0">
197           <tgroup cols="2">
198             <colspec align="center" colwidth="1cm" />
199
200             <tbody>
201               <row>
202                 <entry>0</entry>
203
204                 <entry>OK</entry>
205               </row>
206
207               <row>
208                 <entry>1</entry>
209
210                 <entry>Bad command line parameter</entry>
211               </row>
212
213               <row>
214                 <entry>2</entry>
215
216                 <entry>Problem with opening LinCAN driver</entry>
217               </row>
218
219               <row>
220                 <entry>3</entry>
221
222                 <entry>Problem with filter</entry>
223               </row>
224
225               <row>
226                 <entry>4</entry>
227
228                 <entry>Insufficient memory</entry>
229               </row>
230
231               <row>
232                 <entry>5</entry>
233
234                 <entry>Read syscall error</entry>
235               </row>
236
237               <row>
238                 <entry>6</entry>
239
240                 <entry>Write syscall error</entry>
241               </row>
242
243               <row>
244                 <entry>7</entry>
245
246                 <entry>Select syscall error</entry>
247               </row>
248
249               <row>
250                 <entry>8</entry>
251
252                 <entry>Flush (ioctl syscall) error</entry>
253               </row>
254             </tbody>
255           </tgroup>
256         </informaltable>
257       </refsect1>
258
259       <refsect1>
260         <title>Examples</title>
261
262         <para>On one computer one runs slave with 10 threads:</para>
263
264         <screen><prompt>root@pc104:~%</prompt> canping -d /dev/can1 -s 10</screen>
265
266         <para>and on another computer master is run with 10 threads
267         too:</para>
268
269         <screen><prompt>sojka@glab:~%</prompt> canping -d /dev/can4 -m 10 -v -c 100 -w 10
270 Total count: 1000, Timeouts: 0
271 Summary statistics:
272 Id 1000: count = 100 mean = 8005.16 stddev = 691.01 min = 2022 max = 11133 [us] loss = 0% (0) 
273 Id 1002: count = 100 mean = 8013.10 stddev = 641.19 min = 4013 max = 12885 [us] loss = 0% (0) 
274 Id 1004: count = 100 mean = 8035.99 stddev = 575.36 min = 5996 max = 13081 [us] loss = 0% (0) 
275 Id 1006: count = 100 mean = 8062.38 stddev = 626.46 min = 7005 max = 14061 [us] loss = 0% (0)
276 Id 1008: count = 100 mean = 8082.63 stddev = 740.59 min = 5963 max = 15020 [us] loss = 0% (0)
277 Id 1010: count = 100 mean = 8089.04 stddev = 831.64 min = 7018 max = 15970 [us] loss  = 0% (0)
278 Id 1012: count = 100 mean = 8105.02 stddev = 952.95 min = 7011 max = 16970 [us] loss = 0% (0) 
279 Id 1014: count = 100 mean = 8129.57 stddev = 1037.39 min = 7020 max = 17906 [us] loss = 0% (0) 
280 Id 1016: count = 100 mean = 8144.46 stddev = 1154.17 min = 7019 max = 18870 [us] loss = 0% (0) 
281 Id 1018: count = 100 mean = 8157.85 stddev = 1259.84 min = 5994 max = 19842 [us] loss = 0% (0)</screen>
282
283         <para>At the end of program execution, there are statistics for each
284         packet type (ID). These contain mean round trip times (RTT), standard
285         deviations of RTT, minimal and maximal RTT and packet losses
286         (percentage and absolute).</para>
287       </refsect1>
288     </refentry>
289   </section>
290
291   <section>
292     <title>Implementation details</title>
293
294     <para>The structure of <productname>canping</productname> is as follows.
295     After the initialization and parsing of command line options (function
296     <function>parse_optins()</function>), communicating threads are started.
297     The code of these threads is made up by
298     <function>master_thread()</function> and
299     <function>slave_thread()</function> functions which are described in the
300     following section.</para>
301
302     <para>After these threads are finished (either after pressing
303     <keycap>Ctrl-C</keycap> or due to <parameter>-c</parameter> switch),
304     summary statistics are written to stdout and the application
305     finishes.</para>
306
307     <section>
308       <title>Usage of the LinCAN driver</title>
309
310       <para>This section will cover <function>master_thread()</function>
311       function. Code of <function>slave_thread()</function> is very similar to
312       <function>master_thread()</function>, so it will not be covered here.
313       These functions represent typical usage of the LinCAN driver in
314       applications and if you are looking for examples how to use the LinCAN
315       driver, this is probably the most important section for you.</para>
316
317       <para>The <function>master_thread()</function> function is responsible
318       for opening the driver, sending message with a particular ID and waiting
319       for response message. Sending and receiving messages is done
320       periodically in a loop.</para>
321
322       <section>
323         <title>Opening the Driver</title>
324
325         <para>At the beginning of every access to the LinCAN driver, the
326         driver has to be opened. This is done by calling
327         <function>open()</function>.<programlisting>canfd = open(option_device, O_RDWR)</programlisting></para>
328
329         <para>The value of the <varname>option_device</varname> variable
330         specifies the name of CAN device e.g. <filename>/dev/can0</filename>
331         and the second parameter contains additional flags. We are using a
332         <constant>O_RDWR</constant> flag which means that we want to use the
333         driver for both reading and writing (messages). You can also use the
334         <constant>O_NOBLOCK</constant> flag in addition. For further details
335         regarding this flag see the LinCAN documentation.</para>
336
337         <para>If the opening operation succeeds, the <varname>canfd</varname>
338         variable contains a valid file descriptor, which is used for further
339         communication with the driver. In the case of an error, we use
340         <function>perror()</function> function to print the reason of the
341         error and then we exit the program with appropriate exit code<footnote>
342             <para>The exit code can be used by an automatic regression tests
343             to detect the reason of failure.</para>
344           </footnote>.</para>
345       </section>
346
347       <section>
348         <title>Setting Filters</title>
349
350         <para>After the device is open, the second step is to create a filter
351         for message receiving. The filter assures this thread only receives
352         messages it is waiting for.</para>
353
354         <programlisting>/* setup filtering of received messages */
355 memset(&amp;canfilt, 0, sizeof(canfilt));
356 canfilt.mask = 0xfffffff;
357 canfilt.id = pong_id; /* pong responces with increased id */
358 ret = ioctl(canfd, CANQUE_FILTER, &amp;canfilt);
359 </programlisting>
360
361         <para>The filter is created by filling the <type>canfilt_t</type>
362         structure and submitting it to the <constant>CANQUE_FILTER</constant>
363         ioctl. Filters allow us to filter messages by various criterions. We
364         use only filtering by an ID. The <varname>mask</varname> member tells
365         which bits of message ID are relevant for filtering and the member
366         <varname>id</varname> contains desired ID bit values. Since we need
367         only to receive messages with one ID <varname>mask</varname> is set to
368         all ones and <varname>id</varname> contains the ID.</para>
369
370         <para>After the filter is set up it is necessary to flush driver
371         queues. The reason for this is that in the time between driver opening
372         and filter setup, there can be some received messages in the queue,
373         which doesn't match the filter criteria. Flushing the queue is done by
374         calling <constant>CANQUE_FLUSH</constant> ioctl.</para>
375
376         <programlisting>ret = ioctl(canfd, CANQUE_FLUSH, NULL);
377 </programlisting>
378       </section>
379
380       <section>
381         <title>Reading and Writing</title>
382
383         <para>As soon as these operations are done, everything is ready for
384         message sending and reception. The message is sent by calling the
385         <function>write()</function> function with <type>canmsg_t</type>
386         structure as the second parameter. The <type>canmsg_t</type> structure
387         should be filled according to the message we wish to send. This
388         comprises of a message ID, message data bytes, the length of message
389         etc. The structure for the ping message is filled by the following
390         commands:</para>
391
392         <programlisting>pingmsg.flags=0;
393 pingmsg.id=ping_id;
394 pingmsg.length = option_length;
395 for (i=0; i &lt; option_length; i++) pingmsg.data[i] = i;
396 </programlisting>
397
398         <para>Later, the message is sent by:</para>
399
400         <programlisting>ret = write(canfd, &amp;pingmsg, sizeof(pingmsg));</programlisting>
401
402         <para>After the message is sent, the program starts waiting for the
403         response message. The <function>select()</function> system call is
404         used for this purpose because it allows us to wait with timeout. If
405         there is a received message, we can read it from the driver by calling
406         <function>read()</function> function.</para>
407
408         <para>Before doing that, it is important to zero
409         <varname>flags</varname> field of <type>canmsg_t</type> structure.
410         This is due to a feature of the driver. Pavel Pí¹a describes this as
411         follows:</para>
412
413         <blockquote>
414           <para>Adding "<function>msg.flags=0;</function>" before
415           "<function>read()</function>" call is required, because random value
416           could trigger RTR read patch in the driver. This obsolete driver
417           read mode should be moved to its own IOCTL in future.</para>
418         </blockquote>
419
420         <programlisting>/* Read the message */
421 pongmsg.flags=0;
422 ret = read(canfd, &amp;pongmsg, sizeof(pongmsg));</programlisting>
423       </section>
424
425       <section>
426         <title>Closing</title>
427
428         <para>At the end, when it is not needed to work with the driver, it
429         should be closed in order to remove all driver resources associated
430         with our application. The driver is closed simply by calling
431         <function>close()</function>.</para>
432
433         <programlisting>close(canfd);</programlisting>
434       </section>
435     </section>
436
437     <section>
438       <title>Other parts of the application</title>
439
440       <section>
441         <title>Lists</title>
442
443         <para>For managing the list of executing threads and their statistics
444         a list implementation from Pavel Pí¹a's <productname>uLan
445         utils</productname> (ulut) package was used. This framework allows us
446         very simple and efficient list handling.</para>
447
448         <para>First, list head should be declared:<programlisting>typedef struct threads {
449         ul_list_head_t head;
450 } threads_t;
451 </programlisting>Since we don't need any additional data, our list head has
452         only one field of the type <type>ul_list_head_t</type>. Next we
453         declare a list element:<programlisting>typedef struct thread_data {
454         pthread_t tid;
455         long int canid;
456
457         int count;
458         double mean;            /* mean value of responses */
459         double moment2nd;       /* used to compute variance of
460                                  * responses */
461         int min, max;           /* min/max response times */
462         int timeout;            /* number of timeouts */
463
464         ul_list_node_t node;
465 } thread_data_t;
466 </programlisting>This structure is used for storing data for every executed
467         thread. In the next step we declare functions for list manipulation.
468         These functions are created automatically by the
469         <function>UL_LIST_CUST_DEC</function> macro.<programlisting>UL_LIST_CUST_DEC(thread_list, threads_t, thread_data_t, head, node);</programlisting>This
470         declares some functions whose names start with the
471         <constant>thread_list_</constant> prefix. We use two of these, namely
472         <function>thread_list_init_head()</function> for list initialization
473         and <function>thread_list_ins_tail()</function> for adding elements to
474         the list.</para>
475
476         <para>We also use a macro <function>ul_list_for_each()</function>
477         (declared in <filename>ul_list.h</filename>) which traverses through
478         all the list elements in a loop.</para>
479       </section>
480
481       <section>
482         <title>Waiting for the thread completion</title>
483
484         <para>After the main thread starts all the communication threads, it
485         is necessary to wait for their completion. This is done in
486         <function>wait_for_threads()</function>. In the simplest case, waiting
487         runs in a while loop and in every iteration is is waited for one
488         thread using a <varname>finish_sem</varname> semaphore. After the
489         <varname>thread_count</varname> iterations, we are sure all the
490         threads finished. Whenever any thread finishes, it increments this
491         semaphore by calling <function>sem_post()</function> and this is why
492         we can wait for a particular number of threads to finish.</para>
493
494         <para>The simplest case of waiting code looks as
495         follows:<programlisting>while (thread_count &gt; 0) {
496         ret = sem_wait(&amp;finish_sem);
497         if (ret == 0) thread_count--;
498 }
499 </programlisting>In the <productname>canping</productname> application we use
500         more difficult code because of printing of progress messages during
501         waiting.</para>
502
503         <para>Finally, when all the threads are finished, we print summary
504         statistics for each thread and free list elements:<programlisting>ul_list_for_each_cut(thread_list, &amp;master_threads, td) {
505         print_stats(td);
506         free(td);
507 }
508 </programlisting></para>
509       </section>
510
511       <section>
512         <title>Signal handling</title>
513
514         <para>In order to exit <productname>canping</productname> by pressing
515         <keycap>Ctrl-C</keycap> (<constant>SIGINT</constant>) or by sending
516         other signal such as <constant>SIGTERM</constant> it is necessary to
517         write and register a signal handler. The handler is registered
518         by:<programlisting>siginterrupt(SIGINT, 1);
519 signal(SIGINT, term_handler);
520 siginterrupt(SIGTERM, 1);
521 signal(SIGTERM, term_handler);
522 </programlisting>This registers the <function>term_handler</function> function
523         as the handler for the <constant>SIGINT</constant> and
524         <constant>SIGTERM</constant> signals. The call to the
525         <function>siginterrupt()</function> function tells the OS that an
526         arrived signal should interrupt currently executed system
527         call<footnote>
528             <para>The behaviour of signals is different in Linux 2.4 and Linux
529             2.6 with NPTL. The call to <function>siginterrupt()</function> is
530             necessary in order to get the same behaviour for both 2.4 and
531             2.6.</para>
532           </footnote>. This is necessary because the master and slave threads
533         executes <function>select()</function> or <function>read()</function>
534         system call, which cause waiting for external event, which can never
535         happen and we want the program to exit even if there is no
536         event.</para>
537
538         <para>The signal handler looks as follows:<programlisting>#define NOT_INTERRUPTED_SYSCALL (errno != EINTR &amp;&amp; errno != ERESTART)
539 #define IS_FINISH_FLAG() (finish_flag)
540
541 void term_handler(int signum)
542 {
543         if (!IS_FINISH_FLAG()) {
544                 finish_flag = 1;
545                 kill_all_threads(signum);
546         }
547 }
548 </programlisting>Whenever the main thread receives a signal it sets
549         <varname>finish_flag</varname> to prevent recursive call to the
550         handler and then sends the same signal to all other threads. The other
551         threads receive the signal and execute the handler. Because the
552         <varname>finish_flag</varname> is set the handler does nothing. The
553         only result of the signal is interruption of currently executed system
554         call. As a consequence, the thread exits the send-receive loop and
555         executes exit code.</para>
556
557         <para>You can notice the macro <varname>IS_FINISH_FLAG</varname>. This
558         macro is defined only for debugging purposes so don't be confused by
559         it.</para>
560       </section>
561     </section>
562   </section>
563
564   <section>
565     <title>Assignment</title>
566
567     <orderedlist>
568       <listitem>
569         <para>Create a simple chat application that will send messages over
570         the CAN bus. The application will read the characters typed on
571         keyboard and send them to the bus. In addition, it will receive CAN
572         messages from other nodes on the bus and print then on screen.</para>
573       </listitem>
574
575       <listitem>
576         <para>Extend the chat application by displaying messages in color
577         depending on the ID of sender. For color and screen management use for
578         example the <productname>ncurses</productname> library (<ulink
579         url="http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/">http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/</ulink>).</para>
580       </listitem>
581     </orderedlist>
582   </section>
583 </chapter>