Files
scylladb/net/xenfront.hh
2014-12-11 13:06:32 +02:00

136 lines
3.3 KiB
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*/
#ifndef XENFRONT_HH_
#define XENFRONT_HH_
#include <memory>
#include "net.hh"
#include "core/sstring.hh"
#include "core/xen/gntalloc.hh"
#include "core/queue.hh"
namespace xen {
std::unique_ptr<net::device> create_xenfront_net_device(boost::program_options::variables_map opts, bool userspace);
boost::program_options::options_description get_xenfront_net_options_description();
struct netif_tx_request {
uint32_t gref;
uint16_t offset;
struct {
uint16_t csum_blank : 1;
uint16_t data_validated : 1;
uint16_t more_data : 1;
uint16_t extra_info : 1;
uint16_t pad : 12;
} flags;
uint16_t id;
uint16_t size;
};
struct netif_tx_response {
uint16_t id;
int16_t status;
};
struct netif_rx_request {
uint16_t id;
uint32_t gref;
};
struct netif_rx_response {
uint16_t id;
uint16_t offset; /* Offset in page of start of received packet */
uint16_t flags; /* NETRXF_* */
int16_t status; /* -ve: NETIF_RSP_* ; +ve: Rx'ed response size. */
};
union tx {
struct netif_tx_request req;
struct netif_tx_response rsp;
};
union rx {
struct netif_rx_request req;
struct netif_rx_response rsp;
};
template <typename T>
class sring {
public:
uint32_t req_prod = 0;
uint32_t req_event = 1;
uint32_t rsp_prod = 0;
uint32_t rsp_event = 1;
uint8_t pad[48] = { 0 };
T _ring[1];
void dump() {
printf("Shared ring status: req_prod: %d, req_event %d, rsp_prod %d, rsp_event %d\n", req_prod, req_event, rsp_prod, rsp_event);
}
sring<T>() = default;
};
using phys = uint64_t;
template <typename T>
class front_ring {
public:
static constexpr uint32_t nr_ents = 256; /* FIXME : DYN */
class entries {
protected:
std::queue<unsigned, circular_buffer<unsigned>> _ids;
semaphore _available = { front_ring::nr_ents };
private:
std::array<gntref, front_ring<T>::nr_ents> _entries;
front_ring<T> *_ring;
std::atomic<uint32_t> _next_idx = { 0 };
public:
entries(front_ring<T> *ring) : _ring(ring) {}
gntref& operator[](std::size_t i) { return _entries[_ring->idx(i)]; }
friend front_ring;
future<> has_room();
unsigned get_index();
void free_index(unsigned index);
};
protected:
static uint32_t idx(int i) { return i & (nr_ents - 1); }
public:
uint32_t req_prod_pvt = 0;
uint32_t rsp_cons = 0;
int32_t ref = -1;
front_ring(gntref r)
: ref(r.xen_id), entries(this)
, _sring(new (r.page) sring<T>()) {
}
entries entries;
future<> process_ring(std::function<bool (gntref &entry, T& el)> func, grant_head *refs);
void dump() {
_sring->dump();
printf("Ring status: req_prod_pvt: %d, rsp cons %d\n\n", req_prod_pvt, rsp_cons);
}
void dump(const char *str, netif_tx_response &r) {
printf("%s: tx_response: id %hu, status %hd\n", str, r.id, r.status);
dump();
}
void dump(const char *str, netif_rx_response &r) {
printf("%s: rx_response: id %hu, offset %hu, flags %hx, status %hd\n", str, r.id, r.offset, r.flags, r.status);
dump();
}
sring<T> *_sring;
T& operator[](std::size_t i) { return _sring->_ring[idx(i)]; }
};
}
#endif /* XENFRONT_HH_ */