Skip to content

IPoIB: the management plane on an IB fabric

S1·E4The tenant network that comes up and answers nothing · Customer PoC cage, two days before acceptance

S1·E4Apply~30 minsources checked todaylab mutates hardwareverified against Linux kernel Documentation/infiniband/ipoib.txt re-fetched and re-quoted 2026-09-07 (mode file, create_child/delete_child, datagram and connected MTU, ARPHRD_INFINIBAND, PKey index 0); RFC 4391; DOCA 3.5.0 IP Over InfiniBand; opensm(8) and partition-config.txt (master)

Builds on: LIDs, GIDs, GUIDs and LMC

Before you read: what do you already know?

3 quick questions. Wrong answers are fine and expected; trying first makes the lesson stick.

After this lesson you can

  • Describe the IPoIB encapsulation and the 20-octet hardware address from RFC 4391 and say why ARP needs a hardware type of its own.
  • Create and remove an IPoIB child interface for a partition and predict its name and PKey.
  • Compute the IPoIB MTU for a given fabric MTU in datagram mode and state what connected mode changes.
  • Write a partitions.conf stanza that will actually produce a working IPoIB interface and name the two mistakes that produce an interface that comes up but never resolves ARP.

Episode 4 — The tenant network that comes up and answers nothing

The situation · Customer PoC cage, two days before acceptance

The pod itself is fine. RDMA benchmarks run at the expected rate, the subnet manager is quiet, one master now, and everything the fabric was bought for works. What does not work is the tenant network the demo rides on: the scheduler, every ssh session. The platform team declared a partition for it, the interface duly appeared on all three hosts, they configured addresses, and nothing reaches anything. The interface is up. It resolves no ARP.

Their storage engineer is downloading a different driver version. The network lead, notebook half full, says show me the counter that makes this the fabric’s fault. You ask instead for the subnet manager’s partition file and for cat /sys/class/net/ib0/pkey from one host.

IPoIB exists because a fabric bought for RDMA still has to carry everything that is not RDMA — ssh, the scheduler, in-band management on the default PKey[9] — and because SHARP itself requires an enabled IPoIB interface on the compute servers in order to use UD multicast for result distribution.[7] The Linux driver is native in the sense of setting the interface type to ARPHRD_INFINIBAND and the hardware address length to 20, so the link layer really is InfiniBand and only the payload is IP.[2] Which means the parts failing here are InfiniBand parts: a broadcast group and a membership bit, both owned by the subnet manager rather than by the host.[5]

When IPoIB comes up and resolves nothing, stop reading the host and read the partition.

Start with what the driver creates, and where it gets its PKey.

1A native driver, not a tunnel

IPoIB is easy to under-estimate as “IP in a tunnel over RDMA”. It is not. The Linux driver is “an implementation of the IP over InfiniBand protocol as specified by RFC 4391 and 4392… It is a ‘native’ implementation in the sense of setting the interface type to ARPHRD_INFINIBAND and the hardware address length to 20”.[2] The link layer really is InfiniBand; only the payload is IP.

That 20-octet hardware address is [8-bit reserved][24-bit QPN][128-bit GID], and RFC 4391 recommends “that the GID formed by the combination of the IB subnet prefix and the port’s ‘Port GUID’ be included in the link-layer/hardware address”.[1] Two consequences follow immediately. First, the address contains a queue-pair number, because delivery on InfiniBand is to a QP and not to a port. Second, ARP cannot reuse Ethernet’s parameters: RFC 4391 section 9.2 states that for IPv4 the ARP hardware type is 32 and “The length of the hardware address used in ARP packet header therefore is 20”.[1]

Every datagram carries a small header of its own: “All IP and ARP datagrams transported over InfiniBand are prefixed by a 4-octet encapsulation header”, whose Reserved field “MUST be set to zero on send and ignored on receive”.[1] Remember that 4 - it is the entire explanation for the MTU arithmetic two segments from now.

Why any of this matters on a fabric bought for RDMA: everything that is not an RDMA application still needs IP. On an InfiniBand-only pod that is ssh, the scheduler, monitoring, and - specifically - SHARP, which requires “Enabled IPoIB interface in compute servers in order to enable using UD multicast for result distribution”.[7] MLNX-OS makes the same point from the switch side: “IP interface ‘ib0’ is running under the default PKEY (0x7fff) and can be used for in-band management connectivity to the system.”[9]

2One interface per port, and children per partition

“When the IPoIB driver is loaded, it creates one interface for each port using the P_Key at index 0.”[2] That single sentence decides your naming and your tenancy model. The base ib0 belongs to whatever partition occupies block 0, index 0 of the port’s PKey table - by default the default partition 0x7fff.[9][5]

Additional partitions get child interfaces, created and destroyed through sysfs:

echo 0x8001 > /sys/class/net/ib0/create_child   # creates ib0.8001 with P_Key 0x8001
echo 0x8001 > /sys/class/net/ib0/delete_child   # removes it

Both lines are quoted from the kernel documentation.[2] The pkey and parent sysfs files expose the mapping afterwards, and “Child interface create/delete can also be done using IPoIB’s rtnl_link_ops, where children created using either way behave the same”.[2]

Which partition lands at index 0 is controlled from the subnet manager, not the host. In partitions.conf, indx0 “indicates that this pkey should be inserted in block 0 index 0”.[5] So if a customer wants their tenant partition to be the base ib0 rather than a child, that is a one-token change in the SM’s partition file - and it changes what the default partition’s interface is called on every host at once.[5]

Default0x7fff · ipoibtenant-a0x7ff1 · indx0 · ipoibgpu01tenant A computefull*gpu02tenant A computefull*stor01shared storagefull*viz01tenant Bfull*
Click a cell: not a member → default → full → limited. * = inherited from defmember.
  • warntenant-a: empty port list — "Empty list means no ports in this partition."
    Definition: [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited] then " : " a port-GUID list and " ; ". Keywords: ALL, ALL_CAS, ALL_SWITCHES, ALL_ROUTERS, SELF (the subnet manager's port). "Empty list means no ports in this partition."
tenant-a 0x7ff1

"defmember=full|limited|both — specifies default membership for port guid list. Default is limited." A GUID written without "=full" inherits it; an unrecognised suffix is also read as limited.

"indx0 — indicates that this pkey should be inserted in block 0 index 0." That slot is what the IPoIB driver reads: it "creates one interface for each port using the P_Key at index 0".

FAE angle. Three lines of answer: own PKey 0x7ff1 with defmember=full inside the tenant, limited membership on 0x7fff outside it, part_enforce=both so the leaf switch drops the mismatch instead of trusting the HCA.

Switch-embedded SM (MLNX-OS): ib partition my-partition pkey 0x7ff2 → partition my-partition → member all; read back with show ib partition. It applies "only when the SM is enabled and running on the system."

# /etc/opensm/partitions.conf   —   opensm -P /etc/opensm/partitions.conf -Z both
Default=0x7fff,ipoib,defmember=full : ALL=full, SELF=full ;
tenant-a=0x7ff1,indx0,ipoib,mtu=5,defmember=full :  ;

Definition: [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited] then " : " a port-GUID list and " ; ". Keywords: ALL, ALL_CAS, ALL_SWITCHES, ALL_ROUTERS, SELF (the subnet manager's port). "Empty list means no ports in this partition."

"The following rule is equivalent to how OpenSM used to run prior to the partition manager: Default=0x7fff,ipoib:ALL=full;"

Toggle ipoib and indx0 on the tenant partition and watch the per-port PKey table change. Then set defmember to limited and read the can-talk-to matrix - that is the ARP failure in this lesson, made visible.

3Datagram or connected: the MTU arithmetic

“The mode is set and read through an interface’s /sys/class/net/<intf name>/mode file.”[2] There are two.

Datagram mode uses the IB unreliable-datagram transport, and “the interface MTU has is equal to the IB L2 MTU minus the IPoIB encapsulation header (4 bytes).”[2] On a typical 2K fabric that is 2048 - 4 = 2044 bytes, which RFC 4391 makes the floor for every implementation: the IB components “may support maximum payloads of 256, 512, 1024, 2048, or 4096 octets… this document requires that all IPoIB implementations support an MTU of 2044 octets”.[1]

Connected mode “takes advantage of the connected nature of the IB transport and allows an MTU up to the maximal IP packet size of 64K.”[2] Two caveats travel with it and both matter operationally: “In connected mode, the interface’s UD QP is still used for multicast and communication with peers that don’t support connected mode”, and “Stateless offloads are supported only in datagram mode.”[2] So connected mode is a large-message optimisation that keeps a datagram path underneath it, and it costs you the offloads.

NVIDIA’s DOCA page adds the numbers a Dell customer will actually hit: IPoIB supports “Varies MTU values: up to 4k in Datagram mode”, the physical port MTU defaults to 4k while “the IPoIB logical MTU defaults to 2k”, and in OpenSM partition files you use “mtu=5 for 4k and mtu=4 for 2k”.[3] The same page describes Enhanced IPoIB, which “enables offloading ULP basic capabilities to a lower vendor specific driver, in order to optimize IPoIB data path” with stateless offloads, multiple queues and interrupt moderation - and is UD mode only.[3]

The trap in one line: the partition file’s mtu= default is 4, meaning 2048, so a host configured for 4092 or 65520 will look up and behave broken until someone compares the two.[5][3]

4The partition side: where a working IPoIB interface actually comes from

An IPoIB interface needs a multicast broadcast group to exist before ARP can work, and that group is created by the subnet manager, not by the host. In partitions.conf the ipoib flag “indicates that this partition may be used for IPoIB, as a result the IPoIB broadcast group will be created with the mgroup_flag flags given, if any”.[5] The flags default to rate=3 (10 Gbps), mtu=4 (2048), sl=0, scope=2 (link local), Q_Key=0x0b1b for IP groups, TClass=0 and FlowLabel=0.[5] One of them carries an explicit warning: “WARNING: changing this [Q_Key] for the broadcast group may break IPoIB on client nodes!!!”[5]

Membership is the second half. P_Key bit 15 is the membership bit - “‘1’ means full member, ‘0’ means limited member” - and “A P_Key match occurs only if at least one of the nodes (sending / receiving) is a full member”.[6] RFC 4391 turns that into a requirement for IPoIB specifically: “a ‘Full Membership’ P_Key (high-order bit is set to 1) MUST be used so that all members may communicate with one another”, and every IPoIB interface “MUST ‘FullMember’ join the IB multicast group defined by the broadcast-GID”.[1]

Now put it beside the partition-file default: defmember “specifies default membership for port guid list. Default is limited.”[5] So a stanza written without =full produces limited members, the broadcast group cannot be full-member joined by them, and the interface comes up and resolves nothing. Two limited members of the same partition also cannot reach each other - that follows from the match rule quoted above, though note that the OpenSM man page never spells out the limited-to-limited case verbatim; the closest primary statement is RFC 4391’s full-membership requirement.[6][1]

The canonical known-good one-liner is worth keeping in a snippet file: Default=0x7fff,ipoib:ALL=full; - “equivalent to how OpenSM used to run prior to the partition manager”.[5] And on the QoS side, OpenSM matches IPoIB traffic by PKey: ipoib :, ipoib, pkey 0x7fff : and any, pkey 0x7fff : are equivalent match rules.[8]

Write the partition, predict the interface

Requirement. A tenant needs its own IPoIB network on PKey 0x8001, at 4K MTU, on three hosts whose port GUIDs are 0x0002c90300a1b2c1, …c2 and …c3. The default partition must remain usable for in-band management.

Step 1 - keep Default explicit. The moment a partition file exists, every port that has no Default rule drops to limited membership, so the Default stanza is not optional even though it looks like boilerplate.[5]

Default=0x7fff, ipoib : ALL=full ;

Step 2 - write the tenant stanza with full membership and the ipoib flag. The grammar is [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited] followed by a port-GUID list.[5]

tenant-a=0x8001, ipoib, mtu=5, defmember=full : 0x0002c90300a1b2c1, 0x0002c90300a1b2c2, 0x0002c90300a1b2c3 ;

mtu=5 asks for a 4K multicast group per NVIDIA’s pairing; defmember=full overrides the documented default of limited; ipoib is what creates the broadcast group at all.[3][5]

Step 3 - predict the result before touching a host. Only the low 15 bits of the PKey are used, so 0x8001 is the partition value and full members will see it in their PKey table with bit 15 set.[5][6] The child interface will be named ib0.8001.[2] Its datagram-mode MTU will be the IB L2 MTU minus 4 - so 4092 if the fabric really carries 4K, and 2044 if anything in the path is still 2K.[2][1]

Step 4 - create it and verify.

echo 0x8001 > /sys/class/net/ib0/create_child
cat /sys/class/net/ib0.8001/pkey
ip -d link show ib0.8001

Expected: pkey reads 0x8001, the link shows link/infiniband with a 20-byte address, and the MTU matches your prediction.[2][1] Rollback: echo 0x8001 > /sys/class/net/ib0/delete_child.[2]

Episode 4 — One token, before lunch

How it ended

The tenant stanza was written without =full, and defmember “specifies default membership for port guid list. Default is limited.”[5] RFC 4391 requires a full-membership P_Key so that all members may communicate with one another, and requires every IPoIB interface to FullMember-join the multicast group defined by the broadcast-GID.[1] So the interface came up, joined nothing it could use, and answered no ARP. What you say to the platform team: “The host was never the problem. Your partition made every one of those ports a limited member, and limited members have nobody to talk to.” Two days later, at 09:00 on acceptance day, twelve of the sixty-four nodes fail the customer’s script — and a technician is already in the aisle with a card in his hand.

Lab

Mutating steps ahead. Needs a maintenance window, out-of-band access (BMC/iDRAC/rshim console) and a rollback path. Record the pre-flight inventory before changing anything. Never on a production host.

Mutating. Step 5 creates a child interface and step 7 changes the IPoIB mode. Both name their rollback. Do this on a Dell-lab host only, never on a host carrying customer traffic.

  1. Pre-flight inventory - capture this before anything: ip -d link show ib0 > /tmp/ipoib-before.txt, cat /sys/class/net/ib0/{pkey,mode}, ibstat, and ls /sys/class/net/ | grep ^ib. Expected: one ib0, a pkey of 0x7fff on a default fabric, and a mode of datagram or connected.
  2. Confirm the interface really is native InfiniBand: ip -d link show ib0. Expected: link/infiniband followed by a 20-byte hardware address, not a 6-byte MAC. If you see link/ether, this port is in Ethernet mode and this lab does not apply.
  3. Record the MTU and check the arithmetic against the fabric: ip link show ib0 | grep mtu and compare with the active MTU from ibv_devinfo. Expected: the IPoIB MTU is the IB L2 MTU minus 4 in datagram mode.
  4. Confirm which partition owns the base interface: cat /sys/class/net/ib0/pkey. Expected: the PKey at index 0 of the port’s table - 0x7fff unless your SM’s partition file uses indx0 elsewhere.
  5. Mutating. Create a child interface for a PKey your local opensm actually defines: echo 0x8001 > /sys/class/net/ib0/create_child, then cat /sys/class/net/ib0.8001/{pkey,parent} and ip -d link show ib0.8001. Expected: a new interface named ib0.8001 with pkey 0x8001 and parent ib0. Rollback: echo 0x8001 > /sys/class/net/ib0/delete_child, then confirm with ls /sys/class/net/ | grep ib0 that it is gone.
  6. Prove the partition dependency rather than assuming it: create a child for a PKey your SM does not define, and observe that the interface appears and carries no traffic. Expected: creation succeeds locally, connectivity does not exist. Rollback: the matching delete_child. This is the whole lesson in one observation.
  7. Mutating, optional. Switch the base interface’s mode: cat /sys/class/net/ib0/mode to record the current value, then echo connected > /sys/class/net/ib0/mode, re-read the MTU, and note what changed. Expected: the interface can now carry a larger MTU and stateless offloads are no longer in play. Rollback: echo datagram > /sys/class/net/ib0/mode and confirm the MTU returns to the value in /tmp/ipoib-before.txt. Note that the kernel documentation is the source for this file; NVIDIA’s DOCA 3.5.0 IPoIB page does not show it.
  8. Optional, where a peer exists: put an IP on both ends of a partition interface and confirm ARP resolves, then repeat on a partition whose members are limited and observe the difference. Expected: full membership resolves, limited does not. Rollback: remove the addresses you added with ip addr del.

Retrieval check

10 questions from memory. Answer before looking anything up; misses become flashcards.

Explain it to a Dell SE

Explain to a Dell SE, in five sentences, what IPoIB is for on a fabric whose whole point is RDMA, and why the tenant interface they just created came up but cannot ping anything.

14 flashcards for this lesson — 0 in deck. Spaced review lives at /review.

Sources

Facts in this lesson were checked against Linux kernel Documentation/infiniband/ipoib.txt re-fetched and re-quoted 2026-09-07 (mode file, create_child/delete_child, datagram and connected MTU, ARPHRD_INFINIBAND, PKey index 0); RFC 4391; DOCA 3.5.0 IP Over InfiniBand; opensm(8) and partition-config.txt (master). Dates are when each page was fetched.

  1. RFC 4391 - Transmission of IP over InfiniBand (IPoIB) · fetched 2026-09-07
  2. ipoib.txt - Linux kernel InfiniBand documentation · fetched 2026-09-07
  3. IP Over InfiniBand - DOCA 3.5.0 · fetched 2026-09-07
  4. opensm(8) man page source - linux-rdma/opensm master · fetched 2026-09-07
  5. OpenSM partitions.conf configuration reference · fetched 2026-09-07
  6. NVIDIA InfiniBand Security Overview and Guidelines - Security in InfiniBand · fetched 2026-09-07
  7. NVIDIA SHARP 3.8.0 - Setting up NVIDIA SHARP Environment · fetched 2026-09-07
  8. QoS Management in OpenSM · fetched 2026-09-07
  9. Subnet Manager - NVIDIA MLNX-OS User Manual v3.12.6200 LTS · fetched 2026-09-07
  10. RFC 4392 - IP over InfiniBand (IPoIB) Architecture · fetched 2026-09-07

The same idea elsewhere

Other lessons that cover this ground, sometimes from another course's angle.