Skip to content

Commit 4fefbb0

Browse files
Added logic to compute ICRC for RoCEv2 over IPv6 (#4154)
* Added logic to compute ICRC for RoCEv2 over IPv6. * Fixed RoCEv2 icrc computation. --------- Co-authored-by: leonidokner <leonidokner@enfabrica.net>
1 parent afe8eec commit 4fefbb0

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

scapy/contrib/roce.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from scapy.fields import ByteEnumField, ByteField, XByteField, \
1515
ShortField, XShortField, XLongField, BitField, XBitField, FCSField
1616
from scapy.layers.inet import IP, UDP
17+
from scapy.layers.inet6 import IPv6
1718
from scapy.layers.l2 import Ether
1819
from scapy.compat import raw
1920
from scapy.error import warning
@@ -179,8 +180,25 @@ def compute_icrc(self, p):
179180
pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)
180181
icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff
181182
return self.pack_icrc(icrc)
183+
elif isinstance(ip, IPv6):
184+
# pseudo-LRH / IPv6 / UDP / BTH / payload
185+
pshdr = Raw(b'\xff' * 8) / ip.copy()
186+
pshdr.hlim = 0xff
187+
pshdr.fl = 0xfffff
188+
pshdr.tc = 0xff
189+
pshdr[UDP].chksum = 0xffff
190+
pshdr[BTH].fecn = 1
191+
pshdr[BTH].becn = 1
192+
pshdr[BTH].resv6 = 0xff
193+
bth = pshdr[BTH].self_build()
194+
payload = raw(pshdr[BTH].payload)
195+
# add ICRC placeholder just to get the right IPv6.plen and
196+
# UDP.length
197+
icrc_placeholder = b'\xff\xff\xff\xff'
198+
pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)
199+
icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff
200+
return self.pack_icrc(icrc)
182201
else:
183-
# TODO support IPv6
184202
warning("The underlayer protocol %s is not supported.",
185203
ip and ip.name)
186204
return self.pack_icrc(0)

test/contrib/roce.uts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,24 @@ assert not pkt[BTH].ackreq
124124
assert pkt[AETH].syndrome == 0
125125
assert pkt[AETH].msn == 5
126126
assert pkt.icrc == 0x25f0c038
127+
128+
= RoCE over IPv6
129+
130+
# an example UC packet
131+
pkt = Ether(dst='24:8a:07:a8:fa:22', src='24:8a:07:a8:fa:22')/ \
132+
IPv6(nh=17,src='2022::1023', dst='2023::1024', \
133+
version=6,hlim=255,plen=44,fl=0x1face,tc=226)/ \
134+
UDP(sport=49152, dport=4791, len=44)/ \
135+
BTH(opcode='UC_SEND_ONLY', migreq=1, padcount=2, pkey=0xffff, dqpn=211, psn=13571856)/ \
136+
Raw(b'F0\x81\x8b\xe2\x895\xd9\x0e\x9a\x95PT\x01\xbe\x88^P\x00\x00')
137+
138+
# include ICRC placeholder
139+
pkt = Ether(pkt.build() + b'\x00' * 4)
140+
141+
assert IPv6 in pkt.layers()
142+
assert UDP in pkt.layers()
143+
print(hex(pkt[UDP].chksum))
144+
assert pkt[UDP].chksum == 0xe7c5
145+
assert BTH in pkt.layers()
146+
print(hex(pkt[BTH].icrc))
147+
assert pkt[BTH].icrc == 0x3e5b743b

0 commit comments

Comments
 (0)