Duplicate Packets (add-group)

 

[Goal]

   If we want to send data packets from source node A and the data packets are received by many receiving nodes, there are some methods. One is to send packets many times, i.e. unicast. But this method cause more bandwidth consumption. Another is to use multicast. But multicast needs that the routers should support multicasting. Here, I use Software-Defined Network (SDN) technique to do this job.

 

[Applications: Those applications that originally use multicast to send packets can be ported to SDN with less resource.]

 

[Example Topology]

In the following topology, there are one sender, H1, and two receivers, H2 and H3. There are also four openvswitches, i.e. S0, S1, S2, and S3. When H1 sends packets to H3, we hope the data packets also can be received by H2. So we will instruct the S0 to duplicate the received the packets that originally are sent to H3. The duplicate packets will be sent to S1, modify the destination MAC and IP Address at S1 and send to S3, and finally arrive at H2. The packets sent from H1 to H3 will go via S0, S2, and S3.

H1-----S0---S1

      |          |

      |          S3 -----H2

      |          |  ----H3

      |          |

S2-------

 
 

 

 

 

 

 

 

 


[Note]

  Make sure that the version of openvswitch is 2.3.1 or newer.

 

[Topology.py]

from mininet.topo import Topo

 

class MyTopo( Topo ):

    "Simple topology example."

 

    def __init__( self ):

        "Create custom topo."

 

        # Initialize topology

        Topo.__init__( self )

 

        # Add hosts and switches

        leftHost = self.addHost( 'h1' )

        rightHost1 = self.addHost( 'h2' )

        rightHost2 = self.addHost( 'h3' )

        Switch0 = self.addSwitch( 's0' )

        Switch1 = self.addSwitch( 's1' )

        Switch2 = self.addSwitch( 's2' )

        Switch3 = self.addSwitch( 's3' )

 

        # Add links

        self.addLink( leftHost, Switch0 )

        self.addLink( Switch0, Switch1 )

        self.addLink( Switch0, Switch2 )

        self.addLink( Switch1, Switch3 )

        self.addLink( Switch2, Switch3 )

        self.addLink( Switch3, rightHost1 )

        self.addLink( Switch3, rightHost2 )

 

 

topos = { 'mytopo': ( lambda: MyTopo() ) }

 

1.      Execute the script.

 

2.      Open another terminal to check the process id of controller. We need to set the rules for all switches manually. So we have to kill the default controller process.

 

3.      Set the protocols to S0, S1, S2, and S3 to support OpenFlow13.

 

4.      Set the rules for S0 to S3 to support the basic operations for packet transmissions.

(s0)

 

(s1)

 

(s2)

 

(s3)

 

5.      Ping tests.

 

6.      Check the MAC address of h2. We have to modify the MAC and IP addresses of the duplicated packets later.

 

7.      Prepare a simple server/client program. The client will send “Hello World” to the server.

(myudp_s.c)

#include <sys/types.h>

#include <sys/socket.h>

#include <string.h>

#include <netinet/in.h>

#include <stdio.h>

#include <stdlib.h>

#define MAXLINE 80

#define SERV_PORT2 8888

//#define SERV_PORT2 9999

 

void do_server(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)

{

  int n;

  socklen_t len;

  char mesg[MAXLINE];

 

  for(;;)

  {

    len = clilen;

    /* waiting for receive data */

    n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

    printf("The server has received a message: %s\n", mesg);

  }

 

}

 

int main(void)

{

  int sockfd;

  struct sockaddr_in servaddr, cliaddr;

  /* create a socket */

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  /* init servaddr */

  bzero(&servaddr, sizeof(servaddr));

  servaddr.sin_family = AF_INET;

  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

  servaddr.sin_port = htons(SERV_PORT2);

 

  /* bind address and port to socket */

  if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)

  {

   perror("bind error");

   exit(1);

  }

 

  do_server(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));

  return 0;

}

 

(myudp_c.c)

#include <sys/types.h>

#include <sys/socket.h>

#include <string.h>

#include <netinet/in.h>

#include <stdio.h>

#include <stdlib.h>

#include <arpa/inet.h>

#include <unistd.h>

#define MAXLINE 80

#define SERV_PORT1 8888

 

void do_cli(FILE *fp, int sockfd, struct sockaddr *pservaddr, socklen_t servlen)

{

  int n;

  char sendline[MAXLINE], recvline[MAXLINE + 1];

  /* connect to server */

  if(connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1)

  {

    perror("connect error");

    exit(1);

  }

 

  /* read a line and send to server */

   strcpy(sendline,"*hello world*");

   write(sockfd, sendline, strlen(sendline)+1);

}

 

int main(int argc, char **argv)

{

  int sockfd;

  struct sockaddr_in servaddr;

 

  /* check args */

  if(argc != 2)

  {

   printf("usage: udp_c <forwarder IP_address>\n");

   exit(1);

  }

 

  /* init servaddr */

  bzero(&servaddr, sizeof(servaddr));

  servaddr.sin_family = AF_INET;

  servaddr.sin_port = htons(SERV_PORT1);

 

  if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)

  {

   printf("[%s] is not a valid IPaddress\n", argv[1]);

   exit(1);

  }

 

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  do_cli(stdin, sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

  return 0;

}

 

Open another terminal to compile these files and copy the executable files to /bin folders.

 

8.      Test for client/server program

 

9.      Now we have to set the rules for S0 to duplicate the packets that sent from h1 to h3.

 

10.  We have to modify the MAC and IP addresses for the duplicated packets at s1.

 

11.  Test. (We can find that when h1 sends the packet to h3, h2 will also receive the duplicated packet.)

 

 

References.

1.      http://hwchiu.logdown.com/posts/207387-multipath-routing-with-group-table-at-mininet

2.      http://manned.org/ovs-ofctl.8

 

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com / smallko@nqu.edu.tw