app/example: nettest app for linux
authorbossjisu <jisuu.kim@samsung.com>
Fri, 4 Aug 2017 06:23:38 +0000 (23:23 -0700)
committerEunBong Song <eunb.song@samsung.com>
Wed, 30 Aug 2017 04:15:49 +0000 (21:15 -0700)
nettest sample application for linux.

Change-Id: Idf328c93dbea9adf8de68c647cf7e8388863df12
Signed-off-by: bossjisu <jisuu.kim@samsung.com>
apps/examples/nettest/linux-nettest.c [new file with mode: 0644]

diff --git a/apps/examples/nettest/linux-nettest.c b/apps/examples/nettest/linux-nettest.c
new file mode 100644 (file)
index 0000000..9d3e396
--- /dev/null
@@ -0,0 +1,821 @@
+/****************************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+
+/* nettest sample application only for Linux */
+
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#define BUF_SIZE 256
+
+#define NUM_PACKETS 100
+
+#define NETTEST_IPV(x) ((x) ? "_V6" : "_V4")
+
+char *g_app_netif_addr;
+char *g_app_target_addr;
+int g_app_target_port;
+
+void ipmcast_sender_thread(int num_packets)
+{
+       int ret = 0;
+       int i = 0;
+       int datalen;
+       struct in_addr localInterface;
+       struct sockaddr_in groupSock;
+       int sd;
+       char *databuf = "Test Data: IP Multicast from TinyAra Node to Linux";
+
+       socklen_t addrlen = sizeof(struct sockaddr_in);
+       printf("\n[MCASTSENDER] start multicast sender\n");
+        
+       /* Create a datagram socket on which to send. */
+       sd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sd < 0) {
+               printf("[MCASTSENDER] [ERR] opening datagram socket");
+               exit(1);
+       }
+       printf("\n[MCASTSENDER] created socket successfully\n");
+
+       /* Disable loopback so you do not receive your own datagrams. */
+       char loopch = 0;
+       if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0) {
+               printf("\n[MCASTSENDER] [ERR] Failed setting IP_MULTICAST_LOOP:");
+               goto errout_with_socket;
+       }
+       printf("\n[MCASTSENDER] setsockopt MULTICAST_LOOP success\n");
+
+       /* initialize socket information */
+       memset((char *)&groupSock, 0, sizeof(groupSock));
+       groupSock.sin_family = AF_INET;
+       groupSock.sin_addr.s_addr = inet_addr(g_app_target_addr);
+       groupSock.sin_port = htons(g_app_target_port);
+
+       /*
+        * Set local interface for outbound multicast datagrams.
+        * The IP address specified must be associated with a local,
+        * multicast-capable interface.
+        */
+       localInterface.s_addr = inet_addr(g_app_netif_addr);
+       if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0) {
+               printf("\n[MCASTSENDER] [ERR] Failed setting local interface");
+               goto errout_with_socket;
+       }
+       printf("\n[MCASTSENDER] setsockopt IP_MULTICAST_IF success\n");
+
+       /*
+        * Send a message to the multicast group specified by the
+        * groupSock sockaddr structure.
+        */
+       datalen = strlen(databuf);
+       printf("\n[MCASTSENDER] datalen = %d \n", datalen);
+
+       for (i = 1; i <= num_packets; i++) {
+               printf("\n[MCASTSENDER] sending mcast message (%s) length (%d) number (%d)\n", databuf, datalen, i);
+               ret = sendto(sd, databuf, datalen, 0, (struct sockaddr *)&groupSock, addrlen);
+               if (ret < 0) {
+                       printf("\n[MCASTSENDER] [ERR] sending datagram message");
+               }
+               sleep(1);
+       }
+
+       printf("\n[MCASTSENDER] Terminate multicast sender after sending sufficient messages (%d)\n", num_packets);
+       close(sd);
+       return;
+
+errout_with_socket:
+       close(sd);
+       exit(1);
+}
+
+void ipmcast_receiver_thread(int num_packets)
+{
+       int ret = 0;
+       int count = 0;
+       int datalen;
+       char databuf[256];
+       int sd;
+       struct sockaddr_in localSock;
+       struct ip_mreq group;
+       printf("\n[MCASTSERV] start multicast receiver\n");
+
+       /* Create a datagram socket on which to receive. */
+       sd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sd < 0) {
+               printf("\n[MCASTSERV] ERR : opening datagram socket\n");
+               exit(1);
+       }
+       printf("\n[MCASTSERV] create socket success\n");
+
+       /*
+        * Enable SO_REUSEADDR to allow multiple instances of this
+        * application to receive copies of the multicast datagrams.
+        */
+       int reuse = 1;
+       ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse));
+       if (ret < 0) {
+               printf("\n[MCASTSERV] ERR: setting SO_REUSEADDR\n");
+               goto errout_with_socket;
+       }
+       printf("\n[MCASTSERV] set reusable success\n");
+
+       /* initialize socket information and bind the socket */
+       memset((char *)&localSock, 0, sizeof(localSock));
+       localSock.sin_family = AF_INET;
+       localSock.sin_port = htons(g_app_target_port);;
+       localSock.sin_addr.s_addr = INADDR_ANY;
+
+       if (bind(sd, (struct sockaddr *)&localSock, sizeof(localSock))) {
+               printf("\n[MCASTSERV] ERR: binding datagram socket\n");
+               goto errout_with_socket;
+       }
+       printf("\n[MCASTSERV] bind socket success\n");
+
+       /*
+        * Join the multicast group 225.1.1.1 on the local 192.168.2.10
+        * interface.  Note that this IP_ADD_MEMBERSHIP option must be
+        * called for each local interface over which the multicast
+        * datagrams are to be received.
+        */
+       group.imr_multiaddr.s_addr = inet_addr(g_app_target_addr);
+       group.imr_interface.s_addr = inet_addr(g_app_netif_addr);
+       if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
+               printf("\n[MCASTSERV] ERR: adding multicast group\n");
+               goto errout_with_socket;
+       }
+       printf("\n[MCASTSERV] join multicast success sucess success success success success success success\n");
+
+       /* Read from the socket. */
+       while (1) {
+               datalen = sizeof(databuf);
+               /* any of the below call read / recv is fine */
+               ret = read(sd, databuf, datalen);
+
+               if (ret < 0) {
+                       printf("\n[MCASTSERV] ERR: reading datagram message\n");
+               } else {
+                       databuf[ret] = '\0';
+                       count++;
+                       if (count > num_packets) {
+                               printf("\n[MCASTSERV] - Received Msg # %d] read (%s) (%d) bytes, Terminating mcast serv as received sufficient packets for testing\n", count, databuf, ret);
+                               break;
+                       } else {
+                               printf("\n[MCASTSERV] - Received Msg # %d] read (%s) (%d) bytes\n", count, databuf, ret);
+                       }
+               }
+       }
+       close(sd);
+       return;
+
+errout_with_socket:
+       close(sd);
+       exit(1);
+}
+
+void udp_client_thread(int num_packets, int ipver)
+{
+       struct sockaddr_in cliaddr;
+
+       struct addrinfo *cliaddr6;
+
+       int fd;
+       int count = 1;
+       int nbytes = 0;
+       socklen_t addrlen;
+       char sbuf[BUF_SIZE];
+       char rbuf[BUF_SIZE];
+
+       if (ipver == 1) {
+
+               char addr6_str[50];
+               char port_str[10];
+               struct addrinfo hints;
+               struct addrinfo *rp;
+
+               memset(addr6_str, 0, 50);
+               snprintf(addr6_str, 50, "%s", g_app_target_addr);
+               memset(port_str, 0, 10);
+               snprintf(port_str, 10, "%d", g_app_target_port);
+
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET6;
+               hints.ai_socktype = SOCK_DGRAM;
+               inet_pton(AF_INET6, addr6_str, &hints.ai_addr);
+
+               if (getaddrinfo(addr6_str, port_str, &hints, &cliaddr6) != 0) {
+                       printf("[UDPCLI%s] getaddrinfo err: %d\n", NETTEST_IPV(ipver), errno);
+                       exit(1);
+               }
+
+               for (rp = cliaddr6; rp != NULL; rp = rp->ai_next) {
+                       memset(addr6_str, 0, 50);
+                       inet_ntop(AF_INET6, rp->ai_addr, addr6_str, 50);
+                       printf("[UDPCLI%s] addr: %s port:%s family: %d type: %d protocol: %d\n", NETTEST_IPV(ipver), addr6_str, port_str, rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+
+                       fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+                       if (fd < 0) {
+                               continue;
+                       }
+
+                       if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                               // connect success
+                               break;
+                       }
+                       close(fd);
+               }
+               if (rp == NULL) {
+                       printf("[UDPCLI%s] fail to open socket\n", NETTEST_IPV(ipver));
+                       freeaddrinfo(cliaddr6);
+                       exit(1);
+               }
+               freeaddrinfo(cliaddr6);
+       } else {
+               char addr6_str[40];
+               fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+               cliaddr.sin_family = AF_INET;
+               cliaddr.sin_port = htons(g_app_target_port);
+               inet_pton(AF_INET, g_app_target_addr, &cliaddr.sin_addr);
+               addrlen = sizeof(struct sockaddr_in);
+
+               inet_ntop(AF_INET, &cliaddr.sin_addr, addr6_str, 40);
+               printf("[UDPCLI%s] addr: %s port: %d\n", NETTEST_IPV(ipver), addr6_str, htons(cliaddr.sin_port));
+       }
+
+       memset(sbuf, 0, BUF_SIZE);
+       snprintf(sbuf, sizeof("hello, UDP_VX"), "hello, UDP%s", NETTEST_IPV(ipver));
+       memset(rbuf, 0, BUF_SIZE);
+
+       while(1) {
+               if (ipver == 1) {
+
+                       nbytes = write(fd, sbuf, BUF_SIZE);
+                       if (nbytes <= 0) {
+                               printf("[UDPCLI%s] write err: %d\n", NETTEST_IPV(ipver), errno);
+                               break;
+                       }
+
+                       nbytes = read(fd, rbuf, BUF_SIZE);
+
+               } else {
+                       nbytes = sendto(fd, sbuf, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, addrlen);
+                       if (nbytes <= 0) {
+                               printf("[UDPCLI%s] sendto err: %d\n", NETTEST_IPV(ipver), errno);
+                               break;
+                       }
+
+                       nbytes = recvfrom(fd, rbuf, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &addrlen);
+               }
+               if (nbytes <= 0) {
+                       printf("[UDPCLI%s] %s err: %d\n", NETTEST_IPV(ipver), ipver ? "read": "recvfrom", errno);
+                       break;
+               } else {
+                       if (num_packets == 0) {
+                               /* infinite test */
+                               if(!(count % 1000)) {
+                                       printf("[UDPCLI%s infinite test #%d] msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, rbuf, nbytes);
+                               }
+                       } else {
+                               printf("[UDPCLI%s test #%d] msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, rbuf, nbytes);
+                               if (count >= num_packets) {
+                                       printf("[UDPCLI%s test done #%d]\n", NETTEST_IPV(ipver), count);
+                                       break;
+                               }
+                       }
+                       count++;
+               }
+       }
+
+       close(fd);
+       return;
+}
+
+void udp_server_thread(int num_packets, int ipver)
+{
+       struct sockaddr_in servaddr;
+       struct sockaddr_in cliaddr;
+
+       struct sockaddr_in6 servaddr6;
+       struct sockaddr_in6 cliaddr6;
+
+       char msg[BUF_SIZE];
+       int fd;
+       int maxfd;
+       int nbytes;
+       int ret = 0;
+       int count = 1;
+       int have_received = 0;
+       socklen_t addrlen;
+       fd_set fds;
+       fd_set rfds;
+       fd_set sfds;
+
+       if (ipver == 1) {
+               /* create IPV6 udp socket */
+
+               fd = socket(AF_INET6, SOCK_DGRAM, 0);
+               if (fd < 0) {
+                       printf("[UDPSERV%s] socket err: %d\n", NETTEST_IPV(ipver), errno);
+                       exit(1);
+               }
+
+               /* initialize socket information */
+               addrlen = sizeof(struct sockaddr_in6);
+               memset(&servaddr6, 0, addrlen);
+
+               servaddr6.sin6_family = AF_INET6;
+               servaddr6.sin6_addr = in6addr_any;
+               servaddr6.sin6_port = htons(g_app_target_port);
+
+               /* bind to the in6addr_any */
+               ret = bind(fd, (struct sockaddr *)&servaddr6, addrlen);
+       } else {
+               /* create IPV4 udp socket */
+               fd = socket(AF_INET, SOCK_DGRAM, 0);
+               if (fd < 0) {
+                       printf("[UDPSERV%s] socket err: %d\n", NETTEST_IPV(ipver), errno);
+                       exit(1);
+               }
+
+               /* initialize socket information */
+               addrlen = sizeof(struct sockaddr_in);
+               memset(&servaddr, 0, addrlen);
+
+               servaddr.sin_family = AF_INET;
+               servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+               servaddr.sin_port = htons(g_app_target_port);
+
+               /* bind to the INADDR_ANY */
+               ret = bind(fd, (struct sockaddr *)&servaddr, addrlen);
+       }
+       if (ret < 0) {
+               printf("[UDPSERV%s] bind err: %d\n", NETTEST_IPV(ipver), errno);
+               goto errout_with_socket;
+       }
+       printf("[UDPSERV%s] waiting on port %d\n", NETTEST_IPV(ipver), g_app_target_port);
+
+       /* fds is used to initialize rfds and sfds */
+       FD_ZERO(&fds);
+       FD_SET(fd, &fds);
+
+       maxfd = fd + 1;
+       while (1) {
+               rfds = fds;
+               FD_ZERO(&sfds);
+               if (have_received) {
+                       /* sfds should be set when it has something to send */
+                       sfds = fds;
+               }
+
+               ret = select(maxfd, &rfds, &sfds, NULL, NULL);
+               if (ret < 0) {
+                       printf("[UDPSERV%s] select err: %d\n", NETTEST_IPV(ipver), errno);
+                       break;
+               }
+               if (ret > 0) {
+                       if (FD_ISSET(fd, &sfds)) {
+                               if (ipver == 1) {
+
+                                       nbytes = sendto(fd, msg, BUF_SIZE, 0, (struct sockaddr *)&cliaddr6, addrlen);
+
+                               } else {
+                                       nbytes = sendto(fd, msg, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, addrlen);
+                               }
+                               if (nbytes <= 0) {
+                                       printf("[UDPSERV%s] sendto err: %d\n", NETTEST_IPV(ipver), errno);
+                                       break;
+                               } else {
+                                       have_received--;
+                                       if (num_packets == 0) {
+                                               /* infinite test */
+                                               if (!(count % 1000)) {
+                                                       printf("[UDPSERV%s infinite test #%d] echoback msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, msg, nbytes);
+                                               }
+                                       } else {
+                                               printf("[UDPSERV%s test #%d] echoback msg(%s) len(%d)\n", NETTEST_IPV(ipver),count, msg, nbytes);
+                                               if (count >= num_packets) {
+                                                       printf("[UDPSERV%s test done #%d]\n", NETTEST_IPV(ipver), count);
+                                                       break;
+                                               }
+                                       }
+                                       count++;
+                               }
+                       }
+                       if (FD_ISSET(fd, &rfds)) {
+                               if (ipver == 1) {
+
+                                       nbytes = recvfrom(fd, msg, BUF_SIZE, 0, (struct sockaddr *)&cliaddr6, &addrlen);
+
+                               } else {
+                                       nbytes = recvfrom(fd, msg, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &addrlen);
+                               }
+                               if (nbytes <= 0) {
+                                       printf("[UDPSERV%s] recvfrom err: %d\n", NETTEST_IPV(ipver), errno);
+                                       break;
+                               }
+                               have_received++;
+                       }
+               } else {
+                       printf("[UDPSERV%s] select err: %d\n", NETTEST_IPV(ipver), errno);
+                       break;
+               }
+       }
+
+       close(fd);
+       return;
+
+errout_with_socket:
+       close(fd);
+       exit(1);
+}
+
+void tcp_client_thread(int num_packets, int ipver)
+{
+       struct sockaddr_in cliaddr;
+
+       struct addrinfo *cliaddr6;
+
+       int ret;
+       int fd;
+       int count = 1;
+       int nbytes = 0;
+       socklen_t addrlen;
+       char sbuf[BUF_SIZE];
+       char rbuf[BUF_SIZE];
+
+       if (ipver == 1) {
+
+               char addr6_str[50];
+               char port_str[10];
+               struct addrinfo hints;
+               struct addrinfo *rp;
+
+               memset(addr6_str, 0, 50);
+               snprintf(addr6_str, 50, "%s", g_app_target_addr);
+               memset(port_str, 0, 10);
+               snprintf(port_str, 10, "%d", g_app_target_port);
+
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET6;
+               hints.ai_socktype = SOCK_STREAM;
+               inet_pton(AF_INET6, addr6_str, &hints.ai_addr);
+
+               ret = getaddrinfo(addr6_str, port_str, &hints, &cliaddr6);
+               if (ret != 0) {
+                       printf("[TCPCLI%s] getaddrinfo err: %d\n", NETTEST_IPV(ipver), ret);
+                       exit(1);
+               }
+
+               for (rp = cliaddr6; rp != NULL; rp = rp->ai_next) {
+                       memset(addr6_str, 0, 50);
+                       inet_ntop(AF_INET6, rp->ai_addr, addr6_str, 50);
+                       printf("[TCPCLI%s] addr: %s port:%s family: %d type: %d protocol: %d\n", NETTEST_IPV(ipver), addr6_str, port_str, rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+
+                       fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+                       if (fd < 0) {
+                               continue;
+                       }
+
+                       if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                               /* success */
+                               break;
+                       }
+                       close(fd);
+               }
+               if (rp == NULL) {
+                       printf("[TCPCLI%s] connection fail\n", NETTEST_IPV(ipver));
+                       freeaddrinfo(cliaddr6);
+                       exit(1);
+               }
+               freeaddrinfo(cliaddr6);
+       } else {
+               char addr6_str[40];
+               fd = socket(AF_INET, SOCK_STREAM, 0);
+
+               cliaddr.sin_family = AF_INET;
+               cliaddr.sin_port = htons(g_app_target_port);
+               inet_pton(AF_INET, g_app_target_addr, &cliaddr.sin_addr);
+               addrlen = sizeof(struct sockaddr_in);
+
+               inet_ntop(AF_INET, &cliaddr.sin_addr, addr6_str, 40);
+               printf("[TCPCLI%s] addr: %s port: %d\n", NETTEST_IPV(ipver), addr6_str, htons(cliaddr.sin_port));
+
+               ret = connect(fd, (struct sockaddr *)&cliaddr, addrlen);
+       }
+       if (ret < 0) {
+               printf("[TCPCLI%s] connect err: %d\n", NETTEST_IPV(ipver), errno);
+               close(fd);
+               exit(1);
+       }
+
+       memset(sbuf, 0, BUF_SIZE);
+       snprintf(sbuf, sizeof("hello, TCP_VX"), "hello, TCP%s", NETTEST_IPV(ipver));
+       memset(rbuf, 0, BUF_SIZE);
+
+       while(1) {
+               nbytes = send(fd, sbuf, BUF_SIZE, 0);
+               if (nbytes <= 0) {
+                       printf("[TCPCLI%s] send err: %d\n", NETTEST_IPV(ipver), errno);
+                       break;
+               }
+
+               nbytes = recv(fd, rbuf, BUF_SIZE, 0);
+               if (nbytes <= 0) {
+                       printf("[TCPCLI%s] recv err: %d\n", NETTEST_IPV(ipver), errno);
+                       break;
+               }
+
+               if (num_packets == 0) {
+                       if(!(count % 1000)) {
+                               printf("[TCPCLI%s infinite test #%d] msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, rbuf, nbytes);
+                       }
+               } else {
+                       printf("[TCPCLI%s test #%d] msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, rbuf, nbytes);
+                       if (count >= num_packets) {
+                               printf("[TCPCLI%s test done #%d]\n", NETTEST_IPV(ipver), count);
+                               break;
+                       }
+               }
+               count++;
+       }
+
+       close(fd);
+       return;
+}
+
+void tcp_server_thread(int num_packets, int ipver)
+{
+       struct sockaddr_in servaddr;
+       struct sockaddr_in cliaddr;
+
+       struct sockaddr_in6 servaddr6;
+       struct sockaddr_in6 cliaddr6;
+
+       char msg[BUF_SIZE];
+       int listenfd = -1;
+       int connfd = -1;
+       int ret = 0;
+       int nbytes = 0;
+       int count = 1;
+       socklen_t addrlen;
+
+       if (ipver == 1) {
+               /* create tcp ipv6 socket */
+
+               listenfd = socket(AF_INET6, SOCK_STREAM, 0);
+       } else {
+               /* create tcp ipv4 socket */
+               listenfd = socket(AF_INET, SOCK_STREAM, 0);
+       }
+       if (listenfd < 0) {
+               printf("[TCPSERV%s] socket err: %d\n", NETTEST_IPV(ipver), errno);
+               exit(1);
+       }
+
+       /* Enable SO_REUSEADDR to allow multiple instances */
+       int reuse = 1;
+       ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse));
+       if (ret < 0) {
+               printf("[TCPSERV%s] setsockopt err: %d\n", NETTEST_IPV(ipver), errno);
+               goto errout_with_socket;
+       }
+
+       if (ipver == 1) {
+
+               char addr6_str[40];
+
+               /* initialize ipv6 socket information */
+               addrlen = sizeof(struct sockaddr_in6);
+               memset(&servaddr6, 0, addrlen);
+               servaddr6.sin6_family = AF_INET6;
+               servaddr6.sin6_addr = in6addr_any;
+               servaddr6.sin6_port = htons(g_app_target_port);
+
+               inet_ntop(AF_INET6, (void *)&servaddr6.sin6_addr, addr6_str, 40);
+               printf("[TCPSERV%s] addr6_str: %s, port: %d\n", NETTEST_IPV(ipver), addr6_str, htons(servaddr6.sin6_port));
+
+               /* bind to in6addr_any */
+               ret = bind(listenfd, (struct sockaddr *)&servaddr6, addrlen);
+
+       } else {
+               char addr_str[40];
+
+               /* initialize ipv4 socket information */
+               addrlen = sizeof(struct sockaddr_in);
+               memset(&servaddr, 0, addrlen);
+               servaddr.sin_family = AF_INET;
+               servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+               servaddr.sin_port = htons(g_app_target_port);
+
+               inet_ntop(AF_INET, (void *)&servaddr.sin_addr, addr_str, 40);
+               printf("[TCP_SERV%s] addr_str: %s, port: %d\n", NETTEST_IPV(ipver), addr_str, htons(servaddr.sin_port));
+
+               /* bind to in6addr_any */
+               ret = bind(listenfd, (struct sockaddr *)&servaddr, addrlen);
+       }
+       if (ret < 0) {
+               printf("[TCPSERV%s] bind err: %d\n", NETTEST_IPV(ipver), errno);
+               goto errout_with_socket;
+       }
+
+       /* start listening socket fd */
+       ret = listen(listenfd, 1024);
+       if (ret < 0) {
+               printf("[TCPSERV%s] listen err: %d\n", NETTEST_IPV(ipver), errno);
+               goto errout_with_socket;
+       }
+
+       if (ipver == 1) {
+
+               /* accept ipv6 socket */
+               connfd = accept(listenfd, (struct sockaddr *)&cliaddr6, &addrlen);
+
+       } else {
+               /* accept ipv4 socket */
+               connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &addrlen);
+       }
+       if (connfd < 0) {
+               printf("[TCPSERV%s] accept err: %d\n", NETTEST_IPV(ipver), errno);
+               goto errout_with_socket;
+       }
+
+       while (1) {
+               /* echo back loop */
+               nbytes = recv(connfd, msg, BUF_SIZE, 0);
+               if (nbytes <= 0) {
+                       printf("[TCPSERV%s] recv err: %d\n", NETTEST_IPV(ipver), errno);
+                       break;
+               }
+
+               nbytes = send(connfd, msg, BUF_SIZE, 0);
+               if (nbytes <= 0) {
+                       printf("[TCPSERV%s] send err: %d\n", NETTEST_IPV(ipver),errno);
+                       break;
+               }
+
+               if (num_packets == 0) {
+                       /* Infinite echo back */
+                       if (!(count % 1000)) {
+                               printf("[TCPSERV%s infinite test #%d] echoback msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, msg, nbytes);
+                       }
+               } else {
+                       printf("[TCPSERV%s test #%d] echoback msg(%s) len(%d)\n", NETTEST_IPV(ipver), count, msg, nbytes);
+                       if (count >= num_packets) {
+                               printf("[TCPSERV%s test done #%d]\n", NETTEST_IPV(ipver), count);
+                               break;
+                       }
+               }
+               count++;
+       }
+
+       if (connfd > 0) {
+               close(connfd);
+       }
+       close(listenfd);
+       return;
+
+errout_with_socket:
+       close(listenfd);
+       exit(1);
+}
+
+/* Sample App to test Transport Layer (TCP / UDP) / IP Multicast Functionality */
+int main(int argc, char *argv[])
+{
+       int proto;
+       int num_packets_to_process;
+
+       if (argc < 3) {
+               printf("\nUsage1: %s proto target_port option1\n", argv[0]);
+               printf("\tUsage1 is for echoback SERVER\n");
+               printf("Parameter:\n");
+               printf("\tproto - 0(tcp ipv4 echoback), 1(tcp ipv6 echoback)\n");
+               printf("\t        2(udp ipv4 echoback), 3(udp ipv6 echoback)\n");
+               printf("\ttarget_port - port address to bind\n");
+               printf("\toption1 - number of pakcets to test, default: %d\n", NUM_PACKETS);
+               printf("Sample Command(tcp ipv4 echoback server): nettest 0 8888 1000(option1)\n\n");
+
+               printf("Usage2: %s proto target_addr target_port option1\n", argv[0]);
+               printf("\tUsage2 is for CLIENT that expects echoing back from the server\n");
+               printf("Parameter:\n");
+               printf("\tproto - 10(tcp ipv4 client), 11(tcp ipv6 client)\n");
+               printf("\t        12(udp ipv4 client), 13(udp ipv6 client)\n");
+               printf("\ttarget_addr - target IP address to send or connect\n");
+               printf("\ttarget_port - target port address to send or connect\n");
+               printf("\toption1 - number of packets to test, default: %d\n\n", NUM_PACKETS);
+               printf("Sample Command(udp ipv6 client): nettest 13 fe80::dcc3:3084:cb9b:38ce%%wl1 8888 1000(option1)\n\n");
+
+               return 0;
+       }
+
+       proto = atoi(argv[1]);
+       num_packets_to_process = NUM_PACKETS;
+
+       if (proto >= 0 && proto < 10) {
+               g_app_target_port = atoi(argv[2]);
+
+               if (argc >= 4) {
+                       num_packets_to_process = atoi(argv[3]);
+               }
+       }
+
+       if (proto >= 10 && proto < 20) {
+               g_app_target_addr = argv[2];
+               g_app_target_port = atoi(argv[3]);
+
+               if (argc >= 5) {
+                       num_packets_to_process = atoi(argv[4]);
+               }
+       }
+
+       if (proto >= 20 && proto < 30) {
+               g_app_target_addr = argv[2];
+               g_app_target_port = atoi(argv[3]);
+
+               if (argc >= 5) {
+                       num_packets_to_process = atoi(argv[4]);
+               }
+
+               if (argc >= 6) {
+                       g_app_netif_addr = argv[5];
+               } else {
+                       g_app_netif_addr = INADDR_ANY;
+               }
+       }
+
+       switch (proto) {
+       case 0:
+               /* IPV4 TCP echo back server test */
+               tcp_server_thread(num_packets_to_process, 0);
+               break;
+       case 1:
+               /* IPV6 TCP echo back server test */
+               tcp_server_thread(num_packets_to_process, 1);
+               break;
+       case 2:
+               /* IPV4 UDP echo back server test */
+               udp_server_thread(num_packets_to_process, 0);
+               break;
+       case 3:
+               /* IPV6 UDP echo back server test */
+               udp_server_thread(num_packets_to_process, 1);
+               break;
+
+       case 10:
+               /* IPV4 TCP client test */
+               tcp_client_thread(num_packets_to_process, 0);
+               break;
+       case 11:
+               /* IPV6 TCP client test */
+               tcp_client_thread(num_packets_to_process, 1);
+               break;
+       case 12:
+               /* IPV4 UDP client test */
+               udp_client_thread(num_packets_to_process, 0);
+               break;
+       case 13:
+               /* IPV6 UDP client test */
+               udp_client_thread(num_packets_to_process, 1);
+               break;
+
+       case 20:
+               /* ipmulticast send */
+               ipmcast_sender_thread(num_packets_to_process);
+               break;
+       case 21:
+               /* ipmulticast receive */
+               ipmcast_receiver_thread(num_packets_to_process);
+               break;
+       default:
+               printf("[NETTEST APP] Invalid proto type\n");
+               break;
+       }
+       printf("\nExiting nettest_main thread, job finished\n");
+       return 0;
+}