Motr  M0
lnet_core.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #ifndef __KERNEL__
24 #include <stdio.h> /* snprintf */
25 #endif /* __KERNEL__ */
26 #include "lib/misc.h" /* m0_strtou32 */
27 #include "motr/magic.h"
28 
34 #ifdef NLX_DEBUG
35 static void nlx_print_core_ep_addr(const char *pre,
36  const struct nlx_core_ep_addr *cepa)
37 {
38  NLXP("%s: %p nlx_core_ep_addr\n", pre, cepa);
39  NLXP("\t nid = %ld\n", (unsigned long) cepa->cepa_nid);
40  NLXP("\t pid = %d\n", (unsigned) cepa->cepa_pid);
41  NLXP("\t portal = %d\n", (unsigned) cepa->cepa_portal);
42  NLXP("\t tmid = %d\n", (unsigned) cepa->cepa_tmid);
43 }
44 
45 static void
46 nlx_print_core_buffer_event(const char *pre,
47  const struct nlx_core_buffer_event *lcbev)
48 {
49  NLXP("%s: %p nlx_core_buffer_event\n", pre, lcbev);
50  NLXP("\tcbe_buffer_id: %lx\n", (unsigned long) lcbev->cbe_buffer_id);
51  NLXP("\t cbe_time: %lx\n", (unsigned long) lcbev->cbe_time);
52  NLXP("\t cbe_status: %d\n", lcbev->cbe_status);
53  NLXP("\t cbe_unlinked: %d\n", (int) lcbev->cbe_unlinked);
54  NLXP("\t cbe_length: %ld\n", (unsigned long) lcbev->cbe_length);
55  NLXP("\t cbe_offset: %ld\n", (unsigned long) lcbev->cbe_offset);
56  NLXP("\t cbe_sender: %ld %d %d %d\n",
57  (unsigned long) lcbev->cbe_sender.cepa_nid,
58  (unsigned) lcbev->cbe_sender.cepa_pid,
59  (unsigned) lcbev->cbe_sender.cepa_portal,
60  (unsigned) lcbev->cbe_sender.cepa_tmid);
61 }
62 
63 static void
64 nlx_print_net_buffer_event(const char *pre,
65  const struct m0_net_buffer_event *nbev)
66 {
67  NLXP("%s: %p m0_net_buffer_event\n", (char*) pre, nbev);
68  NLXP("\t nbe_time: %lx\n", (unsigned long) nbev->nbe_time);
69  NLXP("\tnbe_status: %d\n", nbev->nbe_status);
70  NLXP("\tnbe_length: %ld\n", (unsigned long) nbev->nbe_length);
71  NLXP("\tnbe_offset: %ld\n", (unsigned long) nbev->nbe_offset);
72  if (nbev->nbe_ep != NULL)
73  NLXP("\t nbe_ep: %s\n", (char*) nbev->nbe_ep->nep_addr);
74  else
75  NLXP("\t nbe_ep: %s\n", (char*) "NULL");
76  NLXP("\tnbe_buffer: %p\n", nbev->nbe_buffer);
77  if (nbev->nbe_buffer != NULL) {
78  struct m0_net_buffer *nb = nbev->nbe_buffer;
79  NLXP("\t\t nb_qtype: %d\n", nb->nb_qtype);
80  NLXP("\t\t nb_flags: %lx\n", (unsigned long) nb->nb_flags);
81  }
82 }
83 
84 static void nlx_print_core_buffer(const char *pre,
85  const struct nlx_core_buffer *lcb)
86 {
87  NLXP("%s: %p nlx_core_buffer\n", pre, lcb);
88  NLXP("\t magic: %lx\n", (unsigned long) lcb->cb_magic);
89  NLXP("\t buffer_id: %p\n", (void *) lcb->cb_buffer_id);
90  NLXP("\t qtype: %u\n", (unsigned) lcb->cb_qtype);
91  NLXP("\t length: %lu\n", (unsigned long) lcb->cb_length);
92  NLXP("\t min_receive_size: %lu\n",
93  (unsigned long) lcb->cb_min_receive_size);
94  NLXP("\t max_operations: %u\n", (unsigned) lcb->cb_max_operations);
95  NLXP("\t match_bits: %lx\n", (unsigned long) lcb->cb_match_bits);
96  nlx_print_core_ep_addr("\t cb_addr", &lcb->cb_addr);
97 }
98 
99 static inline uint64_t nlx_core_buf_desc_checksum(const struct nlx_core_buf_desc
100  *cbd);
101 
102 static void nlx_print_core_buf_desc(const char *pre,
103  const struct nlx_core_buf_desc *cbd)
104 {
105  NLXP("%s: %p nlx_core_buf_desc\n", pre, cbd);
106  NLXP("\t match_bits: %lx\n", (unsigned long) cbd->cbd_match_bits);
107  NLXP("\t qtype: %u\n", (unsigned) cbd->cbd_qtype);
108  NLXP("\t size: %ld\n", (unsigned long) cbd->cbd_size);
109  NLXP("\t checksum: %lx\n", (unsigned long) cbd->cbd_checksum);
110  nlx_print_core_ep_addr("\t passive_ep", &cbd->cbd_passive_ep);
111  NLXP("\t <checksum>: %lx\n", (unsigned long)
113 }
114 #endif
115 
120 static bool nlx_core_tm_invariant(const struct nlx_core_transfer_mc *lctm)
121 {
122  return lctm != NULL && lctm->ctm_magic == M0_NET_LNET_CORE_TM_MAGIC &&
125 }
126 
134 static bool nlx_core_tm_is_locked(const struct nlx_core_transfer_mc *lctm)
135 {
136  const struct nlx_xo_transfer_mc *xtm;
137 
138  if (!nlx_core_tm_invariant(lctm))
139  return false;
140  xtm = container_of(lctm, struct nlx_xo_transfer_mc, xtm_core);
141  return nlx_tm_invariant(xtm->xtm_tm) &&
142  m0_mutex_is_locked(&xtm->xtm_tm->ntm_mutex);
143 }
144 
149 static bool nlx_core_buffer_invariant(const struct nlx_core_buffer *lcb)
150 {
151  return lcb != NULL && lcb->cb_magic == M0_NET_LNET_CORE_BUF_MAGIC &&
152  lcb->cb_buffer_id != 0;
153 }
154 
155 static uint32_t nlx_core_kmem_loc_checksum(const struct nlx_core_kmem_loc *loc)
156 {
157  int i;
158  uint32_t ret;
159 
160  for (i = 0, ret = 0; i < ARRAY_SIZE(loc->kl_data); ++i)
161  ret ^= loc->kl_data[i];
162  return ret;
163 }
164 
166 {
167  struct nlx_core_buffer_event *bev;
168  if (ql != NULL) {
169  bev = container_of(ql, struct nlx_core_buffer_event,
170  cbe_tm_link);
172  }
173 }
174 
175 M0_INTERNAL int nlx_core_bevq_provision(struct nlx_core_domain *lcdom,
176  struct nlx_core_transfer_mc *lctm,
177  size_t need)
178 {
179  size_t have;
180  int num_to_alloc;
181  int rc = 0;
182 
184  M0_PRE(need > 0);
185 
187  M0_ASSERT(have >= lctm->ctm_bev_needed);
188  num_to_alloc = lctm->ctm_bev_needed + need - have;
189  while (num_to_alloc > 0) {
190  struct nlx_core_buffer_event *bev;
191  rc = nlx_core_new_blessed_bev(lcdom, lctm, &bev);/* {uk} vary */
192  if (rc != 0)
193  break;
194  bev_cqueue_add(&lctm->ctm_bevq, &bev->cbe_tm_link);
195  --num_to_alloc;
196  }
197  if (rc == 0)
198  lctm->ctm_bev_needed += need;
200  M0_POST(have >= lctm->ctm_bev_needed);
201  return M0_RC(rc);
202 }
203 
204 M0_INTERNAL void nlx_core_bevq_release(struct nlx_core_transfer_mc *lctm,
205  size_t release)
206 {
208  M0_PRE(release > 0);
209  M0_PRE(lctm->ctm_bev_needed >= release);
210 
211  lctm->ctm_bev_needed -= release;
212  return;
213 }
214 
215 M0_INTERNAL bool nlx_core_buf_event_get(struct nlx_core_transfer_mc *lctm,
216  struct nlx_core_buffer_event *lcbe)
217 {
218  struct nlx_core_bev_link *link;
219  struct nlx_core_buffer_event *bev;
220 
221  M0_PRE(lcbe != NULL);
223 
224  link = bev_cqueue_get(&lctm->ctm_bevq);
225  if (link != NULL) {
226  bev = container_of(link, struct nlx_core_buffer_event,
227  cbe_tm_link);
228  *lcbe = *bev;
229  M0_SET0(&lcbe->cbe_tm_link); /* copy is not in queue */
230  /* Event structures released when network buffer unlinked */
231  return true;
232  }
233  return false;
234 }
235 
243 static uint64_t nlx_core_match_bits_encode(uint32_t tmid, uint64_t counter)
244 {
245  uint64_t mb;
246  mb = ((uint64_t) tmid << M0_NET_LNET_TMID_SHIFT) |
248  return mb;
249 }
250 
258 static inline void nlx_core_match_bits_decode(uint64_t mb,
259  uint32_t *tmid,
260  uint64_t *counter)
261 {
262  *tmid = (uint32_t) (mb >> M0_NET_LNET_TMID_SHIFT);
264  return;
265 }
266 
267 #define CBD_EP(f) cbd->cbd_passive_ep.cepa_ ## f
268 #define TM_EP(f) lctm->ctm_addr.cepa_ ## f
269 #define B_EP(f) lcbuf->cb_addr.cepa_ ## f
270 
277 static inline uint64_t nlx_core_buf_desc_checksum(const struct nlx_core_buf_desc
278  *cbd)
279 {
280  int i;
281  uint64_t checksum;
282 
283  /* ensure that the checksum computation covers all the payload */
284  M0_CASSERT(sizeof *cbd ==
285  sizeof cbd->cbd_data + sizeof cbd->cbd_checksum);
286 
287  for (i = 0, checksum = 0; i < ARRAY_SIZE(cbd->cbd_data); ++i)
288  checksum ^= cbd->cbd_data[i];
289  return __cpu_to_le64(checksum);
290 }
291 
292 M0_INTERNAL void nlx_core_buf_desc_encode(struct nlx_core_transfer_mc *lctm,
293  struct nlx_core_buffer *lcbuf,
294  struct nlx_core_buf_desc *cbd)
295 {
301 
302  /* generate match bits */
303  lcbuf->cb_match_bits =
305  lctm->ctm_mb_counter);
308 
309  /* create the descriptor */
310  M0_SET_ARR0(cbd->cbd_data);
311  cbd->cbd_match_bits = __cpu_to_le64(lcbuf->cb_match_bits);
312 
313  CBD_EP(nid) = __cpu_to_le64(TM_EP(nid));
314  CBD_EP(pid) = __cpu_to_le32(TM_EP(pid));
315  CBD_EP(portal) = __cpu_to_le32(TM_EP(portal));
316  CBD_EP(tmid) = __cpu_to_le32(TM_EP(tmid));
317 
318  cbd->cbd_qtype = __cpu_to_le32(lcbuf->cb_qtype);
319  cbd->cbd_size = __cpu_to_le64(lcbuf->cb_length);
320 
322 
323  NLXDBG(lctm, 2, nlx_print_core_buf_desc("encode", cbd));
324 
327  return;
328 }
329 
330 M0_INTERNAL int nlx_core_buf_desc_decode(struct nlx_core_transfer_mc *lctm,
331  struct nlx_core_buffer *lcbuf,
332  struct nlx_core_buf_desc *cbd)
333 {
334  uint64_t i64;
335  uint32_t i32;
336 
337  NLXDBG(lctm, 2, nlx_print_core_buf_desc("decode", cbd));
338 
344 
345  i64 = nlx_core_buf_desc_checksum(cbd);
346  if (i64 != cbd->cbd_checksum)
347  return M0_ERR(-EINVAL);
348 
349  i64 = __le64_to_cpu(cbd->cbd_size);
350 
351  i32 = __le32_to_cpu(cbd->cbd_qtype);
352  if (i32 == M0_NET_QT_PASSIVE_BULK_SEND) {
353  if (lcbuf->cb_qtype != M0_NET_QT_ACTIVE_BULK_RECV)
354  return M0_ERR(-EPERM);
355  if (i64 > lcbuf->cb_length)
356  return M0_ERR(-EFBIG);
357  lcbuf->cb_length = i64; /* passive send size used */
358  } else if (i32 == M0_NET_QT_PASSIVE_BULK_RECV) {
359  if (lcbuf->cb_qtype != M0_NET_QT_ACTIVE_BULK_SEND)
360  return M0_ERR(-EPERM);
361  if (lcbuf->cb_length > i64)
362  return M0_ERR(-EFBIG);
363  /* active send size used */
364  } else
365  return M0_ERR(-EINVAL);
366 
367  B_EP(nid) = __le64_to_cpu(CBD_EP(nid));
368  B_EP(pid) = __le32_to_cpu(CBD_EP(pid));
369  B_EP(portal) = __le32_to_cpu(CBD_EP(portal));
370  B_EP(tmid) = __le32_to_cpu(CBD_EP(tmid));
371 
372  lcbuf->cb_match_bits = __le64_to_cpu(cbd->cbd_match_bits);
373  nlx_core_match_bits_decode(lcbuf->cb_match_bits, &i32, &i64);
374  if (i64 < M0_NET_LNET_BUFFER_ID_MIN ||
376  i32 != B_EP(tmid))
377  return M0_ERR(-EINVAL);
378 
379  return 0;
380 }
381 
382 #undef B_EP
383 #undef TM_EP
384 #undef CBD_EP
385 
387  const char *ep_addr,
388  struct nlx_core_ep_addr *cepa)
389 {
390  char nidstr[M0_NET_LNET_NIDSTR_SIZE];
391  char *cp = strchr(ep_addr, ':');
392  char *endp;
393  size_t n = cp - ep_addr;
394  uint64_t nid;
395  int rc;
396 
397  M0_ENTRY("ep_addr=%s", ep_addr);
398 
399  if (cp == NULL || n == 0 || n >= sizeof nidstr)
400  return M0_ERR(-EINVAL);
401  strncpy(nidstr, ep_addr, n);
402  nidstr[n] = 0;
403  rc = nlx_core_nidstr_decode(lcdom, nidstr, &nid);
404  if (rc != 0)
405  return M0_RC(rc);
406  cepa->cepa_nid = nid;
407  ++cp;
408  cepa->cepa_pid = m0_strtou32(cp, &endp, 10);
409  if (*endp != ':')
410  return M0_ERR(-EINVAL);
411  cp = endp + 1;
412  cepa->cepa_portal = m0_strtou32(cp, &endp, 10);
413  if (*endp != ':')
414  return M0_ERR(-EINVAL);
415  cp = endp + 1;
416  if (strcmp(cp, "*") == 0) {
418  } else {
419  cepa->cepa_tmid = m0_strtou32(cp, &endp, 10);
420  if (*endp != 0 || cepa->cepa_tmid > M0_NET_LNET_TMID_MAX ||
421  cepa->cepa_tmid == 0)
422  return M0_ERR(-EINVAL);
423  }
424  return 0;
425 }
426 
428  const struct nlx_core_ep_addr *cepa,
430 {
431  const char *fmt;
432  int rc;
433  int n;
434 
435  rc = nlx_core_nidstr_encode(lcdom, cepa->cepa_nid, buf);
436  M0_ASSERT(rc == 0);
437  n = strlen(buf);
438 
439  if (cepa->cepa_tmid != M0_NET_LNET_TMID_INVALID)
440  fmt = ":%u:%u:%u";
441  else
442  fmt = ":%u:%u:*";
443  snprintf(buf + n, M0_NET_LNET_XEP_ADDR_LEN - n, fmt,
444  cepa->cepa_pid, cepa->cepa_portal, cepa->cepa_tmid);
445 }
446 
447 M0_INTERNAL void nlx_core_dom_set_debug(struct nlx_core_domain *lcdom,
448  unsigned dbg)
449 {
450  lcdom->_debug_ = dbg;
451 }
452 
453 M0_INTERNAL void nlx_core_tm_set_debug(struct nlx_core_transfer_mc *lctm,
454  unsigned dbg)
455 {
456  lctm->_debug_ = dbg;
457 }
458  /* LNetCore */
460 
461 /*
462  * Local variables:
463  * c-indentation-style: "K&R"
464  * c-basic-offset: 8
465  * tab-width: 8
466  * fill-column: 79
467  * scroll-step: 1
468  * End:
469  */
static void bev_cqueue_add(struct nlx_core_bev_cqueue *q, struct nlx_core_bev_link *ql)
Definition: bev_cqueue.c:628
m0_bcount_t cbd_size
static uint32_t nlx_core_kmem_loc_checksum(const struct nlx_core_kmem_loc *loc)
Definition: lnet_core.c:155
static struct nlx_core_bev_link * bev_cqueue_get(struct nlx_core_bev_cqueue *q)
Definition: bev_cqueue.c:722
#define M0_PRE(cond)
struct nlx_core_bev_link cbe_tm_link
#define CBD_EP(f)
Definition: lnet_core.c:267
#define NULL
Definition: misc.h:38
static size_t bev_cqueue_size(const struct nlx_core_bev_cqueue *q)
Definition: bev_cqueue.c:711
#define TM_EP(f)
Definition: lnet_core.c:268
static const char * ep_addr
Definition: rpc_machine.c:35
struct nlx_core_ep_addr cb_addr
string release
Definition: conf.py:42
static void nlx_core_match_bits_decode(uint64_t mb, uint32_t *tmid, uint64_t *counter)
Definition: lnet_core.c:258
static bool nlx_core_buffer_invariant(const struct nlx_core_buffer *lcb)
Definition: lnet_core.c:149
#define NLXDBG(ptr, dbg, stmt)
Definition: lnet_main.c:877
#define M0_CASSERT(cond)
uint64_t nb_flags
Definition: net.h:1489
m0_time_t nbe_time
Definition: net.h:1197
const char * nep_addr
Definition: net.h:503
m0_bindex_t nbe_offset
Definition: net.h:1238
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
m0_bcount_t nbe_length
Definition: net.h:1226
struct m0_net_buffer * nbe_buffer
Definition: net.h:1194
#define NLXP(fmt,...)
Definition: lnet_main.c:876
struct m0_net_end_point * nbe_ep
Definition: net.h:1251
M0_INTERNAL int nlx_core_nidstr_encode(struct nlx_core_domain *lcdom, uint64_t nid, char nidstr[M0_NET_LNET_NIDSTR_SIZE])
Definition: klnet_core.c:1732
Definition: sock.c:887
M0_INTERNAL void nlx_core_dom_set_debug(struct nlx_core_domain *lcdom, unsigned dbg)
Definition: lnet_core.c:447
static bool nlx_core_tm_is_locked(const struct nlx_core_transfer_mc *lctm)
Definition: lnet_core.c:134
M0_INTERNAL int nlx_core_new_blessed_bev(struct nlx_core_domain *cd, struct nlx_core_transfer_mc *ctm, struct nlx_core_buffer_event **bevp)
Definition: klnet_core.c:1785
return M0_RC(rc)
M0_INTERNAL void nlx_core_bevq_release(struct nlx_core_transfer_mc *lctm, size_t release)
Definition: lnet_core.c:204
#define M0_ENTRY(...)
Definition: trace.h:170
int i
Definition: dir.c:1033
#define M0_SET_ARR0(arr)
Definition: misc.h:72
struct nlx_core_ep_addr ctm_addr
int32_t nbe_status
Definition: net.h:1218
return M0_ERR(-EOPNOTSUPP)
enum m0_net_queue_type nb_qtype
Definition: net.h:1363
M0_INTERNAL void nlx_core_tm_set_debug(struct nlx_core_transfer_mc *lctm, unsigned dbg)
Definition: lnet_core.c:453
uint32_t kl_data[3]
M0_INTERNAL int nlx_core_bevq_provision(struct nlx_core_domain *lcdom, struct nlx_core_transfer_mc *lctm, size_t need)
Definition: lnet_core.c:175
struct mock_balloc mb
Definition: ad.c:173
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
struct nlx_core_bev_cqueue ctm_bevq
m0_bcount_t cb_min_receive_size
static int counter
Definition: mutex.c:32
nlx_core_opaque_ptr_t cbe_buffer_id
char * fmt(const char *format,...) __attribute__((format(printf
static bool nlx_tm_invariant(const struct m0_net_transfer_mc *tm)
void nlx_core_ep_addr_encode(struct nlx_core_domain *lcdom, const struct nlx_core_ep_addr *cepa, char buf[M0_NET_LNET_XEP_ADDR_LEN])
Definition: lnet_core.c:427
#define M0_POST(cond)
M0_INTERNAL bool nlx_core_buf_event_get(struct nlx_core_transfer_mc *lctm, struct nlx_core_buffer_event *lcbe)
Definition: lnet_core.c:215
uint32_t cb_max_operations
struct nlx_core_ep_addr cbe_sender
static uint64_t nlx_core_buf_desc_checksum(const struct nlx_core_buf_desc *cbd)
Definition: lnet_core.c:277
uint32_t m0_strtou32(const char *str, char **endptr, int base)
Definition: kmisc.c:32
int nlx_core_ep_addr_decode(struct nlx_core_domain *lcdom, const char *ep_addr, struct nlx_core_ep_addr *cepa)
Definition: lnet_core.c:386
uint64_t cb_match_bits
M0_INTERNAL void nlx_core_buf_desc_encode(struct nlx_core_transfer_mc *lctm, struct nlx_core_buffer *lcbuf, struct nlx_core_buf_desc *cbd)
Definition: lnet_core.c:292
uint64_t n
Definition: fops.h:107
m0_bcount_t cb_length
#define NLX_FREE_ALIGNED_PTR(ptr)
Definition: lnet_core.h:633
enum m0_net_queue_type cb_qtype
#define B_EP(f)
Definition: lnet_core.c:269
static bool nlx_core_tm_invariant(const struct nlx_core_transfer_mc *lctm)
Definition: lnet_core.c:120
static void nlx_core_bev_free_cb(struct nlx_core_bev_link *ql)
Definition: lnet_core.c:165
struct m0_net_transfer_mc * xtm_tm
Definition: lnet_xo.h:87
struct nlx_core_ep_addr cbd_passive_ep
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL int nlx_core_buf_desc_decode(struct nlx_core_transfer_mc *lctm, struct nlx_core_buffer *lcbuf, struct nlx_core_buf_desc *cbd)
Definition: lnet_core.c:330
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL int nlx_core_nidstr_decode(struct nlx_core_domain *lcdom, const char *nidstr, uint64_t *nid)
Definition: klnet_core.c:1710
uint64_t cbd_data[5]
nlx_core_opaque_ptr_t cb_buffer_id
struct nlx_core_transfer_mc xtm_core
Definition: lnet_xo.h:104
static uint64_t nlx_core_match_bits_encode(uint32_t tmid, uint64_t counter)
Definition: lnet_core.c:243