diff --git a/README.md b/README.md
index 03a7338..041745c 100644
--- a/README.md
+++ b/README.md
@@ -150,9 +150,11 @@ The rack front, drawn from the rack units set on cutsheet items, top first.
and facing.
- **Shelves to scale**: a shelf draws its contents left to right by **Position on shelf**, at true scale
(a 19" panel is 482.6 mm). Gear with a drawing, such as the IceWhale ZimaBoard 832 (traced from
- IceWhale's labelled photo of its port end), shows its real ports: each RJ45's link light follows the
- host's physical NICs in name order (first NIC on the left jack), and the status glow follows the
- host. Anything else is a labelled box.
+ IceWhale's labelled photo of its port end), shows its real ports: the onboard RJ45 link lights follow
+ enp2s0 (left) and enp3s0 (right), and the status glow follows the host. The "ZimaBoard 832 +
+ ConnectX-3" drawing adds the single-port SFP+ card lying flat in the side PCIe slot, as in the rack,
+ with a DAC attached; its round dot is Gandalf's link mark for enp1s0 (the slot is PCI bus 1), not an
+ LED on the card. Anything else is a labelled box.
- **Racks**: admins name a rack and set its height with **Rack settings** on the page, and add more with
**+ Rack** (a tab per rack). Renaming a rack moves its items; an empty rack can be deleted. Each item
has a rack (empty means the first). Until a rack is saved, racks come from config:
diff --git a/cutsheet.py b/cutsheet.py
index d471e9d..052679b 100644
--- a/cutsheet.py
+++ b/cutsheet.py
@@ -38,6 +38,7 @@ CHASSIS = {
'sliger-cx4712': 'Sliger CX4712 4U (10-bay)',
'rosewill-rsv-l4500u': 'Rosewill RSV-L4500U 4U (15-bay)',
'zimaboard-832': 'IceWhale ZimaBoard 832 (shelf gear)',
+ 'zimaboard-832-cx3': 'IceWhale ZimaBoard 832 + ConnectX-3 SFP+ in PCIe (shelf gear)',
'server-1u': 'Generic 1U server',
'server-2u': 'Generic 2U server',
'server-4u': 'Generic 4U server',
diff --git a/static/fronts.js b/static/fronts.js
index 499984d..48951b2 100644
--- a/static/fronts.js
+++ b/static/fronts.js
@@ -172,10 +172,18 @@ function zimaUsb(x, y) {
${Array.from({ length: 5 }, (_, i) => ``).join('')}`;
}
+// Which NIC is which on a ZimaBoard: the onboard Realtek GbE ports enumerate on PCI buses 2 and 3
+// (enp2s0 left jack, enp3s0 right), and a card in the PCIe slot on bus 1 (enp1s0, enp1s0d1).
+const ZIMA_NICS = { rj45: ['enp2s0', 'enp3s0'], slot: /^enp1s0/ };
+
+function zimaNic(ctx, name) {
+ const n = (ctx.interfaces || []).find(i => i.name === name);
+ return n ? n.up : ctx.status === 'up';
+}
+
function zimaFront(ctx) {
- // ctx: { status, interfaces: [{name, up}] } - one RJ45 per NIC, left to right
- const nics = ctx.interfaces || [];
- const link = i => (nics[i] ? nics[i].up : ctx.status === 'up');
+ // ctx: { status, interfaces: [{name, up}] }
+ const link = i => zimaNic(ctx, ZIMA_NICS.rj45[i]);
const on = ctx.status === 'up' || ctx.status === 'degraded';
const pads = [60, 105, 420, 470, 640, 700, 790, 835]
.map(x => ``).join('');
@@ -199,10 +207,47 @@ function zimaFront(ctx) {
`;
}
+// A Mellanox ConnectX-3 single-port SFP+ card (MCX311A) in the ZimaBoard's side PCIe slot, lying flat
+// beside the board as in the rack photo (wiki.lotusguild.org/zimaboards.jpg): its front edge is about
+// 54 mm (572 px at the ZimaBoard photo's 10.59 px/mm), PCB at the board's PCB height, heatsink on the
+// chip, and the SFP+ cage toward the board with a DAC plugged in and its pull tab hanging down.
+// The round dot on the cage is Gandalf's link mark (like the cutsheet marks), not an LED on the card.
+const CX3_PX = 572;
+
+function cx3Card(up) {
+ return `
+
+
+
+
+
+
+ ${Array.from({ length: 9 }, (_, i) => ``).join('')}
+
+
+
+
+
+
+ Gandalf: SFP+ link ${up ? 'up' : 'down'}`;
+}
+
+function zimaCx3Front(ctx) {
+ return `${cx3Card(zimaNic(ctx, (ctx.interfaces || []).map(i => i.name).find(n => ZIMA_NICS.slot.test(n)) || 'enp1s0'))}
+ ${zimaFront(ctx)}`;
+}
+
+const ZIMA_SPECS = 'Intel Celeron N3450, 8GB LPDDR4, 32GB eMMC, 2x GbE, 2x USB 3.0, 2x SATA, PCIe 2.0 x4, 6W';
+
const SHELF_GEAR = {
'zimaboard-832': {
label: 'IceWhale ZimaBoard 832', mm: ZIMA.mm, width: ZIMA.width, height: ZIMA.height, draw: zimaFront,
- specs: 'Intel Celeron N3450, 8GB LPDDR4, 32GB eMMC, 2x GbE, 2x USB 3.0, 2x SATA, PCIe 2.0 x4, 6W',
+ specs: ZIMA_SPECS,
+ },
+ 'zimaboard-832-cx3': {
+ label: 'IceWhale ZimaBoard 832 + ConnectX-3 SFP+', mm: ZIMA.mm * (ZIMA.width + CX3_PX) / ZIMA.width,
+ width: ZIMA.width + CX3_PX, height: ZIMA.height, draw: zimaCx3Front,
+ specs: `${ZIMA_SPECS}; Mellanox ConnectX-3 10G SFP+ (enp1s0) in the PCIe slot, DAC attached`,
},
};
diff --git a/static/style.css b/static/style.css
index 90020a6..1391918 100644
--- a/static/style.css
+++ b/static/style.css
@@ -1617,3 +1617,15 @@ body.fp-marks-off .fp-svg .fp-mark { display: none; }
.zb-dc-face { fill: #2b2b2b; }
.zb-dc-ring { fill: #4b4b4b; }
.zb-dc-pin { fill: #c9a43a; }
+.cx-pcb { fill: #1d6b43; }
+.cx-pcb-edge { fill: #2f8a5a; }
+.cx-part { fill: #26292d; }
+.cx-heatsink { fill: #18191b; }
+.cx-fin { fill: #2c2e31; }
+.cx-cage { fill: #c8cbcf; stroke: #85898f; stroke-width: 3; }
+.cx-cage-lip { fill: #dde0e3; }
+.cx-plug { fill: #2b2e33; }
+.cx-boot { fill: #1b1d20; }
+.cx-cable { fill: #0e0f10; }
+.cx-tab { fill: none; stroke: #c9ccd0; stroke-width: 9; stroke-linejoin: round; }
+.cx-link { stroke: #101418; stroke-width: 3; }