From patchwork Sat Mar 29 02:56:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Santosh Shukla X-Patchwork-Id: 27387 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f72.google.com (mail-pb0-f72.google.com [209.85.160.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 44FCA20062 for ; Sat, 29 Mar 2014 02:56:48 +0000 (UTC) Received: by mail-pb0-f72.google.com with SMTP id jt11sf14160242pbb.7 for ; Fri, 28 Mar 2014 19:56:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:to:cc:subject:date:message-id :in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe:content-type; bh=i50YGgtr7aZUUabgG6dgcvUlOHHAxzkKKg/rkc6xsLE=; b=QkeIKYEe4dGuT2gRzkN/u2m/nCFh6SxBKjU9gooA0KzYZRLlFwUEJh/qhPbJR3I7hH j9q4ds+4yr6+gvbWCmwXTWPMC8w8oJhIQ7B23j2V0BLlzA1bFtRCGdnlh9GUyG5fyWaG GalpT4mbA+k+MfmPS/JdFY56NB3qpbucN+U3yOEN0zb5OiW5vkZ+HVhgEzXCD4OLEJpr nTO2KE/i6+MDRu4FbRScyIvS94kQ5lgfGXyD5OpWygqbNsfiiJf63if64vBSUV8t00sf xRcndFfC4ER5tKNBgVx4bhI6uxsWdb2H7iVPt6F3n/GmviAkOzVtMC7bo6+lBfvM3hQg iS/Q== X-Gm-Message-State: ALoCoQliI2zlKqGjJmdtKNBIlHpXYLOaHV679cg5cXKbvwiyFbg1GnX2m2CQoGHZw9hwGBkI5mXq X-Received: by 10.66.252.198 with SMTP id zu6mr3419432pac.25.1396061807300; Fri, 28 Mar 2014 19:56:47 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: lng-odp@linaro.org Received: by 10.51.17.107 with SMTP id gd11ls199594igd.4.canary; Fri, 28 Mar 2014 19:56:47 -0700 (PDT) X-Received: by 10.50.141.199 with SMTP id rq7mr233327igb.11.1396061807047; Fri, 28 Mar 2014 19:56:47 -0700 (PDT) Received: from mail-ig0-f174.google.com (mail-ig0-f174.google.com [209.85.213.174]) by mx.google.com with ESMTPS id mx10si8800106icb.122.2014.03.28.19.56.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 28 Mar 2014 19:56:47 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.213.174 is neither permitted nor denied by best guess record for domain of santosh.shukla@linaro.org) client-ip=209.85.213.174; Received: by mail-ig0-f174.google.com with SMTP id h18so1593775igc.1 for ; Fri, 28 Mar 2014 19:56:47 -0700 (PDT) X-Received: by 10.51.15.195 with SMTP id fq3mr278021igd.5.1396061806846; Fri, 28 Mar 2014 19:56:46 -0700 (PDT) Received: from santosh-Latitude-E5530-non-vPro.hil-sjccahw.sjc.wayport.net (ip-64-134-223-31.public.wayport.net. [64.134.223.31]) by mx.google.com with ESMTPSA id c10sm8865398igj.17.2014.03.28.19.56.45 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 28 Mar 2014 19:56:46 -0700 (PDT) From: Santosh Shukla To: lng-odp@linaro.org Cc: santosh shukla Subject: [lng-odp] [ODP/PATCH v3 2/2] timer:ping test application Date: Fri, 28 Mar 2014 19:56:30 -0700 Message-Id: <1396061790-26705-2-git-send-email-santosh.shukla@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1396061790-26705-1-git-send-email-santosh.shukla@linaro.org> References: <1396061790-26705-1-git-send-email-santosh.shukla@linaro.org> X-Original-Sender: santosh.shukla@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.213.174 is neither permitted nor denied by best guess record for domain of santosh.shukla@linaro.org) smtp.mail=santosh.shukla@linaro.org Precedence: list Mailing-list: list lng-odp@linaro.org; contact lng-odp+owners@linaro.org List-ID: X-Google-Group-Id: 474323889996 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: santosh shukla Application open PF_INET socket, spawns two thread, one is sender_ping_thr another one listen_thr. Each send request arms timer for absolute timeout duration Whenever listner thread recieves ack, it cancels the timer_out and free the timeout buffer i.e. tmo_buf allocate while arming.. Otherwise timeout-event-notfier will enqueue time out even to queue for that pckt_cnt. Signed-off-by: santosh shukla --- V2 change : - incorporated style comment in patch - odp queue based socket api need more changes specific to flag setting like socket flag, socket type, parameterising setsockopt this program need flags i.e..SOL_IP, IP_TTL etc,, At this point my initial effort says it will take little more time to get other parameter support in pktio socket param in odp therefore I suggest that this could be todo and seubsequent patch to include qeueue-base-socket method as and when I manage solve socket parameter problem for this application. V3 change : - Removed git am -3 warning. test/api_test/Makefile | 16 +- test/api_test/odp_common.h | 1 + test/api_test/odp_timer_ping.c | 335 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 test/api_test/odp_timer_ping.c diff --git a/test/api_test/Makefile b/test/api_test/Makefile index bd99c50..0398cd2 100644 --- a/test/api_test/Makefile +++ b/test/api_test/Makefile @@ -11,6 +11,7 @@ ODP_ROOT = ../.. ODP_ATOMIC = odp_atomic ODP_SHM = odp_shm ODP_RING = odp_ring +ODP_TIM = odp_timer include $(ODP_ROOT)/Makefile.inc include ../Makefile.inc @@ -32,13 +33,18 @@ RING_OBJS = RING_OBJS += $(OBJ_DIR)/odp_common.o RING_OBJS += $(OBJ_DIR)/odp_ring_test.o -DEPS = $(ATOMIC_OBJS:.o=.d) $(SHM_OBJS:.o=.d) $(RING_OBJS:.o=.d) +TIM_OBJS = +TIM_OBJS += $(OBJ_DIR)/odp_common.o +TIM_OBJS += $(OBJ_DIR)/odp_timer_ping.o + +DEPS = $(ATOMIC_OBJS:.o=.d) $(SHM_OBJS:.o=.d) $(RING_OBJS:.o=.d) $(TIM_OBJS:.o=.d) .PHONY: all -all: $(OBJ_DIR) $(ODP_ATOMIC) $(ODP_SHM) $(ODP_RING) +all: $(OBJ_DIR) $(ODP_ATOMIC) $(ODP_SHM) $(ODP_RING) $(ODP_TIM) atomic: $(OBJ_DIR) $(ODP_ATOMIC) shm: $(OBJ_DIR) $(ODP_SHM) ring: $(OBJ_DIR) $(ODP_RING) +timer: $(OBJ_DIR) $(ODP_TIM) -include $(DEPS) @@ -64,12 +70,17 @@ $(ODP_RING): $(ODP_LIB) $(RING_OBJS) $(ECHO) Linking $< $(CC) $(LDFLAGS) $(RING_OBJS) $(ODP_LIB) $(STD_LIBS) -o $@ +$(ODP_TIM): $(ODP_LIB) $(TIM_OBJS) + $(ECHO) Linking $< + $(CC) $(LDFLAGS) $(TIM_OBJS) $(ODP_LIB) $(STD_LIBS) -o $@ + .PHONY: clean clean: $(RMDIR) $(OBJ_DIR) $(RM) $(ODP_ATOMIC) $(RM) $(ODP_SHM) $(RM) $(ODP_RING) + $(RM) $(ODP_TIM) $(MAKE) -C $(ODP_DIR) clean .PHONY: install @@ -78,3 +89,4 @@ install: install -m 0755 $(ODP_ATOMIC) $(DESTDIR)/share/odp/ install -m 0755 $(ODP_SHM) $(DESTDIR)/share/odp/ install -m 0755 $(ODP_RING) $(DESTDIR)/share/odp/ + install -m 0755 $(ODP_TIM) $(DESTDIR)/share/odp/ diff --git a/test/api_test/odp_common.h b/test/api_test/odp_common.h index e8201ac..f5183e1 100644 --- a/test/api_test/odp_common.h +++ b/test/api_test/odp_common.h @@ -20,6 +20,7 @@ typedef enum { ODP_SHM_TEST, ODP_RING_TEST_BASIC, ODP_RING_TEST_STRESS, + ODP_TIMER_PING_TEST, ODP_MAX_TEST } odp_test_case_e; diff --git a/test/api_test/odp_timer_ping.c b/test/api_test/odp_timer_ping.c new file mode 100644 index 0000000..c1abc27 --- /dev/null +++ b/test/api_test/odp_timer_ping.c @@ -0,0 +1,335 @@ +/* Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP timer ping example application. + * application open PF_INET socket, every ping send request + * will arm timer for some duration, if ping_ack rxvd with + * time band.. listen thread will cancel timer and free the + * tmo_buffer.. otherwise timer expiration event will exit + * application lead to test failure.. + * - two thread used, one listener other one sender. + * - run ./odp_timer + * In ubuntu, you need run using sudo ./odp_timer + * - so to tigger timeout explicitly.. ping with badipaddr + * Otherwise timeout may happen bcz of slow nw speed + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MSG_POOL_SIZE (4*1024*1024) +#define BUF_SIZE 8 +#define PING_CNT 10 + + +static odp_timer_t test_timer_ping; +static odp_timer_tmo_t test_ping_tmo; + +#define PKTSIZE 64 +struct packet { + struct icmphdr hdr; + char msg[PKTSIZE-sizeof(struct icmphdr)]; +}; + +int pid = -1; +struct protoent *proto; + +struct sockaddr_in dst_addr; + +/* local struct for ping_timer_thread argument */ +typedef struct { + pthrd_arg thrdarg; + int result; +} ping_arg_t; + +static int ping_sync_flag; + + +static void dump_icmp_pkt(void *buf, int bytes, int pkt_cnt) +{ + int i; + struct iphdr *ip = buf; + + ODP_DBG("---dump icmp pkt_cnt %d------\n", pkt_cnt); + for (i = 0; i < bytes; i++) { + if (!(i & 15)) + ODP_DBG("\n %x: ", i); + ODP_DBG("%d ", ((unsigned char *)buf)[i]); + } + ODP_DBG("\n"); + char addrstr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, &ip->daddr, addrstr, sizeof(addrstr)); + ODP_DBG("byte %d, Ack rxvd for msg_cnt [%d] from %s\n", bytes, pkt_cnt, addrstr); +} + + +static int listen_to_pingack(void) +{ + int sd, i; + struct sockaddr_in addr; + unsigned char buf[1024]; + int bytes, len; + + sd = socket(PF_INET, SOCK_RAW, proto->p_proto); + if (sd < 0) { + ODP_ERR("Listener socket open failed\n"); + return -1; + } + + for (i = 0; i < PING_CNT; i++) { + len = sizeof(addr); + + bzero(buf, sizeof(buf)); + bytes = recvfrom(sd, buf, sizeof(buf), 0, + (struct sockaddr *)&addr, + (socklen_t *)&len); + if (bytes > 0) { + /* pkt rxvd therefore cancel the timeout */ + if (odp_timer_cancel_tmo(test_timer_ping, + test_ping_tmo) != 0) { + ODP_ERR("cancel_tmo failed ..exiting listner thread\n"); + return -1; + } + + /* cruel bad hack used for sender, listner ipc.. + * euwww.. FIXME .. + */ + ping_sync_flag = true; + + odp_buffer_free(test_ping_tmo); + + dump_icmp_pkt(buf, bytes, i); + } else { + ODP_ERR("recvfrom operation failed for msg_cnt [%d]\n", i); + return -1; + } + } + + return 0; +} + + +static int send_ping_request(struct sockaddr_in *addr) +{ + const int val = 255; + uint32_t i, j; + int sd, cnt = 1; + struct packet pckt; + + uint64_t tick; + odp_queue_t queue; + odp_buffer_t buf; + + int thr; + thr = odp_thread_id(); + + sd = socket(PF_INET, SOCK_RAW, proto->p_proto); + if (sd < 0) { + ODP_ERR("Sender socket open failed\n"); + return -1; + } + + if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) { + ODP_ERR("Error setting TTL option\n"); + return -1; + } + if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) { + ODP_ERR("Request for nonblocking I/O failed\n"); + return -1; + } + + /* get the ping queue */ + queue = odp_queue_lookup("ping_timer_queue"); + + for (i = 0; i < PING_CNT; i++) { + /* prepare icmp pkt */ + bzero(&pckt, sizeof(pckt)); + pckt.hdr.type = ICMP_ECHO; + pckt.hdr.un.echo.id = pid; + + for (j = 0; j < sizeof(pckt.msg)-1; j++) + pckt.msg[j] = j+'0'; + + pckt.msg[j] = 0; + pckt.hdr.un.echo.sequence = cnt++; + pckt.hdr.checksum = odp_chksum(&pckt, sizeof(pckt)); + + + /* txmit the pkt */ + if (sendto(sd, &pckt, sizeof(pckt), 0, + (struct sockaddr *)addr, sizeof(*addr)) <= 0) { + ODP_ERR("sendto operation failed msg_cnt [%d]..exiting sender thread\n", i); + return -1; + } + printf(" icmp_sent msg_cnt %d\n", i); + + /* arm the timer */ + tick = odp_timer_current_tick(test_timer_ping); + ODP_DBG(" [%i] current tick %"PRIu64"\n", thr, tick); + + tick += 1000; + test_ping_tmo = odp_timer_absolute_tmo(test_timer_ping, tick, + queue, + ODP_BUFFER_INVALID); + + /* wait for timeout event */ + while ((buf = odp_queue_deq(queue) == ODP_BUFFER_INVALID)) { + /* flag true means ack rxvd.. a cruel hack as I + * am confused on method to get away from while + * loop in case of ack rxvd.. + * FIXME.. + */ + if (ping_sync_flag) { + ping_sync_flag = false; + ODP_DBG(" [%d] done :)!!\n", i); + buf = ODP_BUFFER_INVALID; + break; + } + } + + /* free tmo_buf for timeout case */ + if (buf != ODP_BUFFER_INVALID) { + ODP_DBG(" [%i] timeout msg_cnt [%i] (:-\n", thr, i); + odp_buffer_free(buf); + } + } + + return 0; +} + + +static void *ping_timer_thread(void *arg) +{ + ping_arg_t *parg = (ping_arg_t *)arg; + int thr; + + thr = odp_thread_id(); + + printf("Ping thread %i starts\n", thr); + + switch (parg->thrdarg.testcase) { + case ODP_TIMER_PING_TEST: + if (thr == 1) + if (send_ping_request(&dst_addr) < 0) + parg->result = -1; + if (thr == 2) + if (listen_to_pingack() < 0) + parg->result = -1; + break; + default: + ODP_ERR("Invalid test case [%d]\n", parg->thrdarg.testcase); + } + + + fflush(stdout); + + return parg; +} + +static int ping_init(int count, char *name[]) +{ + struct hostent *hname; + if (count != 2) { + ODP_ERR("usage: %s \n", name[0]); + return -1; + } + + if (count > 1) { + pid = getpid(); + proto = getprotobyname("ICMP"); + hname = gethostbyname(name[1]); + bzero(&dst_addr, sizeof(dst_addr)); + dst_addr.sin_family = hname->h_addrtype; + dst_addr.sin_port = 0; + dst_addr.sin_addr.s_addr = *(long *)hname->h_addr; + } + printf("ping to addr %s\n", name[1]); + + return 0; +} + + +int main(int argc ODP_UNUSED, char *argv[] ODP_UNUSED) +{ + ping_arg_t pingarg; + odp_queue_t queue; + odp_buffer_pool_t pool; + void *pool_base; + + if (odp_test_global_init() != 0) + return -1; + + odp_print_system_info(); + + if (ping_init(argc, argv) != 0) + return -1; + + /* + * Create message pool + */ + pool_base = odp_shm_reserve("msg_pool", + MSG_POOL_SIZE, ODP_CACHE_LINE_SIZE); + + pool = odp_buffer_pool_create("msg_pool", pool_base, MSG_POOL_SIZE, + BUF_SIZE, + ODP_CACHE_LINE_SIZE, + ODP_BUFFER_TYPE_RAW); + if (pool == ODP_BUFFER_POOL_INVALID) { + ODP_ERR("Pool create failed.\n"); + return -1; + } + + /* + * Create a queue for timer test + */ + queue = odp_queue_create("ping_timer_queue", ODP_QUEUE_TYPE_SCHED, + NULL); + + if (queue == ODP_QUEUE_INVALID) { + ODP_ERR("Timer queue create failed.\n"); + return -1; + } + + test_timer_ping = odp_timer_create("ping_timer", pool, + 1000000, 1000000, 1000000000000); + odp_shm_print_all(); + + pingarg.thrdarg.testcase = ODP_TIMER_PING_TEST; + pingarg.thrdarg.numthrds = odp_sys_core_count(); + + pingarg.result = 0; + + /* Create and launch worker threads */ + odp_test_thread_create(ping_timer_thread, (pthrd_arg *)&pingarg); + + /* Wait for worker threads to exit */ + odp_test_thread_exit(&pingarg.thrdarg); + + ODP_DBG("ping timer test %s\n", (pingarg.result == 0) ? "passed" : "failed"); + + printf("ODP ping timer test complete\n\n"); + + return 0; +} +