linux/drivers/staging/lustre/lnet/selftest/ping_test.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  19 *
  20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  21 * CA 95054 USA or visit www.sun.com if you need additional information or
  22 * have any questions.
  23 *
  24 * GPL HEADER END
  25 */
  26/*
  27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2012, Intel Corporation.
  31 */
  32/*
  33 * This file is part of Lustre, http://www.lustre.org/
  34 * Lustre is a trademark of Sun Microsystems, Inc.
  35 *
  36 * lnet/selftest/conctl.c
  37 *
  38 * Test client & Server
  39 *
  40 * Author: Liang Zhen <liangzhen@clusterfs.com>
  41 */
  42
  43#include "selftest.h"
  44
  45#define LST_PING_TEST_MAGIC     0xbabeface
  46
  47static int ping_srv_workitems = SFW_TEST_WI_MAX;
  48module_param(ping_srv_workitems, int, 0644);
  49MODULE_PARM_DESC(ping_srv_workitems, "# PING server workitems");
  50
  51typedef struct {
  52        spinlock_t      pnd_lock;       /* serialize */
  53        int             pnd_counter;    /* sequence counter */
  54} lst_ping_data_t;
  55
  56static lst_ping_data_t  lst_ping_data;
  57
  58static int
  59ping_client_init(sfw_test_instance_t *tsi)
  60{
  61        sfw_session_t *sn = tsi->tsi_batch->bat_session;
  62
  63        LASSERT(tsi->tsi_is_client);
  64        LASSERT(sn != NULL && (sn->sn_features & ~LST_FEATS_MASK) == 0);
  65
  66        spin_lock_init(&lst_ping_data.pnd_lock);
  67        lst_ping_data.pnd_counter = 0;
  68
  69        return 0;
  70}
  71
  72static void
  73ping_client_fini(sfw_test_instance_t *tsi)
  74{
  75        sfw_session_t *sn = tsi->tsi_batch->bat_session;
  76        int errors;
  77
  78        LASSERT(sn != NULL);
  79        LASSERT(tsi->tsi_is_client);
  80
  81        errors = atomic_read(&sn->sn_ping_errors);
  82        if (errors)
  83                CWARN("%d pings have failed.\n", errors);
  84        else
  85                CDEBUG(D_NET, "Ping test finished OK.\n");
  86}
  87
  88static int
  89ping_client_prep_rpc(sfw_test_unit_t *tsu,
  90                     lnet_process_id_t dest, srpc_client_rpc_t **rpc)
  91{
  92        srpc_ping_reqst_t *req;
  93        sfw_test_instance_t *tsi = tsu->tsu_instance;
  94        sfw_session_t *sn = tsi->tsi_batch->bat_session;
  95        struct timeval tv;
  96        int rc;
  97
  98        LASSERT(sn != NULL);
  99        LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);
 100
 101        rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, 0, 0, rpc);
 102        if (rc != 0)
 103                return rc;
 104
 105        req = &(*rpc)->crpc_reqstmsg.msg_body.ping_reqst;
 106
 107        req->pnr_magic = LST_PING_TEST_MAGIC;
 108
 109        spin_lock(&lst_ping_data.pnd_lock);
 110        req->pnr_seq = lst_ping_data.pnd_counter++;
 111        spin_unlock(&lst_ping_data.pnd_lock);
 112
 113        cfs_fs_timeval(&tv);
 114        req->pnr_time_sec  = tv.tv_sec;
 115        req->pnr_time_usec = tv.tv_usec;
 116
 117        return rc;
 118}
 119
 120static void
 121ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
 122{
 123        sfw_test_instance_t *tsi = tsu->tsu_instance;
 124        sfw_session_t *sn = tsi->tsi_batch->bat_session;
 125        srpc_ping_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst;
 126        srpc_ping_reply_t *reply = &rpc->crpc_replymsg.msg_body.ping_reply;
 127        struct timeval tv;
 128
 129        LASSERT(sn != NULL);
 130
 131        if (rpc->crpc_status != 0) {
 132                if (!tsi->tsi_stopping) /* rpc could have been aborted */
 133                        atomic_inc(&sn->sn_ping_errors);
 134                CERROR("Unable to ping %s (%d): %d\n",
 135                        libcfs_id2str(rpc->crpc_dest),
 136                        reqst->pnr_seq, rpc->crpc_status);
 137                return;
 138        }
 139
 140        if (rpc->crpc_replymsg.msg_magic != SRPC_MSG_MAGIC) {
 141                __swab32s(&reply->pnr_seq);
 142                __swab32s(&reply->pnr_magic);
 143                __swab32s(&reply->pnr_status);
 144        }
 145
 146        if (reply->pnr_magic != LST_PING_TEST_MAGIC) {
 147                rpc->crpc_status = -EBADMSG;
 148                atomic_inc(&sn->sn_ping_errors);
 149                CERROR("Bad magic %u from %s, %u expected.\n",
 150                        reply->pnr_magic, libcfs_id2str(rpc->crpc_dest),
 151                        LST_PING_TEST_MAGIC);
 152                return;
 153        }
 154
 155        if (reply->pnr_seq != reqst->pnr_seq) {
 156                rpc->crpc_status = -EBADMSG;
 157                atomic_inc(&sn->sn_ping_errors);
 158                CERROR("Bad seq %u from %s, %u expected.\n",
 159                        reply->pnr_seq, libcfs_id2str(rpc->crpc_dest),
 160                        reqst->pnr_seq);
 161                return;
 162        }
 163
 164        cfs_fs_timeval(&tv);
 165        CDEBUG(D_NET, "%d reply in %u usec\n", reply->pnr_seq,
 166                (unsigned)((tv.tv_sec - (unsigned)reqst->pnr_time_sec) * 1000000
 167                           + (tv.tv_usec - reqst->pnr_time_usec)));
 168        return;
 169}
 170
 171static int
 172ping_server_handle(struct srpc_server_rpc *rpc)
 173{
 174        struct srpc_service *sv  = rpc->srpc_scd->scd_svc;
 175        srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
 176        srpc_msg_t *replymsg = &rpc->srpc_replymsg;
 177        srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst;
 178        srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply;
 179
 180        LASSERT(sv->sv_id == SRPC_SERVICE_PING);
 181
 182        if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
 183                LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
 184
 185                __swab32s(&req->pnr_seq);
 186                __swab32s(&req->pnr_magic);
 187                __swab64s(&req->pnr_time_sec);
 188                __swab64s(&req->pnr_time_usec);
 189        }
 190        LASSERT(reqstmsg->msg_type == srpc_service2request(sv->sv_id));
 191
 192        if (req->pnr_magic != LST_PING_TEST_MAGIC) {
 193                CERROR("Unexpected magic %08x from %s\n",
 194                        req->pnr_magic, libcfs_id2str(rpc->srpc_peer));
 195                return -EINVAL;
 196        }
 197
 198        rep->pnr_seq   = req->pnr_seq;
 199        rep->pnr_magic = LST_PING_TEST_MAGIC;
 200
 201        if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
 202                replymsg->msg_ses_feats = LST_FEATS_MASK;
 203                rep->pnr_status = EPROTO;
 204                return 0;
 205        }
 206
 207        replymsg->msg_ses_feats = reqstmsg->msg_ses_feats;
 208
 209        CDEBUG(D_NET, "Get ping %d from %s\n",
 210               req->pnr_seq, libcfs_id2str(rpc->srpc_peer));
 211        return 0;
 212}
 213
 214sfw_test_client_ops_t ping_test_client;
 215void ping_init_test_client(void)
 216{
 217        ping_test_client.tso_init     = ping_client_init;
 218        ping_test_client.tso_fini     = ping_client_fini;
 219        ping_test_client.tso_prep_rpc = ping_client_prep_rpc;
 220        ping_test_client.tso_done_rpc = ping_client_done_rpc;
 221}
 222
 223srpc_service_t ping_test_service;
 224void ping_init_test_service(void)
 225{
 226        ping_test_service.sv_id       = SRPC_SERVICE_PING;
 227        ping_test_service.sv_name     = "ping_test";
 228        ping_test_service.sv_handler  = ping_server_handle;
 229        ping_test_service.sv_wi_total = ping_srv_workitems;
 230}
 231