From 20d2725ed94deaa51c51e6d4dccc646da33b252b Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 10:08:53 +0200 Subject: [PATCH 01/11] core: shared_ptr add noexcept Add missing noexcepts. Those on constructors are needed to be able to store shared pointers in growable containers efficiently. --- core/shared_ptr.hh | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/core/shared_ptr.hh b/core/shared_ptr.hh index 8cb15d38e4..a4f9333df6 100644 --- a/core/shared_ptr.hh +++ b/core/shared_ptr.hh @@ -123,25 +123,25 @@ template class lw_shared_ptr { mutable shared_ptr_impl* _p = nullptr; private: - lw_shared_ptr(shared_ptr_impl* p) : _p(p) { + lw_shared_ptr(shared_ptr_impl* p) noexcept : _p(p) { if (_p) { ++_p->_count; } } template - static lw_shared_ptr make(A&&... a) { + static lw_shared_ptr make(A&&... a) noexcept { return lw_shared_ptr(new typename shared_ptr_impl::ctor(std::forward(a)...)); } public: using element_type = T; - lw_shared_ptr() = default; - lw_shared_ptr(const lw_shared_ptr& x) : _p(x._p) { + lw_shared_ptr() noexcept = default; + lw_shared_ptr(const lw_shared_ptr& x) noexcept : _p(x._p) { if (_p) { ++_p->_count; } } - lw_shared_ptr(lw_shared_ptr&& x) : _p(x._p) { + lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) { x._p = nullptr; } ~lw_shared_ptr() { @@ -149,31 +149,31 @@ public: delete _p->to_internal_object(); } } - lw_shared_ptr& operator=(const lw_shared_ptr& x) { + lw_shared_ptr& operator=(const lw_shared_ptr& x) noexcept { if (_p != x._p) { this->~lw_shared_ptr(); new (this) lw_shared_ptr(x); } return *this; } - lw_shared_ptr& operator=(lw_shared_ptr&& x) { + lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept { if (_p != x._p) { this->~lw_shared_ptr(); new (this) lw_shared_ptr(std::move(x)); } return *this; } - lw_shared_ptr& operator=(T&& x) { + lw_shared_ptr& operator=(T&& x) noexcept { this->~lw_shared_ptr(); new (this) lw_shared_ptr(make_lw_shared(std::move(x))); return *this; } - T& operator*() const { return *_p->to_value(); } - T* operator->() const { return _p->to_value(); } - T* get() const { return _p->to_value(); } + T& operator*() const noexcept { return *_p->to_value(); } + T* operator->() const noexcept { return _p->to_value(); } + T* get() const noexcept { return _p->to_value(); } - long int use_count() { + long int use_count() noexcept { if (_p) { return _p->_count; } else { @@ -181,15 +181,15 @@ public: } } - operator lw_shared_ptr() const { + operator lw_shared_ptr() const noexcept { return lw_shared_ptr(_p); } - explicit operator bool() const { + explicit operator bool() const noexcept { return _p; } - bool owned() const { + bool owned() const noexcept { return _p->_count == 1; } @@ -260,37 +260,37 @@ class shared_ptr { mutable shared_ptr_count_base* _b = nullptr; mutable T* _p = nullptr; private: - explicit shared_ptr(shared_ptr_count_for* b) : _b(b), _p(&b->data) { + explicit shared_ptr(shared_ptr_count_for* b) noexcept : _b(b), _p(&b->data) { ++_b->count; } - shared_ptr(shared_ptr_count_base* b, T* p) : _b(b), _p(p) { + shared_ptr(shared_ptr_count_base* b, T* p) noexcept : _b(b), _p(p) { // test _p, not _b, since dynamic_pointer_cast<>() can zero p but not b if (_p) { ++_b->count; } } - explicit shared_ptr(enable_shared_from_this* p) : _b(p), _p(static_cast(p)) { + explicit shared_ptr(enable_shared_from_this* p) noexcept : _b(p), _p(static_cast(p)) { if (_b) { ++_b->count; } } public: - shared_ptr() = default; - shared_ptr(const shared_ptr& x) + shared_ptr() noexcept = default; + shared_ptr(const shared_ptr& x) noexcept : _b(x._b) , _p(x._p) { if (_b) { ++_b->count; } } - shared_ptr(shared_ptr&& x) + shared_ptr(shared_ptr&& x) noexcept : _b(x._b) , _p(x._p) { x._b = nullptr; x._p = nullptr; } template ::value>> - shared_ptr(const shared_ptr& x) + shared_ptr(const shared_ptr& x) noexcept : _b(x._b) , _p(x._p) { if (_b) { @@ -298,7 +298,7 @@ public: } } template ::value>> - shared_ptr(shared_ptr&& x) + shared_ptr(shared_ptr&& x) noexcept : _b(x._b) , _p(x._p) { x._b = nullptr; @@ -309,14 +309,14 @@ public: delete _b; } } - shared_ptr& operator=(const shared_ptr& x) { + shared_ptr& operator=(const shared_ptr& x) noexcept { if (this != &x) { this->~shared_ptr(); new (this) shared_ptr(x); } return *this; } - shared_ptr& operator=(shared_ptr&& x) { + shared_ptr& operator=(shared_ptr&& x) noexcept { if (this != &x) { this->~shared_ptr(); new (this) shared_ptr(std::move(x)); @@ -324,7 +324,7 @@ public: return *this; } template ::value>> - shared_ptr& operator=(const shared_ptr& x) { + shared_ptr& operator=(const shared_ptr& x) noexcept { if (this != &x) { this->~shared_ptr(); new (this) shared_ptr(x); @@ -332,23 +332,23 @@ public: return *this; } template ::value>> - shared_ptr& operator=(shared_ptr&& x) { + shared_ptr& operator=(shared_ptr&& x) noexcept { if (this != &x) { this->~shared_ptr(); new (this) shared_ptr(std::move(x)); } return *this; } - explicit operator bool() const { + explicit operator bool() const noexcept { return _p; } - T& operator*() const{ + T& operator*() const noexcept { return *_p; } - T* operator->() const { + T* operator->() const noexcept { return _p; } - T* get() const { + T* get() const noexcept { return _p; } From f58926acd158d6f6e54e822677fc01ec9d4b9edd Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 10:16:09 +0200 Subject: [PATCH 02/11] core: fix circular_buffer::emplace_(back|front) to take universal references --- core/circular_buffer.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/circular_buffer.hh b/core/circular_buffer.hh index cd729d20fa..f19f259669 100644 --- a/core/circular_buffer.hh +++ b/core/circular_buffer.hh @@ -46,11 +46,11 @@ public: void push_front(const T& data); void push_front(T&& data); template - void emplace_front(A... args); + void emplace_front(A&&... args); void push_back(const T& data); void push_back(T&& data); template - void emplace_back(A... args); + void emplace_back(A&&... args); T& front(); T& back(); void pop_front(); @@ -187,7 +187,7 @@ template template inline void -circular_buffer::emplace_front(Args... args) { +circular_buffer::emplace_front(Args&&... args) { maybe_expand(); auto p = &_impl.storage[mask(_impl.begin - 1)]; _impl.construct(p, std::forward(args)...); @@ -218,7 +218,7 @@ template template inline void -circular_buffer::emplace_back(Args... args) { +circular_buffer::emplace_back(Args&&... args) { maybe_expand(); auto p = &_impl.storage[mask(_impl.end)]; _impl.construct(p, std::forward(args)...); From 6da00ab956fd7e4ea55b0f5f204630aaf2673390 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 10:19:36 +0200 Subject: [PATCH 03/11] net: continue network stack inversion into udp Poll udp channels from ipv4 instead of pushing packets from udp to ipv4 --- net/ip.hh | 3 ++- net/udp.cc | 27 ++++++++++++++++++++------- net/udp.hh | 4 ++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/net/ip.hh b/net/ip.hh index 5017fe1450..3d59548253 100644 --- a/net/ip.hh +++ b/net/ip.hh @@ -214,6 +214,7 @@ private: std::unordered_map> _channels; int _queue_size = default_queue_size; uint16_t _next_anonymous_port = min_anonymous_port; + circular_buffer, size_t>> _packetq; private: uint16_t next_port(uint16_t port); public: @@ -236,7 +237,7 @@ public: ipv4_udp(ipv4& inet); udp_channel make_channel(ipv4_addr addr); virtual void received(packet p, ipv4_address from, ipv4_address to) override; - void send(uint16_t src_port, ipv4_addr dst, packet &&p, l4send_completion completion); + void send(uint16_t src_port, ipv4_addr dst, packet &&p, lw_shared_ptr channel); bool forward(forward_hash& out_hash_data, packet& p, size_t off) override; void set_queue_size(int size) { _queue_size = size; } }; diff --git a/net/udp.cc b/net/udp.cc index f9cd0f6152..fb55b524fd 100644 --- a/net/udp.cc +++ b/net/udp.cc @@ -53,8 +53,6 @@ private: ipv4_udp::registration _reg; bool _closed; lw_shared_ptr _state; - // Limit number of data queued into send queue - lw_shared_ptr _user_queue_space; public: native_channel(ipv4_udp &proto, ipv4_udp::registration reg, lw_shared_ptr state) @@ -63,7 +61,6 @@ public: , _closed(false) , _state(state) { - _user_queue_space = make_lw_shared(212992); } virtual future receive() override { @@ -76,8 +73,8 @@ public: virtual future<> send(ipv4_addr dst, packet p) override { auto len = p.len(); - return _user_queue_space->wait(len).then([this, dst, p = std::move(p), len] () mutable { - _proto.send(_reg.port(), dst, std::move(p), l4send_completion(_user_queue_space, len)); + return _state->wait_for_send_buffer(len).then([this, dst, p = std::move(p), len] () mutable { + _proto.send(_reg.port(), dst, std::move(p), _state); }); } @@ -100,6 +97,19 @@ const int ipv4_udp::default_queue_size = 1024; ipv4_udp::ipv4_udp(ipv4& inet) : _inet(inet) { + _inet.register_packet_provider([this] { + std::experimental::optional l4p; + if (!_packetq.empty()) { + ipv4_traits::l4packet p; + lw_shared_ptr channel; + size_t len; + std::tie(p, channel, len) = std::move(_packetq.front()); + _packetq.pop_front(); + l4p = std::move(p); + channel->complete_send(len); + } + return l4p; + }); } bool ipv4_udp::forward(forward_hash& out_hash_data, packet& p, size_t off) @@ -124,8 +134,9 @@ void ipv4_udp::received(packet p, ipv4_address from, ipv4_address to) } } -void ipv4_udp::send(uint16_t src_port, ipv4_addr dst, packet &&p, l4send_completion completion) +void ipv4_udp::send(uint16_t src_port, ipv4_addr dst, packet &&p, lw_shared_ptr channel) { + size_t len = p.len(); auto src = _inet.host_address(); auto hdr = p.prepend_header(); hdr->src_port = src_port; @@ -148,7 +159,9 @@ void ipv4_udp::send(uint16_t src_port, ipv4_addr dst, packet &&p, l4send_complet oi.protocol = ip_protocol_num::udp; p.set_offload_info(oi); - _inet.send(dst, ip_protocol_num::udp, std::move(p), std::move(completion)); + _inet.get_l2_dst_address(dst).then([this, dst, p = std::move(p), channel = std::move(channel), len] (ethernet_address e_dst) mutable { + _packetq.emplace_back(std::make_tuple(ipv4_traits::l4packet{dst, std::move(p), e_dst, ip_protocol_num::udp}, std::move(channel), len)); + }); } uint16_t ipv4_udp::next_port(uint16_t port) { diff --git a/net/udp.hh b/net/udp.hh index ed22a45150..1eee00fd19 100644 --- a/net/udp.hh +++ b/net/udp.hh @@ -30,7 +30,11 @@ struct udp_hdr { struct udp_channel_state { queue _queue; + // Limit number of data queued into send queue + semaphore _user_queue_space = {212992}; udp_channel_state(size_t queue_size) : _queue(queue_size) {} + future<> wait_for_send_buffer(size_t len) { return _user_queue_space.wait(len); } + void complete_send(size_t len) { _user_queue_space.signal(len); } }; } From fda06cd81f62f67648364758a6d4cf207245311a Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 11:38:01 +0200 Subject: [PATCH 04/11] net: continue network stack inversion into icmp Poll icmp from ipv4 instead of pushing packets from icmp to ipv4. Also limit how much memory outstanding icmp packets can consume. --- net/ip.cc | 7 ++++++- net/ip.hh | 14 +++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/net/ip.cc b/net/ip.cc index c3a82e6671..d2a280abbd 100644 --- a/net/ip.cc +++ b/net/ip.cc @@ -442,7 +442,12 @@ void icmp::received(packet p, ipaddr from, ipaddr to) { checksummer csum; csum.sum(reinterpret_cast(hdr), p.len()); hdr->csum = csum.get(); - _inet.send(to, from, std::move(p)); + + if (_queue_space.try_wait(p.len())) { // drop packets that do not fit the queue + _inet.get_l2_dst_address(from).then([this, from, p = std::move(p)] (ethernet_address e_dst) mutable { + _packetq.emplace_back(ipv4_traits::l4packet{from, std::move(p), e_dst, ip_protocol_num::icmp}); + }); + } } } diff --git a/net/ip.hh b/net/ip.hh index 3d59548253..ad2a8305b3 100644 --- a/net/ip.hh +++ b/net/ip.hh @@ -185,10 +185,22 @@ class icmp { public: using ipaddr = ipv4_address; using inet_type = ipv4_l4; - explicit icmp(inet_type& inet) : _inet(inet) {} + explicit icmp(inet_type& inet) : _inet(inet) { + _inet.register_packet_provider([this] { + std::experimental::optional l4p; + if (!_packetq.empty()) { + l4p = std::move(_packetq.front()); + _packetq.pop_front(); + _queue_space.signal(l4p.value().p.len()); + } + return l4p; + }); + } void received(packet p, ipaddr from, ipaddr to); private: inet_type& _inet; + circular_buffer _packetq; + semaphore _queue_space = {212992}; }; class ipv4_icmp final : public ip_protocol { From d10575aea5c68999f672172377144e14e3069757 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 13:01:20 +0200 Subject: [PATCH 05/11] net: add tcp packet queue for non tcb packets Some packets generated by tcp do not belong to any connection. Currently such packets are pushed to ipv4 directly. This patch adds a packet queue for ipv4 to poll them from and limits amount of memory those packets can consume. --- net/tcp.hh | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/net/tcp.hh b/net/tcp.hh index 1f3c9512e6..e886642a16 100644 --- a/net/tcp.hh +++ b/net/tcp.hh @@ -317,6 +317,9 @@ private: std::default_random_engine _e; std::uniform_int_distribution _port_dist{41952, 65535}; circular_buffer, ethernet_address>> _poll_tcbs; + // queue for packets that do not belong to any tcb + circular_buffer _packetq; + semaphore _queue_space = {212992}; public: class connection { lw_shared_ptr _tcb; @@ -390,18 +393,25 @@ private: template tcp::tcp(inet_type& inet) : _inet(inet), _e(_rd()) { - _inet.register_packet_provider([this] { + _inet.register_packet_provider([this, tcb_polled = 0u] () mutable { std::experimental::optional l4p; auto c = _poll_tcbs.size(); - while (c--) { - lw_shared_ptr tcb; - ethernet_address dst; - std::tie(tcb, dst) = std::move(_poll_tcbs.front()); - _poll_tcbs.pop_front(); - l4p = tcb->get_packet(); - if (l4p) { - l4p.value().e_dst = dst; - break; + if (!_packetq.empty() && (!(tcb_polled % 128) || c == 0)) { + l4p = std::move(_packetq.front()); + _packetq.pop_front(); + _queue_space.signal(l4p.value().p.len()); + } else { + while (c--) { + tcb_polled++; + lw_shared_ptr tcb; + ethernet_address dst; + std::tie(tcb, dst) = std::move(_poll_tcbs.front()); + _poll_tcbs.pop_front(); + l4p = tcb->get_packet(); + if (l4p) { + l4p.value().e_dst = dst; + break; + } } } return l4p; @@ -496,7 +506,11 @@ void tcp::received(packet p, ipaddr from, ipaddr to) { template void tcp::send(ipaddr from, ipaddr to, packet p) { - _inet.send(from, to, std::move(p)); + if (_queue_space.try_wait(p.len())) { // drop packets that do not fit the queue + _inet.get_l2_dst_address(to).then([this, to, p = std::move(p)] (ethernet_address e_dst) mutable { + _packetq.emplace_back(ipv4_traits::l4packet{to, std::move(p), e_dst, ip_protocol_num::tcp}); + }); + } } template From 9c229d449a279703dc33a2c2dc9946bc0e2733c7 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 13:08:08 +0200 Subject: [PATCH 06/11] net: remove unused ipv4_l4::send() function After previous patches this one is no longer used. --- net/ip.hh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net/ip.hh b/net/ip.hh index ad2a8305b3..b613d1c1b2 100644 --- a/net/ip.hh +++ b/net/ip.hh @@ -99,7 +99,6 @@ public: ipv4& _inet; public: ipv4_l4(ipv4& inet) : _inet(inet) {} - void send(ipv4_address from, ipv4_address to, packet p); void register_packet_provider(ipv4_traits::packet_provider_type func); future get_l2_dst_address(ipv4_address to); }; @@ -386,12 +385,6 @@ public: future get_l2_dst_address(ipv4_address to); }; -template -inline -void ipv4_l4::send(ipv4_address from, ipv4_address to, packet p) { - _inet.send(/* from, */ to, ProtoNum, std::move(p)); -} - template inline void ipv4_l4::register_packet_provider(ipv4_traits::packet_provider_type func) { From 19ced3da4c1e657be8ba3d68d77b8753c243d301 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 14:08:20 +0200 Subject: [PATCH 07/11] net: fix dhcp to use use udp socket to send packets No need for ad-hoc code to create udp packets. --- net/arp.hh | 4 +++- net/dhcp.cc | 46 +++++++++------------------------------------ net/ip.cc | 3 +++ net/native-stack.cc | 8 +++++--- 4 files changed, 20 insertions(+), 41 deletions(-) diff --git a/net/arp.hh b/net/arp.hh index 676101337f..fed08f9454 100644 --- a/net/arp.hh +++ b/net/arp.hh @@ -101,7 +101,9 @@ private: void send(l2addr to, packet p); public: future<> send_query(const l3addr& paddr); - explicit arp_for(arp& a) : arp_for_protocol(a, L3::arp_protocol_type()) {} + explicit arp_for(arp& a) : arp_for_protocol(a, L3::arp_protocol_type()) { + _table[L3::broadcast_address()] = ethernet::broadcast_address(); + } future lookup(const l3addr& addr); void learn(l2addr l2, l3addr l3); void run(); diff --git a/net/dhcp.cc b/net/dhcp.cc index 5ceded52d9..255cf80669 100644 --- a/net/dhcp.cc +++ b/net/dhcp.cc @@ -155,14 +155,11 @@ public: } __attribute__((packed)); struct dhcp_packet_base { - ip_hdr ip; - udp_hdr udp; - dhcp_payload dhp; template auto adjust_endianness(Adjuster a) { - return a(ip, udp, dhp); + return a(dhp); } } __attribute__((packed)); @@ -255,7 +252,9 @@ public: impl(ipv4 & stack) : _stack(stack) - {} + { + _sock = _stack.get_udp().make_channel({0, client_port}); + } future<> process_packet(packet p, dhcp_payload* dhp, size_t opt_off) { _retry_timer.cancel(); @@ -350,30 +349,7 @@ public: } template - future<> build_ip_headers_and_send(T && pkt) { - auto size = sizeof(pkt); - auto & ip = pkt.ip; - - ip.ihl = sizeof(ip) / 4; - ip.ver = 4; - ip.dscp = 0; - ip.ecn = 0; - ip.len = uint16_t(size); - ip.id = 0; - ip.frag = 0; - ip.ttl = 64; - ip.csum = 0; - ip.ip_proto = uint8_t(ip_protocol_num::udp); - ip.dst_ip = ipv4_address(0xffffffff); - - auto & udp = pkt.udp; - - udp.src_port = client_port; - udp.dst_port = server_port; - udp.len = uint16_t(size - sizeof(ip)); - udp.cksum = 0; // TODO etc. - - + future<> send(T && pkt) { pkt.dhp.bootp.xid = _xid; auto ipf = _stack.netif(); auto mac = ipf->hw_address().mac; @@ -381,13 +357,8 @@ public: pkt = hton(pkt); - checksummer csum; - csum.sum(reinterpret_cast(&ip), sizeof(ip)); - ip.csum = csum.get(); + _sock.send({0xffffffff, server_port}, packet(reinterpret_cast(&pkt), sizeof(pkt))); - packet p(reinterpret_cast(&pkt), sizeof(pkt)); - - _stack.send_raw(ethernet::broadcast_address(), std::move(p)); return make_ready_future<>(); } @@ -411,7 +382,7 @@ public: _xid = xid_dist(e1); _state = state::DISCOVER; - return build_ip_headers_and_send(d); + return send(d); } future<> send_request(const lease & info) { @@ -430,7 +401,7 @@ public: log() << "sending request for " << info.ip << std::endl; _state = state::REQUEST; - return build_ip_headers_and_send(d); + return send(d); } private: @@ -439,6 +410,7 @@ private: timer<> _timer; timer<> _retry_timer; ipv4 & _stack; + udp_channel _sock; uint32_t _xid = 0; }; diff --git a/net/ip.cc b/net/ip.cc index d2a280abbd..e267ba2d30 100644 --- a/net/ip.cc +++ b/net/ip.cc @@ -28,6 +28,9 @@ ipv4::ipv4(interface* netif) : _netif(netif) , _global_arp(netif) , _arp(_global_arp) + , _host_address(0) + , _gw_address(0) + , _netmask(0) , _l3(netif, eth_protocol_num::ipv4, [this] { return get_packet(); }) , _rx_packets(_l3.receive([this] (packet p, ethernet_address ea) { return handle_received_packet(std::move(p), ea); }, diff --git a/net/native-stack.cc b/net/native-stack.cc index 6a8c26a964..a33933f68f 100644 --- a/net/native-stack.cc +++ b/net/native-stack.cc @@ -165,13 +165,15 @@ add_native_net_options_description(boost::program_options::options_description & native_network_stack::native_network_stack(boost::program_options::variables_map opts, std::shared_ptr dev) : _netif(std::move(dev)) , _inet(&_netif) { - _inet.set_host_address(ipv4_address(opts["host-ipv4-addr"].as())); - _inet.set_gw_address(ipv4_address(opts["gw-ipv4-addr"].as())); - _inet.set_netmask_address(ipv4_address(opts["netmask-ipv4-addr"].as())); _inet.get_udp().set_queue_size(opts["udpv4-queue-size"].as()); _dhcp = opts["host-ipv4-addr"].defaulted() && opts["gw-ipv4-addr"].defaulted() && opts["netmask-ipv4-addr"].defaulted() && opts["dhcp"].as(); + if (!_dhcp) { + _inet.set_host_address(ipv4_address(_dhcp ? 0 : opts["host-ipv4-addr"].as())); + _inet.set_gw_address(ipv4_address(opts["gw-ipv4-addr"].as())); + _inet.set_netmask_address(ipv4_address(opts["netmask-ipv4-addr"].as())); + } } server_socket From f11e1f31d693f2290352247bf9dd654b45e1748e Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 12 Jan 2015 15:52:22 +0200 Subject: [PATCH 08/11] net: cleanup ipv4 code that is no longer used --- net/ip.cc | 43 +++++++++++++++++-------------------------- net/ip.hh | 27 ++------------------------- 2 files changed, 19 insertions(+), 51 deletions(-) diff --git a/net/ip.cc b/net/ip.cc index e267ba2d30..e9f3094822 100644 --- a/net/ip.cc +++ b/net/ip.cc @@ -205,10 +205,10 @@ future ipv4::get_l2_dst_address(ipv4_address to) { return _arp.lookup(dst); } -void ipv4::send(ipv4_address to, ip_protocol_num proto_num, packet p, l4send_completion complete, std::experimental::optional e_dst) { +void ipv4::send(ipv4_address to, ip_protocol_num proto_num, packet p, ethernet_address e_dst) { auto needs_frag = this->needs_frag(p, proto_num, hw_features()); - auto send_pkt = [this, to, proto_num, needs_frag, complete = std::move(complete), e_dst = std::move(e_dst)] (packet& pkt, uint16_t remaining, uint16_t offset) mutable { + auto send_pkt = [this, to, proto_num, needs_frag, e_dst] (packet& pkt, uint16_t remaining, uint16_t offset) mutable { auto iph = pkt.prepend_header(); iph->ihl = sizeof(*iph) / 4; iph->ver = 4; @@ -241,14 +241,7 @@ void ipv4::send(ipv4_address to, ip_protocol_num proto_num, packet p, l4send_com iph->csum = csum.get(); } - auto&& send_complete = remaining ? l4send_completion() : std::move(complete); - if (!e_dst) { - get_l2_dst_address(to).then([this, pkt = std::move(pkt), send_complete = std::move(send_complete)] (ethernet_address e_dst) mutable { - send_raw(e_dst, std::move(pkt), std::move(send_complete)); - }); - } else { - send_raw(e_dst.value(), std::move(pkt), std::move(send_complete)); - } + _packetq.push_back(l3_protocol::l3packet{eth_protocol_num::ipv4, e_dst, std::move(pkt)}); }; if (needs_frag) { @@ -269,29 +262,27 @@ void ipv4::send(ipv4_address to, ip_protocol_num proto_num, packet p, l4send_com } } -void ipv4::send_raw(ethernet_address dst, packet p, l4send_completion complete) { - _packetq.push_back(ipv4packet{l3_protocol::l3packet{eth_protocol_num::ipv4, dst, std::move(p)}, std::move(complete)}); -} - std::experimental::optional ipv4::get_packet() { - for (size_t i = 0; i < _pkt_providers.size(); i++) { - auto l4p = _pkt_providers[_pkt_provider_idx++](); - if (_pkt_provider_idx == _pkt_providers.size()) { - _pkt_provider_idx = 0; - } - if (l4p) { - auto l4pv = std::move(l4p.value()); - send(l4pv.to, l4pv.proto_num, std::move(l4pv.p), l4send_completion(), l4pv.e_dst); - break; + // _packetq will be mostly empty here unless it hold remnants of previously + // fragmented packet + if (_packetq.empty()) { + for (size_t i = 0; i < _pkt_providers.size(); i++) { + auto l4p = _pkt_providers[_pkt_provider_idx++](); + if (_pkt_provider_idx == _pkt_providers.size()) { + _pkt_provider_idx = 0; + } + if (l4p) { + auto l4pv = std::move(l4p.value()); + send(l4pv.to, l4pv.proto_num, std::move(l4pv.p), l4pv.e_dst); + break; + } } } std::experimental::optional p; if (!_packetq.empty()) { - auto ipv4p = std::move(_packetq.front()); + p = std::move(_packetq.front()); _packetq.pop_front(); - p = std::move(ipv4p.l3packet); - ipv4p.complete(); } return p; } diff --git a/net/ip.hh b/net/ip.hh index b613d1c1b2..db86411deb 100644 --- a/net/ip.hh +++ b/net/ip.hh @@ -138,21 +138,6 @@ struct l4connid { } }; -class l4send_completion { - lw_shared_ptr _stream; - size_t _len = 0; -public: - l4send_completion() = default; - l4send_completion(lw_shared_ptr s, size_t l) : _stream(std::move(s)), _len(l) {} - l4send_completion(l4send_completion&) = delete; - l4send_completion(l4send_completion&& v) : _stream(std::move(v._stream)), _len(v._len) {} - void operator()() { - if (_len) { - _stream->signal(_len); - } - } -}; - class ipv4_tcp final : public ip_protocol { ipv4_l4 _inet_l4; std::unique_ptr> _tcp; @@ -328,13 +313,7 @@ private: static constexpr uint32_t _frag_high_thresh{4 * 1024 * 1024}; uint32_t _frag_mem{0}; timer _frag_timer; - struct ipv4packet { - l3_protocol::l3packet l3packet; - l4send_completion complete; - ipv4packet(ipv4packet&& v) noexcept : l3packet(std::move(v.l3packet)), complete(std::move(v.complete)) {} - ipv4packet(l3_protocol::l3packet&& p, l4send_completion&& c) : l3packet(std::move(p)), complete(std::move(c)) {} - }; - circular_buffer _packetq; + circular_buffer _packetq; unsigned _pkt_provider_idx = 0; private: future<> handle_received_packet(packet p, ethernet_address from); @@ -368,9 +347,7 @@ public: // But for now, a simple single raw pointer suffices void set_packet_filter(ip_packet_filter *); ip_packet_filter * packet_filter() const; - void send(ipv4_address to, ip_protocol_num proto_num, packet p, l4send_completion complete = l4send_completion(), - std::experimental::optional e_dst = std::experimental::optional()); - void send_raw(ethernet_address, packet, l4send_completion completion = l4send_completion()); + void send(ipv4_address to, ip_protocol_num proto_num, packet p, ethernet_address e_dst); tcp& get_tcp() { return *_tcp._tcp; } ipv4_udp& get_udp() { return _udp; } void register_l4(proto_type id, ip_protocol* handler); From 585f6452b92a3578ce77717eb589196912f3b432 Mon Sep 17 00:00:00 2001 From: Vlad Zolotarov Date: Mon, 12 Jan 2015 18:29:07 +0200 Subject: [PATCH 09/11] DPDK: Properly handle the case when RSS info is not available (e.g. VF case) - Adjust the asserts. - Add an assert in the place where we should not get if RSS info is not provided. Signed-off-by: Vlad Zolotarov Signed-off-by: Avi Kivity --- net/dpdk.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/dpdk.cc b/net/dpdk.cc index b1e7a4abc5..f50e4ff554 100644 --- a/net/dpdk.cc +++ b/net/dpdk.cc @@ -181,6 +181,7 @@ public: virtual future<> link_ready() { return _link_ready_promise.get_future(); } virtual std::unique_ptr init_local_queue(boost::program_options::variables_map opts, uint16_t qid) override; virtual unsigned hash2qid(uint32_t hash) override { + assert(_redir_table.size()); return _redir_table[hash & (_redir_table.size() - 1)]; } uint8_t port_idx() { return _port_idx; } @@ -301,17 +302,16 @@ int dpdk_device::init_port_start() // This comes from the ETH_RSS_RETA_NUM_ENTRIES being 128 _rss_table_bits = 7; #else - // Check that the returned RETA size is sane: - // greater than 0 and is a power of 2. - assert(_dev_info.reta_size && - (_dev_info.reta_size & (_dev_info.reta_size - 1)) == 0); - - // Set the RSS table to the correct size - _redir_table.resize(_dev_info.reta_size); - _rss_table_bits = std::lround(std::log2(_dev_info.reta_size)); - printf("Port %d: RSS table size is %d\n", - _port_idx, _dev_info.reta_size); + if (_dev_info.reta_size) { + // RETA size should be a power of 2 + assert((_dev_info.reta_size & (_dev_info.reta_size - 1)) == 0); + // Set the RSS table to the correct size + _redir_table.resize(_dev_info.reta_size); + _rss_table_bits = std::lround(std::log2(_dev_info.reta_size)); + printf("Port %d: RSS table size is %d\n", + _port_idx, _dev_info.reta_size); + } #endif } @@ -709,7 +709,8 @@ void dpdk_device::get_rss_table() #else void dpdk_device::get_rss_table() { - assert(_dev_info.reta_size); + if (_dev_info.reta_size == 0) + return; int i, reta_conf_size = std::max(1, _dev_info.reta_size / RTE_RETA_GROUP_SIZE); From 66a6a3b50e5963835feda82f708a8e5c178929f6 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Mon, 12 Jan 2015 14:56:52 -0200 Subject: [PATCH 10/11] add a header to file.hh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I am currently unable to use core/file.hh in a fresh include file. Type conflicts arise, which probably don't happen in other existing files because of existing includes that end up getting the environment all right beforehand. FAILED: g++ -MMD -MT build/release/db/db.o -MF build/release/db/db.o.d -std=gnu++1y -g -Wall -Werror -fvisibility=hidden -pthread -I. -DHAVE_XEN -DHAVE_HWLOC -DHAVE_NUMA -O2 -I build/release/gen -c -o build/release/db/db.o db/db.cc In file included from ./sstables.hh:4:0, from ./database.hh:22, from db/composites/composite.hh:27, from db/db.cc:8: ./core/file.hh:35:64: error: ‘iovec’ was not declared in this scope virtual future write_dma(uint64_t pos, std::vector iov) = 0; Adding to the include list of file.hh makes it includable (apparently) anywhere. Signed-off-by: Glauber Costa --- core/file.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/core/file.hh b/core/file.hh index fbcb0fa9c4..d24ffa9c57 100644 --- a/core/file.hh +++ b/core/file.hh @@ -11,6 +11,7 @@ #include #include #include +#include enum class directory_entry_type { block_device, From a52a3dd5cab3f41932d96fd2c13de7386801c0db Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 12 Jan 2015 20:25:21 +0200 Subject: [PATCH 11/11] sstring: add standard member typedefs Add standard member typedefs, so that standard algorithms looking for them using their standard names can find them and not spew error messages. --- core/sstring.hh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/sstring.hh b/core/sstring.hh index 8bfe1f4c4e..60cee6ebe5 100644 --- a/core/sstring.hh +++ b/core/sstring.hh @@ -17,12 +17,12 @@ #include #include "core/temporary_buffer.hh" -template +template class basic_sstring { union contents { struct external_type { char_type* str; - size_type size; + Size size; int8_t pad; } external; struct internal_type { @@ -44,6 +44,19 @@ class basic_sstring { char_type* str() { return is_internal() ? u.internal.str : u.external.str; } +public: + using value_type = char_type; + using traits_type = std::char_traits; + using allocator_type = std::allocator; + using reference = char_type&; + using const_reference = const char_type&; + using pointer = char_type*; + using const_pointer = const char_type*; + using iterator = char_type*; + using const_iterator = const char_type*; + // FIXME: add reverse_iterator and friend + using difference_type = ssize_t; // std::make_signed_t can be too small + using size_type = Size; public: struct initialized_later {};