From 9ae11f7ecf8baac23c56432204d5f2590ff3c940 Mon Sep 17 00:00:00 2001 From: leonidokner Date: Wed, 18 Oct 2023 22:24:57 +0000 Subject: [PATCH 1/2] Added logic to compute ICRC for RoCEv2 over IPv6. --- scapy/contrib/roce.py | 18 +++++++++++++++++- test/contrib/roce.uts | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/scapy/contrib/roce.py b/scapy/contrib/roce.py index 9a6683cefa1..7b6f1dfe4fa 100644 --- a/scapy/contrib/roce.py +++ b/scapy/contrib/roce.py @@ -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 @@ -179,8 +180,23 @@ 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'\x6fffffff') / ip.copy() + pshdr.hlim = 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) diff --git a/test/contrib/roce.uts b/test/contrib/roce.uts index 757163d3049..2bd9276a9ed 100644 --- a/test/contrib/roce.uts +++ b/test/contrib/roce.uts @@ -124,3 +124,23 @@ 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 == 0x40a2 +assert BTH in pkt.layers() +assert pkt[BTH].icrc == 0x59a80012 From 48e07fe57aae8fbeecb084fc0e2c2daa332af8ea Mon Sep 17 00:00:00 2001 From: leonidokner Date: Thu, 19 Oct 2023 00:55:33 +0000 Subject: [PATCH 2/2] Fixed RoCEv2 icrc computation. --- scapy/contrib/roce.py | 4 +++- test/contrib/roce.uts | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scapy/contrib/roce.py b/scapy/contrib/roce.py index 7b6f1dfe4fa..93dceab693b 100644 --- a/scapy/contrib/roce.py +++ b/scapy/contrib/roce.py @@ -182,8 +182,10 @@ def compute_icrc(self, p): return self.pack_icrc(icrc) elif isinstance(ip, IPv6): # pseudo-LRH / IPv6 / UDP / BTH / payload - pshdr = Raw(b'\x6fffffff') / ip.copy() + 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 diff --git a/test/contrib/roce.uts b/test/contrib/roce.uts index 2bd9276a9ed..ff19affec3c 100644 --- a/test/contrib/roce.uts +++ b/test/contrib/roce.uts @@ -141,6 +141,7 @@ 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 == 0x40a2 +assert pkt[UDP].chksum == 0xe7c5 assert BTH in pkt.layers() -assert pkt[BTH].icrc == 0x59a80012 +print(hex(pkt[BTH].icrc)) +assert pkt[BTH].icrc == 0x3e5b743b