Ejemplo n.º 1
0
std::unique_ptr<IOBuf> LZ4Codec::doCompress(const IOBuf* data) {
  std::unique_ptr<IOBuf> clone;
  if (data->isChained()) {
    // LZ4 doesn't support streaming, so we have to coalesce
    clone = data->clone();
    clone->coalesce();
    data = clone.get();
  }

  uint32_t extraSize = encodeSize() ? kMaxVarintLength64 : 0;
  auto out = IOBuf::create(extraSize + LZ4_compressBound(data->length()));
  if (encodeSize()) {
    encodeVarintToIOBuf(data->length(), out.get());
  }

  int n;
  if (highCompression_) {
    n = LZ4_compressHC(reinterpret_cast<const char*>(data->data()),
                       reinterpret_cast<char*>(out->writableTail()),
                       data->length());
  } else {
    n = LZ4_compress(reinterpret_cast<const char*>(data->data()),
                     reinterpret_cast<char*>(out->writableTail()),
                     data->length());
  }

  CHECK_GE(n, 0);
  CHECK_LE(n, out->capacity());

  out->append(n);
  return out;
}
Ejemplo n.º 2
0
std::unique_ptr<IOBuf> SnappyCodec::doUncompress(const IOBuf* data,
                                                 uint64_t uncompressedLength) {
  uint32_t actualUncompressedLength = 0;

  {
    IOBufSnappySource source(data);
    if (!snappy::GetUncompressedLength(&source, &actualUncompressedLength)) {
      throw std::runtime_error("snappy::GetUncompressedLength failed");
    }
    if (uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH &&
        uncompressedLength != actualUncompressedLength) {
      throw std::runtime_error("snappy: invalid uncompressed length");
    }
  }

  auto out = IOBuf::create(actualUncompressedLength);

  {
    IOBufSnappySource source(data);
    if (!snappy::RawUncompress(&source,
                               reinterpret_cast<char*>(out->writableTail()))) {
      throw std::runtime_error("snappy::RawUncompress failed");
    }
  }

  out->append(actualUncompressedLength);
  return out;
}
Ejemplo n.º 3
0
fbstring IOBuf::moveToFbString() {
  // malloc-allocated buffers are just fine, everything else needs
  // to be turned into one.
  if (!sharedInfo() ||         // user owned, not ours to give up
      sharedInfo()->freeFn ||  // not malloc()-ed
      headroom() != 0 ||       // malloc()-ed block doesn't start at beginning
      tailroom() == 0 ||       // no room for NUL terminator
      isShared() ||            // shared
      isChained()) {           // chained
    // We might as well get rid of all head and tailroom if we're going
    // to reallocate; we need 1 byte for NUL terminator.
    coalesceAndReallocate(0, computeChainDataLength(), this, 1);
  }

  // Ensure NUL terminated
  *writableTail() = 0;
  fbstring str(reinterpret_cast<char*>(writableData()),
               length(),  capacity(),
               AcquireMallocatedString());

  if (flags() & kFlagFreeSharedInfo) {
    delete sharedInfo();
  }

  // Reset to a state where we can be deleted cleanly
  flagsAndSharedInfo_ = 0;
  buf_ = nullptr;
  clear();
  return str;
}
Ejemplo n.º 4
0
void TunIntf::handlerReady(uint16_t events) noexcept {
  CHECK(fd_ != -1);
  const int MaxSentOneTime = 16;
  // TODO: The packet size should be as same as MTU (hard code 1500 for now).
  // Since this is L3 packet size, we should also reserve some space for L2
  // header, which is 18 bytes (including one vlan tag)
  const int l3Len = 1500;
  int sent = 0;
  int dropped = 0;
  uint64_t bytes = 0;
  bool fdFail = false;
  try {
    while (sent + dropped < MaxSentOneTime) {
      std::unique_ptr<TxPacket> pkt;
      pkt = sw_->allocateL3TxPacket(l3Len);
      auto buf = pkt->buf();
      int ret = 0;
      do {
        ret = read(fd_, buf->writableTail(), buf->tailroom());
      } while (ret == -1 && errno == EINTR);
      if (ret < 0) {
        if (errno != EAGAIN) {
          sysLogError(ret, "Failed to read on ", fd_);
          // Cannot continue read on this fd
          fdFail = true;
        }
        break;
      } else if (ret == 0) {
        // Nothing to read. It shall not happen as the fd is non-blocking.
        // Just add this case to be safe.
        break;
      } else if (ret > buf->tailroom()) {
        // The pkt is larger than the buffer. We don't have complete packet.
        // It shall not happen unless the MTU is mis-match. Drop the packet.
        LOG(ERROR) << "Too large packet (" << ret << " > " << buf->tailroom()
                   << ") received from host. Drop the packet.";
        dropped++;
      } else {
        bytes += ret;
        buf->append(ret);
        sw_->sendL3Packet(rid_, std::move(pkt));
        sent++;
      }
    }
  } catch (const std::exception& ex) {
    LOG(ERROR) << "Hit some error when forwarding packets :"
               << folly::exceptionStr(ex);
  }
  if (fdFail) {
    unregisterHandler();
  }
  VLOG(4) << "Forwarded " << sent << " packets (" << bytes
          << " bytes) from host @ fd " << fd_ << " for router " << rid_
          << " dropped:" << dropped;
}
Ejemplo n.º 5
0
std::unique_ptr<IOBuf> ZSTDCodec::doCompress(const IOBuf* data) {
  // Support earlier versions of the codec (working with a single IOBuf,
  // and using ZSTD_decompress which requires ZSTD frame to contain size,
  // which isn't populated by streaming API).
  if (!data->isChained()) {
    auto out = IOBuf::createCombined(ZSTD_compressBound(data->length()));
    const auto rc = ZSTD_compress(
        out->writableData(),
        out->capacity(),
        data->data(),
        data->length(),
        level_);
    zstdThrowIfError(rc);
    out->append(rc);
    return out;
  }

  auto zcs = ZSTD_createCStream();
  SCOPE_EXIT {
    ZSTD_freeCStream(zcs);
  };

  auto rc = ZSTD_initCStream(zcs, level_);
  zstdThrowIfError(rc);

  Cursor cursor(data);
  auto result = IOBuf::createCombined(ZSTD_compressBound(cursor.totalLength()));

  ZSTD_outBuffer out;
  out.dst = result->writableTail();
  out.size = result->capacity();
  out.pos = 0;

  for (auto buffer = cursor.peekBytes(); !buffer.empty();) {
    ZSTD_inBuffer in;
    in.src = buffer.data();
    in.size = buffer.size();
    for (in.pos = 0; in.pos != in.size;) {
      rc = ZSTD_compressStream(zcs, &out, &in);
      zstdThrowIfError(rc);
    }
    cursor.skip(in.size);
    buffer = cursor.peekBytes();
  }

  rc = ZSTD_endStream(zcs, &out);
  zstdThrowIfError(rc);
  CHECK_EQ(rc, 0);

  result->append(out.pos);
  return result;
}
Ejemplo n.º 6
0
pair<void*,uint64_t>
IOBufQueue::preallocateSlow(uint64_t min, uint64_t newAllocationSize,
                            uint64_t max) {
  // Avoid grabbing update guard, since we're manually setting the cache ptrs.
  flushCache();
  // Allocate a new buffer of the requested max size.
  unique_ptr<IOBuf> newBuf(IOBuf::create(std::max(min, newAllocationSize)));

  tailStart_ = newBuf->writableTail();
  cachePtr_->cachedRange = std::pair<uint8_t*, uint8_t*>(
      tailStart_, tailStart_ + newBuf->tailroom());
  appendToChain(head_, std::move(newBuf), false);
  return make_pair(writableTail(), std::min<uint64_t>(max, tailroom()));
}
Ejemplo n.º 7
0
std::unique_ptr<IOBuf> SnappyCodec::doCompress(const IOBuf* data) {
  IOBufSnappySource source(data);
  auto out =
    IOBuf::create(snappy::MaxCompressedLength(source.Available()));

  snappy::UncheckedByteArraySink sink(reinterpret_cast<char*>(
      out->writableTail()));

  size_t n = snappy::Compress(&source, &sink);

  CHECK_LE(n, out->capacity());
  out->append(n);
  return out;
}
Ejemplo n.º 8
0
std::unique_ptr<IOBuf> LZ4Codec::doUncompress(
    const IOBuf* data,
    uint64_t uncompressedLength) {
  std::unique_ptr<IOBuf> clone;
  if (data->isChained()) {
    // LZ4 doesn't support streaming, so we have to coalesce
    clone = data->clone();
    clone->coalesce();
    data = clone.get();
  }

  folly::io::Cursor cursor(data);
  uint64_t actualUncompressedLength;
  if (encodeSize()) {
    actualUncompressedLength = decodeVarintFromCursor(cursor);
    if (uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH &&
        uncompressedLength != actualUncompressedLength) {
      throw std::runtime_error("LZ4Codec: invalid uncompressed length");
    }
  } else {
    actualUncompressedLength = uncompressedLength;
    if (actualUncompressedLength == UNKNOWN_UNCOMPRESSED_LENGTH ||
        actualUncompressedLength > maxUncompressedLength()) {
      throw std::runtime_error("LZ4Codec: invalid uncompressed length");
    }
  }

  auto sp = StringPiece{cursor.peekBytes()};
  auto out = IOBuf::create(actualUncompressedLength);
  int n = LZ4_decompress_safe(
      sp.data(),
      reinterpret_cast<char*>(out->writableTail()),
      sp.size(),
      actualUncompressedLength);

  if (n < 0 || uint64_t(n) != actualUncompressedLength) {
    throw std::runtime_error(to<std::string>(
        "LZ4 decompression returned invalid value ", n));
  }
  out->append(actualUncompressedLength);
  return out;
}
Ejemplo n.º 9
0
std::unique_ptr<IOBuf> ZSTDCodec::doUncompress(const IOBuf* data,
                                               uint64_t uncompressedLength) {
  size_t rc;
  auto out = IOBuf::createCombined(uncompressedLength);

  CHECK_GE(out->capacity(), uncompressedLength);
  CHECK_EQ(out->length(), 0);

  rc = ZSTD_decompress(
      out->writableTail(), out->capacity(), data->data(), data->length());

  if (ZSTD_isError(rc)) {
    throw std::runtime_error(to<std::string>(
          "ZSTD decompression returned an error: ",
          ZSTD_getErrorName(rc)));
  }

  out->append(rc);
  CHECK_EQ(out->length(), rc);

  return out;
}