source: trunk/packages/xen-3.1/xen-3.1/tools/vnet/vnet-module/varp_socket.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 21.0 KB
Line 
1/*
2 * Copyright (C) 2004, 2005, 2006 Mike Wray <mike.wray@hp.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19#include <linux/kernel.h>
20#include <linux/types.h>
21#include <linux/version.h>
22
23#include <asm/uaccess.h>
24#include <linux/net.h>
25#include <linux/in.h>
26#include <linux/ip.h>
27#include <linux/sched.h>
28#include <linux/file.h>
29#include <linux/version.h>
30#include <linux/smp_lock.h>
31#include <net/sock.h>
32
33#include <if_varp.h>
34#include <varp.h>
35#include <vnet_forward.h>
36
37/* Get macros needed to define system calls as functions in the kernel. */
38#define __KERNEL_SYSCALLS__
39int errno=0;
40#include <linux/unistd.h>
41
42#define MODULE_NAME "VARP"
43#define DEBUG 1
44#undef DEBUG
45#include "debug.h"
46
47/** @file
48 * Support for the VARP udp sockets.
49 */
50
51#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
52
53/* Compensate for struct sock fields having 'sk_' added to them in 2.6. */
54#define sk_receive_queue receive_queue
55#define sk_sleep         sleep
56
57/* Here because inline in 'socket.c' (2.4, in net.h for 2.6). */
58#define sockfd_put(sock) fput((sock)->file)
59
60#endif
61
62static inline mm_segment_t change_fs(mm_segment_t fs){
63    mm_segment_t oldfs = get_fs();
64    set_fs(fs);
65    return oldfs;
66}
67
68/** Define the fcntl() syscall. */
69static inline _syscall3(int, fcntl,
70                        unsigned int, fd, 
71                        unsigned int, cmd,
72                        unsigned long, arg)
73
74/* Replicate the user-space socket API.
75 * The parts we need anyway.
76 *
77 * Some architectures use socketcall() to multiplex the socket-related calls,
78 * but others define individual syscalls instead.
79 * Architectures using socketcall() define __ARCH_WANT_SYS_SOCKETCALL.
80 */
81
82#ifdef __ARCH_WANT_SYS_SOCKETCALL
83
84/* Define the socketcall() syscall.
85 * Multiplexes all the socket-related calls.
86 *
87 * @param call socket call id
88 * @param args arguments (upto 6)
89 * @return call-dependent value
90 */
91static inline _syscall2(int, socketcall,
92                        int, call,
93                        unsigned long *, args)
94
95int socket(int family, int type, int protocol){
96    unsigned long args[6];
97   
98    args[0] = (unsigned long)family;
99    args[1] = (unsigned long)type;
100    args[2] = (unsigned long)protocol;
101    return socketcall(SYS_SOCKET, args);
102}
103
104int bind(int fd, struct sockaddr *umyaddr, int addrlen){
105    unsigned long args[6];
106   
107    args[0] = (unsigned long)fd;
108    args[1] = (unsigned long)umyaddr;
109    args[2] = (unsigned long)addrlen;
110    return socketcall(SYS_BIND, args);
111}
112
113int connect(int fd, struct sockaddr *uservaddr, int addrlen){
114    unsigned long args[6];
115   
116    args[0] = (unsigned long)fd;
117    args[1] = (unsigned long)uservaddr;
118    args[2] = (unsigned long)addrlen;
119    return socketcall(SYS_CONNECT, args);
120}
121
122int sendto(int fd, void * buff, size_t len,
123           unsigned flags, struct sockaddr *addr,
124           int addr_len){
125    unsigned long args[6];
126   
127    args[0] = (unsigned long)fd;
128    args[1] = (unsigned long)buff;
129    args[2] = (unsigned long)len;
130    args[3] = (unsigned long)flags;
131    args[4] = (unsigned long)addr;
132    args[5] = (unsigned long)addr_len;
133    return socketcall(SYS_SENDTO, args);
134}
135
136int recvfrom(int fd, void * ubuf, size_t size,
137             unsigned flags, struct sockaddr *addr,
138             int *addr_len){
139    unsigned long args[6];
140   
141    args[0] = (unsigned long)fd;
142    args[1] = (unsigned long)ubuf;
143    args[2] = (unsigned long)size;
144    args[3] = (unsigned long)flags;
145    args[4] = (unsigned long)addr;
146    args[5] = (unsigned long)addr_len;
147    return socketcall(SYS_RECVFROM, args);
148}
149
150int setsockopt(int fd, int level, int optname, void *optval, int optlen){
151    unsigned long args[6];
152   
153    args[0] = (unsigned long)fd;
154    args[1] = (unsigned long)level;
155    args[2] = (unsigned long)optname;
156    args[3] = (unsigned long)optval;
157    args[4] = (unsigned long)optlen;
158    return socketcall(SYS_SETSOCKOPT, args);
159}
160
161int getsockopt(int fd, int level, int optname, void *optval, int *optlen){
162    unsigned long args[6];
163   
164    args[0] = (unsigned long)fd;
165    args[1] = (unsigned long)level;
166    args[2] = (unsigned long)optname;
167    args[3] = (unsigned long)optval;
168    args[4] = (unsigned long)optlen;
169    return socketcall(SYS_GETSOCKOPT, args);
170}
171
172int shutdown(int fd, int how){
173    unsigned long args[6];
174   
175    args[0] = (unsigned long)fd;
176    args[1] = (unsigned long)how;
177    return socketcall(SYS_SHUTDOWN, args);
178}
179
180int getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len){
181    unsigned long args[6];
182   
183    args[0] = (unsigned long)fd;
184    args[1] = (unsigned long)usockaddr;
185    args[2] = (unsigned long)usockaddr_len;
186    return socketcall(SYS_GETSOCKNAME, args);
187}
188
189#else /* !__ARCH_WANT_SYS_SOCKETCALL */
190
191/* No socketcall - define the individual syscalls. */
192
193static inline _syscall3(int, socket,
194                        int, family,
195                        int, type,
196                        int, protocol);
197
198static inline _syscall3(int, bind,
199                        int, fd,
200                        struct sockaddr *, umyaddr,
201                        int, addrlen);
202
203static inline _syscall3(int, connect,
204                        int, fd,
205                        struct sockaddr *, uservaddr,
206                        int, addrlen);
207
208static inline _syscall6(int, sendto,
209                        int, fd,
210                        void *, buff,
211                        size_t, len,
212                        unsigned, flags,
213                        struct sockaddr *, addr,
214                        int, addr_len);
215
216static inline _syscall6(int, recvfrom,
217                        int, fd,
218                        void *, ubuf,
219                        size_t, size,
220                        unsigned, flags,
221                        struct sockaddr *, addr,
222                        int *, addr_len);
223
224static inline _syscall5(int, setsockopt,
225                        int, fd,
226                        int, level,
227                        int, optname,
228                        void *, optval,
229                        int, optlen);
230
231static inline _syscall5(int, getsockopt,
232                        int, fd,
233                        int, level,
234                        int, optname,
235                        void *, optval,
236                        int *, optlen);
237
238static inline _syscall2(int, shutdown,
239                        int, fd,
240                        int, how);
241
242static inline _syscall3(int, getsockname,
243                        int, fd,
244                        struct sockaddr *, usockaddr,
245                        int *, usockaddr_len);
246
247#endif /* __ARCH_WANT_SYS_SOCKETCALL */
248
249/*============================================================================*/
250/** Socket flags. */
251enum VsockFlag {
252    VSOCK_REUSE     =  1,
253    VSOCK_BIND      =  2,
254    VSOCK_CONNECT   =  4,
255    VSOCK_BROADCAST =  8,
256    VSOCK_MULTICAST = 16,
257    VSOCK_NONBLOCK  = 32,
258 };
259
260/** Convert socket flags to a string.
261 *
262 * @param flags flags
263 * @return static string
264 */
265char * socket_flags(int flags){
266    static char s[7];
267    int i = 0;
268    s[i++] = (flags & VSOCK_CONNECT   ? 'c' : '-');
269    s[i++] = (flags & VSOCK_BIND      ? 'b' : '-');
270    s[i++] = (flags & VSOCK_REUSE     ? 'r' : '-');
271    s[i++] = (flags & VSOCK_BROADCAST ? 'B' : '-');
272    s[i++] = (flags & VSOCK_MULTICAST ? 'M' : '-');
273    s[i++] = (flags & VSOCK_NONBLOCK  ? 'N' : '-');
274    s[i++] = '\0';
275    return s;
276}
277
278/** Control flag for whether varp should be running.
279 * If this is set 0 then the varp thread will notice and
280 * (eventually) exit.
281 */
282atomic_t varp_run = ATOMIC_INIT(0);
283
284enum {
285    VARP_STATE_EXITED  = 2,
286    VARP_STATE_RUNNING = 1,
287    VARP_STATE_NONE    = 0,
288    VARP_STATE_ERROR   = -1,
289};
290
291/** State indicating whether the varp thread is running. */
292atomic_t varp_state = ATOMIC_INIT(VARP_STATE_NONE);
293
294int varp_thread_err = 0;
295
296/** The varp multicast socket. */
297int varp_mcast_sock = -1;
298
299/** The varp unicast socket. */
300int varp_ucast_sock = -1;
301
302/** Set socket option to reuse address.
303 *
304 * @param sock socket
305 * @param reuse flag
306 * @return 0 on success, error code otherwise
307 */
308int setsock_reuse(int sock, int reuse){
309    int err = 0;
310    err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
311    if(err < 0){
312        eprintf("> setsockopt SO_REUSEADDR: %d %d\n", err, errno);
313    }
314    return err;
315}
316
317/** Set socket broadcast option.
318 *
319 * @param sock socket
320 * @param bcast flag
321 * @return 0 on success, error code otherwise
322 */
323int setsock_broadcast(int sock, int bcast){
324    int err = 0;
325    err = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast));
326    if(err < 0){
327        eprintf("> setsockopt SO_BROADCAST: %d %d\n", err, errno);
328    }
329    return err;
330}
331
332/** Join a socket to a multicast group.
333 *
334 * @param sock socket
335 * @param saddr multicast address
336 * @return 0 on success, error code otherwise
337 */
338int setsock_multicast(int sock, uint32_t saddr){
339    int err = 0;
340    struct ip_mreqn mreq = {};
341    int mloop = 0;
342
343    // See 'man 7 ip' for these options.
344    mreq.imr_multiaddr.s_addr = saddr;       // IP multicast address.
345    mreq.imr_address.s_addr   = INADDR_ANY;  // Interface IP address.
346    mreq.imr_ifindex = 0;                    // Interface index (0 means any).
347    err = setsockopt(sock, SOL_IP, IP_MULTICAST_LOOP, &mloop, sizeof(mloop));
348    if(err < 0){
349        eprintf("> setsockopt IP_MULTICAST_LOOP: %d %d\n", err, errno);
350        goto exit;
351    }
352    err = setsockopt(sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
353    if(err < 0){
354        eprintf("> setsockopt IP_ADD_MEMBERSHIP: %d %d\n", err, errno);
355        goto exit;
356    }
357  exit:
358    return err;
359}
360
361/** Set a socket's multicast ttl (default is 1).
362 * @param sock socket
363 * @param ttl ttl
364 * @return 0 on success, error code otherwise
365 */
366int setsock_multicast_ttl(int sock, uint8_t ttl){
367    int err = 0;
368    err = setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
369    return err;
370}
371
372/** Create a socket.
373 * The flags can include values from enum VsockFlag.
374 *
375 * @param socktype socket type
376 * @param saddr address
377 * @param port port
378 * @param flags flags
379 * @param val return value for the socket connection
380 * @return 0 on success, error code otherwise
381 */
382int create_socket(int socktype, uint32_t saddr, uint32_t port, int flags, int *val){
383    int err = 0;
384    int sock;
385    struct sockaddr_in addr_in;
386    struct sockaddr *addr = (struct sockaddr *)&addr_in;
387    int addr_n = sizeof(addr_in);
388    int sockproto = 0;
389
390    //dprintf(">\n");
391    addr_in.sin_family      = AF_INET;
392    addr_in.sin_addr.s_addr = saddr;
393    addr_in.sin_port        = port;
394    dprintf("> flags=%s addr=%u.%u.%u.%u port=%d\n",
395            socket_flags(flags),
396            NIPQUAD(saddr), ntohs(port));
397
398    switch(socktype){
399    case SOCK_DGRAM:  sockproto = IPPROTO_UDP; break;
400    case SOCK_STREAM: sockproto = IPPROTO_TCP; break;
401    }
402    sock = socket(AF_INET, socktype, sockproto);
403    if(sock < 0) goto exit;
404    if(flags & VSOCK_REUSE){
405        err = setsock_reuse(sock, 1);
406        if(err < 0) goto exit;
407    }
408    if(flags & VSOCK_BROADCAST){
409        err = setsock_broadcast(sock, 1);
410        if(err < 0) goto exit;
411    }
412    if(flags & VSOCK_MULTICAST){
413        err = setsock_multicast(sock, saddr);
414        if(err < 0) goto exit;
415    }
416    if(flags & VSOCK_CONNECT){
417        err = connect(sock, addr, addr_n);
418        if(err < 0) goto exit;
419    }
420    if(flags & VSOCK_BIND){
421        err = bind(sock, addr, addr_n);
422        if(err < 0) goto exit;
423    }
424    if(flags & VSOCK_NONBLOCK){
425        err = fcntl(sock, F_SETFL, O_NONBLOCK);
426        if(err < 0) goto exit;
427    }
428  exit:
429    *val = (err ? -1 : sock);
430    if(err) eprintf("> err=%d errno=%d\n", err, errno);
431    return err;
432}
433
434/** Open the varp multicast socket.
435 *
436 * @param mcaddr multicast address
437 * @param port port
438 * @param val return parameter for the socket
439 * @return 0 on success, error code otherwise
440 */
441int varp_mcast_open(uint32_t mcaddr, uint16_t port, int *val){
442    int err = 0;
443    int flags = VSOCK_REUSE;
444    int sock = 0;
445   
446    dprintf(">\n");
447    flags |= VSOCK_MULTICAST;
448    flags |= VSOCK_BROADCAST;
449   
450    err = create_socket(SOCK_DGRAM, mcaddr, port, flags, &sock);
451    if(err < 0) goto exit;
452    if(MULTICAST(mcaddr)){
453        err = setsock_multicast_ttl(sock, 1);
454        if(err < 0) goto exit;
455    }
456  exit:
457    if(err){
458        shutdown(sock, 2);
459    }
460    *val = (err ? -1 : sock);
461    dprintf("< err=%d val=%d\n", err, *val);
462    return err;
463}
464
465/** Open the varp unicast socket.
466 *
467 * @param addr address
468 * @param port port
469 * @param val return parameter for the socket
470 * @return 0 on success, error code otherwise
471 */
472int varp_ucast_open(uint32_t addr, u16 port, int *val){
473    int err = 0;
474    int flags = (VSOCK_BIND | VSOCK_REUSE);
475    dprintf(">\n");
476    err = create_socket(SOCK_DGRAM, addr, port, flags, val);
477    dprintf("< err=%d val=%d\n", err, *val);
478    return err;
479}
480
481/**
482 * Return code > 0 means the handler owns the packet.
483 * Return code <= 0 means we still own it, with < 0 meaning
484 * an error.
485 */
486static int handle_varp_skb(struct sk_buff *skb){
487    int err = 0;
488    switch(skb->pkt_type){
489    case PACKET_BROADCAST:
490    case PACKET_MULTICAST:
491        vnet_forward_send(skb);
492        /* Fall through. */
493    case PACKET_HOST:
494        err = varp_handle_message(skb);
495        break;
496    case PACKET_OTHERHOST:
497        dprintf("> PACKET_OTHERHOST\n");
498        break;
499    case PACKET_OUTGOING:
500        dprintf("> PACKET_OUTGOING\n");
501        break;
502    case PACKET_FASTROUTE:
503        dprintf("> PACKET_FASTROUTE\n");
504        break;
505    case PACKET_LOOPBACK:
506        // Outbound mcast/bcast are echoed with this type. Drop.
507        dprintf("> LOOP src=" IPFMT " dst=" IPFMT " dev=%s\n",
508                NIPQUAD(skb->nh.iph->saddr),
509                NIPQUAD(skb->nh.iph->daddr),
510                (skb->dev ? skb->dev->name : "??"));
511      default:
512        // Drop.
513        break;
514    }
515    if(err <= 0){
516        kfree_skb(skb);
517    }
518    return (err < 0 ? err : 0);
519}
520
521/** Handle some skbs on a varp socket (if any).
522 *
523 * @param fd socket file descriptor
524 * @param n maximum number of skbs to handle
525 * @return number of skbs handled
526 */
527static int handle_varp_sock(int fd, int n){
528    int ret = 0;
529    int err = 0;
530    struct sk_buff *skb;
531    struct socket *sock = NULL;
532
533    sock = sockfd_lookup(fd, &err);
534    if (!sock){
535        wprintf("> no sock for fd=%d\n", fd);
536        goto exit;
537    }
538    for( ; ret < n; ret++){
539        if(!sock->sk) break;
540        skb = skb_dequeue(&sock->sk->sk_receive_queue);
541        if(!skb) break;
542        // Call the skb destructor so it isn't charged to the socket anymore.
543        // An skb from a socket receive queue is charged to the socket
544        // by skb_set_owner_r() until its destructor is called.
545        // If the destructor is not called the socket will run out of
546        // receive queue space and be unable to accept incoming skbs.
547        // The destructor used is sock_rfree(), see 'include/net/sock.h'.
548        // Other destructors: sock_wfree, sk_stream_rfree.
549        skb_orphan(skb);
550        handle_varp_skb(skb);
551    }
552    sockfd_put(sock);
553  exit:
554    dprintf("< ret=%d\n", ret);
555    return ret;
556}
557
558/** Add a wait queue to a socket.
559 *
560 * @param fd socket file descriptor
561 * @param waitq queue
562 * @return 0 on success, error code otherwise
563 */
564int sock_add_wait_queue(int fd, wait_queue_t *waitq){
565    int err = -EINVAL;
566    struct socket *sock = NULL;
567
568    if(fd < 0) goto exit;
569    sock = sockfd_lookup(fd, &err);
570    if (!sock) goto exit;
571    add_wait_queue(sock->sk->sk_sleep, waitq);
572    sockfd_put(sock);
573    err = 0;
574  exit:
575    return err;
576}
577
578/** Remove a wait queue from a socket.
579 *
580 * @param fd socket file descriptor
581 * @param waitq queue
582 * @return 0 on success, error code otherwise
583 */
584int sock_remove_wait_queue(int fd, wait_queue_t *waitq){
585    int err = -EINVAL;
586    struct socket *sock = NULL;
587
588    if(fd < 0) goto exit;
589    sock = sockfd_lookup(fd, &err);
590    if (!sock) goto exit;
591    remove_wait_queue(sock->sk->sk_sleep, waitq);
592    sockfd_put(sock);
593    err = 0;
594  exit:
595    return err;
596}
597
598#if 0
599// Default data ready function on a socket.
600static void sock_def_readable(struct sock *sk, int len)
601{
602        read_lock(&sk->sk_callback_lock);
603        if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
604                wake_up_interruptible(sk->sk_sleep);
605        sk_wake_async(sk,1,POLL_IN);
606        read_unlock(&sk->sk_callback_lock);
607}
608#endif
609
610static void sock_data_ready(struct sock *sk, int len){
611    struct sk_buff *skb;
612    //read_lock(&sk->sk_callback_lock);
613    skb = skb_dequeue(&sk->sk_receive_queue);
614    if(skb){
615        skb_orphan(skb);
616    }
617    //read_unlock(&sk->sk_callback_lock);
618    if(skb){
619        handle_varp_skb(skb);
620    }
621}
622
623/** Set the data ready callback on a socket.
624 */
625int sock_set_callback(int fd){
626    int err = -EINVAL;
627    struct socket *sock = NULL;
628
629    if(fd < 0) goto exit;
630    sock = sockfd_lookup(fd, &err);
631    if (!sock) goto exit;
632    sock->sk->sk_data_ready = sock_data_ready;
633    sockfd_put(sock);
634    err = 0;
635  exit:
636    return err;
637}
638
639/** Open the sockets. */
640int varp_sockets_open(u32 mcaddr, u16 port){
641    int err = 0;
642    mm_segment_t oldfs;
643
644    dprintf("> mcaddr=%u.%u.%u.%u port=%u\n", NIPQUAD(mcaddr), ntohs(port));
645    oldfs = change_fs(KERNEL_DS);
646    err = varp_mcast_open(mcaddr, port, &varp_mcast_sock);
647    if(err < 0 ) goto exit;
648    err = varp_ucast_open(INADDR_ANY, port, &varp_ucast_sock);
649    if(err < 0 ) goto exit;
650    sock_set_callback(varp_ucast_sock);
651    sock_set_callback(varp_mcast_sock);
652  exit:
653    set_fs(oldfs);
654    dprintf("< err=%d\n", err);
655    return err;
656}       
657
658/** Close the sockets. */
659void varp_sockets_close(void){
660    mm_segment_t oldfs;
661    oldfs = change_fs(KERNEL_DS);
662    if(varp_mcast_sock >= 0){
663        shutdown(varp_mcast_sock, 2);
664        varp_mcast_sock = -1;
665    }
666    if(varp_ucast_sock >= 0){
667        shutdown(varp_ucast_sock, 2);
668        varp_ucast_sock = -1;
669    }
670    set_fs(oldfs);
671}
672
673/** Loop handling the varp sockets.
674 * We use kernel API for this (waitqueue, schedule_timeout) instead
675 * of select because the select syscall was returning EFAULT. Oh well.
676 *
677 * @param arg arguments
678 * @return exit code
679 */
680int varp_main(void *arg){
681    int err = 0;
682    long timeout = 1 * HZ;
683    int count = 0;
684    DECLARE_WAITQUEUE(mcast_wait, current);
685    DECLARE_WAITQUEUE(ucast_wait, current);
686
687    dprintf("> start\n");
688    snprintf(current->comm, sizeof(current->comm), "varp_main");
689
690    err = sock_add_wait_queue(varp_mcast_sock, &mcast_wait);
691    if(err) goto exit_mcast_sock;
692    err = sock_add_wait_queue(varp_ucast_sock, &ucast_wait);
693    if(err) goto exit_ucast_sock;
694    atomic_set(&varp_state, VARP_STATE_RUNNING);
695    for( ; atomic_read(&varp_run); ){
696        count = 0;
697        count += handle_varp_sock(varp_mcast_sock, 1);
698        count += handle_varp_sock(varp_ucast_sock, 16);
699        if(!count){
700            if(!atomic_read(&varp_run)) break;
701            // No skbs were handled, go to sleep.
702            set_current_state(TASK_INTERRUPTIBLE);
703            schedule_timeout(timeout);
704            __set_current_state(TASK_RUNNING);
705        }
706    }
707  exit_ucast_sock:
708    sock_remove_wait_queue(varp_ucast_sock, &ucast_wait);
709  exit_mcast_sock:
710    sock_remove_wait_queue(varp_mcast_sock, &mcast_wait);
711    varp_sockets_close();
712    if(err){
713        eprintf("%s< err=%d\n", __FUNCTION__, err);
714    }
715    varp_thread_err = err;
716    atomic_set(&varp_state, VARP_STATE_EXITED);
717    //MOD_DEC_USE_COUNT;
718    return err;
719}
720
721/** Close the varp sockets and stop the thread handling them.
722 */
723void varp_close(void){
724    int tries = 10;
725    dprintf(">\n");
726    // Tell the varp thread to stop and wait a while for it.
727    atomic_set(&varp_run, 0);
728    while(atomic_read(&varp_state) == VARP_STATE_RUNNING && tries-- > 0){
729        set_current_state(TASK_INTERRUPTIBLE);
730        schedule_timeout(HZ / 2);
731        __set_current_state(TASK_RUNNING);
732    }
733    //MOD_DEC_USE_COUNT;
734    dprintf("<\n");
735}   
736
737/** Open the varp sockets and start the thread handling them.
738 *
739 * @param mcaddr multicast address
740 * @param port port
741 * @return 0 on success, error code otherwise
742 */
743int varp_open(u32 mcaddr, u16 port){
744    int err = 0;
745   
746    //MOD_INC_USE_COUNT;
747    dprintf(">\n");
748    err = varp_sockets_open(mcaddr, port);
749    if(err) goto exit;
750    atomic_set(&varp_run, 1);
751    atomic_set(&varp_state, VARP_STATE_NONE);
752    kernel_thread(varp_main, NULL, (CLONE_FS | CLONE_FILES | CLONE_SIGHAND));
753#if 0
754    while(atomic_read(&varp_state) == VARP_STATE_NONE){
755        set_current_state(TASK_INTERRUPTIBLE);
756        schedule_timeout(1 * HZ);
757        __set_current_state(TASK_RUNNING);
758    }
759    err = varp_thread_err;
760#endif
761  exit:
762    if(err){
763        wprintf("> err=%d\n", err);
764    }
765    return err;
766}
Note: See TracBrowser for help on using the repository browser.