No, it doesn't work.

Attaching the applications being used.

"Select" also has similar kind of issue when called from non-main thread

Thread 9 "nstack_select" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd77fe700 (LWP 63170)]
0x00007ffff4e1d032 in ldp_select_init_maps (original=0x7fffbc0008c0,
resultb=0x7fffe002e514, libcb=0x7fffe002e544, vclb=0x7fffe002e52c, nfds=34,
minbits=64, n_bytes=5, si_bits=0x7fffd77fdc20,
    libc_bits=0x7fffd77fdc28) at
/home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:601
601   clib_bitmap_validate (*vclb, minbits);
(gdb) bt
#0  0x00007ffff4e1d032 in ldp_select_init_maps (original=0x7fffbc0008c0,
resultb=0x7fffe002e514, libcb=0x7fffe002e544, vclb=0x7fffe002e52c, nfds=34,
minbits=64, n_bytes=5, si_bits=0x7fffd77fdc20,
    libc_bits=0x7fffd77fdc28) at
/home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:601
#1  0x00007ffff4e1db47 in ldp_pselect (nfds=34, readfds=0x7fffbc0008c0,
writefds=0x7fffbc000cd0, exceptfds=0x7fffbc0010e0, timeout=0x7fffd77fdcb0,
sigmask=0x0)
    at
/home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:723
#2  0x00007ffff4e1e5d5 in select (nfds=34, readfds=0x7fffbc0008c0,
writefds=0x7fffbc000cd0, exceptfds=0x7fffbc0010e0, timeout=0x7fffd77fdd20)
    at
/home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:857
#3  0x00007ffff7b4c42a in nstack_select_thread (arg=0x0) at
/home/root1/sharath/2019/vpp_ver/19.04/dmm/src/nSocket/nstack/event/select/nstack_select.c:651
#4  0x00007ffff78ed6ba in start_thread (arg=0x7fffd77fe700) at
pthread_create.c:333
#5  0x00007ffff741b41d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:109


Before https://gerrit.fd.io/r/#/c/18597/ I have tried to fix the issue.

The below changes fixed epoll_wait and epoll_ctl issues for me.[doesn't
include the changes of https://gerrit.fd.io/r/#/c/18597/]

diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c
index fb19b5d..e6c891b 100644
--- a/src/vcl/vcl_locked.c
+++ b/src/vcl/vcl_locked.c
@@ -564,7 +564,10 @@ vls_attr (vls_handle_t vlsh, uint32_t op, void
*buffer, uint32_t * buflen)

   if (!(vls = vls_get_w_dlock (vlsh)))
     return VPPCOM_EBADFD;
+
+  vls_mt_guard (0, VLS_MT_OP_XPOLL);
   rv = vppcom_session_attr (vls_to_sh_tu (vls), op, buffer, buflen);
+  vls_mt_unguard ();
   vls_get_and_unlock (vlsh);
   return rv;
 }
@@ -773,8 +776,10 @@ vls_epoll_ctl (vls_handle_t ep_vlsh, int op,
vls_handle_t vlsh,
   vls_table_rlock ();
   ep_vls = vls_get_and_lock (ep_vlsh);
   vls = vls_get_and_lock (vlsh);
+  vls_mt_guard (0, VLS_MT_OP_XPOLL);
   ep_sh = vls_to_sh (ep_vls);
   sh = vls_to_sh (vls);
+  vls_mt_unguard ();

   if (PREDICT_FALSE (!vlsl->epoll_mp_check))
     vls_epoll_ctl_mp_checks (vls, op);

Thanks,
Sharath.

On Fri, Mar 29, 2019 at 9:15 PM Florin Coras <fcoras.li...@gmail.com> wrote:

> Interesting. What application are you running and does this [1] fix the
> issue for you?
>
> In short, many of vls’ apis check if the call is coming in on a new
> pthread and program vcl accordingly if yes. The patch makes sure vls_attr
> does that as well.
>
> Thanks,
> Florin
>
> [1] https://gerrit.fd.io/r/#/c/18597/
>
> On Mar 29, 2019, at 4:29 AM, Dave Barach via Lists.Fd.Io <
> dbarach=cisco....@lists.fd.io> wrote:
>
> For whatever reason, the vls layer received an event notification which
> didn’t end well. vcl_worker_get (wrk_index=4294967295) [aka 0xFFFFFFFF]
> will never work.
>
> I’ll let Florin comment further. He’s in the PDT time zone, so don’t
> expect to hear from him for a few hours.
>
> D.
>
> *From:* vpp-dev@lists.fd.io <vpp-dev@lists.fd.io> *On Behalf Of *sharath
> kumar
> *Sent:* Friday, March 29, 2019 12:18 AM
> *To:* vpp-dev@lists.fd.io; csit-...@lists.fd.io
> *Subject:* [vpp-dev] multi-threaded application, "epoll_wait" and
> "epoll_ctl" have "received signal SIGABRT, Aborted".
>
> Hello all,
>
> I am a newbie to VPP.
>
> I am trying to run VPP with a multi-threaded application.
> "recv" works fine from non-main threads,
> whereas "epoll_wait" and "epoll_ctl" have "received signal SIGABRT,
> Aborted".
>
> Is this a known issue?
> Or am I doing something wrong?
>
> Attaching  backtrace for  "epoll_wait" and "epoll_ctl"
>
> Thread 9 "dmm_vcl_epoll" received signal SIGABRT, Aborted.
> [Switching to Thread 0x7fffd67fe700 (LWP 56234)]
> 0x00007ffff7349428 in __GI_raise (sig=sig@entry=6) at
> ../sysdeps/unix/sysv/linux/raise.c:54
> 54          ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
> (gdb) bt
> #0  0x00007ffff7349428 in __GI_raise (sig=sig@entry=6) at
> ../sysdeps/unix/sysv/linux/raise.c:54
> #1  0x00007ffff734b02a in __GI_abort () at abort.c:89
> #2  0x00007ffff496d873 in os_panic () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/unix-misc.c:176
> #3  0x00007ffff48ce42c in debugger () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/error.c:84
> #4  0x00007ffff48ce864 in _clib_error (how_to_die=2, function_name=0x0,
> line_number=0, fmt=0x7ffff4bfe0e0 "%s:%d (%s) assertion `%s' fails")
>     at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/error.c:143
> #5  0x00007ffff4bcca7d in vcl_worker_get (wrk_index=4294967295) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_private.h:540
> #6  0x00007ffff4bccabe in vcl_worker_get_current () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_private.h:554
> #7  0x00007ffff4bd7c49 in vppcom_session_attr (session_handle=4278190080,
> op=6, buffer=0x0, buflen=0x0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vppcom.c:2606
> #8  0x00007ffff4bfc7fd in vls_attr (vlsh=0, op=6, buffer=0x0, buflen=0x0)
> at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_locked.c:569
> #9  0x00007ffff4e21736 in ldp_epoll_pwait (epfd=32, events=0x7fffd67fad20,
> maxevents=1024, timeout=100, sigmask=0x0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:2203
> #10 0x00007ffff4e21948 in epoll_wait (epfd=32, events=0x7fffd67fad20,
> maxevents=1024, timeout=100) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:2257
> #11 0x00007ffff4e13041 in dmm_vcl_epoll_thread (arg=0x0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/dmm_vcl_adpt.c:75
> #12 0x00007ffff78ed6ba in start_thread (arg=0x7fffd67fe700) at
> pthread_create.c:333
> #13 0x00007ffff741b41d in clone () at
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
>
>
>
>
> Thread 11 "vs_epoll" received signal SIGABRT, Aborted.
> 0x00007ffff7349428 in __GI_raise (sig=sig@entry=6) at
> ../sysdeps/unix/sysv/linux/raise.c:54
> 54          ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
> (gdb) bt
> #0  0x00007ffff7349428 in __GI_raise (sig=sig@entry=6) at
> ../sysdeps/unix/sysv/linux/raise.c:54
> #1  0x00007ffff734b02a in __GI_abort () at abort.c:89
> #2  0x00007ffff496d873 in os_panic () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/unix-misc.c:176
> #3  0x00007ffff48ce42c in debugger () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/error.c:84
> #4  0x00007ffff48ce864 in _clib_error (how_to_die=2, function_name=0x0,
> line_number=0, fmt=0x7ffff4bfe1a0 "%s:%d (%s) assertion `%s' fails")
>     at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vppinfra/error.c:143
> #5  0x00007ffff4bcca7d in vcl_worker_get (wrk_index=4294967295) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_private.h:540
> #6  0x00007ffff4bccabe in vcl_worker_get_current () at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_private.h:554
> #7  0x00007ffff4bd597a in vppcom_epoll_ctl (vep_handle=4278190080, op=1,
> session_handle=4278190082, event=0x7fffd4dfb3b0)
>     at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vppcom.c:2152
> #8  0x00007ffff4bfd061 in vls_epoll_ctl (ep_vlsh=0, op=1, vlsh=2,
> event=0x7fffd4dfb3b0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/vcl_locked.c:787
> #9  0x00007ffff4e213b6 in epoll_ctl (epfd=32, op=1, fd=34,
> event=0x7fffd4dfb3b0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/ldp.c:2118
> #10 0x00007ffff4e12f88 in vpphs_ep_ctl_ops (epFD=-1, proFD=34, ctl_ops=0,
> events=0x7fffd5190078, pdata=0x7fffd53f01d0)
>     at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/stacks/vpp/vpp/src/vcl/dmm_vcl_adpt.c:48
> #11 0x00007ffff7b4d502 in nsep_epctl_triggle (epi=0x7fffd5190018,
> info=0x7fffd53f01d0, triggle_ops=0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/src/nSocket/nstack/event/epoll/nstack_eventpoll.c:134
> #12 0x00007ffff7b4de31 in nsep_insert_node (ep=0x7fffd50bffa8,
> event=0x7fffd4dfb5a0, fdInfo=0x7fffd53f01d0)
>     at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/src/nSocket/nstack/event/epoll/nstack_eventpoll.c:250
> #13 0x00007ffff7b4e480 in nsep_epctl_add (ep=0x7fffd50bffa8, fd=22,
> events=0x7fffd4dfb5a0) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/src/nSocket/nstack/event/epoll/nstack_eventpoll.c:294
> #14 0x00007ffff7b44db0 in nstack_epoll_ctl (epfd=21, op=1, fd=22,
> event=0x7fffd4dfb630) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/src/nSocket/nstack/nstack_socket.c:2499
> #15 0x0000000000401e65 in process_server_msg_thread (pArgv=<optimized
> out>) at
> /home/root1/sharath/2019/vpp_ver/19.04/dmm/app_example/perf-test/multi_tcp_epoll_app_Ser.c:369
> #16 0x00007ffff78ed6ba in start_thread (arg=0x7fffd4dff700) at
> pthread_create.c:333
> #17 0x00007ffff741b41d in clone () at
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
>
> Thanks and Regards,
> Sharath.
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
>
> View/Reply Online (#12665): https://lists.fd.io/g/vpp-dev/message/12665
> Mute This Topic: https://lists.fd.io/mt/30819724/675152
> Group Owner: vpp-dev+ow...@lists.fd.io
> Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub  [fcoras.li...@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
>
>
/*
*
* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
* 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.
*/

#define _GNU_SOURCE
#include <sys/socket.h>
#include <fcntl.h>
#include <memory.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <time.h>
#include <linux/tcp.h>
#include <sched.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>

#define _BIND bind
#define _LISTEN listen
#define _SOCKET socket
#define _ACCEPT accept
#define _SEND send
#define _RECV recv
#define _CLOSE close
#define _CONNECT connect
#define _PROTOCOL IPPROTO_TCP

#define MAX_TEST_TIME 1000
#define MSG_LENGTH 256
#define CORE_NUM 8
#define START_CPU_ID 2
#define MAX_CONN_LIMIT 256
#define MAX_PORT_NUM 65535
//1:A-B ;0:A-B-A
#define SEND_RECV_MODE 1
#define MAX_EVENTS 1000
#define Default_PortID 12345
#define Default_SleepCnt 10000
#define Default_SleepTime 1000000
#define  Flag_Print 1
#define  Fd_Number 1

static struct sockaddr_in g_dest;
static struct sockaddr_in g_src;
static struct sockaddr_in g_recv;

int times = MAX_TEST_TIME;
int msg_length = MSG_LENGTH;
int coreNum = CORE_NUM;
int startCPUId = START_CPU_ID;
int connectNum = MAX_CONN_LIMIT;
int msgMode = SEND_RECV_MODE;
int sleepCnt = Default_SleepCnt;
int sleepTime = Default_SleepTime;      //us
int fdNumber = Fd_Number;
int flagPrint = Flag_Print;
int unitPrint = 0;
int waitTime = 0;

int srcPort = Default_PortID;
int destPort = 0;
int recvPort = 0;
char sendarr[256] = "";
char recvarr[256] = "";
char destarr[256] = "";

static void
setArgsDefault ()
{

  memset (&g_dest, 0, sizeof (g_dest));
  g_dest.sin_family = AF_INET;
  g_dest.sin_addr.s_addr = inet_addr ("127.0.0.1");
  g_dest.sin_port = htons (12345);
  bzero (&(g_dest.sin_zero), 8);

  memset (&g_src, 0, sizeof (g_src));
  g_src.sin_family = AF_INET;
  g_src.sin_addr.s_addr = inet_addr ("0.0.0.0");
  g_src.sin_port = htons (7895);
  bzero (&(g_src.sin_zero), 8);

  memset (&g_recv, 0, sizeof (g_recv));
  g_recv.sin_family = AF_INET;
  g_recv.sin_addr.s_addr = inet_addr ("0.0.0.0");
  g_recv.sin_port = htons (7895);
  bzero (&(g_recv.sin_zero), 8);

}

static int
process_arg (int argc, char *argv[])
{
  int opt = 0;
  int error = 0;
  const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:";
  int rw_mark = 0;

  if (argc < 4)
    {
      printf
        ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n");
      printf
        ("\t-t MAX_TEST_TIME; -i  msg_interval ; -f  client fd number ; -r receive port; -n connectNum(one server vs n client)\n");
      return 0;
    }
  while ((opt = getopt (argc, argv, optstring)) != -1)
    {
      switch (opt)
        {
        case 'p':
          destPort = atoi (optarg);
          g_dest.sin_port = htons (atoi (optarg));
          break;
        case 'd':
          stpcpy (destarr, optarg);
          g_dest.sin_addr.s_addr = inet_addr (optarg);
          break;
        case 's':
          stpcpy (sendarr, optarg);
          g_src.sin_addr.s_addr = inet_addr (optarg);
          g_recv.sin_addr.s_addr = inet_addr (optarg);
          break;
        case 'a':
          //g_src.sin_port = htons(atoi(optarg));
          srcPort = atoi (optarg);
          break;
        case 'l':
          msg_length = atoi (optarg);
          break;
        case 't':
          times = atoi (optarg);
          break;
        case 'e':
          sleepCnt = atoi (optarg);
          break;
        case 'i':
          sleepTime = atoi (optarg);
          break;
        case 'f':
          fdNumber = atoi (optarg);
          break;
        case 'r':
          recvPort = atoi (optarg);
          g_recv.sin_port = htons (atoi (optarg));
          break;
        case 'n':
          connectNum = atoi (optarg);
          break;
        case 'w':
          waitTime = atoi (optarg);
          break;
        case 'u':
          unitPrint = atoi (optarg);
          break;
        case 'x':
          flagPrint = atoi (optarg);
          break;

        }
    }
  return 1;
}

void
process_client (void)
{
  int sendLen = 0;
  int i = 0, t = 0, p = 0, optval = 0, ret = 0;
  char send_buf[1000] = "";
  int c_socketfd[100] = { 0 };
  int errbind[1000] = { 0 };
  int errconn[1000] = { 0 };

  int send_count[1000] = { 0 };
  int pps = 0;
  long pps_time = 0;

  struct timespec startTime, endTime;
  struct timespec countStart;
  struct timespec countEnd;
  memset (&countStart, 0, sizeof (countStart));
  memset (&countEnd, 0, sizeof (countEnd));

  for (i = 0; i < fdNumber; i++)
    {
      c_socketfd[i] = _SOCKET (PF_INET, SOCK_STREAM, _PROTOCOL);
      if (0 > c_socketfd[i])
        {
          printf ("client %d failed,err %d\n", i, errno);
        }
      else
        {
          printf ("client %d created success\n", i);
        }
    }

  for (i = 0; i < fdNumber; i++)
    {
      optval = 1;
      ret =
        setsockopt (c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
                    sizeof (optval));
      if (ret == -1)
        {
          printf ("Couldn't setsockopt(SO_REUSEADDR)\n");
          break;
        }
    }

  for (i = 0; i < fdNumber; i++)
    {
      g_src.sin_port = htons (srcPort + i);
      errbind[i] =
        _BIND (c_socketfd[i], (struct sockaddr *) &g_src, sizeof (g_src));
      if (errbind[i] < 0)
        {
          printf ("client %d bind Failed %d\n", i, errno);
          _CLOSE (c_socketfd[i]);
          c_socketfd[i] = -1;
          continue;
        }
      else
        {
          printf ("client %d bind Success port:%d IP:%s\n", i,
                  ntohs (g_src.sin_port),
                  inet_ntoa (*((struct in_addr *) &(g_src.sin_addr.s_addr))));
        }
    }
  for (i = 0; i < fdNumber; i++)
    {
      if (errbind[i] >= 0)
        {
          errconn[i] =
            _CONNECT (c_socketfd[i], (struct sockaddr *) &g_dest,
                      sizeof (g_dest));
          if (errconn[i] < 0)
            {
              printf ("client %d Connect Failed %d\n", i, errno);
              _CLOSE (c_socketfd[i]);
              c_socketfd[i] = -1;
              continue;
            }
          else
            {
              printf ("client %d Connect Success port:%d, IP:%s\n", i,
                      ntohs (g_dest.sin_port),
                      inet_ntoa (*
                                 ((struct in_addr *)
                                  &(g_dest.sin_addr.s_addr))));
            }
        }
    }

  sleep (1);

  clock_gettime (CLOCK_MONOTONIC, &startTime);
  clock_gettime (CLOCK_MONOTONIC, &countStart);

  for (t = 0; t < times; t++)
    {
      for (i = 0; i < fdNumber; i++)
        {
          if (c_socketfd[i] < 0)
            {
              continue;
            }
          do
            {
              sendLen = _SEND (c_socketfd[i], send_buf, msg_length, 0);
            }
          while (sendLen <= 0);
          send_count[i]++;
        }

      if (0 != sleepTime)
        {
          if ((t % sleepCnt) == 0)
            {
              usleep (sleepTime);
            }
        }

      if ((send_count[0] % unitPrint) == 0)
        {
          clock_gettime (CLOCK_MONOTONIC, &countEnd);

          pps_time =
            (countEnd.tv_sec - countStart.tv_sec) * 1000000000 +
            countEnd.tv_nsec - countStart.tv_nsec;
          pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber;
          if ((flagPrint != 0))
            {
              printf (" sendcount %d, time: %ld ns\n",
                      send_count[0] * fdNumber, pps_time);
            }
          printf ("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps);
          clock_gettime (CLOCK_MONOTONIC, &countStart);
        }

    }

  clock_gettime (CLOCK_MONOTONIC, &endTime);

  for (i = 0; i < fdNumber; i++)
    {
      printf ("client %d send %d , sendtime :%ld s %ld ns\n", i,
              send_count[i], endTime.tv_sec - startTime.tv_sec,
              endTime.tv_nsec - startTime.tv_nsec);
    }

  for (i = 0; i < fdNumber; i++)
    {
      printf ("client %d close!\n", i);
      if (c_socketfd[i] > 0)
        _CLOSE (c_socketfd[i]);
    }

  pthread_exit (NULL);
}

/*
   using this thread to do recv msg;
*/
void *
process_server_msg_thread (void *pArgv)
{
  int recvLen = 0, recvLen2 = 0;
  char send_buf[1000];
  char recv_buf[1000];
  int recv_count = 0;
  long recv_ppstime = 0;
  int recv_pps = 0;
  int ret;
  struct epoll_event event;

  struct epoll_event eventList[MAX_EVENTS];

  struct timespec recvStart;
  struct timespec recvEnd;
  memset (&recvStart, 0, sizeof (recvStart));
  memset (&recvEnd, 0, sizeof (recvEnd));

  pthread_detach (pthread_self ());

  int msgEpFd = epoll_create (100);
  int msgFd = *(int *) pArgv;

  event.events = EPOLLIN | EPOLLET;
  event.data.fd = msgFd;
  if (epoll_ctl (msgEpFd, EPOLL_CTL_ADD, msgFd, &event) < 0)
    {
      printf ("epoll add fd[%d] to msgEpfd:[%d] failed\n", msgFd, msgEpFd);
      close (msgEpFd);
      close (msgFd);
      return NULL;
    }

  clock_gettime (CLOCK_MONOTONIC, &recvStart);
  while (1)
    {
      int timeout = -1;
      int m;
      int sock;
      ret = epoll_wait (msgEpFd, eventList, MAX_EVENTS, timeout);
      if (ret == 0)
        continue;

      for (m = 0; m < ret; m++)
        {
          if ((eventList[m].events & EPOLLERR)
              || (eventList[m].events & EPOLLHUP)
              || !(eventList[m].events & EPOLLIN))
            {
              printf ("fd %d epoll error event:%d\n", eventList[m].data.fd,
                      eventList[m].events);
              close (eventList[m].data.fd);
              continue;
            }
          else
            {
              recvLen = 0;
              recvLen2 = 0;
              sock = eventList[m].data.fd;

              do
                {
                  recvLen2 =
                    recv (sock, recv_buf + recvLen, msg_length - recvLen, 0);
                  if (recvLen2 <= 0)
                    {
                      break;
                    }
                  else if (recvLen2 == msg_length - recvLen)
                    {
                      recvLen = 0;
                      recv_count++;
                      if (msg_length != send (sock, send_buf, msg_length, 0))
                        {
                          printf ("send failed!====, need exit\n");
                        }
                    }
                  else if (recvLen2 < msg_length - recvLen)
                    {
                      recvLen += recvLen2;
                    }
                  if ((flagPrint != 0) && ((recv_count % unitPrint) == 0))
                    {
                      clock_gettime (CLOCK_MONOTONIC, &recvEnd);
                      recv_ppstime =
                        (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 +
                        recvEnd.tv_nsec - recvStart.tv_nsec;
                      recv_pps =
                        ((float) 1000000000 / recv_ppstime) * unitPrint;
                      printf ("receive count:%d, receive time: %ld ns\n",
                              recv_count, recv_ppstime);
                      printf ("receive pps = %d\n", recv_pps);
                      clock_gettime (CLOCK_MONOTONIC, &recvStart);
                    }
                }
              while (1);
            }

        }

      if (recv_count == times)
        {
          break;
        }
    }
  close (msgFd);
  close (msgEpFd);
}

/*
   using this thread to do accept connect
*/
void *
process_server_accept_thread (void *pArgv)
{
  int listenFd = 0;
  int x, optval, ret = 0;
  int acpt_socketfd[1000] = { 0 };

  listenFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (0 > listenFd)
    {
      printf ("ERROR:socket failed,errno [%d]\n", errno);
      return NULL;
    }
  else
    {
      printf ("INFO:Create listen socket Success, listenFd[%d]\n", listenFd);
    }

  if (0 > fcntl (listenFd, F_SETFL, O_NONBLOCK))
    {
      printf ("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno);
      close (listenFd);
    }

  optval = 1;
  ret =
    setsockopt (listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
                sizeof (optval));
  if (ret == -1)
    {
      printf ("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd,
              errno);
      close (listenFd);
      return NULL;
    }

  if (0 !=
      bind (listenFd, (struct sockaddr *) &g_recv, sizeof (struct sockaddr)))
    {
      printf ("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno);
      printf ("INFO:Bind Failed, port %d IP:%s\n", ntohs (g_recv.sin_port),
              inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr))));
      close (listenFd);
      //return NULL;
      exit (-1);
    }
  else
    {
      printf ("INFO:Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port),
              inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr))));
    }

  if (0 != listen (listenFd, 100))
    {
      printf ("server socket listen failed. err %d\n", errno);
      close (listenFd);
      return NULL;
    }
  printf ("Listen Success\n");

  int accEpFd;
  struct epoll_event eventList[100];
  accEpFd = epoll_create (100);
  struct epoll_event event;
  event.events = EPOLLIN | EPOLLET;
  event.data.fd = listenFd;

  if (epoll_ctl (accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0)
    {
      printf ("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd);
      exit (-1);
    }

  int timeout = -1;
  int accpedNum = 0;
  while (accpedNum < connectNum)
    {
      ret = epoll_wait (accEpFd, eventList, connectNum, timeout);

      if (ret < 0)
        {
          printf ("accept_thread epoll_wait error, epfd[%d], errno[%d]\n",
                  accEpFd, errno);
          continue;
        }
      else if (ret == 0)
        continue;

      /*loop done ever Event */
      for (x = 0; x < ret; x++)
        {
          printf ("event:%d; ret:%d\n", eventList[x].events, ret);
          if ((eventList[x].events & EPOLLERR)
              || !(eventList[x].events & EPOLLIN))
            {
              printf ("epoll fd %d error\n", eventList[x].data.fd);
              close (eventList[x].data.fd);
              continue;
            }

          while (1)
            {
              acpt_socketfd[accpedNum] =
                accept4 (listenFd, NULL, NULL, SOCK_NONBLOCK);
              if (acpt_socketfd[accpedNum] < 0)
                {
                  printf ("no more connect\n");
                  break;
                }
              /*add new accptFd to MsgEpFD */
              pthread_t ser_rcv_thread_id;
              if (pthread_create
                  (&ser_rcv_thread_id, NULL, process_server_msg_thread,
                   (void *) &acpt_socketfd[accpedNum]) == -1)
                {
                  printf ("create process_server_msg_thread fail\n");
                  break;
                }

              printf ("accept cnt [%d], cur accept fd [%d]\n", accpedNum,
                      acpt_socketfd[accpedNum]);
              accpedNum++;
            }
        }
    }

  //close (listenFd);
  close (accEpFd);

  while (1)
    {
      sleep (10);
    }

  pthread_exit (NULL);
}

void
main (int argc, char *argv[])
{
  socklen_t addrlen = sizeof (struct sockaddr);
  int err = 0, result = 0, ret = 0;
  int i = 0, j = 0, optval = 0, z = 0, x, listenfd;
  cpu_set_t mask;

  setArgsDefault ();
  ret = process_arg (argc, argv);
  if (ret != 1)
    {
      printf ("The param error\n");
      return;
    }

  pthread_t server_thread_id;

  if (pthread_create
      (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1)
    {
      printf ("create process_server_accept_thread fail\n");
      return;
    }

  printf ("create process_server_accept_thread success\n");

  if (server_thread_id != 0)
    {
      printf ("Server Thread join\n");
      pthread_join (server_thread_id, NULL);
    }

  while (1)
    {
      sleep (10);
    }

  return;
}
/*
*
* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
* 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.
*/

#define _GNU_SOURCE
#include <sys/socket.h>
#include <fcntl.h>
#include <memory.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <time.h>
#include <linux/tcp.h>
#include <sched.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>

#define _BIND bind
#define _LISTEN listen
#define _SOCKET socket
#define _ACCEPT accept
#define _SEND send
#define _RECV recv
#define _CLOSE close
#define _CONNECT connect
#define _PROTOCOL IPPROTO_TCP

#define MAX_TEST_TIME 1000
#define MSG_LENGTH 256
#define CORE_NUM 8
#define START_CPU_ID 2
#define MAX_CONN_LIMIT 256
#define MAX_PORT_NUM 65535
//1:A-B ;0:A-B-A
#define SEND_RECV_MODE 1
#define MAX_EVENTS 1000
#define Default_PortID 12345
#define Default_SleepCnt 10000
#define Default_SleepTime 1000000
#define  Flag_Print 1
#define  Fd_Number 1

static struct sockaddr_in g_dest;
static struct sockaddr_in g_src;
static struct sockaddr_in g_recv;

int times = MAX_TEST_TIME;
int msg_length = MSG_LENGTH;
int coreNum = CORE_NUM;
int startCPUId = START_CPU_ID;
int connectNum = MAX_CONN_LIMIT;
int msgMode = SEND_RECV_MODE;
int sleepCnt = Default_SleepCnt;
int sleepTime = Default_SleepTime;      //us
int fdNumber = Fd_Number;
int flagPrint = Flag_Print;
int unitPrint = 0;
int waitTime = 0;

int srcPort = Default_PortID;
int destPort = 0;
int recvPort = 0;
char sendarr[256] = "";
char recvarr[256] = "";
char destarr[256] = "";

static void
setArgsDefault ()
{

  memset (&g_dest, 0, sizeof (g_dest));
  g_dest.sin_family = AF_INET;
  g_dest.sin_addr.s_addr = inet_addr ("127.0.0.1");
  g_dest.sin_port = htons (12345);
  bzero (&(g_dest.sin_zero), 8);

  memset (&g_src, 0, sizeof (g_src));
  g_src.sin_family = AF_INET;
  g_src.sin_addr.s_addr = inet_addr ("0.0.0.0");
  g_src.sin_port = htons (7895);
  bzero (&(g_src.sin_zero), 8);

  memset (&g_recv, 0, sizeof (g_recv));
  g_recv.sin_family = AF_INET;
  g_recv.sin_addr.s_addr = inet_addr ("0.0.0.0");
  g_recv.sin_port = htons (7895);
  bzero (&(g_recv.sin_zero), 8);

}

static int
process_arg (int argc, char *argv[])
{
  int opt = 0;
  int error = 0;
  const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:";
  int rw_mark = 0;

  if (argc < 4)
    {
      printf
        ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n");
      printf
        ("\t-t MAX_TEST_TIME; -i  msg_interval ; -f  client fd number ; -r receive port; -n connectNum(one server vs n client)\n");
      return 0;
    }
  while ((opt = getopt (argc, argv, optstring)) != -1)
    {
      switch (opt)
        {
        case 'p':
          destPort = atoi (optarg);
          g_dest.sin_port = htons (atoi (optarg));
          break;
        case 'd':
          stpcpy (destarr, optarg);
          g_dest.sin_addr.s_addr = inet_addr (optarg);
          break;
        case 's':
          stpcpy (sendarr, optarg);
          g_src.sin_addr.s_addr = inet_addr (optarg);
          g_recv.sin_addr.s_addr = inet_addr (optarg);
          break;
        case 'a':
          //g_src.sin_port = htons(atoi(optarg));
          srcPort = atoi (optarg);
          break;
        case 'l':
          msg_length = atoi (optarg);
          break;
        case 't':
          times = atoi (optarg);
          break;
        case 'e':
          sleepCnt = atoi (optarg);
          break;
        case 'i':
          sleepTime = atoi (optarg);
          break;
        case 'f':
          fdNumber = atoi (optarg);
          break;
        case 'r':
          recvPort = atoi (optarg);
          g_recv.sin_port = htons (atoi (optarg));
          break;
        case 'n':
          connectNum = atoi (optarg);
          break;
        case 'w':
          waitTime = atoi (optarg);
          break;
        case 'u':
          unitPrint = atoi (optarg);
          break;
        case 'x':
          flagPrint = atoi (optarg);
          break;

        }
    }
  return 1;
}

/*
   using this thread to do recv msg;
*/
void *
process_server_msg_thread (void *pArgv)
{
  int recvLen = 0, recvLen2 = 0;
  char send_buf[1000];
  char recv_buf[1000];
  int recv_count = 0;
  long recv_ppstime = 0;
  int recv_pps = 0;
  int ret;
  struct timeval timeout;
  fd_set rfds;
  int maxfd;

  struct timespec recvStart;
  struct timespec recvEnd;
  memset (&recvStart, 0, sizeof (recvStart));
  memset (&recvEnd, 0, sizeof (recvEnd));

  pthread_detach (pthread_self ());

  int msgFd = *(int *) pArgv;

  clock_gettime (CLOCK_MONOTONIC, &recvStart);
  while (1)
    {
      FD_ZERO (&rfds);
      FD_SET (msgFd, &rfds);
      maxfd = msgFd + 1;
      timeout.tv_sec = 10;
      timeout.tv_usec = 0;
      ret = select (maxfd, &rfds, NULL, NULL, &timeout);

      if (ret <= 0)
        {
          continue;
        }

      if (FD_ISSET (msgFd, &rfds) == 0)
        {
          continue;
        }

      recvLen = 0;
      recvLen2 = 0;

      do
        {
          recvLen2 =
            recv (msgFd, recv_buf + recvLen, msg_length - recvLen, 0);
          if (recvLen2 <= 0)
            {
              break;
            }
          else if (recvLen2 == msg_length - recvLen)
            {
              recvLen = 0;
              recv_count++;
              if (msg_length != send (msgFd, send_buf, msg_length, 0))
                {
                  printf ("send failed!====, need exit\n");
                }
            }
          else if (recvLen2 < msg_length - recvLen)
            {
              recvLen += recvLen2;
            }
          if ((flagPrint != 0) && ((recv_count % unitPrint) == 0))
            {
              clock_gettime (CLOCK_MONOTONIC, &recvEnd);
              recv_ppstime =
                (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 +
                recvEnd.tv_nsec - recvStart.tv_nsec;
              recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint;
              printf ("receive count:%d, receive time: %ld ns\n",
                      recv_count, recv_ppstime);
              printf ("receive pps = %d\n", recv_pps);
              clock_gettime (CLOCK_MONOTONIC, &recvStart);
            }
        }
      while (1);

      if (recv_count == times)
        {
          break;
        }
    }
  close (msgFd);
}

/*
   using this thread to do accept connect
*/
void *
process_server_accept_thread (void *pArgv)
{
  int listenFd = 0;
  int x, optval, ret, m = 0;
  int acpt_socketfd[1000] = { 0 };
  struct timeval timeout;
  fd_set rfds;
  int maxfd;

  listenFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (0 > listenFd)
    {
      printf ("ERROR:socket failed,errno [%d]\n", errno);
      return NULL;
    }
  else
    {
      printf ("INFO:Create listen socket Success, listenFd[%d]\n", listenFd);
    }

  if (0 > fcntl (listenFd, F_SETFL, O_NONBLOCK))
    {
      printf ("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno);
      close (listenFd);
    }

  optval = 1;
  ret =
    setsockopt (listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
                sizeof (optval));
  if (ret == -1)
    {
      printf ("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd,
              errno);
      close (listenFd);
      return NULL;
    }

  if (0 !=
      bind (listenFd, (struct sockaddr *) &g_recv, sizeof (struct sockaddr)))
    {
      printf ("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno);
      printf ("INFO:Bind Failed, port %d IP:%s\n", ntohs (g_recv.sin_port),
              inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr))));
      close (listenFd);
      //return NULL;
      exit (-1);
    }
  else
    {
      printf ("INFO:Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port),
              inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr))));
    }

  if (0 != listen (listenFd, 100))
    {
      printf ("server socket listen failed. err %d\n", errno);
      close (listenFd);
      return NULL;
    }
  printf ("Listen Success\n");

  int accpedNum = 0;
  while (accpedNum < connectNum)
    {
      FD_ZERO (&rfds);
      FD_SET (listenFd, &rfds);
      maxfd = listenFd + 1;
      timeout.tv_sec = 10;
      timeout.tv_usec = 0;
      ret = select (maxfd, &rfds, NULL, NULL, &timeout);

      if (ret <= 0)
        {
          continue;
        }

      if (FD_ISSET (listenFd, &rfds) == 0)
        {
          continue;
        }

      while (1)
        {
          acpt_socketfd[accpedNum] =
            accept4 (listenFd, NULL, NULL, SOCK_NONBLOCK);
          if (acpt_socketfd[accpedNum] < 0)
            {
              printf ("no more connect\n");
              break;
            }
          /*add new accptFd to MsgEpFD */
          pthread_t ser_rcv_thread_id;
          if (pthread_create
              (&ser_rcv_thread_id, NULL, process_server_msg_thread,
               (void *) &acpt_socketfd[accpedNum]) == -1)
            {
              printf ("create process_server_msg_thread fail\n");
              break;
            }

          printf ("accept cnt [%d], cur accept fd [%d]\n", accpedNum,
                  acpt_socketfd[accpedNum]);
          accpedNum++;
        }
    }

  close (listenFd);

  while (1)
    {
      sleep (10);
    }

  pthread_exit (NULL);
}

void
main (int argc, char *argv[])
{
  socklen_t addrlen = sizeof (struct sockaddr);
  int err = 0, result = 0, ret = 0;
  int i = 0, j = 0, optval = 0, z = 0, x, listenfd;
  cpu_set_t mask;

  setArgsDefault ();
  ret = process_arg (argc, argv);
  if (ret != 1)
    {
      printf ("The param error\n");
      return;
    }

  pthread_t server_thread_id;

  if (pthread_create
      (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1)
    {
      printf ("create process_server_accept_thread fail\n");
      return;
    }

  printf ("create process_server_accept_thread success\n");

  if (server_thread_id != 0)
    {
      printf ("Server Thread join\n");
      pthread_join (server_thread_id, NULL);
    }

  while (1)
    {
      sleep (10);
    }

  return;
}
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#12669): https://lists.fd.io/g/vpp-dev/message/12669
Mute This Topic: https://lists.fd.io/mt/30819724/21656
Group Owner: vpp-dev+ow...@lists.fd.io
Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to