Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Proper way to make Cloning devices: (7 Items)
   
Proper way to make Cloning devices  
Hello,

I'd like to ask how I should make Cloning Device (Cloning Interface as a
node in /dev) inside .so driver for io-pkt.

I'm making a native virtual TAP driver with a cloning interface.
Basically, TAP is a virtual ethernet card; so I'm making a driver
loadable into io-pkt. But unlike "real" ethernet cards, TAP is virtual,
so it can be cloned. I wish to make a device file /dev/tap which could
be used to create new virtual network interfaces.

I've tried to find an example in io-pkt SVN repository, but the only
cloning device i found (bpf) is not build into .so module, and it's just
a bsd port.

Could anyone provide me with some sample, or at least a few function
names?

Thank you.
Re: Proper way to make Cloning devices  
Hi Tomasz,

You should know that there is already code in io-pkt to do tun/tap 
(io-pkt/sys/net/if_tun.c and if_tap.c). It just hasn't been enabled yet. 
It's on your todo-/nice-to-have-list. If you are interested you could 
place a call to support and request it, and push the priority of this 
feature.

On to your questions, why are you trying to make a shared object do 
this? It isn't much code and it would be easiest to just have it part of 
the stack.

In any case, The problem of creating a shared object which implements a 
cloner may be two orthogonal problems... If you want a loadable module, 
you should then look for how other loadable modules are done, e.g. under 
io-pkt/sys/lsm/.

If you're wondering how to make a cloning device in general, then I 
gather you've already looked at one example, bpf, but I think vlan is 
maybe a better example to look at. You can see all "cloners" using 
ifconfig -C. There should be bridge, vlan, gif, gre, pppoe, ppp and lo. 
Unless you're using an older QNX (are you?).

If you want to create a new /dev/tap, then you need to create a resource 
manager. But this gets very complicated. Why not take advantage of the 
existing ways of doing this which the other cloneable interfaces are 
doing? They use ioctl commands (SIOCIFGCLONERS, SIOCIFCREATE/DESTROY), 
please see the code in sys/net/if.c. And then ifconfig is used to create 
and destroy them (e.g. ifconfig -C, ifconfig vlan0 create etc, see 
ifconfig docs/use msg).

Hope this helps you,
/P

On 22/03/10 07:46 AM, Tomasz Lis wrote:
> Hello,
>
> I'd like to ask how I should make Cloning Device (Cloning Interface as a
> node in /dev) inside .so driver for io-pkt.
>
> I'm making a native virtual TAP driver with a cloning interface.
> Basically, TAP is a virtual ethernet card; so I'm making a driver
> loadable into io-pkt. But unlike "real" ethernet cards, TAP is virtual,
> so it can be cloned. I wish to make a device file /dev/tap which could
> be used to create new virtual network interfaces.
>
> I've tried to find an example in io-pkt SVN repository, but the only
> cloning device i found (bpf) is not build into .so module, and it's just
> a bsd port.
>
> Could anyone provide me with some sample, or at least a few function
> names?
>
> Thank you.
>    
Re: Proper way to make Cloning devices  
Thank you, Patrik.

Based on your answer, I was able to create the native TAP driver which supports cloning.

There are still some issues with stability, but it works.

The major problem is that when I'm using it to just redirect packets, it takes ~90ms before I got an answer I've sent to
 myself. Under linux, the same task takes ~0.080 ms.

I made a time logging in the driver, and I can see that delay between if_input() call to send a packet, and if_start() 
call which informs that there's a return, if ~60ms; rest of the delay is probably made by my logging routines.

Is there any way to make the io-pkt stack work faster?
Re: Proper way to make Cloning devices  
On 07/05/10 05:57 AM, Tomasz Lis wrote:
> Thank you, Patrik.
>
> Based on your answer, I was able to create the native TAP driver which supports cloning.
>
> There are still some issues with stability, but it works.
>
> The major problem is that when I'm using it to just redirect packets, it takes ~90ms before I got an answer I've sent 
to myself. Under linux, the same task takes ~0.080 ms.
>
> I made a time logging in the driver, and I can see that delay between if_input() call to send a packet, and if_start()
 call which informs that there's a return, if ~60ms; rest of the delay is probably made by my logging routines.
>
> Is there any way to make the io-pkt stack work faster?
>    
Io-pkt is faster.

Sounds like something isn't right somewhere. What driver is being used 
(i.e. is calling ifp->if_input())? Is bridging, fast IP forwarding, or 
regular IP forwarding taking place between the device and the tap 
interface? You can capture and analyze a kernel event trace to see what 
thread is doing and why...

/P
Re: Proper way to make Cloning devices  
Dnia 2010-05-07, pią o godzinie 09:47 -0400, Patrik Lahti pisze:
> On 07/05/10 05:57 AM, Tomasz Lis wrote:
> > Thank you, Patrik.
> >
> > Based on your answer, I was able to create the native TAP driver which supports cloning.
> >
> > There are still some issues with stability, but it works.
> >
> > The major problem is that when I'm using it to just redirect packets, it takes ~90ms before I got an answer I've 
sent to myself. Under linux, the same task takes ~0.080 ms.
> >
> > I made a time logging in the driver, and I can see that delay between if_input() call to send a packet, and 
if_start() call which informs that there's a return, if ~60ms; rest of the delay is probably made by my logging routines
.
> >
> > Is there any way to make the io-pkt stack work faster?
> >    
> Io-pkt is faster.
> 
> Sounds like something isn't right somewhere. What driver is being used 
> (i.e. is calling ifp->if_input())? Is bridging, fast IP forwarding, or 
> regular IP forwarding taking place between the device and the tap 
> interface? You can capture and analyze a kernel event trace to see what 
> thread is doing and why...
> 
> /P

It seems that the delay is generated when sending packets (using write()
to put packets on network stack). I verified that using the TAP made by
Oleg Bolshakov - his TAP sends packets in less than 1 ms. When I used
his driver to write() and my driver read(), times were still under 1ms.

Interesting thing is that when I'm sending next packet, the previous one
is delivered without delay - for example when using:
ping -i 0.01 <TAP_ADDRESS>
I'm getting time=9ms, while for:
ping -i 0.04 <TAP_ADDRESS>
I'm getting time=39ms.
If the interval is over 0.1, delivery time stays at ~100 ms.


I'm calling if_input() from a resource manager thread, like this:

----
	pthread_mutex_lock(&sc->sc_mutex);
	ifp->if_ipackets++;
	// ip_input() needs this
	m->m_pkthdr.rcvif = ifp;

	LOG("%s: calling if_input()", sc->sc_dev.dv_xname);
#if NBPFILTER > 0
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m);
#endif
	s =splnet();
	(*ifp->if_input)(ifp, m);
	splx(s);
	pthread_mutex_unlock(&sc->sc_mutex);
	_IO_SET_WRITE_NBYTES(ctp, msg->i.nbytes);
	LOG("%s: packet %d sent", sc->sc_dev.dv_xname, (int)ifp->if_ipackets);
	(*ifp->if_input)(ifp, NULL);
	return (_RESMGR_NPARTS(0));
----

Both LOG messages: "tap0: calling if_input()" and "tap0: packet <x>
sent" are written to log at same time, but I have to wait 100ms before
tap_start() is called.

I'm forwarding packets in a test program, in short:
----
    fd = open("/dev/tap0", O_RDWR);
    for (n=0;;n++)
    {
        len = read(fd, buff, sizeof(buff) );
        if (len < 0)
            break;
        eh = (eth *)buff;
        if (eh->etype == 0x0008)
        {
            iph = (ip *)&eh->data1;
            // switch IPs
            for (i=0;i<4;i++)
            {
                addr[i] = iph->ip_src[i];
                iph->ip_src[i] = iph->ip_dst[i];
                iph->ip_dst[i] = addr[i];
            }
            write(fd, buff, len);
        }
    }
----


Re: Proper way to make Cloning devices  
I solved the problem.

Originally in BSD, schednetisr() and setsoftnet() were used to inform that there's something on stack. But in io-pkt, 
these functions are defined as 0 - they do not do anything, so it's not enough to call if_input() - the stack must still
 be informed about new packet.

In all original drivers, this is done by calling interrupt_queue() in the interrupt handler. In my case, TAP driver 
doesn't use interrupts, so I didn't called that - and this was the bug.

Now I'm calling interrupt_queue() and sending back the event returned. Packets are delivered in ~1ms, so everything 
seems to work fine.
Re: Proper way to make Cloning devices  
On 12/05/10 08:43 AM, Tomasz Lis wrote:
> I solved the problem.
>
> Originally in BSD, schednetisr() and setsoftnet() were used to inform that there's something on stack. But in io-pkt, 
these functions are defined as 0 - they do not do anything, so it's not enough to call if_input() - the stack must still
 be informed about new packet.
>
> In all original drivers, this is done by calling interrupt_queue() in the interrupt handler. In my case, TAP driver 
doesn't use interrupts, so I didn't called that - and this was the bug.
>
> Now I'm calling interrupt_queue() and sending back the event returned. Packets are delivered in ~1ms, so everything 
seems to work fine.
>    
Thanks for letting us know. Sorry I didn't have time to get back to you, 
but glad you resolved it!

Cheers!
/P