]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - doc/canprio/can_socket_blocking.txt
Note on blocking/nonblocking behaviour of CAN socket with some experiments.
[lisovros/iproute2_canprio.git] / doc / canprio / can_socket_blocking.txt
1 # can_socket_blocking.txt
2
3 # The purpose of this experiment is to show:
4 #    1) "Nonblocking behaviour" (return value of -ENOBUFS) of write() call to
5 #       CAN socket (with default settings set to BLOCKING).
6 #       This can be caused by:
7 #         -- Amount of data sent to a device is much higher than 
8 #            the device is capable of sending (i.e. frames are dropped by the
9 #            device driver).
10 #         -- Amount of data sent to a qdisc (default pfifo gets its size from
11 #            txqueuelen parameter of a device) is much higher than the qdisc 
12 #            can handle -- this leads to packet drop.
13 #
14 #    2) Possibility of blocking behaviour of write() call when internal socket
15 #       buffer (SO_SNDBUF option) is smaller than qdiscs buffer. (3rd part of 
16 #       the experiment tries to show that write is "really blocked" -- that this
17 #       desired behaviour is not caused only in the manner that none ot the
18 #       buffers overruns).
19 ################################################################################
20
21 # Set the same for all parts of the experiment
22 $ sudo ip link set can0 txqueuelen 50
23
24 ################################################################################
25 ##### Default cangen #####
26 ################################################################################
27
28 $ ip link show dev can0
29 3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 50
30     link/can 
31
32 $ ./cangen -g 0 can0 -I i -L 1 -D i -v -v
33   can0    0  [1] 00
34   can0    1  [1] 01
35   can0    2  [1] 02
36   can0    3  [1] 03
37   can0    4  [1] 04
38   can0    5  [1] 05
39   can0    6  [1] 06
40   can0    7  [1] 07
41   can0    8  [1] 08
42   can0    9  [1] 09
43   can0    A  [1] 0A
44   can0    B  [1] 0B
45   can0    C  [1] 0C
46   can0    D  [1] 0D
47   can0    E  [1] 0E
48   can0    F  [1] 0F
49   can0   10  [1] 10
50   can0   11  [1] 11
51   can0   12  [1] 12
52   can0   13  [1] 13
53   can0   14  [1] 14
54   can0   15  [1] 15
55   can0   16  [1] 16
56   can0   17  [1] 17
57   can0   18  [1] 18
58   can0   19  [1] 19
59   can0   1A  [1] 1A
60   can0   1B  [1] 1B
61   can0   1C  [1] 1C
62   can0   1D  [1] 1D
63   can0   1E  [1] 1E
64   can0   1F  [1] 1F
65   can0   20  [1] 20
66   can0   21  [1] 21
67   can0   22  [1] 22
68   can0   23  [1] 23
69   can0   24  [1] 24
70   can0   25  [1] 25
71   can0   26  [1] 26
72   can0   27  [1] 27
73   can0   28  [1] 28
74   can0   29  [1] 29
75   can0   2A  [1] 2A
76   can0   2B  [1] 2B
77   can0   2C  [1] 2C
78   can0   2D  [1] 2D
79   can0   2E  [1] 2E
80   can0   2F  [1] 2F
81   can0   30  [1] 30
82   can0   31  [1] 31
83   can0   32  [1] 32
84   can0   33  [1] 33
85   can0   34  [1] 34
86   can0   35  [1] 35
87   can0   36  [1] 36
88   can0   37  [1] 37
89   can0   38  [1] 38
90   can0   39  [1] 39
91 write: No buffer space available
92
93 $ strace -o cangen.strace -r ./cangen  -g 0 can0 -I 125 -L 1 -D i
94 write: No buffer space available
95
96 $ cat cangen.strace | tail -30
97      0.000082 write(3, "%\1\0\0\1\0\0\0\27\6\0\0\0\0\0\0", 16) = 16
98      0.000091 write(3, "%\1\0\0\1\0\0\0\30\6\0\0\0\0\0\0", 16) = 16
99      0.000082 write(3, "%\1\0\0\1\0\0\0\31\6\0\0\0\0\0\0", 16) = 16
100      0.000082 write(3, "%\1\0\0\1\0\0\0\32\6\0\0\0\0\0\0", 16) = 16
101      0.000081 write(3, "%\1\0\0\1\0\0\0\33\6\0\0\0\0\0\0", 16) = 16
102      0.000082 write(3, "%\1\0\0\1\0\0\0\34\6\0\0\0\0\0\0", 16) = 16
103      0.000081 write(3, "%\1\0\0\1\0\0\0\35\6\0\0\0\0\0\0", 16) = 16
104      0.000082 write(3, "%\1\0\0\1\0\0\0\36\6\0\0\0\0\0\0", 16) = 16
105      0.000050 write(3, "%\1\0\0\1\0\0\0\37\6\0\0\0\0\0\0", 16) = 16
106      0.000082 write(3, "%\1\0\0\1\0\0\0 \6\0\0\0\0\0\0", 16) = 16
107      0.000082 write(3, "%\1\0\0\1\0\0\0!\6\0\0\0\0\0\0", 16) = 16
108      0.000081 write(3, "%\1\0\0\1\0\0\0\"\6\0\0\0\0\0\0", 16) = 16
109      0.000082 write(3, "%\1\0\0\1\0\0\0#\6\0\0\0\0\0\0", 16) = 16
110      0.000082 write(3, "%\1\0\0\1\0\0\0$\6\0\0\0\0\0\0", 16) = 16
111      0.000082 write(3, "%\1\0\0\1\0\0\0%\6\0\0\0\0\0\0", 16) = 16
112      0.000082 write(3, "%\1\0\0\1\0\0\0&\6\0\0\0\0\0\0", 16) = 16
113      0.000081 write(3, "%\1\0\0\1\0\0\0'\6\0\0\0\0\0\0", 16) = 16
114      0.000080 write(3, "%\1\0\0\1\0\0\0(\6\0\0\0\0\0\0", 16) = 16
115      0.000081 write(3, "%\1\0\0\1\0\0\0)\6\0\0\0\0\0\0", 16) = -1 ENOBUFS (No buffer space available)
116      0.000110 dup(2)                    = 4
117      0.000076 fcntl64(4, F_GETFL)       = 0x8002 (flags O_RDWR|O_LARGEFILE)
118      0.000177 brk(0)                    = 0x804e000
119      0.000067 brk(0x806f000)            = 0x806f000
120      0.000092 fstat64(4, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
121      0.000151 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7840000
122      0.000079 _llseek(4, 0, 0xbff26d08, SEEK_CUR) = -1 ESPIPE (Illegal seek)
123      0.000107 write(4, "write: No buffer space available"..., 33) = 33
124      0.000095 close(4)                  = 0
125      0.000066 munmap(0xb7840000, 4096)  = 0
126      0.000100 exit_group(1)             = ?
127
128
129 ################################################################################
130 ##### Cangen with setting of SO_SNDBUF option #####
131 ################################################################################
132
133 $ git diff -U0
134 diff --git a/can-utils/cangen.c b/can-utils/cangen.c
135 index 95dfa46..db3fde2 100644
136 --- a/can-utils/cangen.c
137 +++ b/can-utils/cangen.c
138 @@ -105 +105,3 @@ void print_usage(char *prg)
139 -               "printing sent CAN frames)\n\n");
140 +               "printing sent CAN frames)\n");
141 +       fprintf(stderr, "         -b            (set SO_SNDBUF value of a buffer "
142 +               "-- the kernel doubles this value)\n\n");
143 @@ -144,0 +147 @@ int main(int argc, char **argv)
144 +       int snd_buf = 0;
145 @@ -168 +171 @@ int main(int argc, char **argv)
146 -       while ((opt = getopt(argc, argv, "ig:eI:L:D:xp:n:vh?")) != -1) {
147 +       while ((opt = getopt(argc, argv, "ig:eI:L:D:xp:n:vb:h?")) != -1) {
148 @@ -226,0 +230,4 @@ int main(int argc, char **argv)
149 +               case 'b':
150 +                       snd_buf = atoi(optarg);
151 +                       break;
152 +
153 @@ -301,0 +309,8 @@ int main(int argc, char **argv)
154 +       if (snd_buf > 0)
155 +               setsockopt(s, SOL_SOCKET, SO_SNDBUF, &snd_buf, sizeof(snd_buf));
156 +/*     {
157 +               socklen_t len;
158 +               getsockopt(s, SOL_SOCKET, SO_SNDBUF, &snd_buf, &len);
159 +               printf("SO_SNDBUF: %d\n", snd_buf);
160 +       }
161 +*/
162
163 $ ip link show dev can0
164 3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 50
165     link/can 
166
167 # There is no ENOBUFS error
168 $ ./cangen -b 1024 -g 0 can0 -I 123 -L 1 -D i -v -v | head -10000 | wc -l
169 10000
170
171
172 ################################################################################
173 ##### Throttling of outgoing traffic with TBF #####
174 ################################################################################
175
176 # Default qdisc
177 $ sudo tc qdisc del dev can0 root
178
179 $ strace -o cangen.strace -r ./cangen -b 1024 -g 0 can0 -I 125 -L 1 -D i
180
181 $ cat cangen.strace | tail -30
182      0.000079 write(3, "%\1\0\0\1\0\0\0\276.\0\0\0\0\0\0", 16) = 16
183      0.000079 write(3, "%\1\0\0\1\0\0\0\277.\0\0\0\0\0\0", 16) = 16
184      0.000079 write(3, "%\1\0\0\1\0\0\0\300.\0\0\0\0\0\0", 16) = 16
185      0.000078 write(3, "%\1\0\0\1\0\0\0\301.\0\0\0\0\0\0", 16) = 16
186      0.000078 write(3, "%\1\0\0\1\0\0\0\302.\0\0\0\0\0\0", 16) = 16
187      0.000079 write(3, "%\1\0\0\1\0\0\0\303.\0\0\0\0\0\0", 16) = 16
188      0.000079 write(3, "%\1\0\0\1\0\0\0\304.\0\0\0\0\0\0", 16) = 16
189      0.000077 write(3, "%\1\0\0\1\0\0\0\305.\0\0\0\0\0\0", 16) = 16
190      0.000047 write(3, "%\1\0\0\1\0\0\0\306.\0\0\0\0\0\0", 16) = 16
191      0.000079 write(3, "%\1\0\0\1\0\0\0\307.\0\0\0\0\0\0", 16) = 16
192      0.000079 write(3, "%\1\0\0\1\0\0\0\310.\0\0\0\0\0\0", 16) = 16
193      0.000078 write(3, "%\1\0\0\1\0\0\0\311.\0\0\0\0\0\0", 16) = 16
194      0.000078 write(3, "%\1\0\0\1\0\0\0\312.\0\0\0\0\0\0", 16) = 16
195      0.000341 write(3, "%\1\0\0\1\0\0\0\313.\0\0\0\0\0\0", 16) = 16
196      0.000077 write(3, "%\1\0\0\1\0\0\0\314.\0\0\0\0\0\0", 16) = 16
197      0.000079 write(3, "%\1\0\0\1\0\0\0\315.\0\0\0\0\0\0", 16) = 16
198      0.000078 write(3, "%\1\0\0\1\0\0\0\316.\0\0\0\0\0\0", 16) = 16
199      0.000078 write(3, "%\1\0\0\1\0\0\0\317.\0\0\0\0\0\0", 16) = 16
200      0.000047 write(3, "%\1\0\0\1\0\0\0\320.\0\0\0\0\0\0", 16) = 16
201      0.000080 write(3, "%\1\0\0\1\0\0\0\321.\0\0\0\0\0\0", 16) = 16
202      0.000352 write(3, "%\1\0\0\1\0\0\0\322.\0\0\0\0\0\0", 16) = 16
203      0.000087 write(3, "%\1\0\0\1\0\0\0\323.\0\0\0\0\0\0", 16) = 16
204      0.000080 write(3, "%\1\0\0\1\0\0\0\324.\0\0\0\0\0\0", 16) = 16
205      0.000078 write(3, "%\1\0\0\1\0\0\0\325.\0\0\0\0\0\0", 16) = 16
206      0.000079 write(3, "%\1\0\0\1\0\0\0\326.\0\0\0\0\0\0", 16) = 16
207      0.000078 write(3, "%\1\0\0\1\0\0\0\327.\0\0\0\0\0\0", 16) = 16
208      0.000114 --- SIGINT (Interrupt) @ 0 (0) ---
209      0.000072 sigreturn()               = ? (mask now [])
210      0.000096 close(3)                  = 0
211      0.000102 exit_group(0)             = ?
212
213
214
215
216 # TBF
217 $ sudo tc qdisc add dev can0 root tbf rate 1kbit burst 1kbit latency 50ms
218
219 $ strace -o cangen.strace -r ./cangen -b 1024 -g 0 can0 -I 125 -L 1 -D i
220
221 # Each 5th write blocks for a while
222 $ cat cangen.strace | tail -30
223      0.000048 write(3, "%\1\0\0\1\0\0\0\16\0\0\0\0\0\0\0", 16) = 16
224      0.000047 write(3, "%\1\0\0\1\0\0\0\17\0\0\0\0\0\0\0", 16) = 16
225      0.511054 write(3, "%\1\0\0\1\0\0\0\20\0\0\0\0\0\0\0", 16) = 16
226      0.000081 write(3, "%\1\0\0\1\0\0\0\21\0\0\0\0\0\0\0", 16) = 16
227      0.000047 write(3, "%\1\0\0\1\0\0\0\22\0\0\0\0\0\0\0", 16) = 16
228      0.000048 write(3, "%\1\0\0\1\0\0\0\23\0\0\0\0\0\0\0", 16) = 16
229      0.511835 write(3, "%\1\0\0\1\0\0\0\24\0\0\0\0\0\0\0", 16) = 16
230      0.000104 write(3, "%\1\0\0\1\0\0\0\25\0\0\0\0\0\0\0", 16) = 16
231      0.000050 write(3, "%\1\0\0\1\0\0\0\26\0\0\0\0\0\0\0", 16) = 16
232      0.000047 write(3, "%\1\0\0\1\0\0\0\27\0\0\0\0\0\0\0", 16) = 16
233      0.511787 write(3, "%\1\0\0\1\0\0\0\30\0\0\0\0\0\0\0", 16) = 16
234      0.000078 write(3, "%\1\0\0\1\0\0\0\31\0\0\0\0\0\0\0", 16) = 16
235      0.000049 write(3, "%\1\0\0\1\0\0\0\32\0\0\0\0\0\0\0", 16) = 16
236      0.000048 write(3, "%\1\0\0\1\0\0\0\33\0\0\0\0\0\0\0", 16) = 16
237      0.511823 write(3, "%\1\0\0\1\0\0\0\34\0\0\0\0\0\0\0", 16) = 16
238      0.000080 write(3, "%\1\0\0\1\0\0\0\35\0\0\0\0\0\0\0", 16) = 16
239      0.000048 write(3, "%\1\0\0\1\0\0\0\36\0\0\0\0\0\0\0", 16) = 16
240      0.000049 write(3, "%\1\0\0\1\0\0\0\37\0\0\0\0\0\0\0", 16) = 16
241      0.511859 write(3, "%\1\0\0\1\0\0\0 \0\0\0\0\0\0\0", 16) = 16
242      0.000057 write(3, "%\1\0\0\1\0\0\0!\0\0\0\0\0\0\0", 16) = 16
243      0.000048 write(3, "%\1\0\0\1\0\0\0\"\0\0\0\0\0\0\0", 16) = 16
244      0.000048 write(3, "%\1\0\0\1\0\0\0#\0\0\0\0\0\0\0", 16) = 16
245      0.511819 write(3, "%\1\0\0\1\0\0\0$\0\0\0\0\0\0\0", 16) = 16
246      0.000085 write(3, "%\1\0\0\1\0\0\0%\0\0\0\0\0\0\0", 16) = 16
247      0.000047 write(3, "%\1\0\0\1\0\0\0&\0\0\0\0\0\0\0", 16) = 16
248      0.000048 write(3, "%\1\0\0\1\0\0\0'\0\0\0\0\0\0\0", 16) = 16
249      0.234341 --- SIGINT (Interrupt) @ 0 (0) ---
250      0.000036 sigreturn()               = ? (mask now [])
251      0.000064 close(3)                  = 0
252      0.000069 exit_group(0)             = ?
253
254
255 # Setting socket as O_NONBLOCK
256 # Observing behaviour with throttled outgoing traffic
257
258 $ git diff -U0
259 diff --git a/can-utils/cangen.c b/can-utils/cangen.c
260 index 69b6323..0295f75 100644
261 --- a/can-utils/cangen.c
262 +++ b/can-utils/cangen.c
263 @@ -58,0 +59 @@
264 +#include <fcntl.h>
265 @@ -311,0 +313,2 @@ int main(int argc, char **argv)
266 +       fcntl(s, F_SETFL, O_NONBLOCK);
267 +
268
269 $ strace -o cangen.strace -r ./cangen -b 1024 -g 0 can0 -I 125 -L 1 -D i
270 write: Resource temporarily unavailable
271
272 $ cat cangen.strace | tail -30
273      0.000043 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [1024], 4) = 0
274      0.000043 fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
275      0.000042 bind(3, {sa_family=0x1d /* AF_??? */, sa_data="\0\0\3\0\0\0\1\0\0\0\3708z\267"}, 16) = 0
276      0.000058 write(3, "%\1\0\0\1\0\0\0\0\0\0\0\0\0\0\0", 16) = 16
277      0.000065 write(3, "%\1\0\0\1\0\0\0\1\0\0\0\0\0\0\0", 16) = 16
278      0.000092 write(3, "%\1\0\0\1\0\0\0\2\0\0\0\0\0\0\0", 16) = 16
279      0.000083 write(3, "%\1\0\0\1\0\0\0\3\0\0\0\0\0\0\0", 16) = 16
280      0.000082 write(3, "%\1\0\0\1\0\0\0\4\0\0\0\0\0\0\0", 16) = 16
281      0.000082 write(3, "%\1\0\0\1\0\0\0\5\0\0\0\0\0\0\0", 16) = 16
282      0.000081 write(3, "%\1\0\0\1\0\0\0\6\0\0\0\0\0\0\0", 16) = 16
283      0.000081 write(3, "%\1\0\0\1\0\0\0\7\0\0\0\0\0\0\0", 16) = 16
284      0.000081 write(3, "%\1\0\0\1\0\0\0\10\0\0\0\0\0\0\0", 16) = 16
285      0.000079 write(3, "%\1\0\0\1\0\0\0\t\0\0\0\0\0\0\0", 16) = 16
286      0.000050 write(3, "%\1\0\0\1\0\0\0\n\0\0\0\0\0\0\0", 16) = 16
287      0.000047 write(3, "%\1\0\0\1\0\0\0\v\0\0\0\0\0\0\0", 16) = 16
288      0.000048 write(3, "%\1\0\0\1\0\0\0\f\0\0\0\0\0\0\0", 16) = 16
289      0.000047 write(3, "%\1\0\0\1\0\0\0\r\0\0\0\0\0\0\0", 16) = 16
290      0.000047 write(3, "%\1\0\0\1\0\0\0\16\0\0\0\0\0\0\0", 16) = 16
291      0.000048 write(3, "%\1\0\0\1\0\0\0\17\0\0\0\0\0\0\0", 16) = -1 EAGAIN (Resource temporarily unavailable)
292      0.000064 dup(2)                    = 4
293      0.000040 fcntl64(4, F_GETFL)       = 0x8002 (flags O_RDWR|O_LARGEFILE)
294      0.000101 brk(0)                    = 0x804e000
295      0.000035 brk(0x806f000)            = 0x806f000
296      0.000059 fstat64(4, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
297      0.000079 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7784000
298      0.000047 _llseek(4, 0, 0xbfbb37f8, SEEK_CUR) = -1 ESPIPE (Illegal seek)
299      0.000079 write(4, "write: Resource temporarily unav"..., 40) = 40
300      0.000059 close(4)                  = 0
301      0.000036 munmap(0xb7784000, 4096)  = 0
302      0.000061 exit_group(1)             = ?
303
304