From 606b1b46f5ff382b0d9f35d515f137071785aeab Mon Sep 17 00:00:00 2001 From: Pin-Yen Lin Date: Mon, 13 Aug 2018 14:23:24 +0800 Subject: net: Fix a bug when handling IPv6 packets When gem5 runs with the networking support, it will run into an assertion fail and aborted. This is because it tries to calculate checksum for IPv6 packet and this makes the IpPtr pointer ``ip'' become NULL. For that there is functions and classes for IPv6 in base/inet.cc, I added IPv6 support for i8254xGBe.cc. Because IPv6 header does not have identification number, I ignored some of the debug messages using ip->id(). Change-Id: Ida5e36aefd2c5c26053f8152a0aac24191e7757c Reviewed-on: https://gem5-review.googlesource.com/12339 Reviewed-by: Earl Ou Reviewed-by: Jason Lowe-Power Maintainer: Gabe Black --- src/dev/net/i8254xGBe.cc | 63 +++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/dev/net/i8254xGBe.cc b/src/dev/net/i8254xGBe.cc index 3359b0d61..88528c4b7 100644 --- a/src/dev/net/i8254xGBe.cc +++ b/src/dev/net/i8254xGBe.cc @@ -1373,13 +1373,19 @@ IGbE::RxDescCache::pktComplete() status |= RXDS_EOP; IpPtr ip(pktPtr); + Ip6Ptr ip6(pktPtr); - if (ip) { - DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", ip->id()); - ptype |= RXDP_IPV4; - ip_id = ip->id(); + if (ip || ip6) { + if (ip) { + DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", + ip->id()); + ptype |= RXDP_IPV4; + ip_id = ip->id(); + } + if (ip6) + ptype |= RXDP_IPV6; - if (igbe->regs.rxcsum.ipofld()) { + if (ip && igbe->regs.rxcsum.ipofld()) { DPRINTF(EthernetDesc, "Checking IP checksum\n"); status |= RXDS_IPCS; csum = htole(cksum(ip)); @@ -1390,7 +1396,7 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Checksum is bad!!\n"); } } - TcpPtr tcp(ip); + TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6); if (tcp && igbe->regs.rxcsum.tuofld()) { DPRINTF(EthernetDesc, "Checking TCP checksum\n"); status |= RXDS_TCPCS; @@ -1404,7 +1410,7 @@ IGbE::RxDescCache::pktComplete() } } - UdpPtr udp(ip); + UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6); if (udp && igbe->regs.rxcsum.tuofld()) { DPRINTF(EthernetDesc, "Checking UDP checksum\n"); status |= RXDS_UDPCS; @@ -1838,26 +1844,28 @@ IGbE::TxDescCache::pktComplete() if (useTso) { IpPtr ip(pktPtr); + Ip6Ptr ip6(pktPtr); if (ip) { DPRINTF(EthernetDesc, "TSO: Modifying IP header. Id + %d\n", tsoPkts); ip->id(ip->id() + tsoPkts++); ip->len(pktPtr->length - EthPtr(pktPtr)->size()); - - TcpPtr tcp(ip); - if (tcp) { - DPRINTF(EthernetDesc, - "TSO: Modifying TCP header. old seq %d + %d\n", - tcp->seq(), tsoPrevSeq); - tcp->seq(tcp->seq() + tsoPrevSeq); - if (tsoUsedLen != tsoTotalLen) - tcp->flags(tcp->flags() & ~9); // clear fin & psh - } - UdpPtr udp(ip); - if (udp) { - DPRINTF(EthernetDesc, "TSO: Modifying UDP header.\n"); - udp->len(pktPtr->length - EthPtr(pktPtr)->size()); - } + } + if (ip6) + ip6->plen(pktPtr->length - EthPtr(pktPtr)->size()); + TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6); + if (tcp) { + DPRINTF(EthernetDesc, + "TSO: Modifying TCP header. old seq %d + %d\n", + tcp->seq(), tsoPrevSeq); + tcp->seq(tcp->seq() + tsoPrevSeq); + if (tsoUsedLen != tsoTotalLen) + tcp->flags(tcp->flags() & ~9); // clear fin & psh + } + UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6); + if (udp) { + DPRINTF(EthernetDesc, "TSO: Modifying UDP header.\n"); + udp->len(pktPtr->length - EthPtr(pktPtr)->size()); } tsoPrevSeq = tsoUsedLen; } @@ -1872,19 +1880,20 @@ IGbE::TxDescCache::pktComplete() } // Checksums are only ofloaded for new descriptor types - if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) { + if (TxdOp::isData(desc) && (TxdOp::ixsm(desc) || TxdOp::txsm(desc))) { DPRINTF(EthernetDesc, "Calculating checksums for packet\n"); IpPtr ip(pktPtr); - assert(ip); - if (TxdOp::ixsm(desc)) { + Ip6Ptr ip6(pktPtr); + assert(ip || ip6); + if (ip && TxdOp::ixsm(desc)) { ip->sum(0); ip->sum(cksum(ip)); igbe->txIpChecksums++; DPRINTF(EthernetDesc, "Calculated IP checksum\n"); } if (TxdOp::txsm(desc)) { - TcpPtr tcp(ip); - UdpPtr udp(ip); + TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6); + UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6); if (tcp) { tcp->sum(0); tcp->sum(cksum(tcp)); -- cgit v1.2.3