mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-22 17:40:34 +00:00
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.
82 lines
2.0 KiB
C++
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;
|
|
}
|
|
|
|
|