iPXE
xsigo.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <string.h>
27#include <stdio.h>
28#include <errno.h>
29#include <byteswap.h>
30#include <ipxe/version.h>
31#include <ipxe/timer.h>
32#include <ipxe/malloc.h>
33#include <ipxe/iobuf.h>
34#include <ipxe/retry.h>
35#include <ipxe/process.h>
36#include <ipxe/settings.h>
37#include <ipxe/infiniband.h>
38#include <ipxe/ib_service.h>
39#include <ipxe/ib_cmrc.h>
40#include <ipxe/if_ether.h>
41#include <ipxe/ethernet.h>
42#include <ipxe/eoib.h>
43#include <ipxe/xsigo.h>
44
45/** @file
46 *
47 * Xsigo virtual Ethernet devices
48 *
49 */
50
51/** A Xsigo device */
53 /** Reference count */
54 struct refcnt refcnt;
55 /** Underlying Infiniband device */
57 /** List of Xsigo devices */
59 /** Device name */
60 const char *name;
61
62 /** Link opener timer */
64
65 /** Discovery timer */
67 /** Discovery management transaction (if any) */
69
70 /** List of configuration managers */
72};
73
74/** A Xsigo configuration manager */
76 /** Reference count */
77 struct refcnt refcnt;
78 /** Xsigo device */
80 /** List of managers */
82 /** Device name */
83 char name[16];
84 /** Manager ID */
86
87 /** Data transfer interface */
89 /** Connection timer */
91 /** Keepalive timer */
93 /** Transmission process */
95 /** Pending transmissions */
96 unsigned int pending;
97 /** Transmit sequence number */
99
100 /** List of virtual Ethernet devices */
102};
103
104/** Configuration manager pending transmissions */
106 /** Send connection request */
108 /** Send registration message */
110};
111
112/** A Xsigo virtual Ethernet device */
113struct xsigo_nic {
114 /** Configuration manager */
116 /** List of virtual Ethernet devices */
118 /** Device name */
119 char name[16];
120
121 /** Resource identifier */
123 /** MAC address */
125 /** Network ID */
126 unsigned long network;
127};
128
129/** Configuration manager service ID */
130static union ib_guid xcm_service_id = {
131 .bytes = XCM_SERVICE_ID,
132};
133
134/** List of all Xsigo devices */
135static LIST_HEAD ( xsigo_devices );
136
137/**
138 * Free Xsigo device
139 *
140 * @v refcnt Reference count
141 */
142static void xsigo_free ( struct refcnt *refcnt ) {
143 struct xsigo_device *xdev =
145
146 /* Sanity checks */
147 assert ( ! timer_running ( &xdev->opener ) );
148 assert ( ! timer_running ( &xdev->discovery ) );
149 assert ( xdev->madx == NULL );
150 assert ( list_empty ( &xdev->managers ) );
151
152 /* Drop reference to Infiniband device */
153 ibdev_put ( xdev->ibdev );
154
155 /* Free device */
156 free ( xdev );
157}
158
159/**
160 * Free configuration manager
161 *
162 * @v refcnt Reference count
163 */
164static void xcm_free ( struct refcnt *refcnt ) {
165 struct xsigo_manager *xcm =
167
168 /* Sanity checks */
169 assert ( ! timer_running ( &xcm->reopen ) );
170 assert ( ! timer_running ( &xcm->keepalive ) );
171 assert ( ! process_running ( &xcm->process ) );
172 assert ( list_empty ( &xcm->nics ) );
173
174 /* Drop reference to Xsigo device */
175 ref_put ( &xcm->xdev->refcnt );
176
177 /* Free manager */
178 free ( xcm );
179}
180
181/****************************************************************************
182 *
183 * Virtual Ethernet (XVE) devices
184 *
185 ****************************************************************************
186 */
187
188/**
189 * Create virtual Ethernet device
190 *
191 * @v xcm Configuration manager
192 * @v resource Resource identifier
193 * @v mac Ethernet MAC
194 * @v network Network identifier
195 * @v name Device name
196 * @ret rc Return status code
197 */
198static int xve_create ( struct xsigo_manager *xcm, union ib_guid *resource,
199 const uint8_t *mac, unsigned long network,
200 unsigned long qkey, const char *name ) {
201 struct xsigo_device *xdev = xcm->xdev;
202 struct ib_device *ibdev = xdev->ibdev;
203 struct xsigo_nic *xve;
204 struct ib_address_vector broadcast;
205 int rc;
206
207 /* Allocate and initialise structure */
208 xve = zalloc ( sizeof ( *xve ) );
209 if ( ! xve ) {
210 rc = -ENOMEM;
211 goto err_alloc;
212 }
213 xve->xcm = xcm;
214 snprintf ( xve->name, sizeof ( xve->name ), "%s", name );
215 memcpy ( &xve->resource, resource, sizeof ( xve->resource ) );
216 memcpy ( xve->mac, mac, ETH_ALEN );
217 xve->network = network;
218 DBGC ( xve, "XVE %s created for %s " IB_GUID_FMT "\n",
219 xve->name, xcm->name, IB_GUID_ARGS ( resource ) );
220 DBGC ( xve, "XVE %s is MAC %s on network %ld\n",
221 xve->name, eth_ntoa ( mac ), network );
222
223 /* Construct broadcast address vector */
224 memset ( &broadcast, 0, sizeof ( broadcast ) );
225 broadcast.qpn = IB_QPN_BROADCAST;
226 broadcast.qkey = qkey;
227 broadcast.gid_present = 1;
228 broadcast.gid.dwords[0] = htonl ( XVE_PREFIX );
229 broadcast.gid.words[2] = htons ( ibdev->pkey );
230 broadcast.gid.dwords[3] = htonl ( network );
231
232 /* Create EoIB device */
233 if ( ( rc = eoib_create ( ibdev, xve->mac, &broadcast,
234 xve->name ) ) != 0 ) {
235 DBGC ( xve, "XVE %s could not create EoIB device: %s\n",
236 xve->name, strerror ( rc ) );
237 goto err_create;
238 }
239
240 /* Add to list of virtual Ethernet devices. Do this only
241 * after creating the EoIB device, so that our net device
242 * notifier won't attempt to send an operational state update
243 * before we have acknowledged the installation.
244 */
245 list_add ( &xve->list, &xcm->nics );
246
247 return 0;
248
249 list_del ( &xve->list );
250 err_create:
251 free ( xve );
252 err_alloc:
253 return rc;
254}
255
256/**
257 * Find virtual Ethernet device
258 *
259 * @v xcm Configuration manager
260 * @v resource Resource identifier
261 * @ret xve Virtual Ethernet device, or NULL
262 */
263static struct xsigo_nic * xve_find ( struct xsigo_manager *xcm,
264 union ib_guid *resource ) {
265 struct xsigo_nic *xve;
266
267 list_for_each_entry ( xve, &xcm->nics, list ) {
268 if ( memcmp ( resource, &xve->resource,
269 sizeof ( *resource ) ) == 0 )
270 return xve;
271 }
272 return NULL;
273}
274
275/**
276 * Destroy virtual Ethernet device
277 *
278 * @v xve Virtual Ethernet device
279 */
280static void xve_destroy ( struct xsigo_nic *xve ) {
281 struct xsigo_manager *xcm = xve->xcm;
282 struct xsigo_device *xdev = xcm->xdev;
283 struct ib_device *ibdev = xdev->ibdev;
284 struct eoib_device *eoib;
285
286 /* Destroy corresponding EoIB device, if any */
287 if ( ( eoib = eoib_find ( ibdev, xve->mac ) ) )
288 eoib_destroy ( eoib );
289
290 /* Remove from list of virtual Ethernet devices */
291 list_del ( &xve->list );
292
293 /* Free virtual Ethernet device */
294 DBGC ( xve, "XVE %s destroyed\n", xve->name );
295 free ( xve );
296}
297
298/**
299 * Update virtual Ethernet device MTU
300 *
301 * @v xve Virtual Ethernet device
302 * @v eoib EoIB device
303 * @v mtu New MTU (excluding Ethernet and EoIB headers)
304 * @ret rc Return status code
305 */
306static int xve_update_mtu ( struct xsigo_nic *xve, struct eoib_device *eoib,
307 size_t mtu ) {
308 struct net_device *netdev = eoib->netdev;
309 size_t max;
310
311 /* Check that we can support this MTU */
312 max = ( IB_MAX_PAYLOAD_SIZE - ( sizeof ( struct ethhdr ) +
313 sizeof ( struct eoib_header ) ) );
314 if ( mtu > max ) {
315 DBGC ( xve, "XVE %s cannot support MTU %zd (max %zd)\n",
316 xve->name, mtu, max );
317 return -ERANGE;
318 }
319
320 /* Update MTU. No need to close/reopen the network device,
321 * since our Infiniband stack uses a fixed MTU anyway. Note
322 * that the network device sees the Ethernet frame header but
323 * not the EoIB header.
324 */
325 netdev->max_pkt_len = ( mtu + sizeof ( struct ethhdr ) );
326 netdev->mtu = mtu;
327 DBGC ( xve, "XVE %s has MTU %zd\n", xve->name, mtu );
328
329 return 0;
330}
331
332/**
333 * Open virtual Ethernet device
334 *
335 * @v xve Virtual Ethernet device
336 * @v eoib EoIB device
337 * @v open New administrative state
338 * @ret rc Return status code
339 */
340static int xve_open ( struct xsigo_nic *xve, struct eoib_device *eoib ) {
341 struct net_device *netdev = eoib->netdev;
342 int rc;
343
344 /* Do nothing if network device is already open */
345 if ( netdev_is_open ( netdev ) )
346 return 0;
347 DBGC ( xve, "XVE %s opening network device\n", xve->name );
348
349 /* Open network device */
350 if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
351 DBGC ( xve, "XVE %s could not open: %s\n",
352 xve->name, strerror ( rc ) );
353 return rc;
354 }
355
356 return 0;
357}
358
359/**
360 * Close virtual Ethernet device
361 *
362 * @v xve Virtual Ethernet device
363 * @v eoib EoIB device
364 */
365static void xve_close ( struct xsigo_nic *xve, struct eoib_device *eoib ) {
366 struct net_device *netdev = eoib->netdev;
367
368 /* Do nothing if network device is already closed */
369 if ( ! netdev_is_open ( netdev ) )
370 return;
371
372 /* Close network device */
374 DBGC ( xve, "XVE %s closed network device\n", xve->name );
375}
376
377/**
378 * Update virtual Ethernet device administrative state
379 *
380 * @v xve Virtual Ethernet device
381 * @v eoib EoIB device
382 * @v open New administrative state
383 * @ret rc Return status code
384 */
385static int xve_update_state ( struct xsigo_nic *xve, struct eoib_device *eoib,
386 int open ) {
387
388 /* Open or close device, as applicable */
389 if ( open ) {
390 return xve_open ( xve, eoib );
391 } else {
392 xve_close ( xve, eoib );
393 return 0;
394 }
395}
396
397/**
398 * Update gateway (TCA)
399 *
400 * @v xve Virtual Ethernet device
401 * @v eoib EoIB device
402 * @v av Address vector, or NULL if no gateway
403 * @ret rc Return status code
404 */
405static int xve_update_tca ( struct xsigo_nic *xve, struct eoib_device *eoib,
406 struct ib_address_vector *av ) {
407
408 /* Update gateway address */
409 eoib_set_gateway ( eoib, av );
410 if ( av ) {
411 DBGC ( xve, "XVE %s has TCA " IB_GID_FMT " data %#lx qkey "
412 "%#lx\n", xve->name, IB_GID_ARGS ( &av->gid ), av->qpn,
413 av->qkey );
414 } else {
415 DBGC ( xve, "XVE %s has no TCA\n", xve->name );
416 }
417
418 /* The Linux driver will modify the local device's link state
419 * to reflect the EoIB-to-Ethernet gateway's link state, but
420 * this seems philosophically incorrect since communication
421 * within the EoIB broadcast domain still works regardless of
422 * the state of the gateway.
423 */
424
425 return 0;
426}
427
428/****************************************************************************
429 *
430 * Server management protocol (XSMP) session messages
431 *
432 ****************************************************************************
433 */
434
435/**
436 * Get session message name (for debugging)
437 *
438 * @v type Message type
439 * @ret name Message name
440 */
441static const char * xsmp_session_type ( unsigned int type ) {
442 static char buf[16];
443
444 switch ( type ) {
445 case XSMP_SESSION_TYPE_HELLO: return "HELLO";
446 case XSMP_SESSION_TYPE_REGISTER: return "REGISTER";
447 case XSMP_SESSION_TYPE_CONFIRM: return "CONFIRM";
448 case XSMP_SESSION_TYPE_REJECT: return "REJECT";
449 case XSMP_SESSION_TYPE_SHUTDOWN: return "SHUTDOWN";
450 default:
451 snprintf ( buf, sizeof ( buf ), "UNKNOWN<%d>", type );
452 return buf;
453 }
454}
455
456/**
457 * Extract chassis name (for debugging)
458 *
459 * @v msg Session message
460 * @ret chassis Chassis name
461 */
462static const char * xsmp_chassis_name ( struct xsmp_session_message *msg ) {
463 static char chassis[ sizeof ( msg->chassis ) + 1 /* NUL */ ];
464
465 memcpy ( chassis, msg->chassis, sizeof ( msg->chassis ) );
466 return chassis;
467}
468
469/**
470 * Extract session name (for debugging)
471 *
472 * @v msg Session message
473 * @ret session Session name
474 */
475static const char * xsmp_session_name ( struct xsmp_session_message *msg ) {
476 static char session[ sizeof ( msg->session ) + 1 /* NUL */ ];
477
478 memcpy ( session, msg->session, sizeof ( msg->session ) );
479 return session;
480}
481
482/**
483 * Send session message
484 *
485 * @v xcm Configuration manager
486 * @v type Message type
487 * @ret rc Return status code
488 */
489static int xsmp_tx_session ( struct xsigo_manager *xcm, unsigned int type ) {
490 struct xsigo_device *xdev = xcm->xdev;
491 struct ib_device *ibdev = xdev->ibdev;
493 int rc;
494
495 /* Construct session message */
496 memset ( &msg, 0, sizeof ( msg ) );
497 msg.hdr.type = XSMP_TYPE_SESSION;
498 msg.hdr.len = htons ( sizeof ( msg ) );
499 msg.hdr.seq = htonl ( ++xcm->seq );
500 memcpy ( &msg.hdr.src.guid, &ibdev->gid.s.guid,
501 sizeof ( msg.hdr.src.guid ) );
502 memcpy ( &msg.hdr.dst.guid, &xcm->id.guid,
503 sizeof ( msg.hdr.dst.guid ) );
504 msg.type = type;
505 msg.len = htons ( sizeof ( msg ) - sizeof ( msg.hdr ) );
506 msg.os_type = XSIGO_OS_TYPE_GENERIC;
507 msg.resources = htons ( XSIGO_RESOURCE_XVE |
509 msg.boot = htonl ( XSMP_BOOT_PXE );
510 DBGCP ( xcm, "XCM %s TX[%d] session %s\n", xcm->name,
511 ntohl ( msg.hdr.seq ), xsmp_session_type ( msg.type ) );
512 DBGCP_HDA ( xcm, 0, &msg, sizeof ( msg ) );
513
514 /* Send session message */
515 if ( ( rc = xfer_deliver_raw ( &xcm->xfer, &msg,
516 sizeof ( msg ) ) ) != 0 ) {
517 DBGC ( xcm, "XCM %s TX session %s failed: %s\n", xcm->name,
518 xsmp_session_type ( msg.type ), strerror ( rc ) );
519 return rc;
520 }
521
522 return 0;
523}
524
525/**
526 * Send registration message
527 *
528 * @v xcm Configuration manager
529 * @ret rc Return status code
530 */
531static inline int xsmp_tx_session_register ( struct xsigo_manager *xcm ) {
532
533 DBGC ( xcm, "XCM %s registering with " IB_GUID_FMT "\n",
534 xcm->name, IB_GUID_ARGS ( &xcm->id.guid ) );
535
536 /* Send registration message */
538}
539
540/**
541 * Send keepalive message
542 *
543 * @v xcm Configuration manager
544 * @ret rc Return status code
545 */
546static int xsmp_tx_session_hello ( struct xsigo_manager *xcm ) {
547
548 /* Send keepalive message */
550}
551
552/**
553 * Handle received keepalive message
554 *
555 * @v xcm Configuration manager
556 * @v msg Keepalive message
557 * @ret rc Return status code
558 */
559static int xsmp_rx_session_hello ( struct xsigo_manager *xcm,
561
562 /* Respond to keepalive message. Note that the XCM doesn't
563 * seem to actually ever send these.
564 */
565 return xsmp_tx_session_hello ( xcm );
566}
567
568/**
569 * Handle received registration confirmation message
570 *
571 * @v xcm Configuration manager
572 * @v msg Registration confirmation message
573 * @ret rc Return status code
574 */
575static int xsmp_rx_session_confirm ( struct xsigo_manager *xcm,
576 struct xsmp_session_message *msg ) {
577
578 DBGC ( xcm, "XCM %s registered with \"%s\" as \"%s\"\n", xcm->name,
580
581 return 0;
582}
583
584/**
585 * Handle received registration rejection message
586 *
587 * @v xcm Configuration manager
588 * @v msg Registration confirmation message
589 * @ret rc Return status code
590 */
591static int xsmp_rx_session_reject ( struct xsigo_manager *xcm,
592 struct xsmp_session_message *msg ) {
593
594 DBGC ( xcm, "XCM %s rejected by \"%s\":\n",
595 xcm->name, xsmp_chassis_name ( msg ) );
596 DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
597
598 return -EPERM;
599}
600
601/**
602 * Handle received shutdown message
603 *
604 * @v xcm Configuration manager
605 * @v msg Registration confirmation message
606 * @ret rc Return status code
607 */
609 struct xsmp_session_message *msg ) {
610
611 DBGC ( xcm, "XCM %s shut down by \"%s\":\n",
612 xcm->name, xsmp_chassis_name ( msg ) );
613 DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
614
615 return -ENOTCONN;
616}
617
618/**
619 * Handle received session message
620 *
621 * @v xcm Configuration manager
622 * @v msg Session message
623 * @ret rc Return status code
624 */
625static int xsmp_rx_session ( struct xsigo_manager *xcm,
626 struct xsmp_session_message *msg ) {
627
628 DBGCP ( xcm, "XCM %s RX[%d] session %s\n", xcm->name,
629 ntohl ( msg->hdr.seq ), xsmp_session_type ( msg->type ) );
630 DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
631
632 /* Handle message according to type */
633 switch ( msg->type ) {
635 return xsmp_rx_session_hello ( xcm, msg );
637 return xsmp_rx_session_confirm ( xcm, msg );
639 return xsmp_rx_session_reject ( xcm, msg );
641 return xsmp_rx_session_shutdown ( xcm, msg );
642 default:
643 DBGC ( xcm, "XCM %s RX[%d] session unexpected %s:\n", xcm->name,
644 ntohl ( msg->hdr.seq ), xsmp_session_type ( msg->type ));
645 DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
646 return -EPROTO;
647 }
648}
649
650/****************************************************************************
651 *
652 * Server management protocol (XSMP) virtual Ethernet (XVE) messages
653 *
654 ****************************************************************************
655 */
656
657/**
658 * Get virtual Ethernet message name (for debugging)
659 *
660 * @v type Message type
661 * @ret name Message name
662 */
663static const char * xsmp_xve_type ( unsigned int type ) {
664 static char buf[16];
665
666 switch ( type ) {
667 case XSMP_XVE_TYPE_INSTALL: return "INSTALL";
668 case XSMP_XVE_TYPE_DELETE: return "DELETE";
669 case XSMP_XVE_TYPE_UPDATE: return "UPDATE";
670 case XSMP_XVE_TYPE_OPER_UP: return "OPER_UP";
671 case XSMP_XVE_TYPE_OPER_DOWN: return "OPER_DOWN";
672 case XSMP_XVE_TYPE_OPER_REQ: return "OPER_REQ";
673 case XSMP_XVE_TYPE_READY: return "READY";
674 default:
675 snprintf ( buf, sizeof ( buf ), "UNKNOWN<%d>", type );
676 return buf;
677 }
678}
679
680/**
681 * Send virtual Ethernet message
682 *
683 * @v xcm Configuration manager
684 * @v msg Partial message
685 * @ret rc Return status code
686 */
687static int xsmp_tx_xve ( struct xsigo_manager *xcm,
688 struct xsmp_xve_message *msg ) {
689 struct xsigo_device *xdev = xcm->xdev;
690 struct ib_device *ibdev = xdev->ibdev;
691 int rc;
692
693 /* Fill in common header fields */
694 msg->hdr.type = XSMP_TYPE_XVE;
695 msg->hdr.len = htons ( sizeof ( *msg ) );
696 msg->hdr.seq = htonl ( ++xcm->seq );
697 memcpy ( &msg->hdr.src.guid, &ibdev->gid.s.guid,
698 sizeof ( msg->hdr.src.guid ) );
699 memcpy ( &msg->hdr.dst.guid, &xcm->id.guid,
700 sizeof ( msg->hdr.dst.guid ) );
701 msg->len = htons ( sizeof ( *msg ) - sizeof ( msg->hdr ) );
702 DBGCP ( xcm, "XCM %s TX[%d] xve %s code %#02x\n", xcm->name,
703 ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ),
704 msg->code );
705 DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
706
707 /* Send virtual Ethernet message */
708 if ( ( rc = xfer_deliver_raw ( &xcm->xfer, msg,
709 sizeof ( *msg ) ) ) != 0 ) {
710 DBGC ( xcm, "XCM %s TX xve %s failed: %s\n", xcm->name,
711 xsmp_xve_type ( msg->type ), strerror ( rc ) );
712 return rc;
713 }
714
715 return 0;
716}
717
718/**
719 * Send virtual Ethernet message including current device parameters
720 *
721 * @v xcm Configuration manager
722 * @v msg Partial virtual Ethernet message
723 * @v xve Virtual Ethernet device
724 * @v eoib EoIB device
725 * @ret rc Return status code
726 */
727static int xsmp_tx_xve_params ( struct xsigo_manager *xcm,
728 struct xsmp_xve_message *msg,
729 struct xsigo_nic *xve,
730 struct eoib_device *eoib ) {
731 struct xsigo_device *xdev = xcm->xdev;
732 struct ib_device *ibdev = xdev->ibdev;
733 struct net_device *netdev = eoib->netdev;
734
735 /* Set successful response code */
736 msg->code = 0;
737
738 /* Include network identifier, MTU, and current HCA parameters */
739 msg->network = htonl ( xve->network );
740 msg->mtu = htons ( netdev->max_pkt_len - sizeof ( struct ethhdr ) );
741 msg->hca.prefix_le.qword = bswap_64 ( ibdev->gid.s.prefix.qword );
742 msg->hca.pkey = htons ( ibdev->pkey );
743 msg->hca.qkey = msg->tca.qkey;
744 if ( eoib->qp ) {
745 msg->hca.data = htonl ( eoib->qp->ext_qpn );
746 msg->hca.qkey = htons ( eoib->qp->qkey );
747 }
748
749 /* The message type field is (ab)used to return the current
750 * operational status.
751 */
752 if ( msg->type == XSMP_XVE_TYPE_OPER_REQ ) {
753 msg->type = ( netdev_is_open ( netdev ) ?
755 }
756
757 /* Send message */
758 DBGC ( xve, "XVE %s network %d MTU %d ctrl %#x data %#x qkey %#04x "
759 "%s\n", xve->name, ntohl ( msg->network ), ntohs ( msg->mtu ),
760 ntohl ( msg->hca.ctrl ), ntohl ( msg->hca.data ),
761 ntohs ( msg->hca.qkey ), xsmp_xve_type ( msg->type ) );
762
763 return xsmp_tx_xve ( xcm, msg );
764}
765
766/**
767 * Send virtual Ethernet error response
768 *
769 * @v xcm Configuration manager
770 * @v msg Partial virtual Ethernet message
771 * @ret rc Return status code
772 */
773static inline int xsmp_tx_xve_nack ( struct xsigo_manager *xcm,
774 struct xsmp_xve_message *msg ) {
775
776 /* Set error response code. (There aren't any meaningful
777 * detailed response codes defined by the wire protocol.)
778 */
779 msg->code = XSMP_XVE_CODE_ERROR;
780
781 /* Send message */
782 return xsmp_tx_xve ( xcm, msg );
783}
784
785/**
786 * Send virtual Ethernet notification
787 *
788 * @v xcm Configuration manager
789 * @v type Message type
790 * @v xve Virtual Ethernet device
791 * @v eoib EoIB device
792 * @ret rc Return status code
793 */
794static int xsmp_tx_xve_notify ( struct xsigo_manager *xcm,
795 unsigned int type,
796 struct xsigo_nic *xve,
797 struct eoib_device *eoib ) {
798 struct xsmp_xve_message msg;
799
800 /* Construct message */
801 memset ( &msg, 0, sizeof ( msg ) );
802 msg.type = type;
803 memcpy ( &msg.resource, &xve->resource, sizeof ( msg.resource ) );
804
805 /* Send message */
806 return xsmp_tx_xve_params ( xcm, &msg, xve, eoib );
807}
808
809/**
810 * Send virtual Ethernet current operational state
811 *
812 * @v xcm Configuration manager
813 * @v xve Virtual Ethernet device
814 * @v eoib EoIB device
815 * @ret rc Return status code
816 */
817static inline int xsmp_tx_xve_oper ( struct xsigo_manager *xcm,
818 struct xsigo_nic *xve,
819 struct eoib_device *eoib ) {
820
821 /* Send notification */
822 return xsmp_tx_xve_notify ( xcm, XSMP_XVE_TYPE_OPER_REQ, xve, eoib );
823}
824
825/**
826 * Handle received virtual Ethernet modification message
827 *
828 * @v xcm Configuration manager
829 * @v msg Virtual Ethernet message
830 * @v update Update bitmask
831 * @ret rc Return status code
832 */
833static int xsmp_rx_xve_modify ( struct xsigo_manager *xcm,
834 struct xsmp_xve_message *msg,
835 unsigned int update ) {
836 struct xsigo_device *xdev = xcm->xdev;
837 struct ib_device *ibdev = xdev->ibdev;
838 struct xsigo_nic *xve;
839 struct eoib_device *eoib;
840 struct ib_address_vector tca;
841 size_t mtu;
842 int rc;
843
844 /* Avoid returning uninitialised HCA parameters in response */
845 memset ( &msg->hca, 0, sizeof ( msg->hca ) );
846
847 /* Find virtual Ethernet device */
848 xve = xve_find ( xcm, &msg->resource );
849 if ( ! xve ) {
850 DBGC ( xcm, "XCM %s unrecognised resource " IB_GUID_FMT "\n",
851 xcm->name, IB_GUID_ARGS ( &msg->resource ) );
852 rc = -ENOENT;
853 goto err_no_xve;
854 }
855
856 /* Find corresponding EoIB device */
857 eoib = eoib_find ( ibdev, xve->mac );
858 if ( ! eoib ) {
859 DBGC ( xve, "XVE %s has no EoIB device\n", xve->name );
860 rc = -EPIPE;
861 goto err_no_eoib;
862 }
863
864 /* The Xsigo management software fails to create the EoIB
865 * multicast group. This is a fundamental design flaw.
866 */
868
869 /* Extract modifiable parameters. Note that the TCA GID is
870 * erroneously transmitted as little-endian.
871 */
872 mtu = ntohs ( msg->mtu );
873 memset ( &tca, 0, sizeof ( tca ) );
874 tca.qpn = ntohl ( msg->tca.data );
875 tca.qkey = ntohs ( msg->tca.qkey );
876 tca.gid_present = 1;
877 tca.gid.s.prefix.qword = bswap_64 ( msg->tca.prefix_le.qword );
878 tca.gid.s.guid.qword = bswap_64 ( msg->guid_le.qword );
879
880 /* Update MTU, if applicable */
881 if ( ( update & XSMP_XVE_UPDATE_MTU ) &&
882 ( ( rc = xve_update_mtu ( xve, eoib, mtu ) ) != 0 ) )
883 goto err_mtu;
884 update &= ~XSMP_XVE_UPDATE_MTU;
885
886 /* Update admin state, if applicable */
887 if ( ( update & XSMP_XVE_UPDATE_STATE ) &&
888 ( ( rc = xve_update_state ( xve, eoib, msg->state ) ) != 0 ) )
889 goto err_state;
890 update &= ~XSMP_XVE_UPDATE_STATE;
891
892 /* Remove gateway, if applicable */
893 if ( ( update & XSMP_XVE_UPDATE_GW_DOWN ) &&
894 ( ( rc = xve_update_tca ( xve, eoib, NULL ) ) != 0 ) )
895 goto err_gw_down;
896 update &= ~XSMP_XVE_UPDATE_GW_DOWN;
897
898 /* Update gateway, if applicable */
899 if ( ( update & XSMP_XVE_UPDATE_GW_CHANGE ) &&
900 ( ( rc = xve_update_tca ( xve, eoib, &tca ) ) != 0 ) )
901 goto err_gw_change;
903
904 /* Warn about unexpected updates */
905 if ( update ) {
906 DBGC ( xve, "XVE %s unrecognised update(s) %#08x\n",
907 xve->name, update );
908 }
909
910 xsmp_tx_xve_params ( xcm, msg, xve, eoib );
911 return 0;
912
913 err_gw_change:
914 err_gw_down:
915 err_state:
916 err_mtu:
917 err_no_eoib:
918 err_no_xve:
919 /* Send NACK */
920 xsmp_tx_xve_nack ( xcm, msg );
921 return rc;
922}
923
924/**
925 * Handle received virtual Ethernet installation message
926 *
927 * @v xcm Configuration manager
928 * @v msg Virtual Ethernet message
929 * @ret rc Return status code
930 */
931static int xsmp_rx_xve_install ( struct xsigo_manager *xcm,
932 struct xsmp_xve_message *msg ) {
933 union {
934 struct xsmp_xve_mac msg;
936 } mac;
937 char name[ sizeof ( msg->name ) + 1 /* NUL */ ];
938 unsigned long network;
939 unsigned long qkey;
940 unsigned int update;
941 int rc;
942
943 /* Demangle MAC address (which is erroneously transmitted as
944 * little-endian).
945 */
946 mac.msg.high = bswap_16 ( msg->mac_le.high );
947 mac.msg.low = bswap_32 ( msg->mac_le.low );
948
949 /* Extract interface name (which may not be NUL-terminated) */
950 memcpy ( name, msg->name, ( sizeof ( name ) - 1 /* NUL */ ) );
951 name[ sizeof ( name ) - 1 /* NUL */ ] = '\0';
952
953 /* Extract remaining message parameters */
954 network = ntohl ( msg->network );
955 qkey = ntohs ( msg->tca.qkey );
956 DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " install \"%s\" %s net %ld qkey "
957 "%#lx\n", xcm->name, IB_GUID_ARGS ( &msg->resource ), name,
958 eth_ntoa ( mac.raw ), network, qkey );
959
960 /* Create virtual Ethernet device, if applicable */
961 if ( ( xve_find ( xcm, &msg->resource ) == NULL ) &&
962 ( ( rc = xve_create ( xcm, &msg->resource, mac.raw, network,
963 qkey, name ) ) != 0 ) )
964 goto err_create;
965
966 /* Handle remaining parameters as for a modification message */
967 update = XSMP_XVE_UPDATE_MTU;
968 if ( msg->uplink == XSMP_XVE_UPLINK )
970 return xsmp_rx_xve_modify ( xcm, msg, update );
971
972 err_create:
973 /* Send NACK */
974 xsmp_tx_xve_nack ( xcm, msg );
975 return rc;
976}
977
978/**
979 * Handle received virtual Ethernet deletion message
980 *
981 * @v xcm Configuration manager
982 * @v msg Virtual Ethernet message
983 * @ret rc Return status code
984 */
985static int xsmp_rx_xve_delete ( struct xsigo_manager *xcm,
986 struct xsmp_xve_message *msg ) {
987 struct xsigo_nic *xve;
988
989 DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " delete\n",
990 xcm->name, IB_GUID_ARGS ( &msg->resource ) );
991
992 /* Destroy virtual Ethernet device (if any) */
993 if ( ( xve = xve_find ( xcm, &msg->resource ) ) )
994 xve_destroy ( xve );
995
996 /* Send ACK */
997 msg->code = 0;
998 xsmp_tx_xve ( xcm, msg );
999
1000 return 0;
1001}
1002
1003/**
1004 * Handle received virtual Ethernet update message
1005 *
1006 * @v xcm Configuration manager
1007 * @v msg Virtual Ethernet message
1008 * @ret rc Return status code
1009 */
1011 struct xsmp_xve_message *msg ) {
1012 unsigned int update = ntohl ( msg->update );
1013
1014 DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " update (%08x)\n",
1015 xcm->name, IB_GUID_ARGS ( &msg->resource ), update );
1016
1017 /* Handle as a modification message */
1018 return xsmp_rx_xve_modify ( xcm, msg, update );
1019}
1020
1021/**
1022 * Handle received virtual Ethernet operational request message
1023 *
1024 * @v xcm Configuration manager
1025 * @v msg Virtual Ethernet message
1026 * @ret rc Return status code
1027 */
1029 struct xsmp_xve_message *msg ) {
1030
1031 DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " operational request\n",
1032 xcm->name, IB_GUID_ARGS ( &msg->resource ) );
1033
1034 /* Handle as a nullipotent modification message */
1035 return xsmp_rx_xve_modify ( xcm, msg, 0 );
1036}
1037
1038/**
1039 * Handle received virtual Ethernet readiness message
1040 *
1041 * @v xcm Configuration manager
1042 * @v msg Virtual Ethernet message
1043 * @ret rc Return status code
1044 */
1046 struct xsmp_xve_message *msg ) {
1047 int rc;
1048
1049 DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " ready\n",
1050 xcm->name, IB_GUID_ARGS ( &msg->resource ) );
1051
1052 /* Handle as a nullipotent modification message */
1053 if ( ( rc = xsmp_rx_xve_modify ( xcm, msg, 0 ) ) != 0 )
1054 return rc;
1055
1056 /* Send an unsolicited operational state update, since there
1057 * is no other way to convey the current operational state.
1058 */
1060 if ( ( rc = xsmp_rx_xve_modify ( xcm, msg, 0 ) ) != 0 )
1061 return rc;
1062
1063 return 0;
1064}
1065
1066/**
1067 * Handle received virtual Ethernet message
1068 *
1069 * @v xcm Configuration manager
1070 * @v msg Virtual Ethernet message
1071 * @ret rc Return status code
1072 */
1073static int xsmp_rx_xve ( struct xsigo_manager *xcm,
1074 struct xsmp_xve_message *msg ) {
1075
1076 DBGCP ( xcm, "XCM %s RX[%d] xve %s\n", xcm->name,
1077 ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ) );
1078 DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
1079
1080 /* Handle message according to type */
1081 switch ( msg->type ) {
1083 return xsmp_rx_xve_install ( xcm, msg );
1085 return xsmp_rx_xve_delete ( xcm, msg );
1087 return xsmp_rx_xve_update ( xcm, msg );
1089 return xsmp_rx_xve_oper_req ( xcm, msg );
1091 return xsmp_rx_xve_ready ( xcm, msg );
1092 default:
1093 DBGC ( xcm, "XCM %s RX[%d] xve unexpected %s:\n", xcm->name,
1094 ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ) );
1095 DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
1096 return -EPROTO;
1097 }
1098}
1099
1100/****************************************************************************
1101 *
1102 * Configuration managers (XCM)
1103 *
1104 ****************************************************************************
1105 */
1106
1107/**
1108 * Close configuration manager connection
1109 *
1110 * @v xcm Configuration manager
1111 * @v rc Reason for close
1112 */
1113static void xcm_close ( struct xsigo_manager *xcm, int rc ) {
1114
1115 DBGC ( xcm, "XCM %s closed: %s\n", xcm->name, strerror ( rc ) );
1116
1117 /* Stop transmission process */
1118 process_del ( &xcm->process );
1119
1120 /* Stop keepalive timer */
1121 stop_timer ( &xcm->keepalive );
1122
1123 /* Restart data transfer interface */
1124 intf_restart ( &xcm->xfer, rc );
1125
1126 /* Schedule reconnection attempt */
1127 start_timer ( &xcm->reopen );
1128}
1129
1130/**
1131 * Send data to configuration manager
1132 *
1133 * @v xcm Configuration manager
1134 */
1135static void xcm_step ( struct xsigo_manager *xcm ) {
1136 int rc;
1137
1138 /* Do nothing unless we have something to send */
1139 if ( ! xcm->pending )
1140 return;
1141
1142 /* Send (empty) connection request, if applicable */
1143 if ( xcm->pending & XCM_TX_CONNECT ) {
1144 if ( ( rc = xfer_deliver_raw ( &xcm->xfer, NULL, 0 ) ) != 0 ) {
1145 DBGC ( xcm, "XCM %s could not send connection request: "
1146 "%s\n", xcm->name, strerror ( rc ) );
1147 goto err;
1148 }
1150 return;
1151 }
1152
1153 /* Wait until data transfer interface is connected */
1154 if ( ! xfer_window ( &xcm->xfer ) )
1155 return;
1156
1157 /* Send registration message, if applicable */
1158 if ( xcm->pending & XCM_TX_REGISTER ) {
1159 if ( ( rc = xsmp_tx_session_register ( xcm ) ) != 0 )
1160 goto err;
1162 return;
1163 }
1164
1165 return;
1166
1167 err:
1168 xcm_close ( xcm, rc );
1169}
1170
1171/**
1172 * Receive data from configuration manager
1173 *
1174 * @v xcm Configuration manager
1175 * @v iobuf I/O buffer
1176 * @v meta Data transfer metadata
1177 * @ret rc Return status code
1178 */
1179static int xcm_deliver ( struct xsigo_manager *xcm, struct io_buffer *iobuf,
1180 struct xfer_metadata *meta __unused ) {
1181 union xsmp_message *msg;
1182 size_t len = iob_len ( iobuf );
1183 int rc;
1184
1185 /* Sanity check */
1186 if ( len < sizeof ( msg->hdr ) ) {
1187 DBGC ( xcm, "XCM %s underlength message:\n", xcm->name );
1188 DBGC_HDA ( xcm, 0, iobuf->data, iob_len ( iobuf ) );
1189 rc = -EPROTO;
1190 goto out;
1191 }
1192 msg = iobuf->data;
1193
1194 /* Handle message according to type */
1195 if ( ! msg->hdr.type ) {
1196
1197 /* Ignore unused communication manager private data blocks */
1198 rc = 0;
1199
1200 } else if ( ( msg->hdr.type == XSMP_TYPE_SESSION ) &&
1201 ( len >= sizeof ( msg->sess ) ) ) {
1202
1203 /* Session message */
1204 rc = xsmp_rx_session ( xcm, &msg->sess );
1205
1206 } else if ( ( msg->hdr.type == XSMP_TYPE_XVE ) &&
1207 ( len >= sizeof ( msg->xve ) ) ) {
1208
1209 /* Virtual Ethernet message */
1210 xsmp_rx_xve ( xcm, &msg->xve );
1211
1212 /* Virtual Ethernet message errors are non-fatal */
1213 rc = 0;
1214
1215 } else {
1216
1217 /* Unknown message */
1218 DBGC ( xcm, "XCM %s unexpected message type %d:\n",
1219 xcm->name, msg->hdr.type );
1220 DBGC_HDA ( xcm, 0, iobuf->data, iob_len ( iobuf ) );
1221 rc = -EPROTO;
1222 }
1223
1224 out:
1225 free_iob ( iobuf );
1226 if ( rc != 0 )
1227 xcm_close ( xcm, rc );
1228 return rc;
1229}
1230
1231/** Configuration manager data transfer interface operations */
1237
1238/** Configuration manager data transfer interface descriptor */
1240 INTF_DESC ( struct xsigo_manager, xfer, xcm_xfer_op );
1241
1242/** Configuration manager process descriptor */
1245
1246/**
1247 * Handle configuration manager connection timer expiry
1248 *
1249 * @v timer Connection timer
1250 * @v fail Failure indicator
1251 */
1252static void xcm_reopen ( struct retry_timer *timer, int fail __unused ) {
1253 struct xsigo_manager *xcm =
1255 struct xsigo_device *xdev = xcm->xdev;
1256 struct ib_device *ibdev = xdev->ibdev;
1257 union ib_gid gid;
1258 int rc;
1259
1260 /* Stop transmission process */
1261 process_del ( &xcm->process );
1262
1263 /* Stop keepalive timer */
1264 stop_timer ( &xcm->keepalive );
1265
1266 /* Restart data transfer interface */
1267 intf_restart ( &xcm->xfer, -ECANCELED );
1268
1269 /* Reset sequence number */
1270 xcm->seq = 0;
1271
1272 /* Construct GID */
1273 memcpy ( &gid.s.prefix, &ibdev->gid.s.prefix, sizeof ( gid.s.prefix ) );
1274 memcpy ( &gid.s.guid, &xcm->id.guid, sizeof ( gid.s.guid ) );
1275 DBGC ( xcm, "XCM %s connecting to " IB_GID_FMT "\n",
1276 xcm->name, IB_GID_ARGS ( &gid ) );
1277
1278 /* Open CMRC connection */
1279 if ( ( rc = ib_cmrc_open ( &xcm->xfer, ibdev, &gid,
1280 &xcm_service_id, xcm->name ) ) != 0 ) {
1281 DBGC ( xcm, "XCM %s could not open CMRC connection: %s\n",
1282 xcm->name, strerror ( rc ) );
1283 start_timer ( &xcm->reopen );
1284 return;
1285 }
1286
1287 /* Schedule transmissions */
1289 process_add ( &xcm->process );
1290
1291 /* Start keepalive timer */
1293
1294 return;
1295}
1296
1297/**
1298 * Handle configuration manager keepalive timer expiry
1299 *
1300 * @v timer Connection timer
1301 * @v fail Failure indicator
1302 */
1303static void xcm_keepalive ( struct retry_timer *timer, int fail __unused ) {
1304 struct xsigo_manager *xcm =
1306 int rc;
1307
1308 /* Send keepalive message. The server won't actually respond
1309 * to these, but it gives the RC queue pair a chance to
1310 * complain if it doesn't ever at least get an ACK.
1311 */
1312 if ( ( rc = xsmp_tx_session_hello ( xcm ) ) != 0 ) {
1313 xcm_close ( xcm, rc );
1314 return;
1315 }
1316
1317 /* Restart keepalive timer */
1319}
1320
1321/**
1322 * Create configuration manager
1323 *
1324 * @v xsigo Xsigo device
1325 * @v id Configuration manager ID
1326 * @ret rc Return status code
1327 */
1328static int xcm_create ( struct xsigo_device *xdev,
1329 struct xsigo_manager_id *id ) {
1330 struct xsigo_manager *xcm;
1331
1332 /* Allocate and initialise structure */
1333 xcm = zalloc ( sizeof ( *xcm ) );
1334 if ( ! xcm )
1335 return -ENOMEM;
1336 ref_init ( &xcm->refcnt, xcm_free );
1337 xcm->xdev = xdev;
1338 ref_get ( &xcm->xdev->refcnt );
1339 snprintf ( xcm->name, sizeof ( xcm->name ), "%s:xcm-%d",
1340 xdev->name, ntohs ( id->lid ) );
1341 memcpy ( &xcm->id, id, sizeof ( xcm->id ) );
1342 intf_init ( &xcm->xfer, &xcm_xfer_desc, &xcm->refcnt );
1343 timer_init ( &xcm->keepalive, xcm_keepalive, &xcm->refcnt );
1344 timer_init ( &xcm->reopen, xcm_reopen, &xcm->refcnt );
1346 INIT_LIST_HEAD ( &xcm->nics );
1347
1348 /* Start timer to open connection */
1349 start_timer_nodelay ( &xcm->reopen );
1350
1351 /* Add to list of managers and transfer reference to list */
1352 list_add ( &xcm->list, &xdev->managers );
1353 DBGC ( xcm, "XCM %s created for " IB_GUID_FMT " (LID %d)\n", xcm->name,
1354 IB_GUID_ARGS ( &xcm->id.guid ), ntohs ( id->lid ) );
1355 return 0;
1356}
1357
1358/**
1359 * Find configuration manager
1360 *
1361 * @v xsigo Xsigo device
1362 * @v id Configuration manager ID
1363 * @ret xcm Configuration manager, or NULL
1364 */
1365static struct xsigo_manager * xcm_find ( struct xsigo_device *xdev,
1366 struct xsigo_manager_id *id ) {
1367 struct xsigo_manager *xcm;
1368 union ib_guid *guid = &id->guid;
1369
1370 /* Find configuration manager */
1371 list_for_each_entry ( xcm, &xdev->managers, list ) {
1372 if ( memcmp ( guid, &xcm->id.guid, sizeof ( *guid ) ) == 0 )
1373 return xcm;
1374 }
1375 return NULL;
1376}
1377
1378/**
1379 * Destroy configuration manager
1380 *
1381 * @v xcm Configuration manager
1382 */
1383static void xcm_destroy ( struct xsigo_manager *xcm ) {
1384 struct xsigo_nic *xve;
1385
1386 /* Remove all EoIB NICs */
1387 while ( ( xve = list_first_entry ( &xcm->nics, struct xsigo_nic,
1388 list ) ) ) {
1389 xve_destroy ( xve );
1390 }
1391
1392 /* Stop transmission process */
1393 process_del ( &xcm->process );
1394
1395 /* Stop timers */
1396 stop_timer ( &xcm->keepalive );
1397 stop_timer ( &xcm->reopen );
1398
1399 /* Shut down data transfer interface */
1400 intf_shutdown ( &xcm->xfer, 0 );
1401
1402 /* Remove from list of managers and drop list's reference */
1403 DBGC ( xcm, "XCM %s destroyed\n", xcm->name );
1404 list_del ( &xcm->list );
1405 ref_put ( &xcm->refcnt );
1406}
1407
1408/**
1409 * Synchronise list of configuration managers
1410 *
1411 * @v xdev Xsigo device
1412 * @v ids List of manager IDs
1413 * @v count Number of manager IDs
1414 * @ret rc Return status code
1415 */
1416static int xcm_list ( struct xsigo_device *xdev, struct xsigo_manager_id *ids,
1417 unsigned int count ) {
1418 struct xsigo_manager_id *id;
1419 struct xsigo_manager *xcm;
1420 struct xsigo_manager *tmp;
1421 struct list_head list;
1422 unsigned int i;
1423 int rc;
1424
1425 /* Create list of managers to be retained */
1426 INIT_LIST_HEAD ( &list );
1427 for ( i = 0, id = ids ; i < count ; i++, id++ ) {
1428 if ( ( xcm = xcm_find ( xdev, id ) ) ) {
1429 list_del ( &xcm->list );
1430 list_add_tail ( &xcm->list, &list );
1431 }
1432 }
1433
1434 /* Destroy any managers not in the list */
1435 list_for_each_entry_safe ( xcm, tmp, &xdev->managers, list )
1436 xcm_destroy ( xcm );
1437 list_splice ( &list, &xdev->managers );
1438
1439 /* Create any new managers in the list, and force reconnection
1440 * for any changed LIDs.
1441 */
1442 for ( i = 0, id = ids ; i < count ; i++, id++ ) {
1443 if ( ( xcm = xcm_find ( xdev, id ) ) ) {
1444 if ( xcm->id.lid != id->lid )
1445 start_timer_nodelay ( &xcm->reopen );
1446 continue;
1447 }
1448 if ( ( rc = xcm_create ( xdev, id ) ) != 0 ) {
1449 DBGC ( xdev, "XDEV %s could not create manager: %s\n",
1450 xdev->name, strerror ( rc ) );
1451 return rc;
1452 }
1453 }
1454
1455 return 0;
1456}
1457
1458/****************************************************************************
1459 *
1460 * Configuration manager discovery
1461 *
1462 ****************************************************************************
1463 */
1464
1465/** A stage of discovery */
1467 /** Name */
1468 const char *name;
1469 /** Management transaction operations */
1471};
1472
1473/**
1474 * Handle configuration manager lookup completion
1475 *
1476 * @v ibdev Infiniband device
1477 * @v mi Management interface
1478 * @v madx Management transaction
1479 * @v rc Status code
1480 * @v mad Received MAD (or NULL on error)
1481 * @v av Source address vector (or NULL on error)
1482 */
1483static void xsigo_xcm_complete ( struct ib_device *ibdev,
1484 struct ib_mad_interface *mi __unused,
1485 struct ib_mad_transaction *madx,
1486 int rc, union ib_mad *mad,
1487 struct ib_address_vector *av __unused ) {
1488 struct xsigo_device *xdev = ib_madx_get_ownerdata ( madx );
1489 union xsigo_mad *xsmad = container_of ( mad, union xsigo_mad, mad );
1490 struct xsigo_managers_reply *reply = &xsmad->reply;
1491
1492 /* Check for failures */
1493 if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) )
1494 rc = -ENODEV;
1495 if ( rc != 0 ) {
1496 DBGC ( xdev, "XDEV %s manager lookup failed: %s\n",
1497 xdev->name, strerror ( rc ) );
1498 goto out;
1499 }
1500
1501 /* Sanity checks */
1502 if ( reply->count > ( sizeof ( reply->manager ) /
1503 sizeof ( reply->manager[0] ) ) ) {
1504 DBGC ( xdev, "XDEV %s has too many managers (%d)\n",
1505 xdev->name, reply->count );
1506 goto out;
1507 }
1508
1509 /* Synchronise list of managers */
1510 if ( ( rc = xcm_list ( xdev, reply->manager, reply->count ) ) != 0 )
1511 goto out;
1512
1513 /* Report an empty list of managers */
1514 if ( reply->count == 0 )
1515 DBGC ( xdev, "XDEV %s has no managers\n", xdev->name );
1516
1517 /* Delay next discovery attempt */
1519
1520out:
1521 /* Destroy the completed transaction */
1522 ib_destroy_madx ( ibdev, ibdev->gsi, madx );
1523 xdev->madx = NULL;
1524}
1525
1526/** Configuration manager lookup discovery stage */
1528 .name = "manager",
1529 .op = {
1530 .complete = xsigo_xcm_complete,
1531 },
1532};
1533
1534/**
1535 * Handle directory service lookup completion
1536 *
1537 * @v ibdev Infiniband device
1538 * @v mi Management interface
1539 * @v madx Management transaction
1540 * @v rc Status code
1541 * @v mad Received MAD (or NULL on error)
1542 * @v av Source address vector (or NULL on error)
1543 */
1544static void xsigo_xds_complete ( struct ib_device *ibdev,
1545 struct ib_mad_interface *mi __unused,
1546 struct ib_mad_transaction *madx,
1547 int rc, union ib_mad *mad,
1548 struct ib_address_vector *av __unused ) {
1549 struct xsigo_device *xdev = ib_madx_get_ownerdata ( madx );
1550 union xsigo_mad *xsmad = container_of ( mad, union xsigo_mad, mad );
1551 struct xsigo_managers_request *request = &xsmad->request;
1552 struct ib_service_record *svc;
1553 struct ib_address_vector dest;
1554 union ib_guid *guid;
1555
1556 /* Allow for reuse of transaction pointer */
1557 xdev->madx = NULL;
1558
1559 /* Check for failures */
1560 if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) )
1561 rc = -ENODEV;
1562 if ( rc != 0 ) {
1563 DBGC ( xdev, "XDEV %s directory lookup failed: %s\n",
1564 xdev->name, strerror ( rc ) );
1565 goto out;
1566 }
1567
1568 /* Construct address vector */
1569 memset ( &dest, 0, sizeof ( dest ) );
1570 svc = &mad->sa.sa_data.service_record;
1571 dest.lid = ntohs ( svc->data16[0] );
1572 dest.sl = ibdev->sm_sl;
1573 dest.qpn = IB_QPN_GSI;
1574 dest.qkey = IB_QKEY_GSI;
1575 guid = ( ( union ib_guid * ) &svc->data64[0] );
1576 DBGC2 ( xdev, "XDEV %s found directory at LID %d GUID " IB_GUID_FMT
1577 "\n", xdev->name, dest.lid, IB_GUID_ARGS ( guid ) );
1578
1579 /* Construct request (reusing MAD buffer) */
1580 memset ( request, 0, sizeof ( *request ) );
1581 request->mad_hdr.mgmt_class = XSIGO_MGMT_CLASS;
1582 request->mad_hdr.class_version = XSIGO_MGMT_CLASS_VERSION;
1583 request->mad_hdr.method = IB_MGMT_METHOD_GET;
1584 request->mad_hdr.attr_id = htons ( XSIGO_ATTR_XCM_REQUEST );
1585 memcpy ( &request->server.guid, &ibdev->gid.s.guid,
1586 sizeof ( request->server.guid ) );
1587 snprintf ( request->os_version, sizeof ( request->os_version ),
1589 snprintf ( request->arch, sizeof ( request->arch ), _S2 ( ARCH ) );
1590 request->os_type = XSIGO_OS_TYPE_GENERIC;
1591 request->resources = htons ( XSIGO_RESOURCES_PRESENT |
1594
1595 /* The handling of this request on the server side is a
1596 * textbook example of how not to design a wire protocol. The
1597 * server uses the _driver_ version number to determine which
1598 * fields are present.
1599 */
1600 request->driver_version = htonl ( 0x2a2a2a );
1601
1602 /* The build version field is ignored unless it happens to
1603 * contain the substring "xg-".
1604 */
1605 snprintf ( request->build, sizeof ( request->build ),
1606 "not-xg-%08lx", build_id );
1607
1608 /* The server side user interface occasionally has no way to
1609 * refer to an entry with an empty hostname.
1610 */
1611 fetch_string_setting ( NULL, &hostname_setting, request->hostname,
1612 sizeof ( request->hostname ) );
1613 if ( ! request->hostname[0] ) {
1614 snprintf ( request->hostname, sizeof ( request->hostname ),
1616 IB_GUID_ARGS ( &ibdev->gid.s.guid ) );
1617 }
1618
1619 /* Start configuration manager lookup */
1620 xdev->madx = ib_create_madx ( ibdev, ibdev->gsi, mad, &dest,
1621 &xsigo_xcm_discovery.op );
1622 if ( ! xdev->madx ) {
1623 DBGC ( xdev, "XDEV %s could not start manager lookup\n",
1624 xdev->name );
1625 goto out;
1626 }
1627 ib_madx_set_ownerdata ( xdev->madx, xdev );
1628
1629out:
1630 /* Destroy the completed transaction */
1631 ib_destroy_madx ( ibdev, ibdev->gsi, madx );
1632}
1633
1634/** Directory service lookup discovery stage */
1636 .name = "directory",
1637 .op = {
1638 .complete = xsigo_xds_complete,
1639 },
1640};
1641
1642/**
1643 * Discover configuration managers
1644 *
1645 * @v timer Retry timer
1646 * @v over Failure indicator
1647 */
1648static void xsigo_discover ( struct retry_timer *timer, int over __unused ) {
1649 struct xsigo_device *xdev =
1651 struct ib_device *ibdev = xdev->ibdev;
1652 struct xsigo_discovery *discovery;
1653
1654 /* Restart timer */
1656
1657 /* Cancel any pending discovery transaction */
1658 if ( xdev->madx ) {
1659 discovery = container_of ( xdev->madx->op,
1660 struct xsigo_discovery, op );
1661 DBGC ( xdev, "XDEV %s timed out waiting for %s lookup\n",
1662 xdev->name, discovery->name );
1663 ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
1664 xdev->madx = NULL;
1665 }
1666
1667 /* Start directory service lookup */
1668 xdev->madx = ib_create_service_madx ( ibdev, ibdev->gsi,
1670 &xsigo_xds_discovery.op );
1671 if ( ! xdev->madx ) {
1672 DBGC ( xdev, "XDEV %s could not start directory lookup\n",
1673 xdev->name );
1674 return;
1675 }
1676 ib_madx_set_ownerdata ( xdev->madx, xdev );
1677}
1678
1679/****************************************************************************
1680 *
1681 * Infiniband device driver
1682 *
1683 ****************************************************************************
1684 */
1685
1686/**
1687 * Open link and start discovery
1688 *
1689 * @v opener Link opener
1690 * @v over Failure indicator
1691 */
1692static void xsigo_ib_open ( struct retry_timer *opener, int over __unused ) {
1693 struct xsigo_device *xdev =
1695 struct ib_device *ibdev = xdev->ibdev;
1696 int rc;
1697
1698 /* Open Infiniband device */
1699 if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
1700 DBGC ( xdev, "XDEV %s could not open: %s\n",
1701 xdev->name, strerror ( rc ) );
1702 /* Delay and try again */
1704 return;
1705 }
1706
1707 /* If link is already up, then start discovery */
1708 if ( ib_link_ok ( ibdev ) )
1709 start_timer_nodelay ( &xdev->discovery );
1710}
1711
1712/**
1713 * Probe Xsigo device
1714 *
1715 * @v ibdev Infiniband device
1716 * @ret rc Return status code
1717 */
1718static int xsigo_ib_probe ( struct ib_device *ibdev ) {
1719 struct xsigo_device *xdev;
1720
1721 /* Allocate and initialise structure */
1722 xdev = zalloc ( sizeof ( *xdev ) );
1723 if ( ! xdev )
1724 return -ENOMEM;
1725 ref_init ( &xdev->refcnt, xsigo_free );
1726 xdev->ibdev = ibdev_get ( ibdev );
1727 xdev->name = ibdev->name;
1728 timer_init ( &xdev->opener, xsigo_ib_open, &xdev->refcnt );
1729 timer_init ( &xdev->discovery, xsigo_discover, &xdev->refcnt );
1730 INIT_LIST_HEAD ( &xdev->managers );
1731
1732 /* Start timer to open Infiniband device. (We are currently
1733 * within the Infiniband device probe callback list; opening
1734 * the device here would have interesting side-effects.)
1735 */
1736 start_timer_nodelay ( &xdev->opener );
1737
1738 /* Add to list of devices and transfer reference to list */
1739 list_add_tail ( &xdev->list, &xsigo_devices );
1740 DBGC ( xdev, "XDEV %s created for " IB_GUID_FMT "\n",
1741 xdev->name, IB_GUID_ARGS ( &ibdev->gid.s.guid ) );
1742 return 0;
1743}
1744
1745/**
1746 * Handle device or link status change
1747 *
1748 * @v ibdev Infiniband device
1749 */
1750static void xsigo_ib_notify ( struct ib_device *ibdev ) {
1751 struct xsigo_device *xdev;
1752
1753 /* Stop/restart discovery on any attached devices */
1754 list_for_each_entry ( xdev, &xsigo_devices, list ) {
1755
1756 /* Skip non-attached devices */
1757 if ( xdev->ibdev != ibdev )
1758 continue;
1759
1760 /* Stop any ongoing discovery */
1761 if ( xdev->madx ) {
1762 ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
1763 xdev->madx = NULL;
1764 }
1765 stop_timer ( &xdev->discovery );
1766
1767 /* If link is up, then start discovery */
1768 if ( ib_link_ok ( ibdev ) )
1769 start_timer_nodelay ( &xdev->discovery );
1770 }
1771}
1772
1773/**
1774 * Remove Xsigo device
1775 *
1776 * @v ibdev Infiniband device
1777 */
1778static void xsigo_ib_remove ( struct ib_device *ibdev ) {
1779 struct xsigo_device *xdev;
1780 struct xsigo_device *tmp;
1781
1782 /* Remove any attached Xsigo devices */
1783 list_for_each_entry_safe ( xdev, tmp, &xsigo_devices, list ) {
1784
1785 /* Skip non-attached devices */
1786 if ( xdev->ibdev != ibdev )
1787 continue;
1788
1789 /* Stop any ongoing discovery */
1790 if ( xdev->madx ) {
1791 ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
1792 xdev->madx = NULL;
1793 }
1794 stop_timer ( &xdev->discovery );
1795
1796 /* Destroy all configuration managers */
1797 xcm_list ( xdev, NULL, 0 );
1798
1799 /* Close Infiniband device, if applicable */
1800 if ( ! timer_running ( &xdev->opener ) )
1801 ib_close ( xdev->ibdev );
1802
1803 /* Stop link opener */
1804 stop_timer ( &xdev->opener );
1805
1806 /* Remove from list of devices and drop list's reference */
1807 DBGC ( xdev, "XDEV %s destroyed\n", xdev->name );
1808 list_del ( &xdev->list );
1809 ref_put ( &xdev->refcnt );
1810 }
1811}
1812
1813/** Xsigo Infiniband driver */
1814struct ib_driver xsigo_ib_driver __ib_driver = {
1815 .name = "Xsigo",
1816 .probe = xsigo_ib_probe,
1817 .notify = xsigo_ib_notify,
1818 .remove = xsigo_ib_remove,
1819};
1820
1821/****************************************************************************
1822 *
1823 * Network device driver
1824 *
1825 ****************************************************************************
1826 */
1827
1828/**
1829 * Handle device or link status change
1830 *
1831 * @v netdev Network device
1832 * @v priv Private data
1833 */
1834static void xsigo_net_notify ( struct net_device *netdev,
1835 void *priv __unused ) {
1836 struct xsigo_device *xdev;
1837 struct ib_device *ibdev;
1838 struct xsigo_manager *xcm;
1839 struct xsigo_nic *xve;
1840 struct eoib_device *eoib;
1841
1842 /* Send current operational state to XCM, if applicable */
1843 list_for_each_entry ( xdev, &xsigo_devices, list ) {
1844 ibdev = xdev->ibdev;
1845 list_for_each_entry ( xcm, &xdev->managers, list ) {
1846 list_for_each_entry ( xve, &xcm->nics, list ) {
1847 eoib = eoib_find ( ibdev, xve->mac );
1848 if ( ! eoib )
1849 continue;
1850 if ( eoib->netdev != netdev )
1851 continue;
1852 xsmp_tx_xve_oper ( xcm, xve, eoib );
1853 }
1854 }
1855 }
1856}
1857
1858/** Xsigo network driver */
1859struct net_driver xsigo_net_driver __net_driver = {
1860 .name = "Xsigo",
1861 .notify = xsigo_net_notify,
1862};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 gid[16]
Definition CIB_PRM.h:3
__be32 raw[7]
Definition CIB_PRM.h:0
__be32 qkey
Definition CIB_PRM.h:2
__be32 out[4]
Definition CIB_PRM.h:8
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
union ib_mad mad
Definition arbel.h:1
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
const char * name
Definition ath9k_hw.c:1986
#define max(x, y)
Definition ath.h:41
ring len
Length.
Definition dwmac.h:226
uint64_t guid
GUID.
Definition edd.h:1
uint8_t id
Request identifier.
Definition ena.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint32_t mtu
Maximum MTU.
Definition ena.h:17
static unsigned int unsigned int size_t uint8_t * ids
Definition ena.h:770
uint8_t meta
Metadata flags.
Definition ena.h:3
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
int eoib_create(struct ib_device *ibdev, const uint8_t *hw_addr, struct ib_address_vector *broadcast, const char *name)
Create EoIB device.
Definition eoib.c:619
struct eoib_device * eoib_find(struct ib_device *ibdev, const uint8_t *hw_addr)
Find EoIB device.
Definition eoib.c:677
void eoib_set_gateway(struct eoib_device *eoib, struct ib_address_vector *av)
Set EoIB gateway.
Definition eoib.c:881
void eoib_destroy(struct eoib_device *eoib)
Remove EoIB device.
Definition eoib.c:695
Ethernet over Infiniband.
static void eoib_force_group_creation(struct eoib_device *eoib)
Force creation of multicast group.
Definition eoib.h:81
Error codes.
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
Ethernet protocol.
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGCP_HDA(...)
Definition compiler.h:540
#define DBGC2(...)
Definition compiler.h:522
#define DBGCP(...)
Definition compiler.h:539
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EPROTO
Protocol error.
Definition errno.h:625
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define ERANGE
Result too large.
Definition errno.h:640
#define ENODEV
No such device.
Definition errno.h:510
#define EPERM
Operation not permitted.
Definition errno.h:615
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
int ib_cmrc_open(struct interface *xfer, struct ib_device *ibdev, union ib_gid *dgid, union ib_guid *service_id, const char *name)
Open CMRC connection.
Definition ib_cmrc.c:397
Infiniband Communication-managed Reliable Connections.
#define IB_MGMT_STATUS_OK
Definition ib_mad.h:581
#define IB_MGMT_METHOD_GET
Definition ib_mad.h:570
struct ib_mad_transaction * ib_create_madx(struct ib_device *ibdev, struct ib_mad_interface *mi, union ib_mad *mad, struct ib_address_vector *av, struct ib_mad_transaction_operations *op)
Create management transaction.
Definition ib_mi.c:287
void ib_destroy_madx(struct ib_device *ibdev __unused, struct ib_mad_interface *mi __unused, struct ib_mad_transaction *madx)
Destroy management transaction.
Definition ib_mi.c:327
static __always_inline void ib_madx_set_ownerdata(struct ib_mad_transaction *madx, void *priv)
Set Infiniband management transaction owner-private data.
Definition ib_mi.h:106
static __always_inline void * ib_madx_get_ownerdata(struct ib_mad_transaction *madx)
Get Infiniband management transaction owner-private data.
Definition ib_mi.h:117
#define IB_GID_ARGS(gid)
Infiniband Global Identifier debug message arguments.
Definition ib_packet.h:49
#define IB_GID_FMT
Infiniband Global Identifier debug message format.
Definition ib_packet.h:46
#define IB_GUID_FMT
Infiniband Globally Unique Identifier debug message format.
Definition ib_packet.h:27
#define IB_GUID_ARGS(guid)
Infiniband Globally Unique Identifier debug message arguments.
Definition ib_packet.h:30
struct ib_mad_transaction * ib_create_service_madx(struct ib_device *ibdev, struct ib_mad_interface *mi, const char *name, struct ib_mad_transaction_operations *op)
Create service record management transaction.
Definition ib_service.c:49
Infiniband service records.
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
#define ETH_ALEN
Definition if_ether.h:9
#define bswap_32(value)
Definition byteswap.h:71
#define ntohl(value)
Definition byteswap.h:135
#define htonl(value)
Definition byteswap.h:134
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
#define bswap_64(value)
Definition byteswap.h:83
#define bswap_16(value)
Definition byteswap.h:59
#define _S2(x)
Stringify expanded argument.
Definition compiler.h:53
Configuration settings.
iPXE timers
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
int ib_open(struct ib_device *ibdev)
Open port.
Definition infiniband.c:652
void ib_close(struct ib_device *ibdev)
Close port.
Definition infiniband.c:716
Infiniband protocol.
static __always_inline int ib_link_ok(struct ib_device *ibdev)
Check link state of Infiniband device.
Definition infiniband.h:566
#define __ib_driver
Declare an Infiniband driver.
Definition infiniband.h:497
#define IB_MAX_PAYLOAD_SIZE
Maximum payload size.
Definition infiniband.h:51
static __always_inline struct ib_device * ibdev_get(struct ib_device *ibdev)
Get reference to Infiniband device.
Definition infiniband.h:588
#define IB_QPN_BROADCAST
Broadcast QPN.
Definition infiniband.h:34
#define IB_QPN_GSI
General service interface QPN.
Definition infiniband.h:28
#define IB_QKEY_GSI
General service interface queue key.
Definition infiniband.h:31
static __always_inline void ibdev_put(struct ib_device *ibdev)
Drop reference to Infiniband device.
Definition infiniband.h:599
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
Version number.
unsigned long tmp
Definition linux_pci.h:65
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334
#define list_splice(list, entry)
Move all entries from one list into another list.
Definition list.h:221
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
int netdev_open(struct net_device *netdev)
Open network device.
Definition netdevice.c:862
void netdev_close(struct net_device *netdev)
Close network device.
Definition netdevice.c:896
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
#define __net_driver
Declare a network driver.
Definition netdevice.h:507
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
int open(const char *uri_string)
Open file.
Definition posix_io.c:176
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static int process_running(struct process *process)
Check if process is running.
Definition process.h:176
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
void start_timer(struct retry_timer *timer)
Start timer.
Definition retry.c:94
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
Retry timers.
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
int fetch_string_setting(struct settings *settings, const struct setting *setting, char *data, size_t len)
Fetch value of string setting.
Definition settings.c:842
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An EoIB device.
Definition eoib.h:30
struct ib_queue_pair * qp
Queue pair.
Definition eoib.h:45
struct ib_device * ibdev
Underlying Infiniband device.
Definition eoib.h:36
struct list_head list
List of EoIB devices.
Definition eoib.h:38
struct net_device * netdev
Network device.
Definition eoib.h:34
An EoIB header.
Definition eoib.h:19
An Ethernet link-layer header.
Definition if_ether.h:32
An Infiniband Address Vector.
Definition infiniband.h:73
unsigned long qkey
Queue key.
Definition infiniband.h:80
unsigned int gid_present
GID is present.
Definition infiniband.h:91
union ib_gid gid
GID, if present.
Definition infiniband.h:93
unsigned long qpn
Queue Pair Number.
Definition infiniband.h:75
An Infiniband device.
Definition infiniband.h:399
uint8_t sm_sl
Subnet manager SL.
Definition infiniband.h:448
struct ib_mad_interface * gsi
General services interface.
Definition infiniband.h:462
char name[IBDEV_NAME_LEN]
Name of this Infiniband device.
Definition infiniband.h:409
uint16_t pkey
Partition key.
Definition infiniband.h:450
union ib_gid gid
Port GID (comprising GID prefix and port GUID)
Definition infiniband.h:442
An Infiniband upper-layer driver.
Definition infiniband.h:472
An Infiniband management interface.
Definition ib_mi.h:88
Infiniband management transaction operations.
Definition ib_mi.h:49
An Infiniband management transaction.
Definition ib_mi.h:70
struct ib_mad_transaction_operations * op
Transaction operations.
Definition ib_mi.h:82
unsigned long ext_qpn
Externally-visible queue pair number.
Definition infiniband.h:173
unsigned long qkey
Queue key.
Definition infiniband.h:177
uint64_t data64[2]
Definition ib_mad.h:238
uint16_t data16[8]
Definition ib_mad.h:236
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A doubly-linked list entry (or list head)
Definition list.h:19
A network device.
Definition netdevice.h:353
A network upper-layer driver.
Definition netdevice.h:477
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
A timer.
Definition timer.h:29
Data transfer metadata.
Definition xfer.h:23
A Xsigo device.
Definition xsigo.c:52
struct list_head list
List of Xsigo devices.
Definition xsigo.c:58
const char * name
Device name.
Definition xsigo.c:60
struct refcnt refcnt
Reference count.
Definition xsigo.c:54
struct list_head managers
List of configuration managers.
Definition xsigo.c:71
struct retry_timer opener
Link opener timer.
Definition xsigo.c:63
struct retry_timer discovery
Discovery timer.
Definition xsigo.c:66
struct ib_mad_transaction * madx
Discovery management transaction (if any)
Definition xsigo.c:68
struct ib_device * ibdev
Underlying Infiniband device.
Definition xsigo.c:56
A stage of discovery.
Definition xsigo.c:1466
struct ib_mad_transaction_operations op
Management transaction operations.
Definition xsigo.c:1470
const char * name
Name.
Definition xsigo.c:1468
A Xsigo configuration manager identifier.
Definition xsigo.h:54
uint16_t lid
LID.
Definition xsigo.h:58
union ib_guid guid
Port GUID.
Definition xsigo.h:56
A Xsigo configuration manager.
Definition xsigo.c:75
struct retry_timer keepalive
Keepalive timer.
Definition xsigo.c:92
struct retry_timer reopen
Connection timer.
Definition xsigo.c:90
unsigned int pending
Pending transmissions.
Definition xsigo.c:96
struct xsigo_manager_id id
Manager ID.
Definition xsigo.c:85
struct interface xfer
Data transfer interface.
Definition xsigo.c:88
struct xsigo_device * xdev
Xsigo device.
Definition xsigo.c:79
char name[16]
Device name.
Definition xsigo.c:83
struct process process
Transmission process.
Definition xsigo.c:94
struct refcnt refcnt
Reference count.
Definition xsigo.c:77
struct list_head list
List of managers.
Definition xsigo.c:81
uint32_t seq
Transmit sequence number.
Definition xsigo.c:98
struct list_head nics
List of virtual Ethernet devices.
Definition xsigo.c:101
A Xsigo configuration manager reply MAD.
Definition xsigo.h:103
uint8_t count
Number of XCM records.
Definition xsigo.h:111
struct xsigo_manager_id manager[8]
Managers.
Definition xsigo.h:117
A Xsigo configuration manager request MAD.
Definition xsigo.h:64
A Xsigo virtual Ethernet device.
Definition xsigo.c:113
union ib_guid resource
Resource identifier.
Definition xsigo.c:122
char name[16]
Device name.
Definition xsigo.c:119
struct list_head list
List of virtual Ethernet devices.
Definition xsigo.c:117
unsigned long network
Network ID.
Definition xsigo.c:126
struct xsigo_manager * xcm
Configuration manager.
Definition xsigo.c:115
uint8_t mac[ETH_ALEN]
MAC address.
Definition xsigo.c:124
An XSMP session message.
Definition xsigo.h:165
XSMP virtual Ethernet MAC address.
Definition xsigo.h:237
An XSMP virtual Ethernet message.
Definition xsigo.h:245
uint32_t update
Update bitmask.
Definition xsigo.h:255
static struct tlan_private * priv
Definition tlan.c:225
An Infiniband Global Identifier.
Definition ib_packet.h:34
uint16_t words[8]
Definition ib_packet.h:36
struct ib_gid::@251011351113275240012301235177256303262052134237 s
union ib_guid prefix
Definition ib_packet.h:40
uint32_t dwords[4]
Definition ib_packet.h:37
union ib_guid guid
Definition ib_packet.h:41
An Infiniband Globally Unique Identifier.
Definition ib_packet.h:19
uint64_t qword
Definition ib_packet.h:23
A management datagram.
Definition ib_mad.h:611
A Xsigo MAD.
Definition xsigo.h:123
struct xsigo_managers_reply reply
Configuration manager reply.
Definition xsigo.h:129
struct xsigo_managers_request request
Configuration manager request.
Definition xsigo.h:127
An XSMP message.
Definition xsigo.h:367
unsigned long build_id
Build ID.
Definition version.c:62
const char product_short_name[]
Product short name string.
Definition version.c:77
const char product_version[]
Product version string.
Definition version.c:71
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition xfer.c:289
static void xsigo_ib_notify(struct ib_device *ibdev)
Handle device or link status change.
Definition xsigo.c:1750
static int xsmp_rx_xve_oper_req(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet operational request message.
Definition xsigo.c:1028
static int xsmp_rx_session(struct xsigo_manager *xcm, struct xsmp_session_message *msg)
Handle received session message.
Definition xsigo.c:625
static int xsmp_rx_session_reject(struct xsigo_manager *xcm, struct xsmp_session_message *msg)
Handle received registration rejection message.
Definition xsigo.c:591
static void xcm_free(struct refcnt *refcnt)
Free configuration manager.
Definition xsigo.c:164
static int xsmp_rx_session_hello(struct xsigo_manager *xcm, struct xsmp_session_message *msg __unused)
Handle received keepalive message.
Definition xsigo.c:559
static int xsmp_tx_session_register(struct xsigo_manager *xcm)
Send registration message.
Definition xsigo.c:531
static int xsmp_tx_xve_nack(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Send virtual Ethernet error response.
Definition xsigo.c:773
static const char * xsmp_chassis_name(struct xsmp_session_message *msg)
Extract chassis name (for debugging)
Definition xsigo.c:462
static void xcm_close(struct xsigo_manager *xcm, int rc)
Close configuration manager connection.
Definition xsigo.c:1113
static int xve_open(struct xsigo_nic *xve, struct eoib_device *eoib)
Open virtual Ethernet device.
Definition xsigo.c:340
static struct xsigo_discovery xsigo_xds_discovery
Directory service lookup discovery stage.
Definition xsigo.c:1635
static struct process_descriptor xcm_process_desc
Configuration manager process descriptor.
Definition xsigo.c:1243
static struct xsigo_discovery xsigo_xcm_discovery
Configuration manager lookup discovery stage.
Definition xsigo.c:1527
static union ib_guid xcm_service_id
Configuration manager service ID.
Definition xsigo.c:130
static const char * xsmp_session_name(struct xsmp_session_message *msg)
Extract session name (for debugging)
Definition xsigo.c:475
static int xsmp_tx_xve_params(struct xsigo_manager *xcm, struct xsmp_xve_message *msg, struct xsigo_nic *xve, struct eoib_device *eoib)
Send virtual Ethernet message including current device parameters.
Definition xsigo.c:727
static int xsmp_rx_xve_modify(struct xsigo_manager *xcm, struct xsmp_xve_message *msg, unsigned int update)
Handle received virtual Ethernet modification message.
Definition xsigo.c:833
static int xsmp_rx_xve_install(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet installation message.
Definition xsigo.c:931
static void xcm_destroy(struct xsigo_manager *xcm)
Destroy configuration manager.
Definition xsigo.c:1383
static int xve_update_mtu(struct xsigo_nic *xve, struct eoib_device *eoib, size_t mtu)
Update virtual Ethernet device MTU.
Definition xsigo.c:306
static struct interface_operation xcm_xfer_op[]
Configuration manager data transfer interface operations.
Definition xsigo.c:1232
static int xsmp_rx_xve_delete(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet deletion message.
Definition xsigo.c:985
static int xsmp_rx_session_shutdown(struct xsigo_manager *xcm, struct xsmp_session_message *msg)
Handle received shutdown message.
Definition xsigo.c:608
static void xcm_reopen(struct retry_timer *timer, int fail __unused)
Handle configuration manager connection timer expiry.
Definition xsigo.c:1252
static int xsmp_tx_xve_notify(struct xsigo_manager *xcm, unsigned int type, struct xsigo_nic *xve, struct eoib_device *eoib)
Send virtual Ethernet notification.
Definition xsigo.c:794
static void xsigo_xcm_complete(struct ib_device *ibdev, struct ib_mad_interface *mi __unused, struct ib_mad_transaction *madx, int rc, union ib_mad *mad, struct ib_address_vector *av __unused)
Handle configuration manager lookup completion.
Definition xsigo.c:1483
static void xsigo_net_notify(struct net_device *netdev, void *priv __unused)
Handle device or link status change.
Definition xsigo.c:1834
static int xcm_list(struct xsigo_device *xdev, struct xsigo_manager_id *ids, unsigned int count)
Synchronise list of configuration managers.
Definition xsigo.c:1416
static struct interface_descriptor xcm_xfer_desc
Configuration manager data transfer interface descriptor.
Definition xsigo.c:1239
static int xsmp_tx_session_hello(struct xsigo_manager *xcm)
Send keepalive message.
Definition xsigo.c:546
static int xsmp_tx_xve(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Send virtual Ethernet message.
Definition xsigo.c:687
static int xcm_deliver(struct xsigo_manager *xcm, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive data from configuration manager.
Definition xsigo.c:1179
static int xve_update_state(struct xsigo_nic *xve, struct eoib_device *eoib, int open)
Update virtual Ethernet device administrative state.
Definition xsigo.c:385
static struct xsigo_manager * xcm_find(struct xsigo_device *xdev, struct xsigo_manager_id *id)
Find configuration manager.
Definition xsigo.c:1365
static int xcm_create(struct xsigo_device *xdev, struct xsigo_manager_id *id)
Create configuration manager.
Definition xsigo.c:1328
static int xsmp_tx_session(struct xsigo_manager *xcm, unsigned int type)
Send session message.
Definition xsigo.c:489
static void xve_close(struct xsigo_nic *xve, struct eoib_device *eoib)
Close virtual Ethernet device.
Definition xsigo.c:365
static int xsmp_rx_xve(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet message.
Definition xsigo.c:1073
static void xsigo_ib_remove(struct ib_device *ibdev)
Remove Xsigo device.
Definition xsigo.c:1778
xsigo_manager_pending
Configuration manager pending transmissions.
Definition xsigo.c:105
@ XCM_TX_REGISTER
Send registration message.
Definition xsigo.c:109
@ XCM_TX_CONNECT
Send connection request.
Definition xsigo.c:107
static int xsmp_rx_xve_ready(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet readiness message.
Definition xsigo.c:1045
static int xsmp_rx_session_confirm(struct xsigo_manager *xcm, struct xsmp_session_message *msg)
Handle received registration confirmation message.
Definition xsigo.c:575
static int xve_create(struct xsigo_manager *xcm, union ib_guid *resource, const uint8_t *mac, unsigned long network, unsigned long qkey, const char *name)
Create virtual Ethernet device.
Definition xsigo.c:198
static int xsmp_tx_xve_oper(struct xsigo_manager *xcm, struct xsigo_nic *xve, struct eoib_device *eoib)
Send virtual Ethernet current operational state.
Definition xsigo.c:817
static void xsigo_ib_open(struct retry_timer *opener, int over __unused)
Open link and start discovery.
Definition xsigo.c:1692
static void xcm_step(struct xsigo_manager *xcm)
Send data to configuration manager.
Definition xsigo.c:1135
static void xcm_keepalive(struct retry_timer *timer, int fail __unused)
Handle configuration manager keepalive timer expiry.
Definition xsigo.c:1303
static void xsigo_discover(struct retry_timer *timer, int over __unused)
Discover configuration managers.
Definition xsigo.c:1648
static int xsigo_ib_probe(struct ib_device *ibdev)
Probe Xsigo device.
Definition xsigo.c:1718
static int xve_update_tca(struct xsigo_nic *xve, struct eoib_device *eoib, struct ib_address_vector *av)
Update gateway (TCA)
Definition xsigo.c:405
static void xsigo_free(struct refcnt *refcnt)
Free Xsigo device.
Definition xsigo.c:142
static void xsigo_xds_complete(struct ib_device *ibdev, struct ib_mad_interface *mi __unused, struct ib_mad_transaction *madx, int rc, union ib_mad *mad, struct ib_address_vector *av __unused)
Handle directory service lookup completion.
Definition xsigo.c:1544
static int xsmp_rx_xve_update(struct xsigo_manager *xcm, struct xsmp_xve_message *msg)
Handle received virtual Ethernet update message.
Definition xsigo.c:1010
static struct xsigo_nic * xve_find(struct xsigo_manager *xcm, union ib_guid *resource)
Find virtual Ethernet device.
Definition xsigo.c:263
static void xve_destroy(struct xsigo_nic *xve)
Destroy virtual Ethernet device.
Definition xsigo.c:280
Xsigo virtual Ethernet devices.
#define XSIGO_DISCOVERY_FAILURE_DELAY
Delay between unsuccessful discovery attempts.
Definition xsigo.h:386
#define XVE_PREFIX
Xsigo virtual Ethernet broadcast GID prefix.
Definition xsigo.h:35
#define XSIGO_ATTR_XCM_REQUEST
Xsigo configuration manager request MAD.
Definition xsigo.h:29
#define XDS_SERVICE_NAME
Xsigo directory service record name.
Definition xsigo.h:17
@ XSMP_XVE_UPLINK
Has uplink.
Definition xsigo.h:363
#define XSIGO_KEEPALIVE_INTERVAL
Delay between keepalive requests.
Definition xsigo.h:398
#define XSIGO_RESOURCES_PRESENT
Resource types are present.
Definition xsigo.h:100
@ XSMP_TYPE_SESSION
Session message type.
Definition xsigo.h:159
@ XSMP_TYPE_XVE
Virtual Ethernet message type.
Definition xsigo.h:161
@ XSIGO_RESOURCE_NO_HA
Absence-of-high-availability "resource" type.
Definition xsigo.h:42
@ XSIGO_RESOURCE_XVE
Virtual Ethernet resource type.
Definition xsigo.h:40
#define XSIGO_MGMT_CLASS_VERSION
Xsigo management class version.
Definition xsigo.h:26
xsmp_xve_type
XSMP virtual Ethernet message types.
Definition xsigo.h:315
@ XSMP_XVE_TYPE_INSTALL
Install virtual NIC.
Definition xsigo.h:317
@ XSMP_XVE_TYPE_UPDATE
Update virtual NIC.
Definition xsigo.h:321
@ XSMP_XVE_TYPE_OPER_DOWN
Set operational state down.
Definition xsigo.h:325
@ XSMP_XVE_TYPE_OPER_UP
Set operational state up.
Definition xsigo.h:323
@ XSMP_XVE_TYPE_READY
Virtual NIC is ready.
Definition xsigo.h:329
@ XSMP_XVE_TYPE_DELETE
Delete virtual NIC.
Definition xsigo.h:319
@ XSMP_XVE_TYPE_OPER_REQ
Get operational state.
Definition xsigo.h:327
@ XSMP_XVE_CODE_ERROR
Definition xsigo.h:335
#define XSIGO_DISCOVERY_SUCCESS_DELAY
Delay between successful discovery attempts.
Definition xsigo.h:392
@ XSMP_XVE_UPDATE_STATE
Update administrative state.
Definition xsigo.h:343
@ XSMP_XVE_UPDATE_GW_CHANGE
Update gateway information.
Definition xsigo.h:347
@ XSMP_XVE_UPDATE_GW_DOWN
Update gateway to mark as down.
Definition xsigo.h:345
@ XSMP_XVE_UPDATE_MTU
Update MTU.
Definition xsigo.h:341
xsmp_session_type
XSMP session message types.
Definition xsigo.h:203
@ XSMP_SESSION_TYPE_CONFIRM
Registration confirmation message.
Definition xsigo.h:209
@ XSMP_SESSION_TYPE_REJECT
Registration rejection message.
Definition xsigo.h:211
@ XSMP_SESSION_TYPE_SHUTDOWN
Shutdown message.
Definition xsigo.h:213
@ XSMP_SESSION_TYPE_REGISTER
Initial registration message.
Definition xsigo.h:207
@ XSMP_SESSION_TYPE_HELLO
Keepalive message.
Definition xsigo.h:205
#define XSIGO_MGMT_CLASS
Xsigo management class.
Definition xsigo.h:23
#define XSIGO_OS_TYPE_GENERIC
Generic operating system type.
Definition xsigo.h:32
#define XCM_SERVICE_ID
Xsigo configuration manager service ID.
Definition xsigo.h:20
#define XSIGO_OPEN_RETRY_DELAY
Delay between attempts to open the Infiniband device.
Definition xsigo.h:380
@ XSMP_BOOT_PXE
PXE boot.
Definition xsigo.h:219