Linux Bridge is slow ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have two virtual machine  VM1  and VM2 , which are running on
ubuntu.  Both VM are running  ubunutu. I bridged vnet0 and vnet1  in a
linux bridge on host machine.
 brctl addbr virbr0
 brctl addif  virbr0 vnet0
 brctl addif  virbr0  vnet1

I did a wget of  1.9G file from VM1 to VM2. it took 1 minute 43 sec at
18.6mbps to transfer the file.

I used the attached program ( which is using epoll ) to read and write
packets.  This program will register two network interfaces ( tap77
and tap88 ) with linux stack and will read packets from corresponding
file descriptor in userspace and write it in other.  I bridged
tap77 and vnet0  together  and  tap88 and vnet1 together using a
openvswitch bridge. Her i added an overhead  read, write system call
and  copy_to_user, copy_from_user  copies  in  both directions. [ from
vm1 to vm2  & vm2 to vm1 ] compared to linux bridge implementation
mentioned first.

when i ran wget test. It took less time.  1.9G file from VM1 to VM2.
it took 1 minute 39 sec at 19.3 mbps to transfer the file.

Does that mean that linux bridge is introducing a lot of delay ? i
thought it should be really fast ...any clue or hint is really
appreciated ?


Thanks,
Ratheesh
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/epoll.h>
static int
make_socket_non_blocking (int sfd)
{
  int flags, s;

  flags = fcntl (sfd, F_GETFL, 0);
  if (flags == -1)
    {
      perror ("fcntl");
      return -1;
    }

  flags |= O_NONBLOCK;
  s = fcntl (sfd, F_SETFL, flags);
  if (s == -1)
    {
      perror ("fcntl");
      return -1;
    }

  return 0;
}

int tun_alloc(char *dev)
  {
      struct ifreq ifr;
      int fd, err;

      if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
	 perror("cannot open /dev/net/tun");
         return 0;
      }  

      memset(&ifr, 0, sizeof(ifr));

      /* Flags: IFF_TUN   - TUN device (no Ethernet headers) 
       *        IFF_TAP   - TAP device  
       *
       *        IFF_NO_PI - Do not provide packet information  
       */
      ifr.ifr_flags = IFF_TAP ;
      if( *dev )
         strncpy(ifr.ifr_name, dev, IFNAMSIZ);

      printf("hello");

      //if( err == ioctl(fd, TUNSETIFF, (void *) &ifr) ){
       err= ioctl(fd, TUNSETIFF, (void *) &ifr); 
	if(err < 0 ) {
         close(fd);
         return err;
      }
      strcpy(dev, ifr.ifr_name);
      return fd;
  }

int  main()
{


 char tun_name1[IFNAMSIZ];
 char tun_name2[IFNAMSIZ];
 int tun_fd1, tun_fd2;
 unsigned char  buffer[2048];
 int nread, n ;

#define MAX_EVENTS 10
 struct epoll_event ev_tap77, ev_tap88, events[MAX_EVENTS];
 int  nfds, epollfd;

 epollfd = epoll_create(10);
 if (epollfd == -1) {
	 perror("epoll_create");
	 exit(EXIT_FAILURE);
 } 


 
  /* Connect to the device */
  strcpy(tun_name1, "tap77");
  tun_fd1 = tun_alloc(tun_name1);  /* tun interface */
  //make_socket_non_blocking(tun_fd1); 	
  
  strcpy(tun_name2, "tap88");
  tun_fd2 = tun_alloc(tun_name2);  /* tun interface */
  //make_socket_non_blocking(tun_fd2); 	

  if(tun_fd1 < 0 || tun_fd2 < 0 ){
    perror("\nAllocating interface");
    printf("\n RAT ");	
    exit(1);
  }

  ev_tap77.events = EPOLLIN;
  ev_tap77.data.fd = tun_fd1;
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, tun_fd1 , &ev_tap77) == -1) {
	  perror("epoll_ctl: listen_sock");
	  exit(EXIT_FAILURE);
  }	

  ev_tap88.events = EPOLLIN;
  ev_tap88.data.fd = tun_fd2;
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, tun_fd2, &ev_tap88) == -1) {
	  perror("epoll_ctl: listen_sock");
	  exit(EXIT_FAILURE);
  }	



  /* Now read data coming from the kernel */
  while(1) {
	  /* Note that "buffer" should be at least the MTU size of the interface, eg 1500 bytes */


	  nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
	  if (nfds == -1) {
		  perror("epoll_pwait");
		  exit(EXIT_FAILURE);
	  }

	  for (n = 0; n < nfds; ++n) {
		  if (events[n].data.fd == tun_fd1)  {
			  nread = read(tun_fd1,buffer,sizeof(buffer));
			  if(nread < 0) {
				  perror("Reading from interface");
				  //close(tun_fd1);
				  //close(tun_fd2);
				  //exit(1);
				  continue;	
			  }
    			  printf("Read %d bytes from device %s\n", nread, tun_name1);
			  nread = write(tun_fd2,buffer, nread);
			  //do_use_fd(events[n].data.fd);	
		  } 	

		    if (events[n].data.fd == tun_fd2 ) {
			  nread = read(tun_fd2,buffer,sizeof(buffer));
			  if(nread < 0) {
				  perror("Reading from interface");
				  //close(tun_fd1);
				  //close(tun_fd2);
                                  continue; 
				  //exit(1);
			  }
    			  printf("Read %d bytes from device %s\n", nread, tun_name2);
			  nread = write(tun_fd1,buffer, nread);
		        // 	  do_use_fd(events[n].data.fd);	

                  }
         }


    /* Do whatever with the data */
  }

	printf("hello ///i m done \n");


}

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux