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} |