Skip to content

Commit

Permalink
Added logic to compute ICRC for RoCEv2 over IPv6 (#4154)
Browse files Browse the repository at this point in the history
* Added logic to compute ICRC for RoCEv2 over IPv6.

* Fixed RoCEv2 icrc computation.

---------

Co-authored-by: leonidokner <[email protected]>
  • Loading branch information
leonidokner and leonidokner authored Oct 20, 2023
1 parent afe8eec commit 4fefbb0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
20 changes: 19 additions & 1 deletion scapy/contrib/roce.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from scapy.fields import ByteEnumField, ByteField, XByteField, \
ShortField, XShortField, XLongField, BitField, XBitField, FCSField
from scapy.layers.inet import IP, UDP
from scapy.layers.inet6 import IPv6
from scapy.layers.l2 import Ether
from scapy.compat import raw
from scapy.error import warning
Expand Down Expand Up @@ -179,8 +180,25 @@ def compute_icrc(self, p):
pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)
icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff
return self.pack_icrc(icrc)
elif isinstance(ip, IPv6):
# pseudo-LRH / IPv6 / UDP / BTH / payload
pshdr = Raw(b'\xff' * 8) / ip.copy()
pshdr.hlim = 0xff
pshdr.fl = 0xfffff
pshdr.tc = 0xff
pshdr[UDP].chksum = 0xffff
pshdr[BTH].fecn = 1
pshdr[BTH].becn = 1
pshdr[BTH].resv6 = 0xff
bth = pshdr[BTH].self_build()
payload = raw(pshdr[BTH].payload)
# add ICRC placeholder just to get the right IPv6.plen and
# UDP.length
icrc_placeholder = b'\xff\xff\xff\xff'
pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)
icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff
return self.pack_icrc(icrc)
else:
# TODO support IPv6
warning("The underlayer protocol %s is not supported.",
ip and ip.name)
return self.pack_icrc(0)
Expand Down
21 changes: 21 additions & 0 deletions test/contrib/roce.uts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,24 @@ assert not pkt[BTH].ackreq
assert pkt[AETH].syndrome == 0
assert pkt[AETH].msn == 5
assert pkt.icrc == 0x25f0c038

= RoCE over IPv6

# an example UC packet
pkt = Ether(dst='24:8a:07:a8:fa:22', src='24:8a:07:a8:fa:22')/ \
IPv6(nh=17,src='2022::1023', dst='2023::1024', \
version=6,hlim=255,plen=44,fl=0x1face,tc=226)/ \
UDP(sport=49152, dport=4791, len=44)/ \
BTH(opcode='UC_SEND_ONLY', migreq=1, padcount=2, pkey=0xffff, dqpn=211, psn=13571856)/ \
Raw(b'F0\x81\x8b\xe2\x895\xd9\x0e\x9a\x95PT\x01\xbe\x88^P\x00\x00')

# include ICRC placeholder
pkt = Ether(pkt.build() + b'\x00' * 4)

assert IPv6 in pkt.layers()
assert UDP in pkt.layers()
print(hex(pkt[UDP].chksum))
assert pkt[UDP].chksum == 0xe7c5
assert BTH in pkt.layers()
print(hex(pkt[BTH].icrc))
assert pkt[BTH].icrc == 0x3e5b743b

0 comments on commit 4fefbb0

Please sign in to comment.