Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1676 tullio 1
%----------------------------------------------------------------------------
2
\chapter{The Network Library}
3
%----------------------------------------------------------------------------
4
 
5
To allow communication among different computers, S.Ha.R.K. provides a Network
6
Library implementing the UDP/IP stack on an Ethernet network. The library is
7
organized in three layers:
8
 
9
\begin{itemize}
10
\item low-level driver: this layer is hardware dependent, since it interacts
11
with the network card;
12
\item ethernet layer: this layer allows the upper layer to send and receive
13
ethernet frames. It is not intended to be used by a user program, but only by
14
the code implementing the network protocol;
15
\item high-level layer: this layer implements the network (IP) and the transport
16
(UDP) protocols. It provides the interface used by a user program to access the
17
network through the UDP protocol.
18
\end{itemize}
19
 
20
The low-level driver is implemented in order to respect the system real-time
21
requirements (avoiding unpredictable delays in sending/receiving frames). This
22
result is achieved by solving two different problems: the interrupt handling (in
23
the receive phase) and the mutual exclusion needed for accessing the network
24
card (in the transmission phase). The first problem is solved by using a SOFT
25
task to handle the network card interrupts: on a frame arrival, a task handling
26
the reception is activated. Such a task is guaranteed along with all the other
27
tasks in the system, thus it cannot jeopardize their schedulability. Since a
28
minimum interarrival time for the frames cannot be predicted, the receiving task
29
cannot be a sporadic (HARD) task; therefore the task uses a SOFT\_TASK\_MODEL,
30
and we have used a Constant Bandwidth Server (CBS) to serve it.
31
 
32
The second problem can be solved using two different methods. The first method
33
adopts a shared memory programming paradigm: a task willing to transmit is
34
allowed to access the network card; mutually exclusive accesses are guaranteed
35
by semaphores. This solution is very simple and the introduced overhead is very
36
low. The second soultion is based on the utilization of a server task devoted to
37
send frames on the network on behalf of other tasks. Each task posts its frames
38
in a mailbox, whence the sender task picks them up. At the moment, only the
39
first solution is implemented, but in order to provide a good degree of
40
flexibility, both approaches will be supported as soon as possible.
41
 
42
The most diffused higher level protocols have been implemented upon the ethernet
43
level. In order to use them within a S.Ha.R.K. application, the
44
\texttt{drivers/udpip.h} file, containing the functions prototypes and the data
45
structures, has to be included in the application program. As a first step, the
46
network drivers have to be initialized. This is done by the \texttt{net\_init()}
47
primitive that requires the machine's IP address. After initialization, the
48
program has to bind itself to a port by a socket (in UNIX's fashion) by the
49
\texttt{udp\_bind()} primitive. Afterwards, it is possible eihter to receive
50
packets by using \texttt{udp\_recvfrom()}, or to send them by using
51
\texttt{udp\_sendto()}.
52
 
53
\vspace{10mm}
54
 
55
\begin{intest}
56
NET\_INIT\index{net\_init()}
57
\end{intest}
58
 
59
\begin{description}
60
\item [\textbf{void net\_init(NET\_MODEL {*}m)}]
61
\item [\textbf{Description:}] It is an interface function used for calling the different
62
layers initializing functions. The \texttt{m} parameter specifies the protocols
63
that are going to be activated along with the parameters to be passed to their
64
initializing fucntions. The predefined \texttt{net\_base} value, if used as
65
\texttt{net\_init} parameter, causes the ethernet level to be solely intialized
66
by using a mutex semaphore for enforcing mutual exclusion. Moreover, the
67
\texttt{net\_setudpip(m, addr)} macro is defined to select the UDP/IP protocols
68
stack with local IP address \texttt{addr}, expressed in string format. The task
69
used to handle network card interrupts has a SOFT\_TASK\_MODEL obtained
70
initializing such a model with these arguments: \\
71
\texttt{soft\_task\_default\_model(m);} \\
72
\texttt{soft\_task\_def\_wcet(m, 1000);} \\
73
\texttt{soft\_task\_def\_period(m,20000);} \\
74
\texttt{soft\_task\_def\_met(m, 1000);} \\
75
\texttt{soft\_task\_def\_aperiodic(m);} \\
76
\texttt{soft\_task\_def\_system(m);} \\
77
\texttt{soft\_task\_def\_nokill(m);}
78
\end{description}
79
 
80
\begin{description}
81
\item [Example:]
82
\end{description}
83
 
84
\begin{tt}
85
\begin{verbatim}
86
int main(int argc, char **argvvoid) {
87
    NET_MODEL m = net_base;
88
    char talk_myipaddr[50];
89
    ...
90
    strcpy(talk_myipaddr, "193.205.82.47");
91
    net_setudpip(m, talk_myipaddr);
92
    net_init(&m);
93
    ...
94
\end{verbatim}
95
\end{tt}
96
 
97
\begin{intest}
98
IP\_STR2ADDR\index{ip\_str2addr()}
99
\end{intest}
100
 
101
\begin{description}
102
\item [\textbf{int ip\_srt2addr(char {*}str, IP\_ADDR {*}ip)}]
103
\item [\textbf{Description:}] It converts the IP address, contained in the \texttt{str}
104
string parameter, into \texttt{IP\_ADDR} format. The result is returned in the
105
variable pointed by \texttt{ip}. The function returns \texttt{TRUE} if the
106
operation has been succesful, \texttt{FALSE} otherwise.
107
\end{description}
108
 
109
\begin{intest}
110
UDP\_BIND\index{udp\_bind()}
111
\end{intest}
112
 
113
\begin{description}
114
\item [\textbf{int udp\_bind(UDP\_ADDR {*}a, IP\_ADDR {*}bindlist);}]
115
\item [\textbf{Description:}] It binds the receiving program on the specified UDP port. A
116
socket is created and its identifier is returned. Moreover the host addresses
117
specified through the \texttt{bindlist} parameter are loaded into the ARP table.
118
The port is identified by the \texttt{a} parameter which is composed of the
119
fields named \texttt{s\_addr}, having \texttt{IP\_ADDR} type, and
120
\texttt{s\_port}, having \texttt{WORD} type. The \texttt{s\_port} parameter is
121
the most meaningful since it specifies the port the function binds to. Further
122
details can be found in any UNIX manual. The possibility of specifying the hosts
123
that will be accessed (through the \texttt{bindlist} parameter), permits to add
124
ARP table entries in the network initialization phase. In this way, the timing
125
impredictability introduced by ARP can be reduced. This possibility can be
126
discarded by chosing a \texttt{NULL} value for the \texttt{bindlist} parameter.
127
Otherwise such a parameter has to be a pointer to a \texttt{NULL} terminated
128
\texttt{IP\_ADDR} array. As we said earlier, the returned socket identifier can
129
be fed into the \texttt{udp\_sendto()} primitive.
130
\end{description}
131
 
132
\begin{description}
133
\item [Example:]
134
\end{description}
135
 
136
\begin{tt}
137
\begin{verbatim}
138
void *txsessiontask(void *arg) {
139
    UDP_ADDR local;
140
    IP_ADDR bl[5];
141
    int sock;
142
 
143
    /* The periodic txsessiontask, upon its creation, */
144
    /* creates a socket befor entering */
145
    /* the infinite cycle typical of all */
146
    /* periodic tasks */
147
    local.s_port = 1030; /* local port */
148
 
149
    /* It loads the eth address of the hosts */
150
    /* the task will communicate with */
151
    /* into the ARP table */
152
    ip_str2addr("193.205.82.47", bl);
153
 
154
    /* terminates bind list by NULL */
155
    *((DWORD *)&bl[1]) = NULL;
156
    sock = udp_bind(&local, bl);
157
    ...
158
}
159
\end{verbatim}
160
\end{tt}
161
 
162
\begin{intest}
163
UDP\_SENDTO\index{udp\_sendto()}
164
\end{intest}
165
 
166
\begin{description}
167
\item [\textbf{int udp\_sendto(int s, char {*}buf, int nbytes, UDP\_ADDR {*}to);}]
168
\item [\textbf{Description:}] It sends an UDP packet, with size \texttt{nbytes}, whose
169
body is pointed by \texttt{buf} to an address specified by \texttt{to}. The last
170
parameter has \texttt{UDP\_ADDR} type and identifier either the destination IP
171
address or the port (see \texttt{udp\_bind} for further information on
172
\texttt{UDP\_ADDR}). In order to send a packet a local socket has to be created,
173
by calling the \texttt{udp\_bind()} primitive; its identifier shall be passed by
174
the \texttt{s} parameter.
175
\end{description}
176
 
177
\begin{description}
178
\item [Example:]
179
\end{description}
180
 
181
\begin{tt}
182
\begin{verbatim}
183
void *txsessiontask(void *arg) {
184
    int sock;
185
    UDP_ADDR local, to;
186
    ...
187
    /* socket creation */
188
    ...
189
 
190
    for (;;) {
191
        ...
192
 
193
        /* prepares the destination address */
194
        to.s_port = 1030;
195
        ip_str2Addr("127.0.0.1", &(to.s_addr));
196
        udp_sendto(sock, msg, msglen, &to);
197
        ...
198
        task_endcycle();
199
    }
200
}
201
\end{verbatim}
202
\end{tt}
203
 
204
\begin{intest}
205
UDP\_RECVFROM\index{udp\_recvfrom()}
206
\end{intest}
207
 
208
\begin{description}
209
\item [\textbf{int udp\_recvfrom(int s, char {*}buf, UDP\_ADDR {*}from);}]
210
\item [\textbf{Description:}] It receives a UDP packet from the socket identified by
211
\texttt{s}; the packet body is copied into the buffer pointed by \texttt{buf};
212
the sender address (composed of the pair port-IPaddress) is copied into the
213
variable pointed by \texttt{from}. The primitive returns the number of bytes
214
composing the packet.
215
\end{description}
216
 
217
\begin{description}
218
\item [Example:]
219
\end{description}
220
 
221
\begin{tt}
222
\begin{verbatim}
223
TASK rxsessiontask() {
224
    int sock;
225
    UDP_ADDR local, from;
226
 
227
    /* The non real-time rxsessiontask */
228
    /* creates a receiving socket and */
229
    /* enters an infinite loop waiting */
230
    /* for the incoming packets */
231
    ...
232
    /* During initialization the */
233
    /* socket is created */
234
    ...
235
    for (;;) {
236
        ...
237
        udp_recvfrom(sock, inmsg, &from);
238
        /* from contains the sender address */
239
        ...
240
        task_endcycle();
241
    }
242
}
243
\end{verbatim}
244
\end{tt}
245
 
246
\begin{intest}
247
UDP\_NOTIFY\index{udp\_notify()}
248
\end{intest}
249
 
250
\begin{description}
251
\item [\textbf{int udp\_notify(int s, int({*}f)(int len, BYTE {*}buf, void {*}p))}]
252
\item [Desription:]the notifying function \texttt{f} is associated with the
253
\texttt{s} socket. When a packet addressed to the port the socket is bound to
254
arrives, such a function is invoked. Upon its invocation, the function receives
255
as arguments a pointer to the received packet (\texttt{buf}), the packet size
256
(\texttt{len}), and a pointer specified along with the \texttt{udp\_notify()}
257
call (\texttt{p}). The notifying function is executed within the context of the
258
receiving task; therefore, it should not consume too much time.
259
\end{description}
260
 
261
\begin{description}
262
\item [Example:]
263
\end{description}
264
 
265
\begin{tt}
266
\begin{verbatim}
267
int hrtp_recvfun(int len, BYTE *b, void *p) {
268
    struct HRTP_SESSION *s;
269
    struct HRTP_HDR *h;
270
    ...
271
 
272
    /* Notifying function used for receiving */
273
    /* packets from a session level protocol */
274
    ...
275
    /* p is a pointer to the descriptor of */
276
    /* the session involved in the transmission */
277
    s = p;
278
 
279
    /* the received packet is copied into a private */
280
    /* buffer belonging to the session */
281
    h = (struct HRTP_HDR *) & (s->b[s->recvd * instance_dim]);
282
    memcpy(h, b, len);
283
    ...
284
 
285
    return 0;
286
}
287
...
288
 
289
void hrtp_recv(struct HRTP_SESSION *s, void (*f)(void)) {
290
    udp_notify(s->sock, hrtp_recvfun, (void *)s);
291
    s->notifyparm = f;
292
    s->active = HRTP_RCVIN;
293
}
294
...
295
\end{verbatim}
296
\end{tt}
297
 
298
A programmer that wants to implement a new transport/network level stack
299
different from UDP/IP needs to directly access the Ethernet services. This can
300
be done using the Ethernet layer, accessible through the ``eth.h'' header
301
file.
302
 
303
In order to receive Ethernet frames, a callback function has to be associated to
304
a frame type (the frame type is a field of a frame): each time that a frame of
305
the specified type will arrive, the callback function will be called. A callback
306
can be bound to a frame type using the \texttt{eth\_setHeader} library call.
307
 
308
In order to transmit Ethernet frames, a transmission buffer must be allocated
309
and filled: the header can be filled using \texttt{eth\_setHeader()}, while the
310
body must be explicitly filled after obtaining a pointer to it through
311
\texttt{eth\_getFDB()}. At this point the frame can be sent using
312
\texttt{eth\_sendPKT()}. Transmission buffers can be allocated using the
313
\texttt{netbuff} module: this module (usable including the ``netbuff.h''
314
header file) permits to manage pools of pre-allocated buffers, in order to
315
minimize the unpredictability due to dynamic allocation.
316
 
317
\begin{intest}
318
NETBUFF\_INIT\index{netbuff\_init()}
319
\end{intest}
320
 
321
\begin{description}
322
\item [\textbf{void netbuff\_init(NETBUFF {*}netb, BYTE nbuffs, WORD buffdim);}]
323
\item [\textbf{Description:}] It initializes a pool composed of \texttt{nbuffs} buffers,
324
each of them have \texttt{buffdim} size. The pool is identified by the
325
\texttt{netb} descriptor.
326
\end{description}
327
 
328
\begin{intest}
329
NETBUFF\_GET\index{netbuff\_get()}
330
\end{intest}
331
 
332
\begin{description}
333
\item [\textbf{void {*}netbuff\_get(NETBUFF {*}netb, BYTE flag);}]
334
\item [\textbf{Description:}] It returns a pointer to the first free buffer in the pool
335
identified by \texttt{netb}. The \texttt{flag} parameter, which can assume
336
values \texttt{BLOCK} or \texttt{NON\_BLOCK}, indicates whether the operation is
337
a blocking or non-blocking allocation. If a non-blocking \texttt{netbuff\_get()}
338
is performed when the pool does not contain any free buffer, a NULL pointer is
339
returned.
340
\end{description}
341
 
342
\begin{intest}
343
NETBUFF\_RELEASE\index{netbuff\_release()}
344
\end{intest}
345
 
346
\begin{description}
347
\item [\textbf{void netbuff\_release(NETBUFF {*}netb, void {*}buff);}]
348
\item [\textbf{Description:}] It marks the buffer pointed by \texttt{buff} as free in the
349
\texttt{netb} pool.
350
\end{description}
351
 
352
\begin{intest}
353
ETH\_INIT\index{eth\_init()}
354
\end{intest}
355
 
356
\begin{description}
357
\item [\textbf{void eth\_init(int mode, TASK\_MODEL {*}m);}]
358
\item [\textbf{Description:}] It initializes the Ethernet layer, in order to transmit or
359
receive ethernet frames. If the Ethernet layer has already been initialized, it
360
does nothing.
361
 
362
Each network level protocol that needs to access the network card must pass
363
through the Ethernet layer, which must be initialized before receiving or
364
sending anything. The Ethernet layer will search for a supported network card,
365
enable it and initalize some internal structures.
366
 
367
At the moment, the \texttt{mode} parameter is not used, in the future it will be
368
used to select an operating mode (mutual exclusion on send operation through a
369
dedicated server task or through mutexes).
370
 
371
This library function is called by \texttt{net\_init()} in the standard UDP/IP
372
configuration.
373
 
374
The task model used for the task that handles the network card interrupts can be
375
passed with the m parameter. If it is NULL, a SOFT\_TASK\_MODEL obtained
376
initializing such a model with these arguments will be used: \\
377
\texttt{soft\_task\_default\_model(m);}\\
378
\texttt{soft\_task\_def\_wcet(m,1000);}\\
379
\texttt{soft\_task\_def\_period(m,20000);}\\
380
\texttt{soft\_task\_def\_met(m,1000);}\\
381
\texttt{soft\_task\_def\_aperiodic(m);}\\
382
\texttt{soft\_task\_def\_system(m);}\\
383
\texttt{soft\_task\_def\_nokill(m);}
384
\end{description}
385
 
386
\begin{intest}
387
HTONS \& NTOHS \index{htons()}\index{ntohs()}
388
\end{intest}
389
 
390
\begin{description}
391
\item [\textbf{WORD htons(WORD host);}]
392
\item [\textbf{WORD ntohs(WORD net);}]
393
\item [\textbf{Description:}] These two utility functions convert a WORD from the host
394
format to the net format (\texttt{htons}) and vice-versa (\texttt{ntohs}).
395
\end{description}
396
 
397
\begin{intest}
398
ETH\_GETADDRESS\index{eth\_getAddress()}
399
\end{intest}
400
 
401
\begin{description}
402
\item [\textbf{void eth\_getAddress(ETH\_ADDR {*}eth);}]
403
\item [\textbf{Description:}] It returns the net card Ethernet address in the
404
\texttt{ETH\_ADDR} structure pointed by \texttt{eth}.
405
\end{description}
406
 
407
\begin{intest}
408
ETH\_STR2ADDR\index{eth\_str2addr()}
409
\end{intest}
410
 
411
\begin{description}
412
\item [\textbf{void eth\_str2addr(char {*}add, struct ETH\_ADDR {*}ds);}]
413
\item [\textbf{Description:}] It converts an Ethernet address from the string format
414
({}``xx:xx:xx:xx:xx:xx'') to the byte (\texttt{ETH\_ADDR}) format. The
415
\texttt{add} string contains the address in text format, while \texttt{ds} is a
416
pointer to the \texttt{ETH\_ADDR} structure where the output is placed.
417
\end{description}
418
 
419
\begin{intest}
420
ETH\_SETPROTOCOL\index{eth\_setProtocol()}
421
\end{intest}
422
 
423
\begin{description}
424
\item [\textbf{int eth\_setProtocol(WORD type, void ({*}recv)(void {*}frame))}]
425
\item [\textbf{Description:}] It is used to specify the callback function \texttt{recv} to
426
be called when a frame of type \texttt{type} is received. It returns
427
\texttt{TRUE} in the case of success, \texttt{FALSE} otherwise. When the
428
Ethernet layer will call the \texttt{recv} callback, it will pass to the
429
function a pointer to the received frame.
430
 
431
The callback function runs in the context of the driver task, served by a CBS.
432
 
433
Each high-level protocol must use this library call to register itself in order
434
to process incoming packets.
435
\end{description}
436
 
437
\begin{description}
438
\item [Example:]
439
\end{description}
440
 
441
\begin{tt}
442
\begin{verbatim}
443
void ip_server_recv(void *pkt) {
444
    IP_HEADER *iphd;
445
    ...
446
 
447
    /* This callback is invoked when an IP packet is received */
448
    iphd = (IP_HEADER *)eth_getFDB(pkt);
449
    ...
450
}
451
...
452
 
453
void ip_init(char *localAddr) {
454
    int i;
455
 
456
    /* Initializes IP */
457
    ...
458
    /* Registers the protocol to the ethernet layer */
459
    eth_setProtocol(ETH_IP_TYPE,ip_server_recv);
460
    ...
461
}
462
\end{verbatim}
463
\end{tt}
464
 
465
\begin{intest}
466
ETH\_SETHEADER\index{eth\_setHeader()}
467
\end{intest}
468
 
469
\begin{description}
470
\item [\textbf{void {*}eth\_setHeader(void {*}b, ETH\_ADDR dest, WORD type);}]
471
\item [\textbf{Description:}] It fills the header of the frame pointed by \texttt{b} with
472
the destination address \texttt{dest} and the frame type \texttt{type}. It also
473
returns a pointer to the body of the ethernet frame.
474
\end{description}
475
 
476
\begin{intest}
477
ETH\_GETFDB\index{eth\_getFDB()}
478
\end{intest}
479
 
480
\begin{description}
481
\item [\textbf{void {*}eth\_getFDB(void {*}p)}]
482
\item [\textbf{Description:}] Get First Data Byte. It returns a pointer to the body of the
483
frame pointed by the \texttt{p} parameter.
484
\end{description}
485
 
486
\begin{intest}
487
ETH\_SENDPKT\index{eth\_sendPkt()}
488
\end{intest}
489
 
490
\begin{description}
491
\item [\textbf{int eth\_sendPkt(void {*}p, int len);}]
492
\item [\textbf{Description:}] It transmits the Ethernet frame pointed by \texttt{p},
493
having lenght \texttt{len}. The destination and the frame type must be
494
previously specified using \texttt{eth\_setHeader}.
495
\end{description}
496
 
497
\begin{description}
498
\item [Example:]
499
\end{description}
500
 
501
\begin{tt}
502
\begin{verbatim}
503
void arp_sendRequest(int i) {
504
    ARP_PKT *pkt;
505
    ETH_ADDR broadcast, nulladdr;
506
 
507
    eth_str2Addr("FF:FF:FF:FF:FF:FF", &broadcast);
508
    eth_str2Addr("00:00:00:00:00:00", &nulladdr);
509
    eth_setHeader(arpBuff, broadcast, ETH_ARP_TYPE);
510
    pkt = (ARP_PKT *)eth_getFDB(arpBuff);
511
    pkt->htype = htons(ARP_ETH_TYPE);
512
    pkt->ptype = htons(ARP_IP_TYPE);
513
    pkt->hlen = sizeof(ETH_ADDR);
514
    pkt->plen = sizeof(IP_ADDR);
515
    pkt->operation = htons(ARP_REQUEST);
516
    setEthAddr(pkt->sha, myEthAddr);
517
    setEthAddr(pkt->tha, nulladdr);
518
    setIpAddr(pkt->sip, myIpAddr);
519
    setIpAddr(pkt->tip, arpTable[i].ip);
520
    eth_sendPkt(arpBuff, sizeof(ARP_PKT));
521
}
522
\end{verbatim}
523
\end{tt}
524
 
525
\begin{intest}
526
ETH\_CLOSE\index{eth\_close()}
527
\end{intest}
528
 
529
\begin{description}
530
\item [\textbf{int eth\_close(void);}]
531
\item [\textbf{Description:}] It closes the Ethernet protocol. If it is not explicitly
532
called by the user, it is automatically executed through \texttt{sys\_atexit}.
533
\end{description}