From e9e1ed79779da4be2a6cf9d2229fc10496e54cc7 Mon Sep 17 00:00:00 2001 From: Takuya ASADA Date: Fri, 2 Jan 2015 04:41:11 +0900 Subject: [PATCH] Implement TCP client on native-stack --- net/native-stack.cc | 2 +- net/tcp-stack.hh | 4 ++++ net/tcp.cc | 6 ++++++ net/tcp.hh | 28 +++++++++++++++++++++++++++- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/net/native-stack.cc b/net/native-stack.cc index b67111f0df4..76b8cfcf827 100644 --- a/net/native-stack.cc +++ b/net/native-stack.cc @@ -185,7 +185,7 @@ native_network_stack::listen(socket_address sa, listen_options opts) { future native_network_stack::connect(socket_address sa) { assert(sa.as_posix_sockaddr().sa_family == AF_INET); - return make_ready_future(connected_socket(nullptr)); + return make_ready_future(tcpv4_connect(_inet.get_tcp(), sa)); } using namespace std::chrono_literals; diff --git a/net/tcp-stack.hh b/net/tcp-stack.hh index e6149d1a44e..66316e010a5 100644 --- a/net/tcp-stack.hh +++ b/net/tcp-stack.hh @@ -9,6 +9,7 @@ class listen_options; class server_socket; +class connected_socket; namespace net { @@ -19,6 +20,9 @@ class tcp; server_socket tcpv4_listen(tcp& tcpv4, uint16_t port, listen_options opts); +connected_socket +tcpv4_connect(tcp& tcpv4, socket_address sa); + } #endif diff --git a/net/tcp.cc b/net/tcp.cc index d41b998e87c..9b4a7e15e5a 100644 --- a/net/tcp.cc +++ b/net/tcp.cc @@ -127,5 +127,11 @@ tcpv4_listen(tcp& tcpv4, uint16_t port, listen_options opts) { tcpv4, port, opts)); } +connected_socket +tcpv4_connect(tcp& tcpv4, socket_address sa) { + return connected_socket(std::make_unique>>( + tcpv4.connect(sa))); +} + } diff --git a/net/tcp.hh b/net/tcp.hh index 749a205c433..00aaa8a0719 100644 --- a/net/tcp.hh +++ b/net/tcp.hh @@ -19,6 +19,7 @@ #include #include #include +#include #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include @@ -300,6 +301,9 @@ private: inet_type& _inet; std::unordered_map, connid_hash> _tcbs; std::unordered_map _listening; + std::random_device _rd; + std::default_random_engine _e; + std::uniform_int_distribution _port_dist{41952, 65535}; public: class connection { lw_shared_ptr _tcb; @@ -358,10 +362,11 @@ public: friend class tcp; }; public: - explicit tcp(inet_type& inet) : _inet(inet) {} + explicit tcp(inet_type& inet) : _inet(inet), _e(_rd()) {} void received(packet p, ipaddr from, ipaddr to); bool forward(forward_hash& out_hash_data, packet& p, size_t off); listener listen(uint16_t port, size_t queue_length = 100); + connection connect(socket_address sa); net::hw_features hw_features() { return _inet._inet.hw_features(); } private: void send(ipaddr from, ipaddr to, packet p); @@ -374,6 +379,27 @@ auto tcp::listen(uint16_t port, size_t queue_length) -> listener { return listener(*this, port, queue_length); } +template +auto tcp::connect(socket_address sa) -> connection { + uint16_t src_port; + connid id; + auto src_ip = _inet._inet.host_address(); + auto dst_ip = ipv4_address(sa); + auto dst_port = net::ntoh(sa.u.in.sin_port); + + do { + src_port = _port_dist(_e); + id = connid{src_ip, dst_ip, src_port, dst_port}; + } while (_inet._inet.netif()->hash2cpu(id.hash()) != engine.cpu_id() + || _tcbs.find(id) != _tcbs.end()); + + auto tcbp = make_lw_shared(*this, id); + _tcbs.insert({id, tcbp}); + tcbp->output(); + + return connection(tcbp); +} + template bool tcp::forward(forward_hash& out_hash_data, packet& p, size_t off) { auto th = p.get_header(off);