Test: Add cbench test case for igmp join leave loop test.
cbench code was modified as in cbench.patch to add igmp packet in support.
Disable vtn app activation as it is buggy and fails activation.

Change-Id: Ia37ad3d9e6011b970e24bcb9e0a2bb783e334545
diff --git a/src/test/cbench/cbench.patch b/src/test/cbench/cbench.patch
new file mode 100644
index 0000000..0ce31e1
--- /dev/null
+++ b/src/test/cbench/cbench.patch
@@ -0,0 +1,179 @@
+diff --git a/cbench/cbench.c b/cbench/cbench.c
+index 70fed93..cdf8492 100644
+--- a/cbench/cbench.c
++++ b/cbench/cbench.c
+@@ -45,6 +45,7 @@ struct myargs my_options[] = {
+     {"connect-group-size",  'I', "number of switches in a connection delay group", MYARGS_INTEGER, {.integer = 1}},
+     {"learn-dst-macs",  'L', "send gratuitious ARP replies to learn destination macs before testing", MYARGS_FLAG, {.flag = 1}},
+     {"dpid-offset",  'o', "switch DPID offset", MYARGS_INTEGER, {.integer = 1}},
++    {"igmp-test", 'g', "IGMP join leave test", MYARGS_FLAG, {.flag = 0}},
+     {0, 0, 0, 0}
+ };
+ 
+@@ -257,6 +258,7 @@ int main(int argc, char * argv[])
+     int     learn_dst_macs = myargs_get_default_flag(my_options, "learn-dst-macs");
+     int     dpid_offset = myargs_get_default_integer(my_options, "dpid-offset");
+     int     mode = MODE_LATENCY;
++    int     igmp_test = myargs_get_default_flag(my_options, "igmp-test");
+     int     i,j;
+ 
+     const struct option * long_opts = myargs_to_long(my_options);
+@@ -326,6 +328,9 @@ int main(int argc, char * argv[])
+             case 'o':
+                 dpid_offset = atoi(optarg);
+                 break;
++            case 'g':
++                igmp_test = 1;
++                break;
+             default: 
+                 myargs_usage(my_options, PROG_TITLE, "help message", NULL, 1);
+         }
+@@ -388,7 +393,8 @@ int main(int argc, char * argv[])
+         if(debug)
+             fprintf(stderr,"Initializing switch %d ... ", i+1);
+         fflush(stderr);
+-        fakeswitch_init(&fakeswitches[i],dpid_offset+i,sock,BUFLEN, debug, delay, mode, total_mac_addresses, learn_dst_macs);
++        fakeswitch_init(&fakeswitches[i],dpid_offset+i,sock,BUFLEN, debug, delay, mode, total_mac_addresses,
++                        learn_dst_macs, igmp_test);
+         if(debug)
+             fprintf(stderr," :: done.\n");
+         fflush(stderr);
+diff --git a/cbench/fakeswitch.c b/cbench/fakeswitch.c
+index a424d14..d3f16de 100644
+--- a/cbench/fakeswitch.c
++++ b/cbench/fakeswitch.c
+@@ -25,12 +25,14 @@ static int make_stats_desc_reply(struct ofp_stats_request * req, char * buf, int
+ static int parse_set_config(struct ofp_header * msg);
+ static int make_config_reply( int xid, char * buf, int buflen);
+ static int make_vendor_reply(int xid, char * buf, int buflen);
+-static int make_packet_in(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address);
+ static int packet_out_is_lldp(struct ofp_packet_out * po);
+ static void fakeswitch_handle_write(struct fakeswitch *fs);
+ static void fakeswitch_learn_dstmac(struct fakeswitch *fs);
+ void fakeswitch_change_status_now (struct fakeswitch *fs, int new_status);
+ void fakeswitch_change_status (struct fakeswitch *fs, int new_status);
++static int make_packet_in_default(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address);
++static int make_packet_in_igmp(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address);
++static int (*make_packet_in)(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address);
+ 
+ static struct ofp_switch_config Switch_config = {
+ 	.header = { 	OFP_VERSION,
+@@ -51,7 +53,7 @@ static inline uint64_t ntohll(uint64_t n)
+     return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32);
+ }
+ 
+-void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int debug, int delay, enum test_mode mode, int total_mac_addresses, int learn_dstmac)
++void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int debug, int delay, enum test_mode mode, int total_mac_addresses, int learn_dstmac, int igmp_test)
+ {
+     char buf[BUFLEN];
+     struct ofp_header ofph;
+@@ -62,6 +64,8 @@ void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int
+     fs->outbuf = msgbuf_new(bufsize);
+     fs->probe_state = 0;
+     fs->mode = mode;
++    fs->igmp_test = igmp_test;
++    make_packet_in = igmp_test ? make_packet_in_igmp : make_packet_in_default;
+     fs->probe_size = make_packet_in(fs->id, 0, 0, buf, BUFLEN, fs->current_mac_address++);
+     fs->count = 0;
+     fs->switch_status = START;
+@@ -71,7 +75,6 @@ void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int
+     fs->xid = 1;
+     fs->learn_dstmac = learn_dstmac;
+     fs->current_buffer_id = 1;
+-  
+     ofph.version = OFP_VERSION;
+     ofph.type = OFPT_HELLO;
+     ofph.length = htons(sizeof(ofph));
+@@ -289,8 +292,54 @@ static int packet_out_is_lldp(struct ofp_packet_out * po){
+ 	return ethertype == ETHERTYPE_LLDP;
+ }
+ 
++static int make_packet_in_igmp(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address)
++{
++    struct ofp_packet_in * pi;
++    struct ether_header * eth;
++    static char fake_igmp_join[] = {
++        0x97,0x0a,0x00,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
++        0x01,0x00,0x40,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x00,
++        0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x00,0x46,
++        0xc0,0x00,0x2c,0x00,0x01,0x00,0x00,0x01,0x02,0x3f,0x04,
++        0x01,0x02,0x03,0x04,0xe0,0x00,0x01,0x01,0x94,0x04,0x00,
++        0x00,0x22,0x00,0xf6,0xf5,0x00,0x00,0x00,0x01,0x01,0x00,
++        0x00,0x01,0xe2,0x00,0x00,0x01,0x01,0x02,0x03,0x04,
++    };
++    static char fake_igmp_leave[] = {
++        0x97,0x0a,0x00,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
++        0x01,0x00,0x40,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x00,
++        0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x00,0x46,
++        0xc0,0x00,0x2c,0x00,0x01,0x00,0x00,0x01,0x02,0x3f,0x04,
++        0x01,0x02,0x03,0x04,0xe0,0x00,0x01,0x01,0x94,0x04,0x00,
++        0x00,0x22,0x00,0xf5,0xf5,0x00,0x00,0x00,0x01,0x02,0x00,
++        0x00,0x01,0xe2,0x00,0x00,0x01,0x01,0x02,0x03,0x04,
++    };
++    static char *fake_bufs[2] = { fake_igmp_join, fake_igmp_leave };
++    static int fake_size_map[2] = { (int)sizeof(fake_igmp_join), (int)sizeof(fake_igmp_leave) };
++    static int idx;
++    int cur_idx = idx;
++    int buf_size = fake_size_map[cur_idx];
++    char *fake;
++    fake = fake_bufs[cur_idx];
++    idx ^= 1;
++    assert(buflen > buf_size);
++    memcpy(buf, fake, buf_size);
++    pi = (struct ofp_packet_in *) buf;
++    pi->header.version = OFP_VERSION;
++    pi->header.xid = htonl(xid);
++    pi->buffer_id = htonl(buffer_id);
++    eth = (struct ether_header * ) pi->data;
++    // copy into src mac addr; only 4 bytes, but should suffice to not confuse
++    // the controller; don't overwrite first byte
++    memcpy(&eth->ether_shost[1], &mac_address, sizeof(mac_address));
++    // mark this as coming from us, mostly for debug
++    eth->ether_dhost[5] = switch_id;
++    eth->ether_shost[5] = switch_id;
++    return buf_size;
++}
++
+ /***********************************************************************/
+-static int make_packet_in(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address)
++static int make_packet_in_default(int switch_id, int xid, int buffer_id, char * buf, int buflen, int mac_address)
+ {
+     struct ofp_packet_in * pi;
+     struct ether_header * eth;
+@@ -387,6 +436,7 @@ void fakeswitch_handle_read(struct fakeswitch *fs)
+                 if(fs->switch_status == READY_TO_SEND && (fm->command == htons(OFPFC_ADD) || 
+                         fm->command == htons(OFPFC_MODIFY_STRICT)))
+                 {
++                    debug_msg(fs, "Got FLOW MOD response\n");
+                     fs->count++;        // got response to what we went
+                     fs->probe_state--;
+                 }
+@@ -488,6 +538,7 @@ static void fakeswitch_handle_write(struct fakeswitch *fs)
+         else if ((fs->mode == MODE_THROUGHPUT) && 
+                 (msgbuf_count_buffered(fs->outbuf) < throughput_buffer))  // keep buffer full
+             send_count = (throughput_buffer - msgbuf_count_buffered(fs->outbuf)) / fs->probe_size;
++
+         for (i = 0; i < send_count; i++)
+         {
+             // queue up packet
+diff --git a/cbench/fakeswitch.h b/cbench/fakeswitch.h
+index d0352e7..26eb202 100644
+--- a/cbench/fakeswitch.h
++++ b/cbench/fakeswitch.h
+@@ -39,6 +39,7 @@ struct fakeswitch
+     int current_mac_address;
+     int learn_dstmac;
+     int current_buffer_id;
++    int igmp_test;
+ };
+ 
+ /*** Initialize an already allocated fakeswitch
+@@ -54,7 +55,7 @@ struct fakeswitch
+  * @param total_mac_addresses      The total number of unique mac addresses
+  *                                 to use for packet ins from this switch
+  */
+-void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int debug, int delay, enum test_mode mode, int total_mac_addresses, int learn_dstmac);
++void fakeswitch_init(struct fakeswitch *fs, int dpid, int sock, int bufsize, int debug, int delay, enum test_mode mode, int total_mac_addresses, int learn_dstmac, int igmp_test);
+ 
+ 
+ /*** Set the desired flags for poll()