From 510171d083f8746d6b1949f038cdeba5bb31ea06 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 23 Dec 2014 17:12:35 +0200 Subject: [PATCH] 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. --- net/ip.cc | 2 +- net/net.cc | 19 ++++++++++++------- net/net.hh | 24 +++++++++++------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/net/ip.cc b/net/ip.cc index 103c5145af..5dafa286cc 100644 --- a/net/ip.cc +++ b/net/ip.cc @@ -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 diff --git a/net/net.cc b/net/net.cc index 3665e6ac59..8611502d74 100644 --- a/net/net.cc +++ b/net/net.cc @@ -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)); diff --git a/net/net.hh b/net/net.hh index 394fd8a8ba..a802d472dc 100644 --- a/net/net.hh +++ b/net/net.hh @@ -99,7 +99,7 @@ public: std::function (packet p, ethernet_address from)> next, std::function 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 - 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; }); } };