std::unique_ptr createPacketFromFlow()

in katran/lib/KatranSimulator.cpp [152:208]


std::unique_ptr<folly::IOBuf> createPacketFromFlow(const KatranFlow& flow) {
  int offset = sizeof(struct ethhdr);
  bool is_tcp = true;
  bool is_v4 = true;
  size_t l3hdr_len;

  auto srcExp = folly::IPAddress::tryFromString(flow.src);
  auto dstExp = folly::IPAddress::tryFromString(flow.dst);
  if (srcExp.hasError() || dstExp.hasError()) {
    LOG(ERROR) << "malformed src or dst ip address. src: " << flow.src
               << " dst: " << flow.dst;
    return nullptr;
  }
  auto src = srcExp.value();
  auto dst = dstExp.value();
  if (src.family() != dst.family()) {
    LOG(ERROR) << "src and dst must have same address family";
    return nullptr;
  }
  auto pckt = folly::IOBuf::create(kTestPacketSize);
  if (!pckt) {
    LOG(ERROR) << "cannot allocate IOBuf";
    return pckt;
  }
  if (src.family() == AF_INET) {
    l3hdr_len = sizeof(struct iphdr);
  } else {
    is_v4 = false;
    l3hdr_len = sizeof(struct ipv6hdr);
  }
  offset += l3hdr_len;
  switch (flow.proto) {
    case IPPROTO_TCP:
      break;
    case IPPROTO_UDP:
      is_tcp = false;
      break;
    default:
      LOG(ERROR) << "unsupported protocol: " << flow.proto
                 << " must be either TCP or UDP";
      return nullptr;
  }
  pckt->append(kTestPacketSize);
  auto payload_size = kTestPacketSize - sizeof(struct ethhdr);
  if (is_v4) {
    createV4Packet(src, dst, pckt, flow.proto, payload_size);
  } else {
    createV6Packet(src, dst, pckt, flow.proto, payload_size);
  }
  payload_size -= l3hdr_len;
  if (is_tcp) {
    createTcpHeader(pckt, flow.srcPort, flow.dstPort, offset);
  } else {
    createUdpHeader(pckt, flow.srcPort, flow.dstPort, offset, payload_size);
  }
  return pckt;
}