Whamcloud - gitweb
ec75177208d9aab89498d4480f3a7bae0f61cd77
[fs/lustre-release.git] / lnet / klnds / gnilnd / gnilnd_hss_ops.h
1 /*
2  * Copyright (C) 2010-2012 Cray, Inc.
3  *   Author: Nic Henke <nic@cray.com>
4  *
5  *   This file is part of Lustre, http://www.lustre.org.
6  *
7  *   Lustre is free software; you can redistribute it and/or
8  *   modify it under the terms of version 2 of the GNU General Public
9  *   License as published by the Free Software Foundation.
10  *
11  *   Lustre is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with Lustre; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21 #ifndef _GNILND_HSS_OPS_H
22 #define _GNILND_HSS_OPS_H
23
24 /* for krca nid & nic translation */
25 #include <krca_lib.h>
26 #include <linux/typecheck.h>
27
28 /* the SimNow nodes can't load rca.ko, so we need to detect this
29  * and fake a table that'd work for lookups there */
30
31 typedef struct kgn_nid_entry {
32         __u32   nid;
33         __u32   nicaddr;
34 } kgn_nid_entry_t;
35
36 typedef struct kgn_hssops
37 {
38         /* function pointers for nid and nic conversion */
39         /* from krca_lib.h */
40         int     (*nid_to_nicaddr)(__u32 nid, int numnic, __u32 *nicaddr);
41         int     (*nicaddr_to_nid)(__u32 nicaddr, __u32 *nid);
42         void    (*hb_to_l0)(void);
43 } kgn_hssops_t;
44
45 /* pull in static store in gnilnd.c */
46 extern kgn_hssops_t             kgnilnd_hssops;
47
48 #define GNILND_NO_RCA           0xdeadbeef
49 #define GNILND_NO_QUIESCE       0xdeadbeef
50
51 static inline int
52 kgnilnd_lookup_rca_funcs(void)
53 {
54         void    *funcp;
55
56         funcp = __symbol_get("send_hb_2_l0");
57         if (funcp == 0) {
58                 CERROR("couldn't find send_hb_2_l0\n");
59                 /* not fatal for now */
60         } else {
61                 kgnilnd_hssops.hb_to_l0 = funcp;
62         }
63
64         /* if we find one, we should get the other */
65
66         funcp = __symbol_get("krca_nid_to_nicaddrs");
67         if (funcp == 0) {
68                 kgnilnd_hssops.nid_to_nicaddr = (void *)GNILND_NO_RCA;
69                 kgnilnd_hssops.nicaddr_to_nid = (void *)GNILND_NO_RCA;
70                 LCONSOLE_INFO("using SimNow nid table for RCA translation\n");
71                 return 0;
72         }
73         kgnilnd_hssops.nid_to_nicaddr = funcp;
74
75         funcp = __symbol_get("krca_nicaddr_to_nid");
76         if (funcp == 0) {
77                 CERROR("found krca_nid_to_nicaddrs but not "
78                        "krca_nicaddr_to_nid\n");
79                 return -ESRCH;
80         }
81         kgnilnd_hssops.nicaddr_to_nid = funcp;
82         return 0;
83 }
84
85 #if defined(CONFIG_CRAY_GEMINI)
86 /* Gemini SimNow has a hard coded table to use - no RCA there */
87 #define GNILND_MAX_NID_TABLE    0xffffffff
88 /* this is all of the nodes defined in the Baker SimNow "sim_platforms" page */
89 static kgn_nid_entry_t kgn_nid_table[] = {
90         {0x1, 0x100}, {0x2, 0x101}, {0x3, 0x104}, {0x4, 0x105},
91         {0x5, 0x108}, {0x6, 0x109}, {0x7, 0x10c}, {0x8, 0x10d},
92         {0x9, 0x110}, {0xa, 0x111}, {0xb, 0x114}, {0xc, 0x115},
93         {0xd, 0x118}, {0xe, 0x119}, {0xf, 0x11c}, {0x10, 0x11d},
94         {0x11, 0x120}, {0x12, 0x121}, {0x13, 0x124}, {0x14, 0x125},
95         {0x15, 0x128}, {0x16, 0x129}, {0x17, 0x12c}, {0x18, 0x12d},
96         {0x19, 0x130}, {0x1a, 0x131}, {0x1b, 0x134}, {0x1c, 0x135},
97         {0x1d, 0x138}, {0x1e, 0x139}, {0x1f, 0x13c}, {0x20, 0x13d},
98         {0x21, 0x140}, {0x22, 0x141}, {0x23, 0x144}, {0x24, 0x145},
99         {0x25, 0x148}, {0x26, 0x149}, {0x27, 0x14c}, {0x28, 0x14d},
100         {0x29, 0x150}, {0x2a, 0x151}, {0x2b, 0x154}, {0x2c, 0x155},
101         {0x2d, 0x158}, {0x2e, 0x159}, {0x2f, 0x15c}, {0x30, 0x15d},
102         {0x31, 0x160}, {0x32, 0x161}, {0x33, 0x164}, {0x3d, 0x178},
103         {0x34, 0x165}, {0x3e, 0x179}, {0x35, 0x168}, {0x3f, 0x17c},
104         {0x36, 0x169}, {0x40, 0x17d}, {0x37, 0x16c}, {0x41, 0x180},
105         {0x38, 0x16d}, {0x42, 0x181}, {0x39, 0x170}, {0x3a, 0x171},
106         {0x3b, 0x174}, {0x3c, 0x175}, {0x43, 0x184}, {0x44, 0x185},
107         {0x45, 0x188}, {0x46, 0x189}, {0x47, 0x18c}, {0x48, 0x18d},
108         /* entries after this are for 'dead' peer tests */
109         {0x63, 0x1ff}, {0x111, 0x209},
110         {GNILND_MAX_NID_TABLE, GNILND_MAX_NID_TABLE}
111 };
112 static int
113 gemini_nid_to_nicaddr(__u32 nid, int numnic, __u32 *nicaddr)
114 {
115         int i;
116
117         /* GNILND_NO_RCA, so use hardcoded table for Gemini SimNow */
118         if (numnic > 1) {
119                 CERROR("manual nid2nic translation doesn't support"
120                        "multiple nic addrs (you asked for %d)\n",
121                         numnic);
122                 return -EINVAL;
123         }
124
125         for (i = 0;;i++) {
126                 if (kgn_nid_table[i].nid == GNILND_MAX_NID_TABLE) {
127                         CERROR("could not translate %u to a NIC "
128                                "address\n", nid);
129                         return -ESRCH;
130                 }
131                 if (kgn_nid_table[i].nid == nid) {
132                         *nicaddr = kgn_nid_table[i].nicaddr;
133                         return 1;
134                 }
135         }
136 }
137
138 static int
139 gemini_nicaddr_to_nid(__u32 nicaddr, __u32 *nid)
140 {
141         int i;
142
143         /* GNILND_RCA_NOT_HOME, so use hardcoded table for SimNow */
144         for (i = 0;;i++) {
145                 if (kgn_nid_table[i].nicaddr == GNILND_MAX_NID_TABLE) {
146                         CERROR("could not translate NIC address "
147                                 "%u\n",
148                                 nicaddr);
149                         return -ESRCH;
150                 }
151                 if (kgn_nid_table[i].nicaddr == nicaddr) {
152                         *nid = kgn_nid_table[i].nid;
153                         return 1;
154                 }
155         }
156 }
157
158 static inline int
159 kgnilnd_setup_nic_translation(__u32 device_id)
160 {
161         int rc;
162
163         /* do lookup on first use */
164         if (unlikely(kgnilnd_hssops.nid_to_nicaddr == NULL)) {
165                 rc = kgnilnd_lookup_rca_funcs();
166                 if (rc)
167                         return rc;
168         }
169
170         /* if we have a real function, return - we'll use those going forward */
171         if (likely(kgnilnd_hssops.nid_to_nicaddr != (void *)GNILND_NO_RCA))
172                 return 0;
173
174         kgnilnd_hssops.nid_to_nicaddr = gemini_nid_to_nicaddr;
175         kgnilnd_hssops.nicaddr_to_nid = gemini_nicaddr_to_nid;
176         return 0;
177 }
178
179 #elif defined(CONFIG_CRAY_ARIES)
180 /* for libcfs_ipif_query */
181 #include <libcfs/libcfs.h>
182
183 /* Aries Sim doesn't have hardcoded tables, so we'll hijack the nic_pe
184  * and decode our address and nic addr from that - the rest are just offsets */
185 static __u32 aries_sim_base_nid;
186 static __u32 aries_sim_nic;
187
188 static int
189 aries_nid_to_nicaddr(__u32 nid, int numnic, __u32 *nicaddr)
190 {
191         if (numnic > 1) {
192                 CERROR("manual nid2nic translation doesn't support"
193                        "multiple nic addrs (you asked for %d)\n",
194                         numnic);
195                 return -EINVAL;
196         }
197         if (nid < aries_sim_base_nid) {
198                 CERROR("Request for invalid nid translation %u, minimum %u\n",
199                        nid, aries_sim_base_nid);
200                 return -ESRCH;
201         }
202
203         *nicaddr = nid - aries_sim_base_nid;
204         return 1;
205 }
206
207 static int
208 aries_nicaddr_to_nid(__u32 nicaddr, __u32 *nid)
209 {
210         *nid = aries_sim_base_nid + nicaddr;
211         return 1;
212 }
213
214 /* XXX Nic: This does not support multiple device!!!! */
215 static inline int
216 kgnilnd_setup_nic_translation(__u32 device_id)
217 {
218         char              *if_name = "ipogif0";
219         __u32              ipaddr, netmask, my_nid;
220         int                up, rc;
221
222         /* do lookup on first use */
223         if (unlikely(kgnilnd_hssops.nid_to_nicaddr == NULL)) {
224                 rc = kgnilnd_lookup_rca_funcs();
225                 if (rc)
226                         return rc;
227         }
228
229         /* if we have a real function, return - we'll use those going forward */
230         if (likely(kgnilnd_hssops.nid_to_nicaddr != (void *)GNILND_NO_RCA))
231                 return 0;
232
233         rc = libcfs_ipif_query(if_name, &up, &ipaddr, &netmask);
234         if (rc != 0) {
235                 CERROR("can't get IP interface for %s: %d\n", if_name, rc);
236                 return rc;
237         }
238         if (!up) {
239                 CERROR("IP interface %s is down\n", if_name);
240                 return -ENODEV;
241         }
242
243         my_nid = ((ipaddr >> 8) & 0xFF) + (ipaddr & 0xFF);
244         aries_sim_nic = device_id;
245         aries_sim_base_nid = my_nid - aries_sim_nic;
246
247         kgnilnd_hssops.nid_to_nicaddr = aries_nid_to_nicaddr;
248         kgnilnd_hssops.nicaddr_to_nid = aries_nicaddr_to_nid;
249
250         return 0;
251 }
252 #else
253 #error "Undefined Network Type"
254 #endif
255
256 /* we use RCA types here to get the compiler to whine when we have
257  * mismatched types */
258 static inline int
259 kgnilnd_nid_to_nicaddrs(rca_nid_t nid, int numnic, nic_addr_t *nicaddrs)
260 {
261         /* compile time checks to ensure that the RCA types match
262          * the LNet idea of NID and NIC */
263         typecheck(__u32, nid);
264         typecheck(__u32, *nicaddrs);
265
266         LASSERTF(kgnilnd_hssops.nid_to_nicaddr != NULL, "missing setup?\n");
267
268         return kgnilnd_hssops.nid_to_nicaddr(nid, numnic, nicaddrs);
269 }
270
271 static inline int
272 kgnilnd_nicaddr_to_nid(nic_addr_t nicaddr, rca_nid_t *nid)
273 {
274         /* compile time checks to ensure that the RCA types match
275          * the LNet idea of NID and NIC */
276         typecheck(__u32, nicaddr);
277         typecheck(__u32, nid[0]);
278
279         LASSERTF(kgnilnd_hssops.nicaddr_to_nid != NULL, "missing setup ?\n");
280
281         return kgnilnd_hssops.nicaddr_to_nid(nicaddr, nid);
282 }
283
284 #endif /* _GNILND_HSS_OPS_H */