Files
scylladb/virtiotest.cc
Avi Kivity 9f5c0dbf59 ip: improve endianness adjustment
Rather than hacking around the inability to bind references to unaligned
scalars, wrap them in a struct (which can then be marked as unaligned),
and use the wrapped values everywhere.  This ensures the code works on
platforms that need special instructions for unaligned access.

Adjust the forwarding functions to require references; passing by value
accidentally can lose the conversion.
2014-08-28 23:16:48 +03:00

82 lines
2.0 KiB
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*
*/
#include "virtio.hh"
#include "reactor.hh"
#include "ip.hh"
#include <iostream>
#include <utility>
#include <algorithm>
using namespace net;
void dump_packet(const packet& p) {
std::cout << "rx:";
auto& f = p.fragments[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.fragments[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 != 8) {
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 = 0xc0a87a02; // 192.168.122.2
iph->dst_ip = x;
icmph->type = 0;
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));
}
void echo_packets(net::device& netif) {
netif.receive().then([&netif] (packet p) {
dump_packet(p);
return echo_packet(netif, std::move(p));
}).then([&netif] () {
echo_packets(netif);
});
}
int main(int ac, char** av) {
auto vnet = create_virtio_net_device("tap0");
echo_packets(*vnet);
the_reactor.run();
return 0;
}