diff --git a/scapy/contrib/roce.py b/scapy/contrib/roce.py index 9a6683cefa1..93dceab693b 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,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) diff --git a/test/contrib/roce.uts b/test/contrib/roce.uts index 757163d3049..ff19affec3c 100644 --- a/test/contrib/roce.uts +++ b/test/contrib/roce.uts @@ -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