Whamcloud - gitweb
Branch b1_4
[fs/lustre-release.git] / lnet / selftest / ping_test.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Author: Liang Zhen <liangzhen@clusterfs.com>
5  *
6  * This file is part of Lustre, http://www.lustre.org
7  *
8  * Test client & Server
9  */
10
11 #include "selftest.h"
12
13 #define LST_PING_TEST_MAGIC     0xbabeface
14
15 typedef struct {
16         spinlock_t      pnd_lock;       /* serialize */
17         int             pnd_counter;    /* sequence counter */
18 } lst_ping_data_t;
19
20 static lst_ping_data_t  lst_ping_data;
21
22 static int
23 ping_client_init(sfw_test_instance_t *tsi)
24 {
25         LASSERT (tsi->tsi_is_client);
26
27         spin_lock_init(&lst_ping_data.pnd_lock);
28         lst_ping_data.pnd_counter = 0;
29
30         return 0;
31 }
32
33 static void
34 ping_client_fini (sfw_test_instance_t *tsi)
35 {
36         sfw_session_t *sn = tsi->tsi_batch->bat_session;
37         int            errors;
38
39         LASSERT (sn != NULL);
40         LASSERT (tsi->tsi_is_client);
41
42         errors = atomic_read(&sn->sn_ping_errors);
43         if (errors)
44                 CWARN ("%d pings have failed.\n", errors);
45         else
46                 CDEBUG (D_NET, "Ping test finished OK.\n");
47 }
48
49 static int
50 ping_client_prep_rpc(sfw_test_unit_t *tsu,
51                      lnet_process_id_t dest, srpc_client_rpc_t **rpc)
52 {
53         srpc_ping_reqst_t *req;
54         struct timeval     tv;
55         int                rc;
56
57         rc = sfw_create_test_rpc(tsu, dest, 0, 0, rpc);
58         if (rc != 0)
59                 return rc;
60
61         req = &(*rpc)->crpc_reqstmsg.msg_body.ping_reqst;
62
63         req->pnr_magic = LST_PING_TEST_MAGIC;
64
65         spin_lock(&lst_ping_data.pnd_lock);
66         req->pnr_seq = lst_ping_data.pnd_counter ++;
67         spin_unlock(&lst_ping_data.pnd_lock);
68
69         cfs_fs_timeval(&tv);
70         req->pnr_time_sec  = tv.tv_sec;
71         req->pnr_time_usec = tv.tv_usec;
72
73         return rc;
74 }
75
76 static void
77 ping_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
78 {
79         sfw_test_instance_t *tsi = tsu->tsu_instance;
80         sfw_session_t       *sn = tsi->tsi_batch->bat_session;
81         srpc_ping_reqst_t   *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst;
82         srpc_ping_reply_t   *reply = &rpc->crpc_replymsg.msg_body.ping_reply;
83         struct timeval       tv;
84
85         LASSERT (sn != NULL);
86
87         if (rpc->crpc_status != 0) {
88                 if (!tsi->tsi_stopping) /* rpc could have been aborted */
89                         atomic_inc(&sn->sn_ping_errors);
90                 CERROR ("Unable to ping %s (%d): %d\n",
91                         libcfs_id2str(rpc->crpc_dest),
92                         reqst->pnr_seq, rpc->crpc_status);
93                 return;
94         } 
95
96         if (rpc->crpc_replymsg.msg_magic != SRPC_MSG_MAGIC) {
97                 __swab32s(&reply->pnr_seq);
98                 __swab32s(&reply->pnr_magic);
99                 __swab32s(&reply->pnr_status);
100         }
101         
102         if (reply->pnr_magic != LST_PING_TEST_MAGIC) {
103                 rpc->crpc_status = -EBADMSG;
104                 atomic_inc(&sn->sn_ping_errors);
105                 CERROR ("Bad magic %u from %s, %u expected.\n",
106                         reply->pnr_magic, libcfs_id2str(rpc->crpc_dest),
107                         LST_PING_TEST_MAGIC);
108                 return;
109         } 
110         
111         if (reply->pnr_seq != reqst->pnr_seq) {
112                 rpc->crpc_status = -EBADMSG;
113                 atomic_inc(&sn->sn_ping_errors);
114                 CERROR ("Bad seq %u from %s, %u expected.\n",
115                         reply->pnr_seq, libcfs_id2str(rpc->crpc_dest),
116                         reqst->pnr_seq);
117                 return;
118         }
119
120         cfs_fs_timeval(&tv);
121         CDEBUG (D_NET, "%d reply in %u usec\n", reply->pnr_seq,
122                 (unsigned)((tv.tv_sec - (unsigned)reqst->pnr_time_sec) * 1000000
123                            + (tv.tv_usec - reqst->pnr_time_usec)));
124         return;
125 }
126
127 static int
128 ping_server_handle (srpc_server_rpc_t *rpc)
129 {
130         srpc_service_t    *sv  = rpc->srpc_service;
131         srpc_msg_t        *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
132         srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst;
133         srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply;
134
135         LASSERT (sv->sv_id == SRPC_SERVICE_PING);
136
137         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
138                 LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
139
140                 __swab32s(&reqstmsg->msg_type);
141                 __swab32s(&req->pnr_seq);
142                 __swab32s(&req->pnr_magic);
143                 __swab64s(&req->pnr_time_sec);
144                 __swab64s(&req->pnr_time_usec);
145         }
146         LASSERT (reqstmsg->msg_type == srpc_service2request(sv->sv_id));
147
148         if (req->pnr_magic != LST_PING_TEST_MAGIC) {
149                 CERROR ("Unexpect magic %08x from %s\n",
150                         req->pnr_magic, libcfs_id2str(rpc->srpc_peer));
151                 return -EINVAL;
152         }
153
154         rep->pnr_seq   = req->pnr_seq;
155         rep->pnr_magic = LST_PING_TEST_MAGIC;
156
157         CDEBUG (D_NET, "Get ping %d from %s\n",
158                 req->pnr_seq, libcfs_id2str(rpc->srpc_peer));
159         return 0;
160 }
161
162 sfw_test_client_ops_t ping_test_client = 
163 {
164         .tso_init       = ping_client_init,
165         .tso_fini       = ping_client_fini,
166         .tso_prep_rpc   = ping_client_prep_rpc,
167         .tso_done_rpc   = ping_client_done_rpc,
168 };
169
170 srpc_service_t ping_test_service = 
171 {
172         .sv_name        = "ping test",
173         .sv_handler     = ping_server_handle,
174         .sv_id          = SRPC_SERVICE_PING,
175 };