Files
scylladb/tests/virtiotest.cc
2014-09-25 17:49:38 +03:00

76 lines
2.0 KiB
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*
*/
#include "net/virtio.hh"
#include "core/reactor.hh"
#include "net/ip.hh"
#include <iostream>
#include <utility>
#include <algorithm>
using namespace net;
void dump_packet(const packet& p) {
std::cout << "rx:";
auto f = p.frag(0);
for (unsigned i = 0; i < std::min(f.size, size_t(30)); ++i) {
char x[4];
std::sprintf(x, " %02x", uint8_t(f.base[i]));
std::cout << x;
}
std::cout << "\n";
}
future<> echo_packet(net::device& netif, packet p) {
auto f = p.frag(0);
if (f.size < sizeof(eth_hdr)) {
return make_ready_future<>();
}
auto pos = 0;
auto eh = reinterpret_cast<eth_hdr*>(f.base + pos);
pos += sizeof(*eh);
ntoh(*eh);
if (eh->eth_proto != 0x0800) {
return make_ready_future<>();
}
auto iph = reinterpret_cast<ip_hdr*>(f.base + pos);
ntoh(*iph);
pos += iph->ihl * 4;
if (iph->ver != 4 || iph->ihl < 5 || iph->ip_proto != 1) {
return make_ready_future<>();
}
auto ip_len = iph->len;
auto icmph = reinterpret_cast<icmp_hdr*>(f.base + pos);
if (icmph->type != icmp_hdr::msg_type::echo_request) {
return make_ready_future<>();
}
auto icmp_len = ip_len - iph->ihl * 4;
std::swap(eh->src_mac, eh->dst_mac);
eh->src_mac = {{{ 0x12, 0x23, 0x45, 0x56, 0x67, 0x68 }}};
auto x = iph->src_ip;
iph->src_ip = ipv4_address("192.168.122.2");
iph->dst_ip = x;
icmph->type = icmp_hdr::msg_type::echo_reply;
icmph->csum = 0;
hton(*iph);
hton(*eh);
icmph->csum = ip_checksum(icmph, icmp_len);
iph->csum = 0;
iph->csum = ip_checksum(iph, iph->ihl * 4);
return netif.send(std::move(p));
}
int main(int ac, char** av) {
auto vnet = create_virtio_net_device("tap0");
subscription<packet> rx = vnet->receive([netif = vnet.get(), &rx] (packet p) {
dump_packet(p);
return echo_packet(*netif, std::move(p));
});
engine.run();
return 0;
}