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;
}