Whamcloud - gitweb
LU-9480 lnet: add sanity checks on ping-related constants
[fs/lustre-release.git] / lnet / utils / wirecheck.c
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2014, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32
33 #ifndef _GNU_SOURCE
34 #define _GNU_SOURCE
35 #endif
36
37 #include <stddef.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <linux/lnet/lnet-types.h>
45
46 #ifndef HAVE_STRNLEN
47 #define strnlen(s, i) strlen(s)
48 #endif
49
50 #define BLANK_LINE()                            \
51 do {                                            \
52         printf ("\n");                          \
53 } while (0)
54
55 #define COMMENT(c)                              \
56 do {                                            \
57         printf ("        /* "c" */\n");         \
58 } while (0)
59
60 #define STRINGIFY(a) #a
61
62 #define CHECK_DEFINE(a)                                                 \
63 do {                                                                    \
64         printf ("        CLASSERT ("#a" == "STRINGIFY(a)");\n");        \
65 } while (0)
66
67 #define CHECK_VALUE(a)                                  \
68 do {                                                    \
69         printf ("        CLASSERT ("#a" == %d);\n", a); \
70 } while (0)
71
72 #define CHECK_MEMBER_OFFSET(s,m)                \
73 do {                                            \
74         CHECK_VALUE((int)offsetof(s, m));       \
75 } while (0)
76
77 #define CHECK_MEMBER_SIZEOF(s,m)                \
78 do {                                            \
79         CHECK_VALUE((int)sizeof(((s *)0)->m));  \
80 } while (0)
81
82 #define CHECK_MEMBER(s,m)                       \
83 do {                                            \
84         CHECK_MEMBER_OFFSET(s, m);              \
85         CHECK_MEMBER_SIZEOF(s, m);              \
86 } while (0)
87
88 #define CHECK_STRUCT(s)                         \
89 do {                                            \
90         BLANK_LINE ();                          \
91         COMMENT ("Checks for struct "#s);       \
92         CHECK_VALUE((int)sizeof(s));            \
93 } while (0)
94
95 void
96 check_lnet_handle_wire(void)
97 {
98         CHECK_STRUCT(struct lnet_handle_wire);
99         CHECK_MEMBER(struct lnet_handle_wire, wh_interface_cookie);
100         CHECK_MEMBER(struct lnet_handle_wire, wh_object_cookie);
101 }
102
103 void
104 check_lnet_magicversion (void)
105 {
106         CHECK_STRUCT(struct lnet_magicversion);
107         CHECK_MEMBER(struct lnet_magicversion, magic);
108         CHECK_MEMBER(struct lnet_magicversion, version_major);
109         CHECK_MEMBER(struct lnet_magicversion, version_minor);
110 }
111
112 void
113 check_lnet_hdr (void)
114 {
115         CHECK_STRUCT(struct lnet_hdr);
116         CHECK_MEMBER(struct lnet_hdr, dest_nid);
117         CHECK_MEMBER(struct lnet_hdr, src_nid);
118         CHECK_MEMBER(struct lnet_hdr, dest_pid);
119         CHECK_MEMBER(struct lnet_hdr, src_pid);
120         CHECK_MEMBER(struct lnet_hdr, type);
121         CHECK_MEMBER(struct lnet_hdr, payload_length);
122         CHECK_MEMBER(struct lnet_hdr, msg);
123
124         BLANK_LINE ();
125         COMMENT ("Ack");
126         CHECK_MEMBER(struct lnet_hdr, msg.ack.dst_wmd);
127         CHECK_MEMBER(struct lnet_hdr, msg.ack.match_bits);
128         CHECK_MEMBER(struct lnet_hdr, msg.ack.mlength);
129
130         BLANK_LINE ();
131         COMMENT ("Put");
132         CHECK_MEMBER(struct lnet_hdr, msg.put.ack_wmd);
133         CHECK_MEMBER(struct lnet_hdr, msg.put.match_bits);
134         CHECK_MEMBER(struct lnet_hdr, msg.put.hdr_data);
135         CHECK_MEMBER(struct lnet_hdr, msg.put.ptl_index);
136         CHECK_MEMBER(struct lnet_hdr, msg.put.offset);
137
138         BLANK_LINE ();
139         COMMENT ("Get");
140         CHECK_MEMBER(struct lnet_hdr, msg.get.return_wmd);
141         CHECK_MEMBER(struct lnet_hdr, msg.get.match_bits);
142         CHECK_MEMBER(struct lnet_hdr, msg.get.ptl_index);
143         CHECK_MEMBER(struct lnet_hdr, msg.get.src_offset);
144         CHECK_MEMBER(struct lnet_hdr, msg.get.sink_length);
145
146         BLANK_LINE ();
147         COMMENT ("Reply");
148         CHECK_MEMBER(struct lnet_hdr, msg.reply.dst_wmd);
149
150         BLANK_LINE ();
151         COMMENT ("Hello");
152         CHECK_MEMBER(struct lnet_hdr, msg.hello.incarnation);
153         CHECK_MEMBER(struct lnet_hdr, msg.hello.type);
154 }
155
156 void
157 check_lnet_ni_status(void)
158 {
159         BLANK_LINE();
160         COMMENT("Checks for struct lnet_ni_status and related constants");
161
162         CHECK_DEFINE(LNET_NI_STATUS_INVALID);
163         CHECK_DEFINE(LNET_NI_STATUS_UP);
164         CHECK_DEFINE(LNET_NI_STATUS_DOWN);
165
166         CHECK_STRUCT(struct lnet_ni_status);
167         CHECK_MEMBER(struct lnet_ni_status, ns_nid);
168         CHECK_MEMBER(struct lnet_ni_status, ns_status);
169         CHECK_MEMBER(struct lnet_ni_status, ns_unused);
170 }
171
172 void
173 check_lnet_ping_info(void)
174 {
175         BLANK_LINE();
176         COMMENT("Checks for struct lnet_ping_info and related constants");
177
178         CHECK_DEFINE(LNET_PROTO_PING_MAGIC);
179         CHECK_VALUE(LNET_PING_FEAT_INVAL);
180         CHECK_VALUE(LNET_PING_FEAT_BASE);
181         CHECK_VALUE(LNET_PING_FEAT_NI_STATUS);
182         CHECK_VALUE(LNET_PING_FEAT_RTE_DISABLED);
183         CHECK_VALUE(LNET_PING_FEAT_MULTI_RAIL);
184         CHECK_VALUE(LNET_PING_FEAT_DISCOVERY);
185         CHECK_VALUE(LNET_PING_FEAT_BITS);
186
187         CHECK_STRUCT(struct lnet_ping_info);
188         CHECK_MEMBER(struct lnet_ping_info, pi_magic);
189         CHECK_MEMBER(struct lnet_ping_info, pi_features);
190         CHECK_MEMBER(struct lnet_ping_info, pi_pid);
191         CHECK_MEMBER(struct lnet_ping_info, pi_nnis);
192         CHECK_MEMBER(struct lnet_ping_info, pi_ni);
193 }
194
195 void
196 system_string(char *cmdline, char *str, int len)
197 {
198         int   fds[2];
199         int   rc;
200         pid_t pid;
201
202         rc = pipe (fds);
203         if (rc != 0)
204                 abort ();
205
206         pid = fork ();
207         if (pid == 0) {
208                 /* child */
209                 int   fd = fileno(stdout);
210
211                 rc = dup2(fds[1], fd);
212                 if (rc != fd)
213                         abort();
214
215                 exit(system(cmdline));
216                 /* notreached */
217         } else if ((int)pid < 0) {
218                 abort();
219         } else {
220                 FILE *f = fdopen (fds[0], "r");
221
222                 if (f == NULL)
223                         abort();
224
225                 close(fds[1]);
226
227                 if (fgets(str, len, f) == NULL)
228                         abort();
229
230                 if (waitpid(pid, &rc, 0) != pid)
231                         abort();
232
233                 if (!WIFEXITED(rc) ||
234                     WEXITSTATUS(rc) != 0)
235                         abort();
236
237                 if (strnlen(str, len) == len)
238                         str[len - 1] = 0;
239
240                 if (str[strlen(str) - 1] == '\n')
241                         str[strlen(str) - 1] = 0;
242
243                 fclose(f);
244         }
245 }
246
247 int
248 main (int argc, char **argv)
249 {
250         char unameinfo[256];
251         char gccinfo[256];
252
253         system_string("uname -a", unameinfo, sizeof(unameinfo));
254         system_string("gcc -v 2>&1 | tail -1", gccinfo, sizeof(gccinfo));
255
256         printf ("void lnet_assert_wire_constants (void)\n"
257                 "{\n"
258                 "        /* Wire protocol assertions generated by 'wirecheck'\n"
259                 "         * running on %s\n"
260                 "         * with %s */\n"
261                 "\n", unameinfo, gccinfo);
262
263         BLANK_LINE ();
264
265         COMMENT ("Constants...");
266
267         CHECK_DEFINE (LNET_PROTO_RA_MAGIC);
268
269         CHECK_DEFINE (LNET_PROTO_TCP_MAGIC);
270         CHECK_DEFINE (LNET_PROTO_TCP_VERSION_MAJOR);
271         CHECK_DEFINE (LNET_PROTO_TCP_VERSION_MINOR);
272
273         CHECK_VALUE (LNET_MSG_ACK);
274         CHECK_VALUE (LNET_MSG_PUT);
275         CHECK_VALUE (LNET_MSG_GET);
276         CHECK_VALUE (LNET_MSG_REPLY);
277         CHECK_VALUE (LNET_MSG_HELLO);
278
279         check_lnet_handle_wire();
280         check_lnet_magicversion();
281         check_lnet_hdr();
282         check_lnet_ni_status();
283         check_lnet_ping_info();
284
285         printf ("}\n\n");
286
287         return (0);
288 }