net: add function to map packet's rss hash to a cpu

Provide a function that maps packet's rss hash to a cpu that should handle
it. This function is needed to find appropriate src port for outgoing
tcp/udp connection. Use this function to forward de-fragmented ip packet
to avoid one extra hop too.
This commit is contained in:
Gleb Natapov
2014-12-23 17:12:35 +02:00
committed by Avi Kivity
parent db50b480a3
commit 510171d083
3 changed files with 24 additions and 21 deletions

View File

@@ -155,7 +155,7 @@ ipv4::handle_received_packet(packet p, ethernet_address from) {
hash_data.push_back(hton(h.src_ip.ip));
hash_data.push_back(hton(h.dst_ip.ip));
l4->forward(hash_data, ip_data, l4_offset);
cpu_id = _netif->hash2qid(toeplitz_hash(rsskey, hash_data));
cpu_id = _netif->hash2cpu(toeplitz_hash(rsskey, hash_data));
}
// No need to forward if the dst cpu is the current cpu

View File

@@ -42,8 +42,8 @@ interface::register_l3(eth_protocol_num proto_num,
return l3_rx.packet_stream.listen(std::move(next));
}
unsigned interface::hash2qid(uint32_t hash) {
return _dev->hash2qid(hash);
unsigned interface::hash2cpu(uint32_t hash) {
return _dev->hash2cpu(hash);
}
void interface::forward(unsigned cpuid, packet p) {
@@ -66,12 +66,17 @@ future<> interface::dispatch_packet(packet p) {
auto i = _proto_map.find(ntoh(eh->eth_proto));
if (i != _proto_map.end()) {
l3_rx_stream& l3 = i->second;
auto fw = _dev->forward_dst(p, [&l3] (packet& p) {
forward_hash data;
if (l3.forward(data, p, sizeof(eth_hdr))) {
return toeplitz_hash(rsskey, data);
auto fw = _dev->forward_dst(engine.cpu_id(), [&p, &l3] () {
auto hwrss = p.rss_hash();
if (hwrss) {
return hwrss.value();
} else {
forward_hash data;
if (l3.forward(data, p, sizeof(eth_hdr))) {
return toeplitz_hash(rsskey, data);
}
return 0u;
}
return 0u;
});
if (fw != engine.cpu_id()) {
forward(fw, std::move(p));

View File

@@ -99,7 +99,7 @@ public:
std::function<future<> (packet p, ethernet_address from)> next,
std::function<bool (forward_hash&, packet&, size_t)> forward);
void forward(unsigned cpuid, packet p);
unsigned hash2qid(uint32_t hash);
unsigned hash2cpu(uint32_t hash);
friend class l3_protocol;
};
@@ -145,21 +145,19 @@ public:
engine.at_exit([dev = std::move(dev)] {});
}
template <typename Func>
unsigned forward_dst(packet& p, Func&& hashfn) {
auto& qp = local_queue();
unsigned forward_dst(unsigned src_cpuid, Func&& hashfn) {
auto& qp = queue_for_cpu(src_cpuid);
if (!qp.may_forward()) {
return engine.cpu_id();
return src_cpuid;
}
auto hwrss = p.rss_hash();
uint32_t hash;
if (hwrss) {
hash = hwrss.value();
} else {
hash = hashfn(p);
}
hash >>= _rss_table_bits;
auto hash = hashfn() >> _rss_table_bits;
auto idx = hash % (qp.proxies.size() + 1);
return idx ? qp.proxies[idx - 1] : engine.cpu_id();
return idx ? qp.proxies[idx - 1] : src_cpuid;
}
virtual unsigned hash2cpu(uint32_t hash) {
// there is an assumption here that qid == cpu_id which will
// not necessary be true in the future
return forward_dst(hash2qid(hash), [hash] { return hash; });
}
};