1 #include "hmbdc/Copyright.hpp" 3 #include "hmbdc/tips/rnetmap/Transport.hpp" 4 #include "hmbdc/app/Logger.hpp" 5 #include "hmbdc/comm/inet/Misc.hpp" 6 #include "hmbdc/MetaUtils.hpp" 8 #include <boost/bind.hpp> 9 #include <boost/lexical_cast.hpp> 12 #include <type_traits> 14 namespace hmbdc {
namespace tips {
namespace rnetmap {
16 namespace nmrecvtransport_detail {
24 template <
typename OutputBuffer,
typename Ep2SessionDict>
32 , Ep2SessionDict& sessionDict)
34 , doChecksum_(config_.getExt<
bool>(
"doChecksum"))
36 , pollWaitTimeMillisec_(0)
38 , cmdBuffer_(cmdBuffer)
40 , subscriptions_(subscriptions)
41 , sessionDict_(sessionDict) {
42 auto nmport = config_.
getExt<std::string>(
"netmapPort");
43 busyWait_ = config_.
getExt<
bool>(
"busyWait");
44 if (!busyWait_) pollWaitTimeMillisec_ = config_.
getExt<
int>(
"pollWaitTimeMillisec");
47 bzero(&baseNmd,
sizeof(baseNmd));
48 baseNmd.nr_flags |= NR_ACCEPT_VNET_HDR;
49 config_(baseNmd.nr_tx_slots,
"nmTxSlots");
50 config_(baseNmd.nr_rx_slots,
"nmRxSlots");
51 config_(baseNmd.nr_tx_rings,
"nmTxRings");
52 config_(baseNmd.nr_rx_rings,
"nmRxRings");
54 nmd_ = nm_open(nmport.c_str(), &baseNmd, config_.
getExt<
int>(
"nmOpenFlags"), NULL);
56 HMBDC_THROW(std::runtime_error,
"cannot open " << nmport);
60 memset(&req, 0,
sizeof(req));
61 bcopy(nmd_->req.nr_name, req.nr_name,
sizeof(req.nr_name));
62 req.nr_version = NETMAP_API;
63 req.nr_cmd = NETMAP_VNET_HDR_GET;
64 int err = ioctl(nmd_->fd, NIOCREGIF, &req);
66 HMBDC_THROW(std::runtime_error,
"Unable to get virtio-net header length");
68 virtHeader_ = req.nr_arg1;
73 sleep(config_.
getExt<
int>(
"nmResetWaitSec"));
75 if (hmbdc_unlikely(ioctl(nmd_->fd, NIOCRXSYNC, NULL) < 0)) {
76 HMBDC_THROW(std::runtime_error,
"IO error");
78 for (
int i = nmd_->first_rx_ring; i <= nmd_->last_rx_ring; i++) {
79 struct netmap_ring * rxring = NETMAP_TXRING(nmd_->nifp, i);
80 if (nm_ring_empty(rxring))
82 rxring->head = rxring->cur = rxring->tail;
90 void runOnce() HMBDC_RESTRICT {
92 for (
int i = nmd_->first_rx_ring; i <= nmd_->last_rx_ring; i++) {
93 struct netmap_ring * rxring = NETMAP_RXRING(nmd_->nifp, i);
94 if (nm_ring_empty(rxring))
109 if (hmbdc_likely(busyWait_)) {
110 if (hmbdc_unlikely(ioctl(nmd_->fd, NIOCRXSYNC, NULL) < 0)) {
111 HMBDC_THROW(std::runtime_error,
"IO error");
116 auto res = poll(&pfd_, 1, pollWaitTimeMillisec_);
117 if (hmbdc_unlikely( res < 0)) {
118 HMBDC_THROW(std::runtime_error,
"IO error errno=" << errno);
125 void recvPackets(
struct netmap_ring * HMBDC_RESTRICT ring) HMBDC_RESTRICT {
126 auto cur = ring->cur;
128 while(cur != ring->tail) {
129 struct netmap_slot *slot = &ring->slot[cur];
130 auto *buf = (uint8_t*)NETMAP_BUF(ring, slot->buf_idx);
134 if (p->ipv4.ip.ip_p == IPPROTO_UDP
135 && p->ipv4.ip.ip_off == htons(IP_DF)) {
137 data_ = (uint8_t*)p->ipv4.body;
138 #pragma GCC diagnostic push
139 #
if defined __clang__ || __GNUC_PREREQ(9,0)
140 #pragma GCC diagnostic ignored "-Waddress-of-packed-member" 142 auto ip = &p->ipv4.ip;
143 senderEndpoint_ = ip->ip_src.s_addr;
149 if (data_ + header->wireSize() <= buf + slot->len) {
150 if (hmbdc_unlikely(header->typeTag() == TypeTagBackupSource::typeTag)) {
151 auto it = cmdBuffer_.claim();
152 char* b =
static_cast<char*
>(*it);
153 size_t l = header->messagePayloadLen;
154 l = std::min(cmdBuffer_.maxItemSize(), l);
155 memcpy(b, header->payload(), l);
157 bts.sendFrom = senderEndpoint_;
158 cmdBuffer_.commit(it);
160 auto session = sessionDict_.find(senderEndpoint_);
161 if (hmbdc_unlikely(session != sessionDict_.end())) {
162 auto a = session->second->accept(header);
168 data_ += header->wireSize();
175 cur = nm_ring_next(ring, cur);
178 ring->head = ring->cur = cur;
184 auto tmp = packet->ipv4.ip.ip_sum;
185 packet->ipv4.ip.ip_sum = 0;
186 if (tmp != hmbdc::comm::eth::wrapsum(
187 hmbdc::comm::eth::checksum(&packet->ipv4.ip,
sizeof(packet->ipv4.ip), 0))) {
190 packet->ipv4.ip.ip_sum = tmp;
194 auto tmp = packet->ipv4.udp.check;
195 packet->ipv4.udp.check = 0;
197 auto udp = &packet->ipv4.udp;
198 if (tmp != hmbdc::comm::eth::wrapsum(
199 hmbdc::comm::eth::checksum(udp,
sizeof(*udp),
200 hmbdc::comm::eth::checksum(packet->ipv4.body, payloadWireSize,
201 hmbdc::comm::eth::checksum(&packet->ipv4.ip.ip_src, 2 *
sizeof(packet->ipv4.ip.ip_src),
202 IPPROTO_UDP + (u_int32_t)ntohs(udp->len)))))) {
205 #pragma GCC diagnostic pop 206 packet->ipv4.udp.check = tmp;
211 struct nm_desc *nmd_;
216 int pollWaitTimeMillisec_;
221 uint32_t senderEndpoint_;
224 TypeTagSet
const& subscriptions_;
225 Ep2SessionDict& sessionDict_;
229 template <
typename OutputBuffer,
typename Ep2SessionDict>
230 using NmRecvTransport = nmrecvtransport_detail::NmRecvTransport<OutputBuffer, Ep2SessionDict>;
T getExt(const path_type ¶m, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Definition: MonoLockFreeBuffer.hpp:16
class to hold an hmbdc configuration
Definition: Config.hpp:44
impl class
Definition: NmRecvTransport.hpp:25
Definition: Transport.hpp:13
void syncNetmap() HMBDC_RESTRICT
sync using busy wait or poll depending on config
Definition: NmRecvTransport.hpp:108
Definition: Message.hpp:263