-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfaq.tex
More file actions
493 lines (390 loc) · 15.4 KB
/
faq.tex
File metadata and controls
493 lines (390 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{positioning,calc,decorations.pathreplacing,shapes,fit}
\usepackage{colortbl}
\usepackage{booktabs}
\usepackage{url}
\usepackage{hyperref}
\usepackage{pifont}
\newcommand{\cmark}{\ding{51}}%
\newcommand{\xmark}{\ding{55}}%
\usepackage{array, adjustbox,url}
\usepackage{pifont,marvosym} % wasysym
\usepackage{rotating,subfig}
\usepackage{xspace}
\usepackage{tikz}
\usetikzlibrary{positioning,calc,decorations.pathreplacing,shapes}
\title{GLab: Frequenty Asked Questions}
\author{Christian Grothoff, Hansjürg Wenger}
\date{\today}
\begin{document}
\maketitle
\section{C Programming}
\subsection{How do I print a MAC address?}
Use something like this:
\begin{verbatim}
static void
print_mac (const struct MacAddress *mac)
{
print ("%02X:%02X:%02X:%02X:%02X:%02X\n
mac->mac[0], mac->mac[1],
mac->mac[2], mac->mac[3],
mac->mac[4], mac->mac[5]);
}
\end{verbatim}
\subsection{How do I compare two MAC addresses?}
Use something like this:
\begin{verbatim}
static int
maccmp (const struct MacAddress *mac1,
const struct MacAddress *mac2)
{
return memcmp (mac1, mac2, sizeof (struct MacAddress));
}
\end{verbatim}
\subsection{How do I print an IPv4 address?}
Use something like this:
\begin{verbatim}
#include <arpa/inet.h>
static void
print_ip (const struct in_addr *ip)
{
char buf[INET_ADDRSTRLEN];
print ("%s\n
inet_ntop (AF_INET,
ip,
buf,
sizeof (buf)));
}
\end{verbatim}
\subsection{How do pointers work again?}
Consider this code:
\begin{verbatim}
int i = 5;
int *j = &i;
int k = *j;
\end{verbatim}
$i$ is an integer. When you write just $i$, you will get the value
$5$. $i$ is stored in computer memory. When you write $\&i$, you get
the address where $i$ is stored in memory. $j$ is a pointer to
an integer. So the value of $j$ is an address in memory where we
expect to find an integer. If we want to read the integer at that
address, we write $*j$ to dereference the address $j$.
\subsection{How do arrays work again?}
Arrays in C are represented as pointers to the first element of the
array.
Consider this code:
\begin{verbatim}
int i[] = { 5 , 6 };
int *j = i;
i[0] + j[1]; // 11
\end{verbatim}
Here $i$ is declared as an array with two values, 5 and 6. $j$ is,
like $i$, a pointer. You can treat pointers like arrays and vice-versa.
The only difference is that {\tt sizeof(i)} will give you the size of
the array as the C compiler knows how large the array is in memory, while
{\tt sizeof(j)} will give you the size of (any) pointer.
The following code generates exactly the same situation as the fragment
above:
\begin{verbatim}
int i[2];
int *j = i;
*i = 5;
*(j+1) = 6;
\end{verbatim}
\subsection{How do I get a pointer to the IPv4 header?}
A slightly unclean\footnote{due to unaligned pointer access}
minimalistic solution that works fine on your CPUs would look like
this:
\begin{verbatim}
static void
handle_frame (uint16_t interface,
const void *frame,
size_t frame_size)
{
struct EthernetHeader *eh = frame;
struct IPv4Header *ip = (struct IPv4Header *) &frame[1];
if (frame_size < sizeof (struct EthernetHeader) +
sizeof (struct IPv4Header))
fail ();
// use(ip); here!
}
\end{verbatim}
\subsection{Why does my {\tt printf} not work?}
{\tt printf} prints to {\tt stdout}, which in your setup is the
network-driver which expects to receive frames to be transmitted.
To output to the console, you need to give a special command to
the network-driver. This is provided by the {\tt print()} function,
which thus replaces {\tt printf} for your project. You can
also directly use {\tt fprintf (stderr, ...)} to write to {\tt stderr}
for logging. Note that required output to the user (for grading) must
be generated using {\tt print}.
\subsection{I am using {\tt print}, and it still does not work!}
You might be having a problem with terminal discipline. {\tt print}ing
to {\tt stdout} is by default buffered until a newline is encountered.
Make sure to terminate your output with ``\\n''.
\newpage
\section{Setup}
\subsection{Why do I get ``permission denied'' when running the network-driver, even as root?}
The latest version of the Ubuntu operating system refuses
to grant RAW socket access to binaries that are in the {\tt /home}
directory, even if run by {\tt root}. Copying the binary to
{\tt /root} or {/tt /usr/sbin} makes it work:
\begin{verbatim}
# cp network-driver /usr/sbin/network-driver
# /usr/sbin/network-driver eth0 - ./parser
\end{verbatim}
\subsection{What should my network topology look like?}
Figure~\ref{fig:setup} shows the suggested setup. If you are a team
of three students, you may want to connect a third notebook. If you
are using the Banana PI, you must use Ethernet USB adapters instead of
the Ethernet ports of the PI for the connections to the notebooks for
the {\tt hub}. {\tt switch} and {\tt vswitch} programs.
\begin{figure}[h!]
\centering
\colorlet{FGcolor}{green}
\colorlet{FG100P}{FGcolor!100}
\colorlet{FG90P}{FGcolor!90}
\colorlet{FG80P}{FGcolor!80}
\colorlet{FG70P}{FGcolor!70}
\colorlet{FG60P}{FGcolor!60}
\colorlet{FG50P}{FGcolor!50}
\colorlet{FG40P}{FGcolor!40}
\colorlet{FG30P}{FGcolor!30}
\colorlet{FG20P}{FGcolor!20}
\colorlet{FG10P}{FGcolor!10}
\colorlet{FG00P}{FGcolor!00}
% Use RGB: TUMBlue, TUMDarkBlue, TUMDarkerBlue
\definecolor{color_bg}{rgb}{0,0,1}
\tikzstyle{bg_fill_10} = [fill=FG10P]
\tikzstyle{bg_fill_20} = [fill=FG20P]
\tikzstyle{bg_fill_30} = [fill=FG30P]
\tikzstyle{bg_fill_40} = [fill=FG40P]
\tikzstyle{bg_fill_50} = [fill=FG50P]
\tikzstyle{bg_fill_60} = [fill=FG60P]
\tikzstyle{bg_fill_70} = [fill=FG70P]
\tikzstyle{bg_fill_80} = [fill=FG80P]
\tikzstyle{bg_fill_90} = [fill=FG90P]
\tikzstyle{bg_fill_100} = [fill=FG100P]
% Define Sizes
\newcommand\defaultpicheight{2em}
\newcommand\defaultpicheightsmall{1em}
\newcommand\defaultblockheight{1.5em}
\newcommand\defaultblockwidth{5cm}
\newcommand\defaultblockdistance{0.25em}
\newcommand\defaultinterblockdistance{9em}
\newcommand\dibd{\defaultinterblockdistance}
\newcommand\dbh{\defaultblockheight}
\newcommand\blocksizedecrease{0.95}
\newcommand\blocksizeincrease{1.05}
\newcommand*\circled[1]{\tikz[baseline=(char.base)]{
\node[shape=circle,minimum width = 2em, draw,inner sep=2pt] (char) {#1};}}
% Define Blocks
\tikzstyle{my_block_width} = [minimum width=\defaultblockwidth]
\tikzstyle{my_block_height} = [minimum height=\defaultblockheight]
% Cliparts
%\pgfdeclareimage[height=\defaultpicheight]{webserver}{cliparts/webserver}
%\pgfdeclareimage[height=\defaultpicheight]{house}{cliparts/house}
%\pgfdeclareimage[height=\defaultpicheight]{router}{cliparts/router}
%\pgfdeclareimage[height=\defaultpicheight]{femaleuser}{cliparts/femaleuser}
%\pgfdeclareimage[height=\defaultpicheight]{maleuser}{cliparts/maleuser}
%\pgfdeclareimage[height=\defaultpicheight]{globe}{cliparts/globe}
%\pgfdeclareimage[height=\defaultpicheight]{document}{cliparts/document}
%\pgfdeclareimage[height=\defaultpicheightsmall]{documentsmall}{cliparts/document}
%\pgfdeclareimage[height=\defaultpicheight]{certificate}{cliparts/certificate}
% Block style
\tikzstyle{my_block} = [draw, rectangle, align=center, semithick, rounded corners,
my_block_height, my_block_width]
\tikzstyle{my_dashed_block} = [draw, rectangle, align=center, semithick, dashed, rounded corners,
my_block_height, my_block_width]
\tikzstyle{my_inv_block} = [draw, rectangle, align=center, draw=none,
my_block_height, my_block_width]
\tikzstyle{my_text_block} = [draw, rectangle, align=center, draw=none]
\begin{tikzpicture}[auto, node distance=5cm,>=latex]
\node [my_block, bg_fill_20,
minimum width = \defaultblockwidth,
minimum height = 3 * \defaultblockheight]
(pi){4x USB-Adapter (or Banana Pi)};
\node [my_block, bg_fill_20,
above of = pi,
minimum width = \defaultblockwidth,
minimum height = 3 * \defaultblockheight]
(desktop){Desktop};
\node [my_block, bg_fill_20,
below left of = pi,
minimum width = \defaultblockwidth,
minimum height = 3 * \defaultblockheight]
(notebook1){Notebook};
\node [my_block, bg_fill_20,
below right of = pi,
minimum width = \defaultblockwidth,
minimum height = 3 * \defaultblockheight]
(notebook2){Notebook};
\draw[<->] (pi) -- (desktop) node[midway,above,sloped] {Control (USB)};
\draw[<->] (pi) -- (notebook1) node[midway,above,sloped] {Ethernet};
\draw[<->] (pi) -- (notebook2) node[midway,above,sloped] {Ethernet};
\end{tikzpicture}
\caption{Suggested network topology.}
\label{fig:setup}
\end{figure}
\subsection{My (new) code does not seem to work at all. I've been ignoring the {\em clock skew} warning from {\tt make}. What is going on?}
The PI does not have a real-time clock. Thus, after a reboot, it can
find itself in the past. Your latest edits receive time stamps that
pre-date the binaries it created in the past before its time travels.
Make builds programs using timestamps. Thus, {\tt make} did NOT rebuild
your code, but it figured something might be fishy because your binaries
are from the future. As your binary is your old binary, your new features
do not work at all.
{\bf Solution:} If you ever get a {\em clock skew} warning, run {\tt
make clean} to delete all old binaries.
\subsection{When running {\tt vconfig add}, I get ``File exists''}
The problem is the maximum length of an interface name ({\tt IFNAMSIZ}).
For current kernels, that length is 16 (effectively 15 plus 0-termination).
As network adapters might get names like "enx3c18a0074ae7", the resulting VLAN
names are truncated to 15 characters. The result then looks like this:
\begin{verbatim}
# vconfig set_name_type DEV_PLUS_VID_NO_PAD
Set name-type for VLAN subsystem. Should be visible in /proc/net/vlan/config
# vconfig add enx3c18a0074ae7 5
ERROR: trying to add VLAN #5 to IF -:enx3c18a0074ae7:- error: File exists
\end{verbatim}
What works is using a different style of naming for VLAN interfaces:
\begin{verbatim}
# vconfig set_name_type VLAN_PLUS_VID_NO_PAD
Set name-type for VLAN subsystem. Should be visible in /proc/net/vlan/config
# vconfig add enx3c18a0074ae7 5
Added VLAN with VID == 5 to IF -:enx3c18a0074ae7:-
# ip link show vlan5
13: vlan5@enx3c18a0074ae7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 3c:18:a0:07:4a:e7 brd ff:ff:ff:ff:ff:ff
\end{verbatim}
Alternatively, one can also use the command:
\begin{verbatim}
# ip link add link enx3c18a0074ae7 name vlan5 type vlan id 5
\end{verbatim}
\subsection{My notebook cannot ping the desktop}
This is normal, as your switch/router logic does not forward the
traffic to the desktop's host operating system. Your notebooks can
only reach systems that {\em your} hub, switch or router allows them
to reach.
\subsection{How do I debug my code {\em without} {\tt fprintf()}?}
First, make sure you compiled your code with debug symbols and
without optimizations ({\tt gcc -g -O0}). Then, launch your program as usual:
\begin{verbatim}
# ./network-driver IFCs - prog ARGs
\end{verbatim}
Then, in another shell, check with {\tt ps} which PID your ``prog'' process has:
\begin{verbatim}
# ps ax | grep prog
\end{verbatim}
Now you can attach {\tt gdb} to your running program (substitute \$PID for the PID you got from {\tt ps}):
\begin{verbatim}
# gdb prog
(gdb) attach $PID
\end{verbatim}
You should now set a breakpoint at a location where you want to start debugging,
and then continue execution until the breakpoint is reached:
\begin{verbatim}
(gdb) break handle_frame
(gdb) continue
\end{verbatim}
Then, use ``CTRL-x a'' to enable GDB's code inspection mode to see where you are
executing. Use ``n(ext)'' to execute the next statement. Use ``s(tep)'' to step
into a function call. Use ``print'' or ``x'' (eXamine) to inspect variables and
memory. Use ``cont(inue)'' to run until the next breakpoint. Use ``q(uit)'' to
exit {\tt gdb}. Note that your process will continue.
Final note: this only works if your program does not crash before you can attach
{\tt gdb}. Enable core dumps and inspect the crash with gdb if your program
crashes:
\begin{verbatim}
# ulimit -c 999999
# echo core > /proc/sys/kernel/core_pattern
# ./network-driver ... # reproduce crash
# gdb prog core
(gdb) bt full # view stack trace at time of crash
\end{verbatim}
Read the {\tt gdb} manual for more information on how to use the GNU Debugger!
\subsection{How does grading work?}
You get points for each of the programs:
\begin{center}
\begin{tabular}{l|r}
parser & 0 \\ \hline
hub & 4 \\ \hline
switch & 8 \\ \hline
vswitch& 18 \\ \hline
arp & 12 \\ \hline
router & 18 \\ \hline \hline
total & 60 \\
\end{tabular}
\end{center}
The tests evaluate which features you have correctly implemented.
Parial points are awarded.
\section{Banana PI}
These questions only apply if you use the Banana PI setup of the lab,
which for now is not recommended.
\subsection{How can I connect the PI to the Internet?}
First, you need to configure your desktop as a router:
\begin{verbatim}
# echo 1 > /proc/sys/net/ipv4/ip_forward
# modprobe ip_tables
# /sbin/iptables -t nat -A POSTROUTING -o ethX -j MASQUERADE
\end{verbatim}
Replace $ethX$ with the name of your external network interface
(the one connected to the Internet, often eth2). Finally, you
must tell your PI to use your desktop as its default route:
\begin{verbatim}
# route add default gw 192.168.0.1
\end{verbatim}
\subsection{I get not network traffic on the PI. Why?}
The most common cause is that you did not enable the network adapter,
so the interface is still physically down. For each network interface,
run:
\begin{verbatim}
# ip link set up dev INTERFACENAME
\end{verbatim}
You can check that it worked using:
\begin{verbatim}
# ip link list
\end{verbatim}
If you still see a ``DOWN'' in the line, check the cable.
\end{document}
% Legacy issues, should be resolved.
\subsection{I can't compile the ''network-driver'' on a (lab) PC}
When I try to compile the ''network-driver'' on a lab PC booted from the USB-Stick (Ubuntu 16.04.5 LTS) I get the following error:
\begin{verbatim}
/usr/include/linux/llc.h:26:27: error: ‘IFHWADDRLEN’ undeclared here (not in a function)
\end{verbatim}
Add the line
\begin{verbatim}
#include <linux/if.h>
\end{verbatim}
after the line
\begin{verbatim}
#include <linux/socket.h>
\end{verbatim}
of the file ''/usr/include/linux/llc.h''
\subsection{When running the network-driver with the hub it terminates with ''write-error to tun: Message too long''}
The problem occures because the ethernet card/driver uses ''generic receive offload'' (gro). You have to disable ''gro'' on all interfaces handled by the ''network-driver'' (not only for use with the hub).\newline
To disable ''gro'' on e.g. {\tt eth0} use (as root):
\begin{verbatim}
# ethtool -K eth0 gro off
\end{verbatim}
To display the actual settings use:
\begin{verbatim}
# ethtool -k eth0
\end{verbatim}
To reenable ''gro'' use (as root):
\begin{verbatim}
# ethtool -K eth0 gro on
\end{verbatim}
Eventualy you must also disable ''generic segmentation offload'' (gso).\newline
Details about ''gro'' and ''gso'' see:
\begin{itemize}
\item Wikipedia about
\href{https://en.wikipedia.org/wiki/Large_receive_offload}
{''Large Receive Offload''}\newline
\url{https://en.wikipedia.org/wiki/Large_receive_offload}
\item LWN article \href{https://lwn.net/Articles/358910/}{''JLS2009: Generic receive offload''}\newline
\url{https://lwn.net/Articles/358910/}
\end{itemize}