[PATCH 00/17] Initial seastar ipv6 support

3 views
Skip to first unread message

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:01 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Also at seastar-dev: calle/ipv6

* Adds ipv4 mirror types and/or embedding to address types in seastar.
* Changes posix stack to allow IPv6 addresses for bind/connect.
* Changes UDP interfaces to use socket_address (protocol agnostic address +
port) for connect/send/receive
* Changes UDP packets to return socket_address for packet src/dst
* Changes posix stack to allow ipv6 UDP.
* Changes RPC to allow ipv6 connectivity
* Adds local address query to server tcp/udp sockets

Includes minimal ipv6 test.
Tested on existing unit tests (seastar + scylla)

Calle Wilund (17):
Add packed ipv6 address
Add ipv6_address support to inet_address
Add ipv6_addr
Add ipv6 support to socket_address
Make socket_address default constructor ipv4 any
socket_address: Add != operator
Cleanup and de-inline some helper functions
inet_address: Add wildcard constructor from family
Posix-stack: Add ipv6 support for tcp
UDP: redefine address used as socket_address
RPC: move log to cc file
RCP: make rpc use socket_address to support ipv6
network_stack: Add ipv6 support query
udp_socket: Add local address accessor
native_stack: Make host_address const
server_socket: Add local address accessor
ipv6_test: Add small ipv6 test

configure.py | 3 +
test.py | 1 +
include/seastar/net/api.hh | 67 +++++------
include/seastar/net/inet_address.hh | 26 ++++-
include/seastar/net/ip.hh | 63 ++++++++++-
include/seastar/net/posix-stack.hh | 12 +-
include/seastar/net/socket_defs.hh | 71 ++++++++++--
include/seastar/net/stack.hh | 6 +-
include/seastar/net/tcp.hh | 10 ++
include/seastar/rpc/rpc.hh | 46 ++++----
src/net/native-stack-impl.hh | 7 ++
tests/unit/loopback_socket.hh | 4 +
src/net/inet_address.cc | 214 +++++++++++++++++++++++++++++++++---
src/net/ip.cc | 11 +-
src/net/native-stack.cc | 4 +-
src/net/net.cc | 13 ++-
src/net/posix-stack.cc | 93 +++++++++++-----
src/net/stack.cc | 69 ++++++++++--
src/net/tls.cc | 3 +
src/net/udp.cc | 13 ++-
src/rpc/rpc.cc | 25 ++++-
tests/unit/ipv6_test.cc | 105 ++++++++++++++++++
22 files changed, 701 insertions(+), 165 deletions(-)
create mode 100644 tests/unit/ipv6_test.cc

--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:02 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Corresponding to ipv4_address, packed to potentially allow embedding in
non-aligned wire structures.
---
include/seastar/net/ip.hh | 51 +++++++++++++++++++++++++++++++++++++-
src/net/inet_address.cc | 62 ++++++++++++++++++++++++++++++++++++++++++++++-
src/net/ip.cc | 9 -------
3 files changed, 111 insertions(+), 11 deletions(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 56cec7b3..f99e2ea8 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -105,7 +105,51 @@ struct ipv4_address {

static inline bool is_unspecified(ipv4_address addr) { return addr.ip == 0; }

-std::ostream& operator<<(std::ostream& os, ipv4_address a);
+std::ostream& operator<<(std::ostream& os, const ipv4_address& a);
+
+// IPv6
+struct ipv6_address {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ static_assert(alignof(ipv6_bytes) == 1);
+ static_assert(sizeof(ipv6_bytes) == 16);
+
+ ipv6_address();
+ explicit ipv6_address(const ::in6_addr&);
+ explicit ipv6_address(const ipv6_bytes&);
+ explicit ipv6_address(const std::string&);
+
+ // No need to use packed - we only store
+ // as byte array. If we want to read as
+ // uints or whatnot, we must copy
+ ipv6_bytes ip;
+
+ template <typename Adjuster>
+ auto adjust_endianness(Adjuster a) { return a(ip); }
+
+ bool operator==(const ipv6_address& y) const {
+ return bytes() == y.bytes();
+ }
+ bool operator!=(const ipv6_address& y) const {
+ return !(*this == y);
+ }
+
+ const ipv6_bytes& bytes() const {
+ return ip;
+ }
+
+ bool is_unspecified() const;
+
+ static ipv6_address read(const char*);
+ static ipv6_address consume(const char*& p);
+ void write(char* p) const;
+ void produce(char*& p) const;
+ static constexpr size_t size() {
+ return sizeof(ipv6_bytes);
+ }
+} __attribute__((packed));
+
+std::ostream& operator<<(std::ostream&, const ipv6_address&);

}

@@ -118,6 +162,11 @@ struct hash<seastar::net::ipv4_address> {
size_t operator()(seastar::net::ipv4_address a) const { return a.ip; }
};

+template <>
+struct hash<seastar::net::ipv6_address> {
+ size_t operator()(const seastar::net::ipv6_address&) const;
+};
+
}

namespace seastar {
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index d34f0f7c..89d27e80 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -21,7 +21,7 @@

#include <ostream>
#include <arpa/inet.h>
-
+#include <boost/functional/hash.hpp>
#include <seastar/net/inet_address.hh>
#include <seastar/net/socket_defs.hh>
#include <seastar/net/dns.hh>
@@ -112,6 +112,64 @@ const void * seastar::net::inet_address::data() const {
return &_in;
}

+seastar::net::ipv6_address::ipv6_address(const ::in6_addr& in) {
+ std::copy(std::begin(in.s6_addr), std::end(in.s6_addr), ip.begin());
+}
+
+seastar::net::ipv6_address::ipv6_address(const ipv6_bytes& in)
+ : ip(in)
+{}
+
+seastar::net::ipv6_address::ipv6_address()
+ : ipv6_address(::in6addr_any)
+{}
+
+seastar::net::ipv6_address::ipv6_address(const std::string& addr) {
+ if (!::inet_pton(AF_INET6, addr.c_str(), ip.data())) {
+ throw std::runtime_error(format("Wrong format for IPv6 address {}. Please ensure it's in colon-hex format",
+ addr));
+ }
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::read(const char* s) {
+ auto* b = reinterpret_cast<const uint8_t *>(s);
+ ipv6_address in;
+ std::copy(b, b + ipv6_address::size(), in.ip.begin());
+ return in;
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::consume(const char*& p) {
+ auto res = read(p);
+ p += size();
+ return res;
+}
+
+void seastar::net::ipv6_address::write(char* p) const {
+ std::copy(ip.begin(), ip.end(), p);
+}
+
+void seastar::net::ipv6_address::produce(char*& p) const {
+ write(p);
+ p += size();
+}
+
+bool seastar::net::ipv6_address::is_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const ipv4_address& a) {
+ auto ip = a.ip;
+ return fmt_print(os, "{:d}.{:d}.{:d}.{:d}",
+ (ip >> 24) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 0) & 0xff);
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const ipv6_address& a) {
+ char buffer[64];
+ return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer, sizeof(buffer));
+}

std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];
@@ -138,5 +196,7 @@ std::ostream& operator<<(std::ostream& os, const socket_address& a) {
;
}

+size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {
+ return boost::hash_range(a.ip.begin(), a.ip.end());
}

diff --git a/src/net/ip.cc b/src/net/ip.cc
index 106e5d27..3b872d4b 100644
--- a/src/net/ip.cc
+++ b/src/net/ip.cc
@@ -31,15 +31,6 @@ namespace seastar {

namespace net {

-std::ostream& operator<<(std::ostream& os, ipv4_address a) {
- auto ip = a.ip;
- return fmt_print(os, "{:d}.{:d}.{:d}.{:d}",
- (ip >> 24) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 8) & 0xff,
- (ip >> 0) & 0xff);
-}
-
constexpr std::chrono::seconds ipv4::_frag_timeout;
constexpr uint32_t ipv4::_frag_low_thresh;
constexpr uint32_t ipv4::_frag_high_thresh;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:03 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/inet_address.hh | 25 ++++++++++++++++---
src/net/inet_address.cc | 49 +++++++++++++++++++++++++++----------
2 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/include/seastar/net/inet_address.hh b/include/seastar/net/inet_address.hh
index 849820fd..0d8d3c0e 100644
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
@@ -34,6 +34,7 @@ namespace seastar {
namespace net {

struct ipv4_address;
+struct ipv6_address;

class unknown_host : public std::invalid_argument {
public:
@@ -42,7 +43,7 @@ class unknown_host : public std::invalid_argument {

class inet_address {
public:
- enum class family {
+ enum class family : sa_family_t {
INET = AF_INET, INET6 = AF_INET6
};
private:
@@ -64,9 +65,11 @@ class inet_address {
inet_address(const inet_address&) = default;

inet_address(const ipv4_address&);
+ inet_address(const ipv6_address&);

// throws iff ipv6
ipv4_address as_ipv4_address() const;
+ ipv6_address as_ipv6_address() const;

inet_address& operator=(const inet_address&) = default;
bool operator==(const inet_address&) const;
@@ -75,11 +78,20 @@ class inet_address {
return _in_family;
}

+ bool is_ipv6() const {
+ return _in_family == family::INET6;
+ }
+ bool is_ipv4() const {
+ return _in_family == family::INET;
+ }
+
size_t size() const;
const void * data() const;

- operator const ::in_addr&() const;
- operator const ::in6_addr&() const;
+ operator ::in_addr() const;
+ operator ::in6_addr() const;
+
+ operator ipv6_address() const;

future<sstring> hostname() const;
future<std::vector<sstring>> aliases() const;
@@ -95,3 +107,10 @@ std::ostream& operator<<(std::ostream&, const inet_address::family&);

}
}
+
+namespace std {
+template<>
+struct hash<seastar::net::inet_address> {
+ size_t operator()(const seastar::net::inet_address&) const;
+};
+}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 89d27e80..70badba2 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -27,10 +27,8 @@
#include <seastar/net/dns.hh>
#include <seastar/net/ip.hh>

-namespace seastar {
-
seastar::net::inet_address::inet_address()
- : inet_address(::in_addr{ 0, })
+ : inet_address(::in6_addr{ 0, })
{}

seastar::net::inet_address::inet_address(::in_addr i)
@@ -61,11 +59,13 @@ seastar::net::inet_address::inet_address(const ipv4_address& in)
{}

seastar::net::ipv4_address seastar::net::inet_address::as_ipv4_address() const {
- if (_in_family != family::INET) {
- // TODO: ipv4-compatible ipv6
- throw std::invalid_argument("Not an IPv4 address");
- }
- return ipv4_address(ntoh(_in.s_addr));
+ in_addr in = *this;
+ return ipv4_address(ntoh(in.s_addr));
+}
+
+seastar::net::ipv6_address seastar::net::inet_address::as_ipv6_address() const {
+ in6_addr in6 = *this;
+ return ipv6_address{in6};
}

bool seastar::net::inet_address::operator==(const inet_address& o) const {
@@ -83,20 +83,32 @@ bool seastar::net::inet_address::operator==(const inet_address& o) const {
}
}

-seastar::net::inet_address::operator const ::in_addr&() const {
+seastar::net::inet_address::operator ::in_addr() const {
if (_in_family != family::INET) {
- throw std::invalid_argument("Not an ipv4 address");
+ if (IN6_IS_ADDR_V4MAPPED(&_in6)) {
+ ::in_addr in;
+ in.s_addr = _in6.s6_addr32[3];
+ return in;
+ }
+ throw std::invalid_argument("Not an IPv4 address");
}
return _in;
}

-seastar::net::inet_address::operator const ::in6_addr&() const {
- if (_in_family != family::INET6) {
- throw std::invalid_argument("Not an ipv6 address");
+seastar::net::inet_address::operator ::in6_addr() const {
+ if (_in_family == family::INET) {
+ in6_addr in6 = IN6ADDR_ANY_INIT;
+ in6.s6_addr32[2] = ::htonl(0xffff);
+ in6.s6_addr32[3] = _in.s_addr;
+ return in6;
}
return _in6;
}

+seastar::net::inet_address::operator seastar::net::ipv6_address() const {
+ return as_ipv6_address();
+}
+
size_t seastar::net::inet_address::size() const {
switch (_in_family) {
case family::INET:
@@ -196,6 +208,17 @@ std::ostream& operator<<(std::ostream& os, const socket_address& a) {
;
}

+size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::inet_address& a) const {
+ switch (a.in_family()) {
+ case seastar::net::inet_address::family::INET:
+ return std::hash<seastar::net::ipv4_address>()(a.as_ipv4_address());
+ case seastar::net::inet_address::family::INET6:
+ return std::hash<seastar::net::ipv6_address>()(a.as_ipv6_address());
+ default:
+ return 0;
+ }
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {
return boost::hash_range(a.ip.begin(), a.ip.end());
}
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:04 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 45 +++++++++++++++++++++++++++------
src/net/inet_address.cc | 51 +++++++++++++++++++++++++++++++++++---
src/net/net.cc | 13 +++++++---
src/net/stack.cc | 40 +++++++++++++++++++++++++-----
4 files changed, 127 insertions(+), 22 deletions(-)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index e9327729..5a3a0f0d 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -28,7 +28,12 @@

namespace seastar {

+namespace net {
+class inet_address;
+}
+
struct ipv4_addr;
+struct ipv6_addr;

class socket_address {
public:
@@ -36,16 +41,29 @@ class socket_address {
::sockaddr_storage sas;
::sockaddr sa;
::sockaddr_in in;
+ ::sockaddr_in6 in6;
} u;
- socket_address(sockaddr_in sa) {
+ socket_address(const sockaddr_in& sa) {
u.in = sa;
}
+ socket_address(const sockaddr_in6& sa) {
+ u.in6 = sa;
+ }
socket_address(ipv4_addr);
+ socket_address(const ipv6_addr&);
+ socket_address(const net::inet_address&, uint16_t p = 0);
socket_address() = default;
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
+ ::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
const ::sockaddr& as_posix_sockaddr() const { return u.sa; }
const ::sockaddr_in& as_posix_sockaddr_in() const { return u.in; }
+ const ::sockaddr_in6& as_posix_sockaddr_in6() const { return u.in6; }
+
+ socket_address(uint32_t, uint16_t p = 0);
+
+ net::inet_address addr() const;
+ ::in_port_t port() const;

bool operator==(const socket_address&) const;
};
@@ -58,10 +76,6 @@ enum class transport {
};


-namespace net {
-class inet_address;
-}
-
struct ipv4_addr {
uint32_t ip;
uint16_t port;
@@ -72,10 +86,14 @@ struct ipv4_addr {
ipv4_addr(const std::string &addr);
ipv4_addr(const std::string &addr, uint16_t port);
ipv4_addr(const net::inet_address&, uint16_t);
+ ipv4_addr(const socket_address &);
+ ipv4_addr(const ::in_addr&, uint16_t = 0);

- ipv4_addr(const socket_address &sa) {
- ip = net::ntoh(sa.u.in.sin_addr.s_addr);
- port = net::ntoh(sa.u.in.sin_port);
+ bool is_ip_unspecified() const {
+ return ip == 0;
+ }
+ bool is_port_unspecified() const {
+ return port == 0;
}
};

@@ -92,6 +110,7 @@ struct ipv6_addr {
ipv6_addr(const net::inet_address&, uint16_t = 0);
ipv6_addr(const ::in6_addr&, uint16_t = 0);
ipv6_addr(const ::sockaddr_in6&);
+ ipv6_addr(const socket_address&);

bool is_ip_unspecified() const;
bool is_port_unspecified() const {
@@ -99,4 +118,14 @@ struct ipv6_addr {
}
};

+std::ostream& operator<<(std::ostream&, const ipv4_addr&);
+std::ostream& operator<<(std::ostream&, const ipv6_addr&);
+
+}
+
+namespace std {
+template<>
+struct hash<seastar::socket_address> {
+ size_t operator()(const seastar::socket_address&) const;
+};
}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 7946b2d5..133ac04d 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -229,6 +229,25 @@ bool seastar::ipv6_addr::is_ip_unspecified() const {
return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
}

+seastar::socket_address::socket_address(const net::inet_address& a, uint16_t p)
+ : socket_address(a.is_ipv6() ? socket_address(ipv6_addr(a, p)) : socket_address(ipv4_addr(a, p)))
+{}
+
+seastar::net::inet_address seastar::socket_address::addr() const {
+ switch (as_posix_sockaddr().sa_family) {
+ case AF_INET:
+ return net::inet_address(as_posix_sockaddr_in().sin_addr);
+ case AF_INET6:
+ return net::inet_address(as_posix_sockaddr_in6().sin6_addr);
+ default:
+ return net::inet_address();
+ }
+}
+
+::in_port_t seastar::socket_address::port() const {
+ return net::ntoh(u.in.sin_port);
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];
return os << inet_ntop(int(addr.in_family()), addr.data(), buffer, sizeof(buffer));
@@ -248,10 +267,28 @@ std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address::fam
return os;
}

-std::ostream& operator<<(std::ostream& os, const socket_address& a) {
- return os << seastar::net::inet_address(a.as_posix_sockaddr_in().sin_addr)
- << ":" << ntohs(a.u.in.sin_port)
- ;
+std::ostream& seastar::operator<<(std::ostream& os, const socket_address& a) {
+ auto addr = a.addr();
+ // CMH. maybe skip brackets for ipv4-mapped
+ auto bracket = addr.in_family() == seastar::net::inet_address::family::INET6;
+
+ if (bracket) {
+ os << '[';
+ }
+ os << addr;
+ if (bracket) {
+ os << ']';
+ }
+
+ return os << ':' << ntohs(a.u.in.sin_port);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv4_addr& a) {
+ return os << seastar::socket_address(a);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv6_addr& a) {
+ return os << seastar::socket_address(a);
}

size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::inet_address& a) const {
@@ -265,6 +302,12 @@ size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::ine
}
}

+size_t std::hash<seastar::socket_address>::operator()(const seastar::socket_address& a) const {
+ auto h = std::hash<seastar::net::inet_address>()(a.addr());
+ boost::hash_combine(h, a.as_posix_sockaddr_in().sin_port);
+ return h;
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {
return boost::hash_range(a.ip.begin(), a.ip.end());
}
diff --git a/src/net/net.cc b/src/net/net.cc
index c32e669e..30fb3833 100644
--- a/src/net/net.cc
+++ b/src/net/net.cc
@@ -49,10 +49,15 @@ ipv4_addr::ipv4_addr(const std::string &addr) {
ipv4_addr::ipv4_addr(const std::string &addr, uint16_t port_) : ip(boost::asio::ip::address_v4::from_string(addr).to_ulong()), port(port_) {}

ipv4_addr::ipv4_addr(const net::inet_address& a, uint16_t port)
- : ipv4_addr([&a] {
- ::in_addr in = a;
- return net::ntoh(in.s_addr);
-}(), port)
+ : ipv4_addr(::in_addr(a), port)
+{}
+
+ipv4_addr::ipv4_addr(const socket_address &sa)
+ : ipv4_addr(sa.addr(), sa.port())
+{}
+
+ipv4_addr::ipv4_addr(const ::in_addr& in, uint16_t p)
+ : ip(net::ntoh(in.s_addr)), port(p)
{}

namespace net {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 0193d579..fa172c61 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -151,15 +151,43 @@ void server_socket::abort_accept() {
}

socket_address::socket_address(ipv4_addr addr)
- : socket_address(make_ipv4_address(addr))
-{}
+{
+ u.in.sin_family = AF_INET;
+ u.in.sin_port = htons(addr.port);
+ u.in.sin_addr.s_addr = htonl(addr.ip);
+}

+socket_address::socket_address(const ipv6_addr& addr)
+{
+ u.in6.sin6_family = AF_INET6;
+ u.in6.sin6_port = htons(addr.port);
+ std::copy(addr.ip.begin(), addr.ip.end(), u.in6.sin6_addr.s6_addr);
+}
+
+socket_address::socket_address(uint32_t ipv4, uint16_t p)
+ : socket_address(make_ipv4_address(ipv4, p))
+{}

bool socket_address::operator==(const socket_address& a) const {
- // TODO: handle ipv6
- return std::tie(u.in.sin_family, u.in.sin_port, u.in.sin_addr.s_addr)
- == std::tie(a.u.in.sin_family, a.u.in.sin_port,
- a.u.in.sin_addr.s_addr);
+ if (u.sa.sa_family != a.u.sa.sa_family) {
+ return false;
+ }
+ if (u.in.sin_port != a.u.in.sin_port) {
+ return false;
+ }
+ switch (u.sa.sa_family) {
+ case AF_INET:
+ return u.in.sin_addr.s_addr == a.u.in.sin_addr.s_addr;
+ case AF_INET6:
+ break;
+ default:
+ return false;
+ }
+
+ auto& in1 = as_posix_sockaddr_in6();
+ auto& in2 = a.as_posix_sockaddr_in6();
+
+ return IN6_ARE_ADDR_EQUAL(&in1, &in2);
}

}
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:04 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Like ipv4_addr, i.e. wraps address + port. Badly named, but akin to a
host endian sock_addr_in6.
---
include/seastar/net/ip.hh | 3 +++
include/seastar/net/socket_defs.hh | 21 ++++++++++++++++-
src/net/inet_address.cc | 46 ++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index f99e2ea8..1f506cdd 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -44,6 +44,8 @@

namespace seastar {

+struct ipv6_addr;
+
namespace net {

class ipv4;
@@ -118,6 +120,7 @@ struct ipv6_address {
explicit ipv6_address(const ::in6_addr&);
explicit ipv6_address(const ipv6_bytes&);
explicit ipv6_address(const std::string&);
+ ipv6_address(const ipv6_addr& addr);

// No need to use packed - we only store
// as byte array. If we want to read as
diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index 055db041..e9327729 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -21,6 +21,7 @@
#pragma once

#include <iosfwd>
+#include <array>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <seastar/net/byteorder.hh>
@@ -76,8 +77,26 @@ struct ipv4_addr {
ip = net::ntoh(sa.u.in.sin_addr.s_addr);
port = net::ntoh(sa.u.in.sin_port);
}
+};
+
+struct ipv6_addr {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ ipv6_bytes ip;
+ uint16_t port;
+
+ ipv6_addr(const ipv6_bytes&, uint16_t port = 0);
+ ipv6_addr(uint16_t port = 0);
+ ipv6_addr(const std::string&);
+ ipv6_addr(const std::string&, uint16_t port);
+ ipv6_addr(const net::inet_address&, uint16_t = 0);
+ ipv6_addr(const ::in6_addr&, uint16_t = 0);
+ ipv6_addr(const ::sockaddr_in6&);

- ipv4_addr(socket_address &&sa) : ipv4_addr(sa) {}
+ bool is_ip_unspecified() const;
+ bool is_port_unspecified() const {
+ return port == 0;
+ }
};

}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 70badba2..7946b2d5 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -132,6 +132,10 @@ seastar::net::ipv6_address::ipv6_address(const ipv6_bytes& in)
: ip(in)
{}

+seastar::net::ipv6_address::ipv6_address(const ipv6_addr& addr)
+ : ipv6_address(addr.ip)
+{}
+
seastar::net::ipv6_address::ipv6_address()
: ipv6_address(::in6addr_any)
{}
@@ -183,6 +187,48 @@ std::ostream& seastar::net::operator<<(std::ostream& os, const ipv6_address& a)
return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer, sizeof(buffer));
}

+seastar::ipv6_addr::ipv6_addr(const ipv6_bytes& b, uint16_t p)
+ : ip(b), port(p)
+{}
+
+seastar::ipv6_addr::ipv6_addr(uint16_t p)
+ : ipv6_addr(net::inet_address(), p)
+{}
+
+seastar::ipv6_addr::ipv6_addr(const ::in6_addr& in6, uint16_t p)
+ : ipv6_addr(net::ipv6_address(in6).bytes(), p)
+{}
+
+seastar::ipv6_addr::ipv6_addr(const std::string& s)
+ : ipv6_addr([&] {
+ auto lc = s.find_last_of(']');
+ auto cp = s.find_first_of(':', lc);
+ auto port = cp != std::string::npos ? std::stoul(s.substr(cp + 1)) : 0;
+ auto ss = lc != std::string::npos ? s.substr(1, lc - 1) : s;
+ return ipv6_addr(net::ipv6_address(ss).bytes(), uint16_t(port));
+ }())
+{}
+
+seastar::ipv6_addr::ipv6_addr(const std::string& s, uint16_t p)
+ : ipv6_addr(net::ipv6_address(s).bytes(), p)
+{}
+
+seastar::ipv6_addr::ipv6_addr(const net::inet_address& i, uint16_t p)
+ : ipv6_addr(i.as_ipv6_address().bytes(), p)
+{}
+
+seastar::ipv6_addr::ipv6_addr(const ::sockaddr_in6& s)
+ : ipv6_addr(s.sin6_addr, net::ntoh(s.sin6_port))
+{}
+
+seastar::ipv6_addr::ipv6_addr(const socket_address& s)
+ : ipv6_addr(s.as_posix_sockaddr_in6())
+{}
+
+bool seastar::ipv6_addr::is_ip_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];
return os << inet_ntop(int(addr.in_family()), addr.data(), buffer, sizeof(buffer));
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:05 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 2 +-
src/net/stack.cc | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index 5a3a0f0d..e905219f 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -52,7 +52,7 @@ class socket_address {
socket_address(ipv4_addr);
socket_address(const ipv6_addr&);
socket_address(const net::inet_address&, uint16_t p = 0);
- socket_address() = default;
+ socket_address();
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
diff --git a/src/net/stack.cc b/src/net/stack.cc
index fa172c61..34e8e9cd 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -150,6 +150,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

+socket_address::socket_address()
+ : socket_address(ipv4_addr())
+{}
+
socket_address::socket_address(ipv4_addr addr)
{
u.in.sin_family = AF_INET;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:06 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 3 +++
1 file changed, 3 insertions(+)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index e905219f..5683f632 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -66,6 +66,9 @@ class socket_address {
::in_port_t port() const;

bool operator==(const socket_address&) const;
+ bool operator!=(const socket_address& a) const {
+ return !(*this == a);
+ }
};

std::ostream& operator<<(std::ostream&, const socket_address&);
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:08 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Corresponding to AF_INET/AF_INET6 + zeroed addr
---
include/seastar/net/inet_address.hh | 1 +
src/net/inet_address.cc | 6 ++++++
2 files changed, 7 insertions(+)

diff --git a/include/seastar/net/inet_address.hh b/include/seastar/net/inet_address.hh
index 0d8d3c0e..79798601 100644
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
@@ -56,6 +56,7 @@ class inet_address {
public:

inet_address();
+ inet_address(family);
inet_address(::in_addr i);
inet_address(::in6_addr i);
// NOTE: does _not_ resolve the address. Only parses
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 133ac04d..83d4e74d 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -31,6 +31,12 @@ seastar::net::inet_address::inet_address()
: inet_address(::in6_addr{ 0, })
{}

+seastar::net::inet_address::inet_address(family f)
+ : _in_family(f)
+{
+ memset(&_in6, 0, sizeof(_in6));
+}
+
seastar::net::inet_address::inet_address(::in_addr i)
: _in_family(family::INET), _in(i) {
}
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:08 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/api.hh | 38 ++++++++++----------------------------
1 file changed, 10 insertions(+), 28 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index a4d9fd34..b9c03915 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -36,42 +36,24 @@

namespace seastar {

-static inline
-bool is_ip_unspecified(ipv4_addr &addr) {
- return addr.ip == 0;
-}
-
-static inline
-bool is_port_unspecified(ipv4_addr &addr) {
- return addr.port == 0;
+inline
+bool is_ip_unspecified(const ipv4_addr& addr) {
+ return addr.is_ip_unspecified();
}

-static inline
-std::ostream& operator<<(std::ostream &os, ipv4_addr addr) {
- fmt_print(os, "{:d}.{:d}.{:d}.{:d}",
- (addr.ip >> 24) & 0xff,
- (addr.ip >> 16) & 0xff,
- (addr.ip >> 8) & 0xff,
- (addr.ip) & 0xff);
- return os << ":" << addr.port;
+inline
+bool is_port_unspecified(const ipv4_addr& addr) {
+ return addr.is_port_unspecified();
}

-static inline
-socket_address make_ipv4_address(ipv4_addr addr) {
- socket_address sa;
- sa.u.in.sin_family = AF_INET;
- sa.u.in.sin_port = htons(addr.port);
- sa.u.in.sin_addr.s_addr = htonl(addr.ip);
- return sa;
+inline
+socket_address make_ipv4_address(const ipv4_addr& addr) {
+ return socket_address(addr);
}

inline
socket_address make_ipv4_address(uint32_t ip, uint16_t port) {
- socket_address sa;
- sa.u.in.sin_family = AF_INET;
- sa.u.in.sin_port = htons(port);
- sa.u.in.sin_addr.s_addr = htonl(ip);
- return sa;
+ return make_ipv4_address(ipv4_addr(ip, port));
}

namespace net {
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:09 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/api.hh | 4 +---
include/seastar/net/posix-stack.hh | 4 ++--
src/net/posix-stack.cc | 14 +++++++-------
src/net/stack.cc | 9 +++++++++
4 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index b9c03915..d5f25004 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -275,9 +275,7 @@ class network_stack {
virtual ~network_stack() {}
virtual server_socket listen(socket_address sa, listen_options opts) = 0;
// FIXME: local parameter assumes ipv4 for now, fix when adding other AF
- future<connected_socket> connect(socket_address sa, socket_address local = socket_address(::sockaddr_in{AF_INET, INADDR_ANY, {0}}), transport proto = transport::TCP) {
- return socket().connect(sa, local, proto);
- }
+ future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
virtual future<> initialize() {
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index bb203044..41677006 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -129,8 +129,8 @@ class posix_ap_server_socket_impl : public server_socket_impl {
socket_address addr;
connection(pollable_fd xfd, socket_address xaddr) : fd(std::move(xfd)), addr(xaddr) {}
};
- static thread_local std::unordered_map<::sockaddr_in, promise<connected_socket, socket_address>> sockets;
- static thread_local std::unordered_multimap<::sockaddr_in, connection> conn_q;
+ static thread_local std::unordered_map<socket_address, promise<connected_socket, socket_address>> sockets;
+ static thread_local std::unordered_multimap<socket_address, connection> conn_q;
socket_address _sa;
public:
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index a9225943..92010b5b 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -234,7 +234,7 @@ posix_server_socket_impl<Transport>::abort_accept() {

template <transport Transport>
future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>::accept() {
- auto conni = conn_q.find(_sa.as_posix_sockaddr_in());
+ auto conni = conn_q.find(_sa);
if (conni != conn_q.end()) {
connection c = std::move(conni->second);
conn_q.erase(conni);
@@ -247,7 +247,7 @@ future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>:
}
} else {
try {
- auto i = sockets.emplace(std::piecewise_construct, std::make_tuple(_sa.as_posix_sockaddr_in()), std::make_tuple());
+ auto i = sockets.emplace(std::piecewise_construct, std::make_tuple(_sa), std::make_tuple());
assert(i.second);
return i.first->second.get_future();
} catch (...) {
@@ -259,7 +259,7 @@ future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>:
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::abort_accept() {
- conn_q.erase(_sa.as_posix_sockaddr_in());
+ conn_q.erase(_sa);
auto i = sockets.find(_sa.as_posix_sockaddr_in());
if (i != sockets.end()) {
i->second.set_exception(std::system_error(ECONNABORTED, std::system_category()));
@@ -287,7 +287,7 @@ posix_reuseport_server_socket_impl<Transport>::abort_accept() {
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
- auto i = sockets.find(sa.as_posix_sockaddr_in());
+ auto i = sockets.find(sa);
if (i != sockets.end()) {
try {
std::unique_ptr<connected_socket_impl> csi(new posix_connected_socket_impl<Transport>(make_lw_shared(std::move(fd)), std::move(cth)));
@@ -297,7 +297,7 @@ posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa,
}
sockets.erase(i);
} else {
- conn_q.emplace(std::piecewise_construct, std::make_tuple(sa.as_posix_sockaddr_in()), std::make_tuple(std::move(fd), std::move(addr)));
+ conn_q.emplace(std::piecewise_construct, std::make_tuple(sa), std::make_tuple(std::move(fd), std::move(addr)));
}
}

@@ -371,9 +371,9 @@ ::seastar::socket posix_network_stack::socket() {
}

template<transport Transport>
-thread_local std::unordered_map<::sockaddr_in, promise<connected_socket, socket_address>> posix_ap_server_socket_impl<Transport>::sockets;
+thread_local std::unordered_map<socket_address, promise<connected_socket, socket_address>> posix_ap_server_socket_impl<Transport>::sockets;
template<transport Transport>
-thread_local std::unordered_multimap<::sockaddr_in, typename posix_ap_server_socket_impl<Transport>::connection> posix_ap_server_socket_impl<Transport>::conn_q;
+thread_local std::unordered_multimap<socket_address, typename posix_ap_server_socket_impl<Transport>::connection> posix_ap_server_socket_impl<Transport>::conn_q;

server_socket
posix_ap_network_stack::listen(socket_address sa, listen_options opt) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 34e8e9cd..1eb3faa9 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -20,6 +20,7 @@
*/

#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>
#include <seastar/core/reactor.hh>

namespace seastar {
@@ -194,4 +195,12 @@ bool socket_address::operator==(const socket_address& a) const {
return IN6_ARE_ADDR_EQUAL(&in1, &in2);
}

+future<connected_socket>
+network_stack::connect(socket_address sa, socket_address local, transport proto) {
+ if (local == socket_address()) {
+ local = net::inet_address(sa.addr().in_family());
+ }
+ return socket().connect(sa, local, proto);
+}
+
}
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:10 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
UPD interface/packets are hardcoded to use ipv4_addr as dest/source
addresses. Redefine this to instead use socket_address, which contains
all the multiplexing needed to handle optional ipv6.

Since socket_address also translated transparently to ipv4_addr,
existing programs should continue to work as before (more or less).

Adds actual ipv6 support to posix stack UDP.
---
include/seastar/net/api.hh | 14 +++++-----
include/seastar/net/posix-stack.hh | 2 +-
include/seastar/net/stack.hh | 4 +--
src/net/native-stack.cc | 4 +--
src/net/posix-stack.cc | 52 +++++++++++++++++++++++---------------
src/net/stack.cc | 8 +++---
src/net/udp.cc | 8 +++---
7 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index d5f25004..9d6831de 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -84,8 +84,8 @@ class get_impl;
class udp_datagram_impl {
public:
virtual ~udp_datagram_impl() {};
- virtual ipv4_addr get_src() = 0;
- virtual ipv4_addr get_dst() = 0;
+ virtual socket_address get_src() = 0;
+ virtual socket_address get_dst() = 0;
virtual uint16_t get_dst_port() = 0;
virtual packet& get_data() = 0;
};
@@ -95,8 +95,8 @@ class udp_datagram final {
std::unique_ptr<udp_datagram_impl> _impl;
public:
udp_datagram(std::unique_ptr<udp_datagram_impl>&& impl) : _impl(std::move(impl)) {};
- ipv4_addr get_src() { return _impl->get_src(); }
- ipv4_addr get_dst() { return _impl->get_dst(); }
+ socket_address get_src() { return _impl->get_src(); }
+ socket_address get_dst() { return _impl->get_dst(); }
uint16_t get_dst_port() { return _impl->get_dst_port(); }
packet& get_data() { return _impl->get_data(); }
};
@@ -113,8 +113,8 @@ class udp_channel {
udp_channel& operator=(udp_channel&&);

future<udp_datagram> receive();
- future<> send(ipv4_addr dst, const char* msg);
- future<> send(ipv4_addr dst, packet p);
+ future<> send(const socket_address& dst, const char* msg);
+ future<> send(const socket_address& dst, packet p);
bool is_closed() const;
void close();
};
@@ -277,7 +277,7 @@ class network_stack {
// FIXME: local parameter assumes ipv4 for now, fix when adding other AF
future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
+ virtual net::udp_channel make_udp_channel(const socket_address& = {}) = 0;
virtual future<> initialize() {
return make_ready_future();
}
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 41677006..dbd77556 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -174,7 +174,7 @@ class posix_network_stack : public network_stack {
explicit posix_network_stack(boost::program_options::variables_map opts) : _reuseport(engine().posix_reuseport_available()) {}
virtual server_socket listen(socket_address sa, listen_options opts) override;
virtual ::seastar::socket socket() override;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual net::udp_channel make_udp_channel(const socket_address&) override;
static future<std::unique_ptr<network_stack>> create(boost::program_options::variables_map opts) {
return make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new posix_network_stack(opts)));
}
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index 11b65f70..a7aeac68 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -61,8 +61,8 @@ class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
virtual future<udp_datagram> receive() = 0;
- virtual future<> send(ipv4_addr dst, const char* msg) = 0;
- virtual future<> send(ipv4_addr dst, packet p) = 0;
+ virtual future<> send(const socket_address& dst, const char* msg) = 0;
+ virtual future<> send(const socket_address& dst, packet p) = 0;
virtual bool is_closed() const = 0;
virtual void close() = 0;
};
diff --git a/src/net/native-stack.cc b/src/net/native-stack.cc
index 678e96e4..5812a19f 100644
--- a/src/net/native-stack.cc
+++ b/src/net/native-stack.cc
@@ -151,7 +151,7 @@ class native_network_stack : public network_stack {
explicit native_network_stack(boost::program_options::variables_map opts, std::shared_ptr<device> dev);
virtual server_socket listen(socket_address sa, listen_options opt) override;
virtual ::seastar::socket socket() override;
- virtual udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual udp_channel make_udp_channel(const socket_address& addr) override;
virtual future<> initialize() override;
static future<std::unique_ptr<network_stack>> create(boost::program_options::variables_map opts) {
if (engine().cpu_id() == 0) {
@@ -169,7 +169,7 @@ class native_network_stack : public network_stack {
thread_local promise<std::unique_ptr<network_stack>> native_network_stack::ready_promise;

udp_channel
-native_network_stack::make_udp_channel(ipv4_addr addr) {
+native_network_stack::make_udp_channel(const socket_address& addr) {
return _inet.get_udp().make_channel(addr);
}

diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index 92010b5b..4ba51f0a 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -392,7 +392,10 @@ posix_ap_network_stack::listen(socket_address sa, listen_options opt) {

struct cmsg_with_pktinfo {
struct cmsghdrcmh;
- struct in_pktinfo pktinfo;
+ union {
+ struct in_pktinfo pktinfo;
+ struct in6_pktinfo pkt6info;
+ };
};

class posix_udp_channel : public udp_channel_impl {
@@ -434,8 +437,8 @@ class posix_udp_channel : public udp_channel_impl {
_hdr.msg_namelen = sizeof(_dst.u.sas);
}

- void prepare(ipv4_addr dst, packet p) {
- _dst = make_ipv4_address(dst);
+ void prepare(const socket_address& dst, packet p) {
+ _dst = dst;
_p = std::move(p);
_iovecs = to_iovec(_p);
_hdr.msg_iov = _iovecs.data();
@@ -443,27 +446,27 @@ class posix_udp_channel : public udp_channel_impl {
}
};
std::unique_ptr<pollable_fd> _fd;
- ipv4_addr _address;
+ socket_address _address;
recv_ctx _recv;
send_ctx _send;
bool _closed;
public:
- posix_udp_channel(ipv4_addr bind_address)
+ posix_udp_channel(const socket_address& bind_address)
: _closed(false) {
- auto sa = make_ipv4_address(bind_address);
+ auto sa = bind_address;
file_desc fd = file_desc::socket(sa.u.sa.sa_family, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
fd.setsockopt(SOL_IP, IP_PKTINFO, true);
if (engine().posix_reuseport_available()) {
fd.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1);
}
fd.bind(sa.u.sa, sizeof(sa.u.sas));
- _address = ipv4_addr(fd.get_address());
+ _address = fd.get_address();
_fd = std::make_unique<pollable_fd>(std::move(fd));
}
virtual ~posix_udp_channel() { if (!_closed) close(); };
virtual future<udp_datagram> receive() override;
- virtual future<> send(ipv4_addr dst, const char *msg);
- virtual future<> send(ipv4_addr dst, packet p);
+ virtual future<> send(const socket_address& dst, const char *msg) override;
+ virtual future<> send(const socket_address& dst, packet p) override;
virtual void close() override {
_closed = true;
_fd->abort_reader(std::make_exception_ptr(std::system_error(EPIPE, std::system_category())));
@@ -473,13 +476,13 @@ class posix_udp_channel : public udp_channel_impl {
virtual bool is_closed() const override { return _closed; }
};

-future<> posix_udp_channel::send(ipv4_addr dst, const char *message) {
+future<> posix_udp_channel::send(const socket_address& dst, const char *message) {
auto len = strlen(message);
- return _fd->sendto(make_ipv4_address(dst), message, len)
+ return _fd->sendto(dst, message, len)
.then([len] (size_t size) { assert(size == len); });
}

-future<> posix_udp_channel::send(ipv4_addr dst, packet p) {
+future<> posix_udp_channel::send(const socket_address& dst, packet p) {
auto len = p.len();
_send.prepare(dst, std::move(p));
return _fd->sendmsg(&_send._hdr)
@@ -487,20 +490,20 @@ future<> posix_udp_channel::send(ipv4_addr dst, packet p) {
}

udp_channel
-posix_network_stack::make_udp_channel(ipv4_addr addr) {
+posix_network_stack::make_udp_channel(const socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

class posix_datagram : public udp_datagram_impl {
private:
- ipv4_addr _src;
- ipv4_addr _dst;
+ socket_address _src;
+ socket_address _dst;
packet _p;
public:
- posix_datagram(ipv4_addr src, ipv4_addr dst, packet p) : _src(src), _dst(dst), _p(std::move(p)) {}
- virtual ipv4_addr get_src() override { return _src; }
- virtual ipv4_addr get_dst() override { return _dst; }
- virtual uint16_t get_dst_port() override { return _dst.port; }
+ posix_datagram(const socket_address& src, const socket_address& dst, packet p) : _src(src), _dst(dst), _p(std::move(p)) {}
+ virtual socket_address get_src() override { return _src; }
+ virtual socket_address get_dst() override { return _dst; }
+ virtual uint16_t get_dst_port() override { return _dst.port(); }
virtual packet& get_data() override { return _p; }
};

@@ -508,7 +511,16 @@ future<udp_datagram>
posix_udp_channel::receive() {
_recv.prepare();
return _fd->recvmsg(&_recv._hdr).then([this] (size_t size) {
- auto dst = ipv4_addr(_recv._cmsg.pktinfo.ipi_addr.s_addr, _address.port);
+ socket_address dst;
+ for (auto* cmsg = CMSG_FIRSTHDR(&_recv._hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&_recv._hdr, cmsg)) {
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
+ dst = ipv4_addr(reinterpret_cast<const in_pktinfo*>(CMSG_DATA(cmsg))->ipi_addr, _address.port());
+ break;
+ } else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+ dst = ipv6_addr(reinterpret_cast<const in6_pktinfo*>(CMSG_DATA(cmsg))->ipi6_addr, _address.port());
+ break;
+ }
+ }
return make_ready_future<udp_datagram>(udp_datagram(std::make_unique<posix_datagram>(
_recv._src_addr, dst, packet(fragment{_recv._buffer, size}, make_deleter([buf = _recv._buffer] { delete[] buf; })))));
}).handle_exception([p = _recv._buffer](auto ep) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 1eb3faa9..3426c7fc 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -41,12 +41,12 @@ future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}

-future<> net::udp_channel::send(ipv4_addr dst, const char* msg) {
- return _impl->send(std::move(dst), msg);
+future<> net::udp_channel::send(const socket_address& dst, const char* msg) {
+ return _impl->send(dst, msg);
}

-future<> net::udp_channel::send(ipv4_addr dst, packet p) {
- return _impl->send(std::move(dst), std::move(p));
+future<> net::udp_channel::send(const socket_address& dst, packet p) {
+ return _impl->send(dst, std::move(p));
}

bool net::udp_channel::is_closed() const {
diff --git a/src/net/udp.cc b/src/net/udp.cc
index 9b679a4f..97dabfe2 100644
--- a/src/net/udp.cc
+++ b/src/net/udp.cc
@@ -50,11 +50,11 @@ class native_datagram : public udp_datagram_impl {
_dst = to_ipv4_addr(dst, h.dst_port);
}

- virtual ipv4_addr get_src() override {
+ virtual socket_address get_src() override {
return _src;
};

- virtual ipv4_addr get_dst() override {
+ virtual socket_address get_dst() override {
return _dst;
};

@@ -93,11 +93,11 @@ class native_channel : public udp_channel_impl {
return _state->_queue.pop_eventually();
}

- virtual future<> send(ipv4_addr dst, const char* msg) override {
+ virtual future<> send(const socket_address& dst, const char* msg) override {
return send(dst, packet::from_static_data(msg, strlen(msg)));
}

- virtual future<> send(ipv4_addr dst, packet p) override {
+ virtual future<> send(const socket_address& dst, packet p) override {
auto len = p.len();
return _state->wait_for_send_buffer(len).then([this, dst, p = std::move(p), len] () mutable {
p = packet(std::move(p), make_deleter([s = _state, len] { s->complete_send(len); }));
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:11 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/rpc/rpc.hh | 12 +++---------
src/rpc/rpc.cc | 13 +++++++++++++
2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
index 4a3c8ada..55dff5bd 100644
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -169,17 +169,11 @@ class logger {
_logger = std::move(l);
}

- void operator()(const client_info& info, id_type msg_id, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
- }
+ void operator()(const client_info& info, id_type msg_id, const sstring& str) const;

- void operator()(const client_info& info, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
- }
+ void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
- }
+ void operator()(ipv4_addr addr, const sstring& str) const;
};

class connection {
diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
index 4e37af83..8d70452d 100644
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -4,6 +4,19 @@
namespace seastar {

namespace rpc {
+
+ void logger::operator()(const client_info& info, id_type msg_id, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
+ }
+
+ void logger::operator()(const client_info& info, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ }
+
+ void logger::operator()(ipv4_addr addr, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
+ }
+
no_wait_type no_wait;

constexpr size_t snd_buf::chunk_size;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:12 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/rpc/rpc.hh | 36 ++++++++++++++++++------------------
src/rpc/rpc.cc | 20 ++++++++++----------
2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
index 55dff5bd..b59f58cd 100644
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -173,7 +173,7 @@ class logger {

void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const;
+ void operator()(const socket_address& addr, const sstring& str) const;
};

class connection {
@@ -287,7 +287,7 @@ class connection {
}
xshard_connection_ptr get_stream(connection_id id) const;
void register_stream(connection_id id, xshard_connection_ptr c);
- virtual ipv4_addr peer_address() const = 0;
+ virtual socket_address peer_address() const = 0;

const logger& get_logger() const {
return _logger;
@@ -360,7 +360,7 @@ class client : public rpc::connection, public weakly_referencable<client> {
};
private:
std::unordered_map<id_type, std::unique_ptr<reply_handler_base>> _outstanding;
- ipv4_addr _server_addr;
+ socket_address _server_addr;
client_options _options;
compat::optional<shared_promise<>> _client_negotiated = shared_promise<>();
weak_ptr<client> _parent; // for stream clients
@@ -386,8 +386,8 @@ class client : public rpc::connection, public weakly_referencable<client> {
* @param addr the remote address identifying this client
* @param local the local address of this client
*/
- client(const logger& l, void* s, ipv4_addr addr, ipv4_addr local = ipv4_addr());
- client(const logger& l, void* s, client_options options, ipv4_addr addr, ipv4_addr local = ipv4_addr());
+ client(const logger& l, void* s, const socket_address& addr, const socket_address& local = {});
+ client(const logger& l, void* s, client_options options, const socket_address& addr, const socket_address& local = {});

/**
* Create client object which will attempt to connect to the remote address using the
@@ -397,8 +397,8 @@ class client : public rpc::connection, public weakly_referencable<client> {
* @param local the local address of this client
* @param socket the socket object use to connect to the remote address
*/
- client(const logger& l, void* s, socket socket, ipv4_addr addr, ipv4_addr local = ipv4_addr());
- client(const logger& l, void* s, client_options options, socket socket, ipv4_addr addr, ipv4_addr local = ipv4_addr());
+ client(const logger& l, void* s, socket socket, const socket_address& addr, const socket_address& local = {});
+ client(const logger& l, void* s, client_options options, socket socket, const socket_address& addr, const socket_address& local = {});

stats get_stats() const;
stats& get_stats_internal() {
@@ -410,7 +410,7 @@ class client : public rpc::connection, public weakly_referencable<client> {
future<> stop();
void abort_all_streams();
void deregister_this_stream();
- ipv4_addr peer_address() const override {
+ socket_address peer_address() const override {
return _server_addr;
}
future<> await_connection() {
@@ -484,8 +484,8 @@ class server {
stats& get_stats_internal() {
return _stats;
}
- ipv4_addr peer_address() const override {
- return ipv4_addr(_info.addr);
+ socket_address peer_address() const override {
+ return _info.addr;
}
// Resources will be released when this goes out of scope
future<resource_permit> wait_for_resources(size_t memory_consumed, compat::optional<rpc_clock_type::time_point> timeout) {
@@ -518,8 +518,8 @@ class server {
uint64_t _next_client_id = 1;

public:
- server(protocol_base* proto, ipv4_addr addr, resource_limits memory_limit = resource_limits());
- server(protocol_base* proto, server_options opts, ipv4_addr addr, resource_limits memory_limit = resource_limits());
+ server(protocol_base* proto, const socket_address& addr, resource_limits memory_limit = resource_limits());
+ server(protocol_base* proto, server_options opts, const socket_address& addr, resource_limits memory_limit = resource_limits());
server(protocol_base* proto, server_socket, resource_limits memory_limit = resource_limits(), server_options opts = server_options{});
server(protocol_base* proto, server_options opts, server_socket, resource_limits memory_limit = resource_limits());
void accept();
@@ -560,9 +560,9 @@ class protocol : public protocol_base {
public:
class server : public rpc::server {
public:
- server(protocol& proto, ipv4_addr addr, resource_limits memory_limit = resource_limits()) :
+ server(protocol& proto, const socket_address& addr, resource_limits memory_limit = resource_limits()) :
rpc::server(&proto, addr, memory_limit) {}
- server(protocol& proto, server_options opts, ipv4_addr addr, resource_limits memory_limit = resource_limits()) :
+ server(protocol& proto, server_options opts, const socket_address& addr, resource_limits memory_limit = resource_limits()) :
rpc::server(&proto, opts, addr, memory_limit) {}
server(protocol& proto, server_socket socket, resource_limits memory_limit = resource_limits(), server_options opts = server_options{}) :
rpc::server(&proto, std::move(socket), memory_limit) {}
@@ -577,9 +577,9 @@ class protocol : public protocol_base {
* @param addr the remote address identifying this client
* @param local the local address of this client
*/
- client(protocol& p, ipv4_addr addr, ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, const socket_address& addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, addr, local) {}
- client(protocol& p, client_options options, ipv4_addr addr, ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, client_options options, const socket_address& addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, options, addr, local) {}

/**
@@ -590,9 +590,9 @@ class protocol : public protocol_base {
* @param local the local address of this client
* @param socket the socket object use to connect to the remote address
*/
- client(protocol& p, socket socket, ipv4_addr addr, ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, socket socket, const socket_address& addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, std::move(socket), addr, local) {}
- client(protocol& p, client_options options, socket socket, ipv4_addr addr, ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, client_options options, socket socket, const socket_address& addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, options, std::move(socket), addr, local) {}
};

diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
index 8d70452d..0ac1571a 100644
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -6,15 +6,15 @@ namespace seastar {
namespace rpc {

void logger::operator()(const client_info& info, id_type msg_id, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
+ log(format("client {} msg_id {}: {}", info.addr, msg_id, str));
}

void logger::operator()(const client_info& info, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ (*this)(info.addr, str);
}

- void logger::operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
+ void logger::operator()(const socket_address& addr, const sstring& str) const {
+ log(format("client {}: {}", addr, str));
}

no_wait_type no_wait;
@@ -621,7 +621,7 @@ namespace rpc {
}
}

- client::client(const logger& l, void* s, client_options ops, socket socket, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, client_options ops, socket socket, const socket_address& addr, const socket_address& local)
: rpc::connection(l, s), _socket(std::move(socket)), _server_addr(addr), _options(ops) {
_socket.connect(addr, local).then([this, ops = std::move(ops)] (connected_socket fd) {
fd.set_nodelay(ops.tcp_nodelay);
@@ -711,15 +711,15 @@ namespace rpc {
});
}

- client::client(const logger& l, void* s, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, const socket_address& addr, const socket_address& local)
: client(l, s, client_options{}, engine().net().socket(), addr, local)
{}

- client::client(const logger& l, void* s, client_options options, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, client_options options, const socket_address& addr, const socket_address& local)
: client(l, s, options, engine().net().socket(), addr, local)
{}

- client::client(const logger& l, void* s, socket socket, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, socket socket, const socket_address& addr, const socket_address& local)
: client(l, s, client_options{}, std::move(socket), addr, local)
{}

@@ -944,11 +944,11 @@ namespace rpc {

thread_local std::unordered_map<streaming_domain_type, server*> server::_servers;

- server::server(protocol_base* proto, ipv4_addr addr, resource_limits limits)
+ server::server(protocol_base* proto, const socket_address& addr, resource_limits limits)
: server(proto, engine().listen(addr, listen_options{true}), limits, server_options{})
{}

- server::server(protocol_base* proto, server_options opts, ipv4_addr addr, resource_limits limits)
+ server::server(protocol_base* proto, server_options opts, const socket_address& addr, resource_limits limits)
: server(proto, engine().listen(addr, listen_options{true, opts.load_balancing_algorithm}), limits, opts)
{}

--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:13 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
While not 100% correct, since this should really be per interface etc,
it still allows us some info (hint hint tests)
---
include/seastar/net/api.hh | 6 ++++++
include/seastar/net/posix-stack.hh | 1 +
src/net/posix-stack.cc | 14 ++++++++++++++
3 files changed, 21 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 9d6831de..419b7c21 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -282,6 +282,12 @@ class network_stack {
return make_ready_future();
}
virtual bool has_per_core_namespace() = 0;
+ // NOTE: this is not a correct query approach.
+ // This question should be per NIC, but we have no such
+ // abstraction, so for now this is "stack-wide"
+ virtual bool supports_ipv6() const {
+ return false;
+ }
};

}
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index dbd77556..1e6c06b9 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -179,6 +179,7 @@ class posix_network_stack : public network_stack {
return make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new posix_network_stack(opts)));
}
virtual bool has_per_core_namespace() override { return _reuseport; };
+ bool supports_ipv6() const override;
};

class posix_ap_network_stack : public posix_network_stack {
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index 4ba51f0a..e170fe5d 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -494,6 +494,20 @@ posix_network_stack::make_udp_channel(const socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

+bool
+posix_network_stack::supports_ipv6() const {
+ static bool has_ipv6 = [] {
+ try {
+ posix_udp_channel c(ipv6_addr{});
+ c.close();
+ return true;
+ } catch (...) {}
+ return false;
+ }();
+
+ return has_ipv6;
+}
+
class posix_datagram : public udp_datagram_impl {
private:
socket_address _src;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:15 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/ip.hh | 2 +-
src/net/ip.cc | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index ed1ab9bc..53c2b96b 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -444,7 +444,7 @@ class ipv4 {
public:
explicit ipv4(interface* netif);
void set_host_address(ipv4_address ip);
- ipv4_address host_address();
+ ipv4_address host_address() const;
void set_gw_address(ipv4_address ip);
ipv4_address gw_address() const;
void set_netmask_address(ipv4_address ip);
diff --git a/src/net/ip.cc b/src/net/ip.cc
index 3b872d4b..1e493a32 100644
--- a/src/net/ip.cc
+++ b/src/net/ip.cc
@@ -315,7 +315,7 @@ void ipv4::set_host_address(ipv4_address ip) {
_arp.set_self_addr(ip);
}

-ipv4_address ipv4::host_address() {
+ipv4_address ipv4::host_address() const {
return _host_address;
}

--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:15 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
It is somewhat useful to be able to query which address/port one got
when binding to wildcard.
---
include/seastar/net/api.hh | 2 ++
include/seastar/net/ip.hh | 4 ++++
include/seastar/net/stack.hh | 1 +
src/net/posix-stack.cc | 3 +++
src/net/stack.cc | 4 ++++
src/net/udp.cc | 5 +++++
6 files changed, 19 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 419b7c21..7527ff0f 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -112,6 +112,8 @@ class udp_channel {
udp_channel(udp_channel&&);
udp_channel& operator=(udp_channel&&);

+ socket_address local_address() const;
+
future<udp_datagram> receive();
future<> send(const socket_address& dst, const char* msg);
future<> send(const socket_address& dst, packet p);
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 1f506cdd..ed1ab9bc 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -338,6 +338,10 @@ class ipv4_udp : public ip_protocol {
void send(uint16_t src_port, ipv4_addr dst, packet &&p);
bool forward(forward_hash& out_hash_data, packet& p, size_t off) override;
void set_queue_size(int size) { _queue_size = size; }
+
+ const ipv4& inet() const {
+ return _inet;
+ }
};

struct ip_hdr;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index a7aeac68..62958454 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -60,6 +60,7 @@ class server_socket_impl {
class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
+ virtual socket_address local_address() const = 0;
virtual future<udp_datagram> receive() = 0;
virtual future<> send(const socket_address& dst, const char* msg) = 0;
virtual future<> send(const socket_address& dst, packet p) = 0;
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index e170fe5d..ce24fb94 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -474,6 +474,9 @@ class posix_udp_channel : public udp_channel_impl {
_fd.reset();
}
virtual bool is_closed() const override { return _closed; }
+ socket_address local_address() const override {
+ return _address;
+ }
};

future<> posix_udp_channel::send(const socket_address& dst, const char *message) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 3426c7fc..d021365c 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -37,6 +37,10 @@ net::udp_channel::~udp_channel()
net::udp_channel::udp_channel(udp_channel&&) = default;
net::udp_channel& net::udp_channel::operator=(udp_channel&&) = default;

+socket_address net::udp_channel::local_address() const {
+ return _impl->local_address();
+}
+
future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}
diff --git a/src/net/udp.cc b/src/net/udp.cc
index 97dabfe2..ac4b6abd 100644
--- a/src/net/udp.cc
+++ b/src/net/udp.cc
@@ -21,6 +21,7 @@

#include <seastar/net/ip.hh>
#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -89,6 +90,10 @@ class native_channel : public udp_channel_impl {
close();
}

+ socket_address local_address() const override {
+ return socket_address(_proto.inet().host_address(), _reg.port());
+ }
+
virtual future<udp_datagram> receive() override {
return _state->_queue.pop_eventually();
}
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:17 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Because sometimes it helps to query which address/port a wildcard bind
bound to.
---
include/seastar/net/api.hh | 3 +++
include/seastar/net/ip.hh | 3 +++
include/seastar/net/posix-stack.hh | 5 +++++
include/seastar/net/stack.hh | 1 +
include/seastar/net/tcp.hh | 10 ++++++++++
src/net/native-stack-impl.hh | 7 +++++++
tests/unit/loopback_socket.hh | 4 ++++
src/net/posix-stack.cc | 10 ++++++++++
src/net/stack.cc | 4 ++++
src/net/tls.cc | 3 +++
10 files changed, 50 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 7527ff0f..3bbc7e0c 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -263,6 +263,9 @@ class server_socket {
/// Current and future \ref accept() calls will terminate immediately
/// with an error.
void abort_accept();
+
+ /// Local bound address
+ socket_address local_address() const;
};
/// @}

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 53c2b96b..fbf6a8e2 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -203,6 +203,9 @@ class ipv4_l4 {
ipv4_l4(ipv4& inet) : _inet(inet) {}
void register_packet_provider(ipv4_traits::packet_provider_type func);
future<ethernet_address> get_l2_dst_address(ipv4_address to);
+ const ipv4& inet() const {
+ return _inet;
+ }
};

class ip_protocol {
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 1e6c06b9..d28e9f47 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -136,6 +136,9 @@ class posix_ap_server_socket_impl : public server_socket_impl {
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ socket_address local_address() const override {
+ return _sa;
+ }
static void move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle handle);
};
using posix_tcp_ap_server_socket_impl = posix_ap_server_socket_impl<transport::TCP>;
@@ -151,6 +154,7 @@ class posix_server_socket_impl : public server_socket_impl {
explicit posix_server_socket_impl(socket_address sa, pollable_fd lfd, server_socket::load_balancing_algorithm lba) : _sa(sa), _lfd(std::move(lfd)), _lba(lba) {}
virtual future<connected_socket, socket_address> accept();
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_server_tcp_socket_impl = posix_server_socket_impl<transport::TCP>;
using posix_server_sctp_socket_impl = posix_server_socket_impl<transport::SCTP>;
@@ -163,6 +167,7 @@ class posix_reuseport_server_socket_impl : public server_socket_impl {
explicit posix_reuseport_server_socket_impl(socket_address sa, pollable_fd lfd) : _sa(sa), _lfd(std::move(lfd)) {}
virtual future<connected_socket, socket_address> accept();
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_reuseport_server_tcp_socket_impl = posix_reuseport_server_socket_impl<transport::TCP>;
using posix_reuseport_server_sctp_socket_impl = posix_reuseport_server_socket_impl<transport::SCTP>;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index 62958454..b6619075 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -55,6 +55,7 @@ class server_socket_impl {
virtual ~server_socket_impl() {}
virtual future<connected_socket, socket_address> accept() = 0;
virtual void abort_accept() = 0;
+ virtual socket_address local_address() const = 0;
};

class udp_channel_impl {
diff --git a/include/seastar/net/tcp.hh b/include/seastar/net/tcp.hh
index ef6acae5..d4434469 100644
--- a/include/seastar/net/tcp.hh
+++ b/include/seastar/net/tcp.hh
@@ -663,6 +663,9 @@ class tcp {
semaphore _queue_space = {212992};
metrics::metric_groups _metrics;
public:
+ const inet_type& inet() const {
+ return _inet;
+ }
class connection {
lw_shared_ptr<tcb> _tcb;
public:
@@ -734,6 +737,13 @@ class tcp {
bool full() { return _pending + _q.size() >= _q.max_size(); }
void inc_pending() { _pending++; }
void dec_pending() { _pending--; }
+
+ const tcp& get_tcp() const {
+ return _tcp;
+ }
+ uint16_t port() const {
+ return _port;
+ }
friend class tcp;
};
public:
diff --git a/src/net/native-stack-impl.hh b/src/net/native-stack-impl.hh
index 19f16da9..546c002e 100644
--- a/src/net/native-stack-impl.hh
+++ b/src/net/native-stack-impl.hh
@@ -23,6 +23,7 @@

#include <seastar/core/reactor.hh>
#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -46,6 +47,7 @@ class native_server_socket_impl : public server_socket_impl {
native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};

template <typename Protocol>
@@ -69,6 +71,11 @@ native_server_socket_impl<Protocol>::abort_accept() {
_listener.abort_accept();
}

+template <typename Protocol>
+socket_address native_server_socket_impl<Protocol>::local_address() const {
+ return socket_address(_listener.get_tcp().inet().inet().host_address(), _listener.port());
+}
+
// native_connected_socket_impl
template <typename Protocol>
class native_connected_socket_impl : public connected_socket_impl {
diff --git a/tests/unit/loopback_socket.hh b/tests/unit/loopback_socket.hh
index 888b0692..064d5761 100644
--- a/tests/unit/loopback_socket.hh
+++ b/tests/unit/loopback_socket.hh
@@ -191,6 +191,10 @@ class loopback_server_socket_impl : public net::server_socket_impl {
void abort_accept() override {
_pending->abort(std::make_exception_ptr(std::system_error(ECONNABORTED, std::system_category())));
}
+ socket_address local_address() const override {
+ // CMH dummy
+ return {};
+ }
};


diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index ce24fb94..a0818e31 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -232,6 +232,11 @@ posix_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader(std::make_exception_ptr(std::system_error(ECONNABORTED, std::system_category())));
}

+template <transport Transport>
+socket_address posix_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>::accept() {
auto conni = conn_q.find(_sa);
@@ -284,6 +289,11 @@ posix_reuseport_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader(std::make_exception_ptr(std::system_error(ECONNABORTED, std::system_category())));
}

+template <transport Transport>
+socket_address posix_reuseport_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index d021365c..be1d37f2 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -155,6 +155,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

+socket_address server_socket::local_address() const {
+ return _ssi->local_address();
+}
+
socket_address::socket_address()
: socket_address(ipv4_addr())
{}
diff --git a/src/net/tls.cc b/src/net/tls.cc
index b8106271..856c5c12 100644
--- a/src/net/tls.cc
+++ b/src/net/tls.cc
@@ -1130,6 +1130,9 @@ class server_session : public net::server_socket_impl {
void abort_accept() override {
_sock.abort_accept();
}
+ socket_address local_address() const override {
+ return _sock.local_address();
+ }
private:
shared_ptr<server_credentials> _creds;
server_socket _sock;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 28, 2019, 1:54:17 PM1/28/19
to seastar-dev@googlegroups.com, Calle Wilund
Borderline useless, but at least checks we can bind posix stack sockets
to ipv6.
---
configure.py | 3 ++
test.py | 1 +
tests/unit/ipv6_test.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+)
create mode 100644 tests/unit/ipv6_test.cc

diff --git a/configure.py b/configure.py
index 0fcf7053..857fd633 100755
--- a/configure.py
+++ b/configure.py
@@ -312,6 +312,7 @@ tests = [
'tests/unit/alien_test',
'tests/unit/signal_test',
'tests/unit/simple_stream_test',
+ 'tests/unit/ipv6_test',
] + perf_tests

apps = [
@@ -642,6 +643,7 @@ deps = {
'tests/unit/alien_test': ['tests/unit/alien_test.cc'] + core,
'tests/unit/signal_test': ['tests/unit/signal_test.cc'] + core,
'tests/unit/simple_stream_test': ['tests/unit/simple_stream_test.cc'] + core,
+ 'tests/unit/ipv6_test': ['tests/unit/ipv6_test.cc'] + core + libnet,
}

boost_tests = [
@@ -666,6 +668,7 @@ boost_tests = [
'tests/unit/lowres_clock_test',
'tests/unit/abort_source_test',
'tests/unit/signal_test',
+ 'tests/unit/ipv6_test',
]

for bt in boost_tests:
diff --git a/test.py b/test.py
index bb34126c..272f8575 100755
--- a/test.py
+++ b/test.py
@@ -58,6 +58,7 @@ boost_tests = [
'unit/signal_test',
'unit/simple_stream_test',
'unit/dns_test',
+ 'unit/ipv6_test',
]

other_tests = [
diff --git a/tests/unit/ipv6_test.cc b/tests/unit/ipv6_test.cc
new file mode 100644
index 00000000..9d556655
--- /dev/null
+++ b/tests/unit/ipv6_test.cc
@@ -0,0 +1,105 @@
+/*
+ * This file is open source software, licensed to you under the terms
+ * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. You may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Copyright (C) 2019 Cloudius Systems, Ltd.
+ */
+
+#include "test-utils.hh"
+
+#include <seastar/net/api.hh>
+#include <seastar/net/inet_address.hh>
+#include <seastar/core/reactor.hh>
+#include <seastar/util/log.hh>
+
+using namespace seastar;
+
+static logger iplog("ipv6");
+
+static bool check_ipv6_support() {
+ if (!engine().net().supports_ipv6()) {
+ iplog.info("No IPV6 support detected. Skipping...");
+ return false;
+ }
+ return true;
+}
+
+SEASTAR_TEST_CASE(udp_packet_test) {
+ if (!check_ipv6_support()) {
+ return make_ready_future<>();
+ }
+
+ auto sc = engine().net().make_udp_channel(ipv6_addr{});
+
+ BOOST_REQUIRE(sc.local_address().addr().is_ipv6());
+
+ auto cc = engine().net().make_udp_channel(ipv6_addr{});
+
+ auto f1 = cc.send(sc.local_address(), "apa");
+
+ return f1.then([cc = std::move(cc), sc = std::move(sc)]() mutable {
+ auto src = cc.local_address();
+ cc.close();
+ auto f2 = sc.receive();
+
+ return f2.then([sc = std::move(sc), src](auto pkt) mutable {
+ auto a = sc.local_address();
+ sc.close();
+ BOOST_REQUIRE_EQUAL(src, pkt.get_src());
+ auto dst = pkt.get_dst();
+ // Don't always get a dst address.
+ if (dst != socket_address()) {
+ BOOST_REQUIRE_EQUAL(a, pkt.get_dst());
+ }
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(tcp_packet_test) {
+ if (!check_ipv6_support()) {
+ return make_ready_future<>();
+ }
+
+ return async([] {
+ auto sc = engine().net().listen(ipv6_addr{}, {});
+ auto la = sc.local_address();
+
+ BOOST_REQUIRE(la.addr().is_ipv6());
+
+ auto cc = engine().net().connect(la).get0();
+ auto lc = sc.accept().get0();
+
+ auto strm = cc.output();
+ strm.write("los lobos").get();
+ strm.flush().get();
+
+ auto in = lc.input();
+
+ using consumption_result_type = typename input_stream<char>::consumption_result_type;
+ using stop_consuming_type = typename consumption_result_type::stop_consuming_type;
+ using tmp_buf = stop_consuming_type::tmp_buf;
+
+ in.consume([](tmp_buf buf) {
+ return make_ready_future<consumption_result_type>(stop_consuming<char>({}));
+ }).get();
+
+ strm.close().get();
+ in.close().get();
+ sc.abort_accept();
+ });
+}
+
--
2.14.5

Avi Kivity

<avi@scylladb.com>
unread,
Jan 29, 2019, 9:40:55 AM1/29/19
to Calle Wilund, seastar-dev@googlegroups.com
What are the changes compared to the RFC?

Avi Kivity

<avi@scylladb.com>
unread,
Jan 29, 2019, 9:47:33 AM1/29/19
to Calle Wilund, seastar-dev@googlegroups.com
I did a quick review and it looks good. Still interested about RFC->v1
changes.

On 28/01/2019 20.52, Calle Wilund wrote:

Calle Wilund

<calle@scylladb.com>
unread,
Jan 29, 2019, 10:03:02 AM1/29/19
to Avi Kivity, seastar-dev@googlegroups.com
* Added local_address() for UDP/server sockets.

* Added "supports_ipv6()" to stacks (although to coarse grained query)

* Added rudimentary test.

Avi Kivity

<avi@scylladb.com>
unread,
Jan 29, 2019, 10:33:37 AM1/29/19
to Calle Wilund, seastar-dev@googlegroups.com
This is based on scylla-seastar/master-something, please rebase atop
seastar/master.

On 28/01/2019 20.52, Calle Wilund wrote:

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:32 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Also at seastar-dev: calle/ipv6

* Adds ipv4 mirror types and/or embedding to address types in seastar.
* Changes posix stack to allow IPv6 addresses for bind/connect.
* Changes UDP interfaces to use socket_address (protocol agnostic address +
port) for connect/send/receive
* Changes UDP packets to return socket_address for packet src/dst
* Changes posix stack to allow ipv6 UDP.
* Changes RPC to allow ipv6 connectivity
* Adds local address query to server tcp/udp sockets

Includes minimal ipv6 test.
Tested on existing unit tests (seastar + scylla)

v1:
* Added local_address() for UDP/server sockets.
* Added "supports_ipv6()" to stacks (although to coarse grained query)
* Added rudimentary test.

v2:
* Rebased on latest seastar:master (cmake)

Calle Wilund (18):
Add packed ipv6 address
Add ipv6_address support to inet_address
Add ipv6_addr
Add ipv6 support to socket_address
Make socket_address default constructor ipv4 any
Add socket address uint16_t port only constructor -> ipv4 0.0.0.0:port
socket_address: Add != operator
Cleanup and de-inline some helper functions
inet_address: Add wildcard constructor from family
Posix-stack: Add ipv6 support for tcp
UDP: redefine address used as socket_address
RPC: move log to cc file
RCP: make rpc use socket_address to support ipv6
network_stack: Add ipv6 support query
udp_socket: Add local address accessor
native_stack: Make host_address const
server_socket: Add local address accessor
ipv6_test: Add small ipv6 test

include/seastar/net/api.hh | 61 +++++-----
include/seastar/net/inet_address.hh | 26 ++++-
include/seastar/net/ip.hh | 63 ++++++++++-
include/seastar/net/posix-stack.hh | 12 +-
include/seastar/net/socket_defs.hh | 72 ++++++++++--
include/seastar/net/stack.hh | 6 +-
include/seastar/net/tcp.hh | 10 ++
include/seastar/rpc/rpc.hh | 46 ++++----
src/net/native-stack-impl.hh | 7 ++
tests/unit/loopback_socket.hh | 4 +
src/net/inet_address.cc | 214 +++++++++++++++++++++++++++++++++---
src/net/ip.cc | 11 +-
src/net/native-stack.cc | 4 +-
src/net/net.cc | 13 ++-
src/net/posix-stack.cc | 93 +++++++++++-----
src/net/stack.cc | 75 +++++++++++--
src/net/tls.cc | 3 +
src/net/udp.cc | 13 ++-
src/rpc/rpc.cc | 25 ++++-
tests/unit/ipv6_test.cc | 105 ++++++++++++++++++
tests/unit/CMakeLists.txt | 3 +
21 files changed, 707 insertions(+), 159 deletions(-)
create mode 100644 tests/unit/ipv6_test.cc

--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:33 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Corresponding to ipv4_address, packed to potentially allow embedding in
non-aligned wire structures.
---
include/seastar/net/ip.hh | 51 ++++++++++++++++++++++++++++++++++-
src/net/inet_address.cc | 68 +++++++++++++++++++++++++++++++++++++++++++----
src/net/ip.cc | 9 -------
3 files changed, 113 insertions(+), 15 deletions(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 36d3411e..67b10195 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -97,7 +97,51 @@ struct ipv4_address {

static inline bool is_unspecified(ipv4_address addr) { return addr.ip == 0; }

-std::ostream& operator<<(std::ostream& os, ipv4_address a);
+std::ostream& operator<<(std::ostream& os, const ipv4_address& a);
+
+// IPv6
+struct ipv6_address {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ static_assert(alignof(ipv6_bytes) == 1);
+ static_assert(sizeof(ipv6_bytes) == 16);
+
+ ipv6_address();
+ explicit ipv6_address(const ::in6_addr&);
+ explicit ipv6_address(const ipv6_bytes&);
+ explicit ipv6_address(const std::string&);
+
+std::ostream& operator<<(std::ostream&, const ipv6_address&);

}

@@ -110,6 +154,11 @@ struct hash<seastar::net::ipv4_address> {
size_t operator()(seastar::net::ipv4_address a) const { return a.ip; }
};

+template <>
+struct hash<seastar::net::ipv6_address> {
+ size_t operator()(const seastar::net::ipv6_address&) const;
+};
+
}

namespace seastar {
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index d34f0f7c..5c32d191 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -21,13 +21,12 @@

#include <ostream>
#include <arpa/inet.h>
-
+#include <boost/functional/hash.hpp>
#include <seastar/net/inet_address.hh>
#include <seastar/net/socket_defs.hh>
#include <seastar/net/dns.hh>
#include <seastar/net/ip.hh>
-
-namespace seastar {
+#include <seastar/core/print.hh>

seastar::net::inet_address::inet_address()
: inet_address(::in_addr{ 0, })
@@ -112,6 +111,64 @@ const void * seastar::net::inet_address::data() const {
return &_in;
}

+seastar::net::ipv6_address::ipv6_address(const ::in6_addr& in) {
+ std::copy(std::begin(in.s6_addr), std::end(in.s6_addr), ip.begin());
+}
+
+seastar::net::ipv6_address::ipv6_address(const ipv6_bytes& in)
+ : ip(in)
+{}
+
+seastar::net::ipv6_address::ipv6_address()
+ : ipv6_address(::in6addr_any)
+{}
+
+seastar::net::ipv6_address::ipv6_address(const std::string& addr) {
+ if (!::inet_pton(AF_INET6, addr.c_str(), ip.data())) {
+ throw std::runtime_error(format("Wrong format for IPv6 address {}. Please ensure it's in colon-hex format",
+ addr));
+ }
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::read(const char* s) {
+ auto* b = reinterpret_cast<const uint8_t *>(s);
+ ipv6_address in;
+ std::copy(b, b + ipv6_address::size(), in.ip.begin());
+ return in;
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::consume(const char*& p) {
+ auto res = read(p);
+ p += size();
+ return res;
+}
+
+void seastar::net::ipv6_address::write(char* p) const {
+ std::copy(ip.begin(), ip.end(), p);
+}
+
+void seastar::net::ipv6_address::produce(char*& p) const {
+ write(p);
+ p += size();
+}
+
+bool seastar::net::ipv6_address::is_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const ipv4_address& a) {
+ auto ip = a.ip;
+ return fmt_print(os, "{:d}.{:d}.{:d}.{:d}",
+ (ip >> 24) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 0) & 0xff);
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const ipv6_address& a) {
+ char buffer[64];
+ return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer, sizeof(buffer));
+}

std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];
@@ -132,11 +189,12 @@ std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address::fam
return os;
}

-std::ostream& operator<<(std::ostream& os, const socket_address& a) {
+std::ostream& seastar::operator<<(std::ostream& os, const seastar::socket_address& a) {
return os << seastar::net::inet_address(a.as_posix_sockaddr_in().sin_addr)
<< ":" << ntohs(a.u.in.sin_port)
;
}

+size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {
+ return boost::hash_range(a.ip.begin(), a.ip.end());
}
-
diff --git a/src/net/ip.cc b/src/net/ip.cc
index 6a86cd75..ea6df0f2 100644
--- a/src/net/ip.cc
+++ b/src/net/ip.cc
@@ -41,15 +41,6 @@ ipv4_address::ipv4_address(const std::string& addr) {
ip = static_cast<uint32_t>(std::move(ipv4).to_ulong());

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:34 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/inet_address.hh | 25 +++++++++++++++++---
src/net/inet_address.cc | 47 ++++++++++++++++++++++++++++---------
2 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/include/seastar/net/inet_address.hh b/include/seastar/net/inet_address.hh
index 849820fd..0d8d3c0e 100644
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
+template<>
+struct hash<seastar::net::inet_address> {
+ size_t operator()(const seastar::net::inet_address&) const;
+};
+}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 5c32d191..fffa1a7a 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -29,7 +29,7 @@
#include <seastar/core/print.hh>

seastar::net::inet_address::inet_address()
- : inet_address(::in_addr{ 0, })
+ : inet_address(::in6_addr{ 0, })
{}

seastar::net::inet_address::inet_address(::in_addr i)
@@ -60,11 +60,13 @@ seastar::net::inet_address::inet_address(const ipv4_address& in)
{}

seastar::net::ipv4_address seastar::net::inet_address::as_ipv4_address() const {
- if (_in_family != family::INET) {
- // TODO: ipv4-compatible ipv6
- throw std::invalid_argument("Not an IPv4 address");
- }
- return ipv4_address(ntoh(_in.s_addr));
+ in_addr in = *this;
+ return ipv4_address(ntoh(in.s_addr));
+}
+
+seastar::net::ipv6_address seastar::net::inet_address::as_ipv6_address() const {
+ in6_addr in6 = *this;
+ return ipv6_address{in6};
}

bool seastar::net::inet_address::operator==(const inet_address& o) const {
@@ -82,20 +84,32 @@ bool seastar::net::inet_address::operator==(const inet_address& o) const {
}
}

-seastar::net::inet_address::operator const ::in_addr&() const {
+seastar::net::inet_address::operator ::in_addr() const {
if (_in_family != family::INET) {
- throw std::invalid_argument("Not an ipv4 address");
+ if (IN6_IS_ADDR_V4MAPPED(&_in6)) {
+ ::in_addr in;
+ in.s_addr = _in6.s6_addr32[3];
+ return in;
+ }
+ throw std::invalid_argument("Not an IPv4 address");
}
return _in;
}

-seastar::net::inet_address::operator const ::in6_addr&() const {
- if (_in_family != family::INET6) {
- throw std::invalid_argument("Not an ipv6 address");
+seastar::net::inet_address::operator ::in6_addr() const {
+ if (_in_family == family::INET) {
+ in6_addr in6 = IN6ADDR_ANY_INIT;
+ in6.s6_addr32[2] = ::htonl(0xffff);
+ in6.s6_addr32[3] = _in.s_addr;
+ return in6;
}
return _in6;
}

+seastar::net::inet_address::operator seastar::net::ipv6_address() const {
+ return as_ipv6_address();
+}
+
size_t seastar::net::inet_address::size() const {
switch (_in_family) {
case family::INET:
@@ -195,6 +209,17 @@ std::ostream& seastar::operator<<(std::ostream& os, const seastar::socket_addres
;
}

+size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::inet_address& a) const {
+ switch (a.in_family()) {
+ case seastar::net::inet_address::family::INET:
+ return std::hash<seastar::net::ipv4_address>()(a.as_ipv4_address());
+ case seastar::net::inet_address::family::INET6:
+ return std::hash<seastar::net::ipv6_address>()(a.as_ipv6_address());
+ default:
+ return 0;
+ }
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:35 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Like ipv4_addr, i.e. wraps address + port. Badly named, but akin to a
host endian sock_addr_in6.
---
include/seastar/net/ip.hh | 3 +++
include/seastar/net/socket_defs.hh | 21 ++++++++++++++++-
src/net/inet_address.cc | 46 ++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 67b10195..d5b1e267 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -44,6 +44,8 @@

namespace seastar {

+struct ipv6_addr;
+
namespace net {

class ipv4;
@@ -110,6 +112,7 @@ struct ipv6_address {
explicit ipv6_address(const ::in6_addr&);
explicit ipv6_address(const ipv6_bytes&);
explicit ipv6_address(const std::string&);
+ ipv6_address(const ipv6_addr& addr);

// No need to use packed - we only store
// as byte array. If we want to read as
diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index 055db041..e9327729 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -21,6 +21,7 @@
#pragma once

#include <iosfwd>
+#include <array>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <seastar/net/byteorder.hh>
@@ -76,8 +77,26 @@ struct ipv4_addr {
ip = net::ntoh(sa.u.in.sin_addr.s_addr);
port = net::ntoh(sa.u.in.sin_port);
}
+};
+
+struct ipv6_addr {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ ipv6_bytes ip;
+ uint16_t port;
+
+ ipv6_addr(const ipv6_bytes&, uint16_t port = 0);
+ ipv6_addr(uint16_t port = 0);
+ ipv6_addr(const std::string&);
+ ipv6_addr(const std::string&, uint16_t port);
+ ipv6_addr(const net::inet_address&, uint16_t = 0);
+ ipv6_addr(const ::in6_addr&, uint16_t = 0);
+ ipv6_addr(const ::sockaddr_in6&);

- ipv4_addr(socket_address &&sa) : ipv4_addr(sa) {}
+ bool is_ip_unspecified() const;
+ bool is_port_unspecified() const {
+ return port == 0;
+ }
};

}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index fffa1a7a..452b3a60 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -133,6 +133,10 @@ seastar::net::ipv6_address::ipv6_address(const ipv6_bytes& in)
: ip(in)
{}

+seastar::net::ipv6_address::ipv6_address(const ipv6_addr& addr)
+ : ipv6_address(addr.ip)
+{}
+
seastar::net::ipv6_address::ipv6_address()
: ipv6_address(::in6addr_any)
{}
@@ -184,6 +188,48 @@ std::ostream& seastar::net::operator<<(std::ostream& os, const ipv6_address& a)
return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer, sizeof(buffer));
}

+bool seastar::ipv6_addr::is_ip_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:37 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 45 +++++++++++++++++++++++++++------
src/net/inet_address.cc | 51 +++++++++++++++++++++++++++++++++++---
src/net/net.cc | 13 +++++++---
src/net/stack.cc | 40 +++++++++++++++++++++++++-----
4 files changed, 127 insertions(+), 22 deletions(-)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index e9327729..5a3a0f0d 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -28,7 +28,12 @@

namespace seastar {

+namespace net {
+class inet_address;
+}
+
struct ipv4_addr;
+struct ipv6_addr;

class socket_address {
public:
@@ -36,16 +41,29 @@ class socket_address {
::sockaddr_storage sas;
::sockaddr sa;
::sockaddr_in in;
+ ::sockaddr_in6 in6;
} u;
- socket_address(sockaddr_in sa) {
+ socket_address(const sockaddr_in& sa) {
u.in = sa;
}
+ socket_address(const sockaddr_in6& sa) {
+ u.in6 = sa;
+ }
socket_address(ipv4_addr);
+ socket_address(const ipv6_addr&);
+ socket_address(const net::inet_address&, uint16_t p = 0);
socket_address() = default;
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
+ ::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
const ::sockaddr& as_posix_sockaddr() const { return u.sa; }
const ::sockaddr_in& as_posix_sockaddr_in() const { return u.in; }
+ const ::sockaddr_in6& as_posix_sockaddr_in6() const { return u.in6; }
+
+ socket_address(uint32_t, uint16_t p = 0);
+
+ net::inet_address addr() const;
+ ::in_port_t port() const;

bool operator==(const socket_address&) const;
};
@@ -58,10 +76,6 @@ enum class transport {
};


-namespace net {
-class inet_address;
-}
-
struct ipv4_addr {
uint32_t ip;
uint16_t port;
@@ -72,10 +86,14 @@ struct ipv4_addr {
ipv4_addr(const std::string &addr);
ipv4_addr(const std::string &addr, uint16_t port);
ipv4_addr(const net::inet_address&, uint16_t);
+ ipv4_addr(const socket_address &);
+ ipv4_addr(const ::in_addr&, uint16_t = 0);

- ipv4_addr(const socket_address &sa) {
- ip = net::ntoh(sa.u.in.sin_addr.s_addr);
- port = net::ntoh(sa.u.in.sin_port);
+ bool is_ip_unspecified() const {
+ return ip == 0;
+ }
+ bool is_port_unspecified() const {
+ return port == 0;
}
};

@@ -92,6 +110,7 @@ struct ipv6_addr {
ipv6_addr(const net::inet_address&, uint16_t = 0);
ipv6_addr(const ::in6_addr&, uint16_t = 0);
ipv6_addr(const ::sockaddr_in6&);
+ ipv6_addr(const socket_address&);

bool is_ip_unspecified() const;
bool is_port_unspecified() const {
@@ -99,4 +118,14 @@ struct ipv6_addr {
}
};

+std::ostream& operator<<(std::ostream&, const ipv4_addr&);
+std::ostream& operator<<(std::ostream&, const ipv6_addr&);
+
+}
+
+namespace std {
+template<>
+struct hash<seastar::socket_address> {
+ size_t operator()(const seastar::socket_address&) const;
+};
}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 452b3a60..79afd40b 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -230,6 +230,25 @@ bool seastar::ipv6_addr::is_ip_unspecified() const {
return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b == 0; });
}

+seastar::socket_address::socket_address(const net::inet_address& a, uint16_t p)
+ : socket_address(a.is_ipv6() ? socket_address(ipv6_addr(a, p)) : socket_address(ipv4_addr(a, p)))
+{}
+
+seastar::net::inet_address seastar::socket_address::addr() const {
+ switch (as_posix_sockaddr().sa_family) {
+ case AF_INET:
+ return net::inet_address(as_posix_sockaddr_in().sin_addr);
+ case AF_INET6:
+ return net::inet_address(as_posix_sockaddr_in6().sin6_addr);
+ default:
+ return net::inet_address();
+ }
+}
+
+::in_port_t seastar::socket_address::port() const {
+ return net::ntoh(u.in.sin_port);
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address& addr) {
char buffer[64];
return os << inet_ntop(int(addr.in_family()), addr.data(), buffer, sizeof(buffer));
@@ -249,10 +268,28 @@ std::ostream& seastar::net::operator<<(std::ostream& os, const inet_address::fam
return os;
}

-std::ostream& seastar::operator<<(std::ostream& os, const seastar::socket_address& a) {
- return os << seastar::net::inet_address(a.as_posix_sockaddr_in().sin_addr)
- << ":" << ntohs(a.u.in.sin_port)
- ;
+std::ostream& seastar::operator<<(std::ostream& os, const socket_address& a) {
+ auto addr = a.addr();
+ // CMH. maybe skip brackets for ipv4-mapped
+ auto bracket = addr.in_family() == seastar::net::inet_address::family::INET6;
+
+ if (bracket) {
+ os << '[';
+ }
+ os << addr;
+ if (bracket) {
+ os << ']';
+ }
+
+ return os << ':' << ntohs(a.u.in.sin_port);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv4_addr& a) {
+ return os << seastar::socket_address(a);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv6_addr& a) {
+ return os << seastar::socket_address(a);
}

size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::inet_address& a) const {
@@ -266,6 +303,12 @@ size_t std::hash<seastar::net::inet_address>::operator()(const seastar::net::ine
}
}

+size_t std::hash<seastar::socket_address>::operator()(const seastar::socket_address& a) const {
+ auto h = std::hash<seastar::net::inet_address>()(a.addr());
+ boost::hash_combine(h, a.as_posix_sockaddr_in().sin_port);
+ return h;
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const seastar::net::ipv6_address& a) const {
return boost::hash_range(a.ip.begin(), a.ip.end());
}
diff --git a/src/net/net.cc b/src/net/net.cc
index ed230f99..90de2128 100644
--- a/src/net/net.cc
+++ b/src/net/net.cc
@@ -59,10 +59,15 @@ ipv4_addr::ipv4_addr(const std::string &addr) {
ipv4_addr::ipv4_addr(const std::string &addr, uint16_t port_) : ip(boost::asio::ip::address_v4::from_string(addr).to_ulong()), port(port_) {}

ipv4_addr::ipv4_addr(const net::inet_address& a, uint16_t port)
- : ipv4_addr([&a] {
- ::in_addr in = a;
- return net::ntoh(in.s_addr);
-}(), port)
+ : ipv4_addr(::in_addr(a), port)
+{}
+
+ipv4_addr::ipv4_addr(const socket_address &sa)
+ : ipv4_addr(sa.addr(), sa.port())
+{}
+
+ipv4_addr::ipv4_addr(const ::in_addr& in, uint16_t p)
+ : ip(net::ntoh(in.s_addr)), port(p)
{}

namespace net {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index e979f0c9..80f6947b 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -160,15 +160,43 @@ void server_socket::abort_accept() {
}

socket_address::socket_address(ipv4_addr addr)
- : socket_address(make_ipv4_address(addr))
-{}
+{
+ u.in.sin_family = AF_INET;
+ u.in.sin_port = htons(addr.port);
+ u.in.sin_addr.s_addr = htonl(addr.ip);
+}

+socket_address::socket_address(const ipv6_addr& addr)
+{
+ u.in6.sin6_family = AF_INET6;
+ u.in6.sin6_port = htons(addr.port);
+ std::copy(addr.ip.begin(), addr.ip.end(), u.in6.sin6_addr.s6_addr);
+}
+
+socket_address::socket_address(uint32_t ipv4, uint16_t p)
+ : socket_address(make_ipv4_address(ipv4, p))
+{}

bool socket_address::operator==(const socket_address& a) const {
- // TODO: handle ipv6
- return std::tie(u.in.sin_family, u.in.sin_port, u.in.sin_addr.s_addr)
- == std::tie(a.u.in.sin_family, a.u.in.sin_port,
- a.u.in.sin_addr.s_addr);
+ if (u.sa.sa_family != a.u.sa.sa_family) {
+ return false;
+ }
+ if (u.in.sin_port != a.u.in.sin_port) {
+ return false;
+ }
+ switch (u.sa.sa_family) {
+ case AF_INET:
+ return u.in.sin_addr.s_addr == a.u.in.sin_addr.s_addr;
+ case AF_INET6:
+ break;
+ default:
+ return false;
+ }
+

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:38 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 2 +-
src/net/stack.cc | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index 5a3a0f0d..e905219f 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -52,7 +52,7 @@ class socket_address {
socket_address(ipv4_addr);
socket_address(const ipv6_addr&);
socket_address(const net::inet_address&, uint16_t p = 0);
- socket_address() = default;
+ socket_address();
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 80f6947b..e334d465 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -159,6 +159,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:39 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 1 +
src/net/stack.cc | 4 ++++
2 files changed, 5 insertions(+)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index e905219f..fcc8c225 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -49,6 +49,7 @@ class socket_address {
socket_address(const sockaddr_in6& sa) {
u.in6 = sa;
}
+ socket_address(uint16_t);
socket_address(ipv4_addr);
socket_address(const ipv6_addr&);
socket_address(const net::inet_address&, uint16_t p = 0);
diff --git a/src/net/stack.cc b/src/net/stack.cc
index e334d465..dbd1c098 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -163,6 +163,10 @@ socket_address::socket_address()
: socket_address(ipv4_addr())
{}

+socket_address::socket_address(uint16_t p)
+ : socket_address(ipv4_addr(p))

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:40 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/socket_defs.hh | 3 +++
1 file changed, 3 insertions(+)

diff --git a/include/seastar/net/socket_defs.hh b/include/seastar/net/socket_defs.hh
index fcc8c225..2f5be089 100644
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -67,6 +67,9 @@ class socket_address {
::in_port_t port() const;

bool operator==(const socket_address&) const;
+ bool operator!=(const socket_address& a) const {
+ return !(*this == a);
+ }
};

std::ostream& operator<<(std::ostream&, const socket_address&);
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:41 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/api.hh | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 816e4329..cabc368b 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -35,34 +35,24 @@

namespace seastar {

-static inline
-bool is_ip_unspecified(ipv4_addr &addr) {
- return addr.ip == 0;
+inline
+bool is_ip_unspecified(const ipv4_addr& addr) {
+ return addr.is_ip_unspecified();
}

-static inline
-bool is_port_unspecified(ipv4_addr &addr) {
- return addr.port == 0;
+inline
+bool is_port_unspecified(const ipv4_addr& addr) {
+ return addr.is_port_unspecified();
}

-std::ostream& operator<<(std::ostream& os, ipv4_addr addr);
-

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:42 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Corresponding to AF_INET/AF_INET6 + zeroed addr
---
include/seastar/net/inet_address.hh | 1 +
src/net/inet_address.cc | 6 ++++++
2 files changed, 7 insertions(+)

diff --git a/include/seastar/net/inet_address.hh b/include/seastar/net/inet_address.hh
index 0d8d3c0e..79798601 100644
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
@@ -56,6 +56,7 @@ class inet_address {
public:

inet_address();
+ inet_address(family);
inet_address(::in_addr i);
inet_address(::in6_addr i);
// NOTE: does _not_ resolve the address. Only parses
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
index 79afd40b..915cc6d7 100644
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -32,6 +32,12 @@ seastar::net::inet_address::inet_address()
: inet_address(::in6_addr{ 0, })
{}

+seastar::net::inet_address::inet_address(family f)
+ : _in_family(f)
+{
+ memset(&_in6, 0, sizeof(_in6));
+}
+
seastar::net::inet_address::inet_address(::in_addr i)

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:43 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/api.hh | 6 +-----
include/seastar/net/posix-stack.hh | 4 ++--
src/net/posix-stack.cc | 14 +++++++-------
src/net/stack.cc | 11 +++++++++++
4 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index cabc368b..db052bc6 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -283,11 +283,7 @@ class network_stack {
virtual ~network_stack() {}
virtual server_socket listen(socket_address sa, listen_options opts) = 0;
// FIXME: local parameter assumes ipv4 for now, fix when adding other AF
- future<connected_socket> connect(socket_address sa, socket_address local = socket_address(::sockaddr_in{AF_INET, INADDR_ANY, {0}}), transport proto = transport::TCP) {
- return do_with(socket(), [sa, local, proto](::seastar::socket& s) {
- return s.connect(sa, local, proto);
- });
- }
+ future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
virtual future<> initialize() {
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 725d9b4b..66e92b70 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -130,8 +130,8 @@ class posix_ap_server_socket_impl : public server_socket_impl {
socket_address addr;
connection(pollable_fd xfd, socket_address xaddr) : fd(std::move(xfd)), addr(xaddr) {}
};
- static thread_local std::unordered_map<::sockaddr_in, promise<connected_socket, socket_address>> sockets;
- static thread_local std::unordered_multimap<::sockaddr_in, connection> conn_q;
+ static thread_local std::unordered_map<socket_address, promise<connected_socket, socket_address>> sockets;
+ static thread_local std::unordered_multimap<socket_address, connection> conn_q;
socket_address _sa;
public:
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index dea06771..a359637f 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -234,7 +234,7 @@ posix_server_socket_impl<Transport>::abort_accept() {

template <transport Transport>
future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>::accept() {
- auto conni = conn_q.find(_sa.as_posix_sockaddr_in());
+ auto conni = conn_q.find(_sa);
if (conni != conn_q.end()) {
connection c = std::move(conni->second);
conn_q.erase(conni);
@@ -247,7 +247,7 @@ future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>:
}
} else {
try {
- auto i = sockets.emplace(std::piecewise_construct, std::make_tuple(_sa.as_posix_sockaddr_in()), std::make_tuple());
+ auto i = sockets.emplace(std::piecewise_construct, std::make_tuple(_sa), std::make_tuple());
assert(i.second);
return i.first->second.get_future();
} catch (...) {
@@ -259,7 +259,7 @@ future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>:
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::abort_accept() {
- conn_q.erase(_sa.as_posix_sockaddr_in());
+ conn_q.erase(_sa);
auto i = sockets.find(_sa.as_posix_sockaddr_in());
if (i != sockets.end()) {
i->second.set_exception(std::system_error(ECONNABORTED, std::system_category()));
@@ -287,7 +287,7 @@ posix_reuseport_server_socket_impl<Transport>::abort_accept() {
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
- auto i = sockets.find(sa.as_posix_sockaddr_in());
+ auto i = sockets.find(sa);
if (i != sockets.end()) {
try {
std::unique_ptr<connected_socket_impl> csi(new posix_connected_socket_impl<Transport>(make_lw_shared(std::move(fd)), std::move(cth)));
@@ -297,7 +297,7 @@ posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa,
}
sockets.erase(i);
} else {
- conn_q.emplace(std::piecewise_construct, std::make_tuple(sa.as_posix_sockaddr_in()), std::make_tuple(std::move(fd), std::move(addr)));
+ conn_q.emplace(std::piecewise_construct, std::make_tuple(sa), std::make_tuple(std::move(fd), std::move(addr)));
}
}

@@ -371,9 +371,9 @@ ::seastar::socket posix_network_stack::socket() {
}

template<transport Transport>
-thread_local std::unordered_map<::sockaddr_in, promise<connected_socket, socket_address>> posix_ap_server_socket_impl<Transport>::sockets;
+thread_local std::unordered_map<socket_address, promise<connected_socket, socket_address>> posix_ap_server_socket_impl<Transport>::sockets;
template<transport Transport>
-thread_local std::unordered_multimap<::sockaddr_in, typename posix_ap_server_socket_impl<Transport>::connection> posix_ap_server_socket_impl<Transport>::conn_q;
+thread_local std::unordered_multimap<socket_address, typename posix_ap_server_socket_impl<Transport>::connection> posix_ap_server_socket_impl<Transport>::conn_q;

server_socket
posix_ap_network_stack::listen(socket_address sa, listen_options opt) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index dbd1c098..b336c99e 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -20,6 +20,7 @@
*/

#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>
#include <seastar/core/reactor.hh>

namespace seastar {
@@ -207,4 +208,14 @@ bool socket_address::operator==(const socket_address& a) const {
return IN6_ARE_ADDR_EQUAL(&in1, &in2);
}

+future<connected_socket>
+network_stack::connect(socket_address sa, socket_address local, transport proto) {
+ if (local == socket_address()) {
+ local = net::inet_address(sa.addr().in_family());
+ }
+ return do_with(socket(), [sa, local, proto](::seastar::socket& s) {
+ return s.connect(sa, local, proto);

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:44 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
UPD interface/packets are hardcoded to use ipv4_addr as dest/source
addresses. Redefine this to instead use socket_address, which contains
all the multiplexing needed to handle optional ipv6.

Since socket_address also translated transparently to ipv4_addr,
existing programs should continue to work as before (more or less).

Adds actual ipv6 support to posix stack UDP.
---
include/seastar/net/api.hh | 14 +++++-----
include/seastar/net/posix-stack.hh | 2 +-
include/seastar/net/stack.hh | 4 +--
src/net/native-stack.cc | 4 +--
src/net/posix-stack.cc | 52 +++++++++++++++++++++++---------------
src/net/stack.cc | 8 +++---
src/net/udp.cc | 8 +++---
7 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index db052bc6..0ed5ddc5 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -83,8 +83,8 @@ class get_impl;
class udp_datagram_impl {
public:
virtual ~udp_datagram_impl() {};
- virtual ipv4_addr get_src() = 0;
- virtual ipv4_addr get_dst() = 0;
+ virtual socket_address get_src() = 0;
+ virtual socket_address get_dst() = 0;
virtual uint16_t get_dst_port() = 0;
virtual packet& get_data() = 0;
};
@@ -94,8 +94,8 @@ class udp_datagram final {
std::unique_ptr<udp_datagram_impl> _impl;
public:
udp_datagram(std::unique_ptr<udp_datagram_impl>&& impl) : _impl(std::move(impl)) {};
- ipv4_addr get_src() { return _impl->get_src(); }
- ipv4_addr get_dst() { return _impl->get_dst(); }
+ socket_address get_src() { return _impl->get_src(); }
+ socket_address get_dst() { return _impl->get_dst(); }
uint16_t get_dst_port() { return _impl->get_dst_port(); }
packet& get_data() { return _impl->get_data(); }
};
@@ -112,8 +112,8 @@ class udp_channel {
udp_channel& operator=(udp_channel&&);

future<udp_datagram> receive();
- future<> send(ipv4_addr dst, const char* msg);
- future<> send(ipv4_addr dst, packet p);
+ future<> send(const socket_address& dst, const char* msg);
+ future<> send(const socket_address& dst, packet p);
bool is_closed() const;
/// Causes a pending receive() to complete (possibly with an exception)
void shutdown_input();
@@ -285,7 +285,7 @@ class network_stack {
// FIXME: local parameter assumes ipv4 for now, fix when adding other AF
future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
+ virtual net::udp_channel make_udp_channel(const socket_address& = {}) = 0;
virtual future<> initialize() {
return make_ready_future();
}
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 66e92b70..504040f7 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -175,7 +175,7 @@ class posix_network_stack : public network_stack {
explicit posix_network_stack(boost::program_options::variables_map opts) : _reuseport(engine().posix_reuseport_available()) {}
virtual server_socket listen(socket_address sa, listen_options opts) override;
virtual ::seastar::socket socket() override;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual net::udp_channel make_udp_channel(const socket_address&) override;
static future<std::unique_ptr<network_stack>> create(boost::program_options::variables_map opts) {
return make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new posix_network_stack(opts)));
}
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index d16c32bf..5cc3b203 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -61,8 +61,8 @@ class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
virtual future<udp_datagram> receive() = 0;
- virtual future<> send(ipv4_addr dst, const char* msg) = 0;
- virtual future<> send(ipv4_addr dst, packet p) = 0;
+ virtual future<> send(const socket_address& dst, const char* msg) = 0;
+ virtual future<> send(const socket_address& dst, packet p) = 0;
virtual void shutdown_input() = 0;
virtual void shutdown_output() = 0;
virtual bool is_closed() const = 0;
diff --git a/src/net/native-stack.cc b/src/net/native-stack.cc
index 1b6f434d..57c85193 100644
--- a/src/net/native-stack.cc
+++ b/src/net/native-stack.cc
@@ -151,7 +151,7 @@ class native_network_stack : public network_stack {
explicit native_network_stack(boost::program_options::variables_map opts, std::shared_ptr<device> dev);
virtual server_socket listen(socket_address sa, listen_options opt) override;
virtual ::seastar::socket socket() override;
- virtual udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual udp_channel make_udp_channel(const socket_address& addr) override;
virtual future<> initialize() override;
static future<std::unique_ptr<network_stack>> create(boost::program_options::variables_map opts) {
if (engine().cpu_id() == 0) {
@@ -169,7 +169,7 @@ class native_network_stack : public network_stack {
thread_local promise<std::unique_ptr<network_stack>> native_network_stack::ready_promise;

udp_channel
-native_network_stack::make_udp_channel(ipv4_addr addr) {
+native_network_stack::make_udp_channel(const socket_address& addr) {
return _inet.get_udp().make_channel(addr);
}

diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index a359637f..f33b0a62 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
- virtual future<> send(ipv4_addr dst, const char *msg) override;
- virtual future<> send(ipv4_addr dst, packet p) override;
+ virtual future<> send(const socket_address& dst, const char *msg) override;
+ virtual future<> send(const socket_address& dst, packet p) override;
virtual void shutdown_input() override {
_fd->abort_reader();
}
@@ -477,13 +480,13 @@ class posix_udp_channel : public udp_channel_impl {
virtual bool is_closed() const override { return _closed; }
};

-future<> posix_udp_channel::send(ipv4_addr dst, const char *message) {
+future<> posix_udp_channel::send(const socket_address& dst, const char *message) {
auto len = strlen(message);
- return _fd->sendto(make_ipv4_address(dst), message, len)
+ return _fd->sendto(dst, message, len)
.then([len] (size_t size) { assert(size == len); });
}

-future<> posix_udp_channel::send(ipv4_addr dst, packet p) {
+future<> posix_udp_channel::send(const socket_address& dst, packet p) {
auto len = p.len();
_send.prepare(dst, std::move(p));
return _fd->sendmsg(&_send._hdr)
@@ -491,20 +494,20 @@ future<> posix_udp_channel::send(ipv4_addr dst, packet p) {
}

udp_channel
-posix_network_stack::make_udp_channel(ipv4_addr addr) {
+posix_network_stack::make_udp_channel(const socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

class posix_datagram : public udp_datagram_impl {
private:
- ipv4_addr _src;
- ipv4_addr _dst;
+ socket_address _src;
+ socket_address _dst;
packet _p;
public:
- posix_datagram(ipv4_addr src, ipv4_addr dst, packet p) : _src(src), _dst(dst), _p(std::move(p)) {}
- virtual ipv4_addr get_src() override { return _src; }
- virtual ipv4_addr get_dst() override { return _dst; }
- virtual uint16_t get_dst_port() override { return _dst.port; }
+ posix_datagram(const socket_address& src, const socket_address& dst, packet p) : _src(src), _dst(dst), _p(std::move(p)) {}
+ virtual socket_address get_src() override { return _src; }
+ virtual socket_address get_dst() override { return _dst; }
+ virtual uint16_t get_dst_port() override { return _dst.port(); }
virtual packet& get_data() override { return _p; }
};

@@ -512,7 +515,16 @@ future<udp_datagram>
posix_udp_channel::receive() {
_recv.prepare();
return _fd->recvmsg(&_recv._hdr).then([this] (size_t size) {
- auto dst = ipv4_addr(_recv._cmsg.pktinfo.ipi_addr.s_addr, _address.port);
+ socket_address dst;
+ for (auto* cmsg = CMSG_FIRSTHDR(&_recv._hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&_recv._hdr, cmsg)) {
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
+ dst = ipv4_addr(reinterpret_cast<const in_pktinfo*>(CMSG_DATA(cmsg))->ipi_addr, _address.port());
+ break;
+ } else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+ dst = ipv6_addr(reinterpret_cast<const in6_pktinfo*>(CMSG_DATA(cmsg))->ipi6_addr, _address.port());
+ break;
+ }
+ }
return make_ready_future<udp_datagram>(udp_datagram(std::make_unique<posix_datagram>(
_recv._src_addr, dst, packet(fragment{_recv._buffer, size}, make_deleter([buf = _recv._buffer] { delete[] buf; })))));
}).handle_exception([p = _recv._buffer](auto ep) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index b336c99e..463cf388 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -41,12 +41,12 @@ future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}

-future<> net::udp_channel::send(ipv4_addr dst, const char* msg) {
- return _impl->send(std::move(dst), msg);
+future<> net::udp_channel::send(const socket_address& dst, const char* msg) {
+ return _impl->send(dst, msg);
}

-future<> net::udp_channel::send(ipv4_addr dst, packet p) {
- return _impl->send(std::move(dst), std::move(p));
+future<> net::udp_channel::send(const socket_address& dst, packet p) {
+ return _impl->send(dst, std::move(p));
}

bool net::udp_channel::is_closed() const {
diff --git a/src/net/udp.cc b/src/net/udp.cc
index e591de50..f3c8dff4 100644
--- a/src/net/udp.cc
+++ b/src/net/udp.cc

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:45 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/rpc/rpc.hh | 12 +++---------
src/rpc/rpc.cc | 13 +++++++++++++
2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
index 4a3c8ada..55dff5bd 100644
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -169,17 +169,11 @@ class logger {
_logger = std::move(l);
}

- void operator()(const client_info& info, id_type msg_id, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
- }
+ void operator()(const client_info& info, id_type msg_id, const sstring& str) const;

- void operator()(const client_info& info, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
- }
+ void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
- }
+ void operator()(ipv4_addr addr, const sstring& str) const;
};

class connection {
diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
index 5414b84d..57b36a58 100644
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -5,6 +5,19 @@
namespace seastar {

namespace rpc {
+
+ void logger::operator()(const client_info& info, id_type msg_id, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
+ }
+
+ void logger::operator()(const client_info& info, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ }
+
+ void logger::operator()(ipv4_addr addr, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
+ }

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:46 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/rpc/rpc.hh | 36 ++++++++++++++++++------------------
src/rpc/rpc.cc | 20 ++++++++++----------
2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
index 55dff5bd..b59f58cd 100644
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -173,7 +173,7 @@ class logger {

void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const;
+ void operator()(const socket_address& addr, const sstring& str) const;
};

class connection {
diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
index 57b36a58..c1fb62f8 100644
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -7,15 +7,15 @@ namespace seastar {
namespace rpc {

void logger::operator()(const client_info& info, id_type msg_id, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " + to_sstring(msg_id) + ": " + str);
+ log(format("client {} msg_id {}: {}", info.addr, msg_id, str));
}

void logger::operator()(const client_info& info, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ (*this)(info.addr, str);
}

- void logger::operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)}) + ": " + str);
+ void logger::operator()(const socket_address& addr, const sstring& str) const {
+ log(format("client {}: {}", addr, str));
}

no_wait_type no_wait;
@@ -622,7 +622,7 @@ namespace rpc {
}
}

- client::client(const logger& l, void* s, client_options ops, socket socket, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, client_options ops, socket socket, const socket_address& addr, const socket_address& local)
: rpc::connection(l, s), _socket(std::move(socket)), _server_addr(addr), _options(ops) {
_socket.connect(addr, local).then([this, ops = std::move(ops)] (connected_socket fd) {
fd.set_nodelay(ops.tcp_nodelay);
@@ -712,15 +712,15 @@ namespace rpc {
});
}

- client::client(const logger& l, void* s, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, const socket_address& addr, const socket_address& local)
: client(l, s, client_options{}, engine().net().socket(), addr, local)
{}

- client::client(const logger& l, void* s, client_options options, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, client_options options, const socket_address& addr, const socket_address& local)
: client(l, s, options, engine().net().socket(), addr, local)
{}

- client::client(const logger& l, void* s, socket socket, ipv4_addr addr, ipv4_addr local)
+ client::client(const logger& l, void* s, socket socket, const socket_address& addr, const socket_address& local)
: client(l, s, client_options{}, std::move(socket), addr, local)
{}

@@ -945,11 +945,11 @@ namespace rpc {

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:47 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
While not 100% correct, since this should really be per interface etc,
it still allows us some info (hint hint tests)
---
include/seastar/net/api.hh | 6 ++++++
include/seastar/net/posix-stack.hh | 1 +
src/net/posix-stack.cc | 14 ++++++++++++++
3 files changed, 21 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 0ed5ddc5..88af27a5 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -290,6 +290,12 @@ class network_stack {
return make_ready_future();
}
virtual bool has_per_core_namespace() = 0;
+ // NOTE: this is not a correct query approach.
+ // This question should be per NIC, but we have no such
+ // abstraction, so for now this is "stack-wide"
+ virtual bool supports_ipv6() const {
+ return false;
+ }
};

}
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 504040f7..022a8ffc 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -180,6 +180,7 @@ class posix_network_stack : public network_stack {
return make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new posix_network_stack(opts)));
}
virtual bool has_per_core_namespace() override { return _reuseport; };
+ bool supports_ipv6() const override;
};

class posix_ap_network_stack : public posix_network_stack {
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index f33b0a62..930e8fee 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -498,6 +498,20 @@ posix_network_stack::make_udp_channel(const socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

+bool
+posix_network_stack::supports_ipv6() const {
+ static bool has_ipv6 = [] {
+ try {
+ posix_udp_channel c(ipv6_addr{});
+ c.close();
+ return true;
+ } catch (...) {}
+ return false;
+ }();
+
+ return has_ipv6;
+}
+
class posix_datagram : public udp_datagram_impl {
private:
socket_address _src;
--
2.14.5

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:48 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
It is somewhat useful to be able to query which address/port one got
when binding to wildcard.
---
include/seastar/net/api.hh | 2 ++
include/seastar/net/ip.hh | 4 ++++
include/seastar/net/stack.hh | 1 +
src/net/posix-stack.cc | 3 +++
src/net/stack.cc | 4 ++++
src/net/udp.cc | 5 +++++
6 files changed, 19 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index 88af27a5..eaf68411 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -111,6 +111,8 @@ class udp_channel {
udp_channel(udp_channel&&);
udp_channel& operator=(udp_channel&&);

+ socket_address local_address() const;
+
future<udp_datagram> receive();
future<> send(const socket_address& dst, const char* msg);
future<> send(const socket_address& dst, packet p);
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index d5b1e267..abf4f90a 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -330,6 +330,10 @@ class ipv4_udp : public ip_protocol {
void send(uint16_t src_port, ipv4_addr dst, packet &&p);
bool forward(forward_hash& out_hash_data, packet& p, size_t off) override;
void set_queue_size(int size) { _queue_size = size; }
+
+ const ipv4& inet() const {
+ return _inet;
+ }
};

struct ip_hdr;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index 5cc3b203..70fb51f9 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -60,6 +60,7 @@ class server_socket_impl {
class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
+ virtual socket_address local_address() const = 0;
virtual future<udp_datagram> receive() = 0;
virtual future<> send(const socket_address& dst, const char* msg) = 0;
virtual future<> send(const socket_address& dst, packet p) = 0;
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index 930e8fee..81b6b2d1 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -478,6 +478,9 @@ class posix_udp_channel : public udp_channel_impl {
_fd.reset();
}
virtual bool is_closed() const override { return _closed; }
+ socket_address local_address() const override {
+ return _address;
+ }
};

future<> posix_udp_channel::send(const socket_address& dst, const char *message) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 463cf388..75c59cde 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -37,6 +37,10 @@ net::udp_channel::~udp_channel()
net::udp_channel::udp_channel(udp_channel&&) = default;
net::udp_channel& net::udp_channel::operator=(udp_channel&&) = default;

+socket_address net::udp_channel::local_address() const {
+ return _impl->local_address();
+}
+
future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}
diff --git a/src/net/udp.cc b/src/net/udp.cc
index f3c8dff4..58b76e1a 100644
--- a/src/net/udp.cc
+++ b/src/net/udp.cc
@@ -21,6 +21,7 @@

#include <seastar/net/ip.hh>
#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -89,6 +90,10 @@ class native_channel : public udp_channel_impl {
close();
}

+ socket_address local_address() const override {

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:49 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
---
include/seastar/net/ip.hh | 2 +-
src/net/ip.cc | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index abf4f90a..90d637bd 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -436,7 +436,7 @@ class ipv4 {
public:
explicit ipv4(interface* netif);
void set_host_address(ipv4_address ip);
- ipv4_address host_address();
+ ipv4_address host_address() const;
void set_gw_address(ipv4_address ip);
ipv4_address gw_address() const;
void set_netmask_address(ipv4_address ip);
diff --git a/src/net/ip.cc b/src/net/ip.cc
index ea6df0f2..d82ec0ea 100644
--- a/src/net/ip.cc
+++ b/src/net/ip.cc
@@ -325,7 +325,7 @@ void ipv4::set_host_address(ipv4_address ip) {

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:50 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Because sometimes it helps to query which address/port a wildcard bind
bound to.
---
include/seastar/net/api.hh | 3 +++
include/seastar/net/ip.hh | 3 +++
include/seastar/net/posix-stack.hh | 5 +++++
include/seastar/net/stack.hh | 1 +
include/seastar/net/tcp.hh | 10 ++++++++++
src/net/native-stack-impl.hh | 7 +++++++
tests/unit/loopback_socket.hh | 4 ++++
src/net/posix-stack.cc | 10 ++++++++++
src/net/stack.cc | 4 ++++
src/net/tls.cc | 3 +++
10 files changed, 50 insertions(+)

diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
index eaf68411..1fa06158 100644
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -271,6 +271,9 @@ class server_socket {
/// Current and future \ref accept() calls will terminate immediately
/// with an error.
void abort_accept();
+
+ /// Local bound address
+ socket_address local_address() const;
};
/// @}

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
index 90d637bd..58d6fb2c 100644
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -195,6 +195,9 @@ class ipv4_l4 {
ipv4_l4(ipv4& inet) : _inet(inet) {}
void register_packet_provider(ipv4_traits::packet_provider_type func);
future<ethernet_address> get_l2_dst_address(ipv4_address to);
+ const ipv4& inet() const {
+ return _inet;
+ }
};

class ip_protocol {
diff --git a/include/seastar/net/posix-stack.hh b/include/seastar/net/posix-stack.hh
index 022a8ffc..bd811443 100644
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -137,6 +137,9 @@ class posix_ap_server_socket_impl : public server_socket_impl {
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ socket_address local_address() const override {
+ return _sa;
+ }
static void move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle handle);
};
using posix_tcp_ap_server_socket_impl = posix_ap_server_socket_impl<transport::TCP>;
@@ -152,6 +155,7 @@ class posix_server_socket_impl : public server_socket_impl {
explicit posix_server_socket_impl(socket_address sa, pollable_fd lfd, server_socket::load_balancing_algorithm lba) : _sa(sa), _lfd(std::move(lfd)), _lba(lba) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_server_tcp_socket_impl = posix_server_socket_impl<transport::TCP>;
using posix_server_sctp_socket_impl = posix_server_socket_impl<transport::SCTP>;
@@ -164,6 +168,7 @@ class posix_reuseport_server_socket_impl : public server_socket_impl {
explicit posix_reuseport_server_socket_impl(socket_address sa, pollable_fd lfd) : _sa(sa), _lfd(std::move(lfd)) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_reuseport_server_tcp_socket_impl = posix_reuseport_server_socket_impl<transport::TCP>;
using posix_reuseport_server_sctp_socket_impl = posix_reuseport_server_socket_impl<transport::SCTP>;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
index 70fb51f9..47901fb0 100644
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -55,6 +55,7 @@ class server_socket_impl {
virtual ~server_socket_impl() {}
virtual future<connected_socket, socket_address> accept() = 0;
virtual void abort_accept() = 0;
+ virtual socket_address local_address() const = 0;
};

class udp_channel_impl {
diff --git a/include/seastar/net/tcp.hh b/include/seastar/net/tcp.hh
index 4b9ca96a..a606d09d 100644
--- a/include/seastar/net/tcp.hh
+++ b/include/seastar/net/tcp.hh
@@ -662,6 +662,9 @@ class tcp {
semaphore _queue_space = {212992};
metrics::metric_groups _metrics;
public:
+ const inet_type& inet() const {
+ return _inet;
+ }
class connection {
lw_shared_ptr<tcb> _tcb;
public:
@@ -733,6 +736,13 @@ class tcp {
bool full() { return _pending + _q.size() >= _q.max_size(); }
void inc_pending() { _pending++; }
void dec_pending() { _pending--; }
+
+ const tcp& get_tcp() const {
+ return _tcp;
+ }
+ uint16_t port() const {
+ return _port;
+ }
friend class tcp;
};
public:
diff --git a/src/net/native-stack-impl.hh b/src/net/native-stack-impl.hh
index 07dfed45..4be2ca08 100644
--- a/src/net/native-stack-impl.hh
+++ b/src/net/native-stack-impl.hh
@@ -24,6 +24,7 @@
#include <seastar/core/reactor.hh>
#include <seastar/net/stack.hh>
#include <iostream>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -47,6 +48,7 @@ class native_server_socket_impl : public server_socket_impl {
native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};

template <typename Protocol>
@@ -70,6 +72,11 @@ native_server_socket_impl<Protocol>::abort_accept() {
_listener.abort_accept();
}

+template <typename Protocol>
+socket_address native_server_socket_impl<Protocol>::local_address() const {
+ return socket_address(_listener.get_tcp().inet().inet().host_address(), _listener.port());
+}
+
// native_connected_socket_impl
template <typename Protocol>
class native_connected_socket_impl : public connected_socket_impl {
diff --git a/tests/unit/loopback_socket.hh b/tests/unit/loopback_socket.hh
index 888b0692..064d5761 100644
--- a/tests/unit/loopback_socket.hh
+++ b/tests/unit/loopback_socket.hh
@@ -191,6 +191,10 @@ class loopback_server_socket_impl : public net::server_socket_impl {
void abort_accept() override {
_pending->abort(std::make_exception_ptr(std::system_error(ECONNABORTED, std::system_category())));
}
+ socket_address local_address() const override {
+ // CMH dummy
+ return {};
+ }
};


diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
index 81b6b2d1..f6d36216 100644
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -232,6 +232,11 @@ posix_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader();
}

+template <transport Transport>
+socket_address posix_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
future<connected_socket, socket_address> posix_ap_server_socket_impl<Transport>::accept() {
auto conni = conn_q.find(_sa);
@@ -284,6 +289,11 @@ posix_reuseport_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader();
}

+template <transport Transport>
+socket_address posix_reuseport_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
index 75c59cde..4956b02e 100644
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -164,6 +164,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

+socket_address server_socket::local_address() const {
+ return _ssi->local_address();
+}
+
socket_address::socket_address()
: socket_address(ipv4_addr())
{}
diff --git a/src/net/tls.cc b/src/net/tls.cc
index 96eababb..fd409004 100644
--- a/src/net/tls.cc
+++ b/src/net/tls.cc
@@ -1132,6 +1132,9 @@ class server_session : public net::server_socket_impl {
void abort_accept() override {
_sock.abort_accept();
}
+ socket_address local_address() const override {

Calle Wilund

<calle@scylladb.com>
unread,
Jan 30, 2019, 7:41:51 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
Borderline useless, but at least checks we can bind posix stack sockets
to ipv6.
---
tests/unit/ipv6_test.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++++
tests/unit/CMakeLists.txt | 3 ++
2 files changed, 108 insertions(+)
create mode 100644 tests/unit/ipv6_test.cc

diff --git a/tests/unit/ipv6_test.cc b/tests/unit/ipv6_test.cc
new file mode 100644
index 00000000..1295d441
--- /dev/null
+++ b/tests/unit/ipv6_test.cc
@@ -0,0 +1,105 @@
+/*
+ * This file is open source software, licensed to you under the terms
+ * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. You may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Copyright (C) 2019 Cloudius Systems, Ltd.
+ */
+
+#include <seastar/testing/test_case.hh>
+#include <seastar/net/api.hh>
+#include <seastar/net/inet_address.hh>
+#include <seastar/core/reactor.hh>
+#include <seastar/core/thread.hh>
+#include <seastar/util/log.hh>
+
+using namespace seastar;
+
+static logger iplog("ipv6");
+
+static bool check_ipv6_support() {
+ if (!engine().net().supports_ipv6()) {
+ iplog.info("No IPV6 support detected. Skipping...");
+ return false;
+ }
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index ac51078e..bd64767e 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -294,6 +294,9 @@ seastar_add_test (httpd
httpd_test.cc
loopback_socket.hh)

+seastar_add_test (ipv6
+ SOURCES ipv6_test.cc)
+
seastar_add_test (json_formatter
SOURCES json_formatter_test.cc)

--
2.14.5

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:14 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Add packed ipv6 address

Corresponding to ipv4_address, packed to potentially allow embedding in
non-aligned wire structures.

---
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -97,7 +97,51 @@ struct ipv4_address {

static inline bool is_unspecified(ipv4_address addr) { return addr.ip ==
0; }

-std::ostream& operator<<(std::ostream& os, ipv4_address a);
+std::ostream& operator<<(std::ostream& os, const ipv4_address& a);
+
+// IPv6
+struct ipv6_address {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ static_assert(alignof(ipv6_bytes) == 1);
+ static_assert(sizeof(ipv6_bytes) == 16);
+
+ ipv6_address();
+ explicit ipv6_address(const ::in6_addr&);
+ explicit ipv6_address(const ipv6_bytes&);
+ explicit ipv6_address(const std::string&);
+
+template <>
+struct hash<seastar::net::ipv6_address> {
+ size_t operator()(const seastar::net::ipv6_address&) const;
+};
+
}

namespace seastar {
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -21,13 +21,12 @@

#include <ostream>
#include <arpa/inet.h>
-
+#include <boost/functional/hash.hpp>
#include <seastar/net/inet_address.hh>
#include <seastar/net/socket_defs.hh>
#include <seastar/net/dns.hh>
#include <seastar/net/ip.hh>
-
-namespace seastar {
+#include <seastar/core/print.hh>

seastar::net::inet_address::inet_address()
: inet_address(::in_addr{ 0, })
@@ -112,6 +111,64 @@ const void * seastar::net::inet_address::data() const {
return &_in;
}

+seastar::net::ipv6_address::ipv6_address(const ::in6_addr& in) {
+ std::copy(std::begin(in.s6_addr), std::end(in.s6_addr), ip.begin());
+}
+
+seastar::net::ipv6_address::ipv6_address(const ipv6_bytes& in)
+ : ip(in)
+{}
+
+seastar::net::ipv6_address::ipv6_address()
+ : ipv6_address(::in6addr_any)
+{}
+
+seastar::net::ipv6_address::ipv6_address(const std::string& addr) {
+ if (!::inet_pton(AF_INET6, addr.c_str(), ip.data())) {
+ throw std::runtime_error(format("Wrong format for IPv6 address {}.
Please ensure it's in colon-hex format",
+ addr));
+ }
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::read(const char* s)
{
+ auto* b = reinterpret_cast<const uint8_t *>(s);
+ ipv6_address in;
+ std::copy(b, b + ipv6_address::size(), in.ip.begin());
+ return in;
+}
+
+seastar::net::ipv6_address seastar::net::ipv6_address::consume(const
char*& p) {
+ auto res = read(p);
+ p += size();
+ return res;
+}
+
+void seastar::net::ipv6_address::write(char* p) const {
+ std::copy(ip.begin(), ip.end(), p);
+}
+
+void seastar::net::ipv6_address::produce(char*& p) const {
+ write(p);
+ p += size();
+}
+
+bool seastar::net::ipv6_address::is_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b ==
0; });
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const
ipv4_address& a) {
+ auto ip = a.ip;
+ return fmt_print(os, "{:d}.{:d}.{:d}.{:d}",
+ (ip >> 24) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 0) & 0xff);
+}
+
+std::ostream& seastar::net::operator<<(std::ostream& os, const
ipv6_address& a) {
+ char buffer[64];
+ return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer,
sizeof(buffer));
+}

std::ostream& seastar::net::operator<<(std::ostream& os, const
inet_address& addr) {
char buffer[64];
@@ -132,11 +189,12 @@ std::ostream& seastar::net::operator<<(std::ostream&
os, const inet_address::fam
return os;
}

-std::ostream& operator<<(std::ostream& os, const socket_address& a) {
+std::ostream& seastar::operator<<(std::ostream& os, const
seastar::socket_address& a) {
return os <<
seastar::net::inet_address(a.as_posix_sockaddr_in().sin_addr)
<< ":" << ntohs(a.u.in.sin_port)
;
}

+size_t std::hash<seastar::net::ipv6_address>::operator()(const
seastar::net::ipv6_address& a) const {
+ return boost::hash_range(a.ip.begin(), a.ip.end());
}
-
diff --git a/src/net/ip.cc b/src/net/ip.cc
--- a/src/net/ip.cc
+++ b/src/net/ip.cc

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:15 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Add ipv6_address support to inet_address

---
diff --git a/include/seastar/net/inet_address.hh
b/include/seastar/net/inet_address.hh
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
@@ -34,6 +34,7 @@ namespace seastar {
namespace net {

struct ipv4_address;
+struct ipv6_address;

class unknown_host : public std::invalid_argument {
public:
@@ -42,7 +43,7 @@ public:

class inet_address {
public:
- enum class family {
+ enum class family : sa_family_t {
INET = AF_INET, INET6 = AF_INET6
};
private:
@@ -64,9 +65,11 @@ public:
inet_address(const inet_address&) = default;

inet_address(const ipv4_address&);
+ inet_address(const ipv6_address&);

// throws iff ipv6
ipv4_address as_ipv4_address() const;
+ ipv6_address as_ipv6_address() const;

inet_address& operator=(const inet_address&) = default;
bool operator==(const inet_address&) const;
@@ -75,11 +78,20 @@ public:
return _in_family;
}

+ bool is_ipv6() const {
+ return _in_family == family::INET6;
+ }
+ bool is_ipv4() const {
+ return _in_family == family::INET;
+ }
+
size_t size() const;
const void * data() const;

- operator const ::in_addr&() const;
- operator const ::in6_addr&() const;
+ operator ::in_addr() const;
+ operator ::in6_addr() const;
+
+ operator ipv6_address() const;

future<sstring> hostname() const;
future<std::vector<sstring>> aliases() const;
@@ -95,3 +107,10 @@ std::ostream& operator<<(std::ostream&, const
inet_address::family&);

}
}
+
+namespace std {
+template<>
+struct hash<seastar::net::inet_address> {
+ size_t operator()(const seastar::net::inet_address&) const;
+};
+}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -29,7 +29,7 @@
#include <seastar/core/print.hh>

seastar::net::inet_address::inet_address()
- : inet_address(::in_addr{ 0, })
+ : inet_address(::in6_addr{ 0, })
{}

seastar::net::inet_address::inet_address(::in_addr i)
@@ -60,11 +60,13 @@ seastar::net::inet_address::inet_address(const
ipv4_address& in)
{}

seastar::net::ipv4_address seastar::net::inet_address::as_ipv4_address()
const {
- if (_in_family != family::INET) {
- // TODO: ipv4-compatible ipv6
- throw std::invalid_argument("Not an IPv4 address");
- }
- return ipv4_address(ntoh(_in.s_addr));
+ in_addr in = *this;
+ return ipv4_address(ntoh(in.s_addr));
+}
+
+seastar::net::ipv6_address seastar::net::inet_address::as_ipv6_address()
const {
+ in6_addr in6 = *this;
+ return ipv6_address{in6};
}

bool seastar::net::inet_address::operator==(const inet_address& o) const {
@@ -82,20 +84,32 @@ bool seastar::net::inet_address::operator==(const
inet_address& o) const {
}
}

-seastar::net::inet_address::operator const ::in_addr&() const {
+seastar::net::inet_address::operator ::in_addr() const {
if (_in_family != family::INET) {
- throw std::invalid_argument("Not an ipv4 address");
+ if (IN6_IS_ADDR_V4MAPPED(&_in6)) {
+ ::in_addr in;
+ in.s_addr = _in6.s6_addr32[3];
+ return in;
+ }
+ throw std::invalid_argument("Not an IPv4 address");
}
return _in;
}

-seastar::net::inet_address::operator const ::in6_addr&() const {
- if (_in_family != family::INET6) {
- throw std::invalid_argument("Not an ipv6 address");
+seastar::net::inet_address::operator ::in6_addr() const {
+ if (_in_family == family::INET) {
+ in6_addr in6 = IN6ADDR_ANY_INIT;
+ in6.s6_addr32[2] = ::htonl(0xffff);
+ in6.s6_addr32[3] = _in.s_addr;
+ return in6;
}
return _in6;
}

+seastar::net::inet_address::operator seastar::net::ipv6_address() const {
+ return as_ipv6_address();
+}
+
size_t seastar::net::inet_address::size() const {
switch (_in_family) {
case family::INET:
@@ -195,6 +209,17 @@ std::ostream& seastar::operator<<(std::ostream& os,
const seastar::socket_addres
;
}

+size_t std::hash<seastar::net::inet_address>::operator()(const
seastar::net::inet_address& a) const {
+ switch (a.in_family()) {
+ case seastar::net::inet_address::family::INET:
+ return
std::hash<seastar::net::ipv4_address>()(a.as_ipv4_address());
+ case seastar::net::inet_address::family::INET6:
+ return
std::hash<seastar::net::ipv6_address>()(a.as_ipv6_address());
+ default:
+ return 0;
+ }
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const
seastar::net::ipv6_address& a) const {
return boost::hash_range(a.ip.begin(), a.ip.end());
}

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:16 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Add ipv6_addr

Like ipv4_addr, i.e. wraps address + port. Badly named, but akin to a
host endian sock_addr_in6.

---
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -44,6 +44,8 @@

namespace seastar {

+struct ipv6_addr;
+
namespace net {

class ipv4;
@@ -110,6 +112,7 @@ struct ipv6_address {
explicit ipv6_address(const ::in6_addr&);
explicit ipv6_address(const ipv6_bytes&);
explicit ipv6_address(const std::string&);
+ ipv6_address(const ipv6_addr& addr);

// No need to use packed - we only store
// as byte array. If we want to read as
diff --git a/include/seastar/net/socket_defs.hh
b/include/seastar/net/socket_defs.hh
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -21,6 +21,7 @@
#pragma once

#include <iosfwd>
+#include <array>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <seastar/net/byteorder.hh>
@@ -76,8 +77,26 @@ struct ipv4_addr {
ip = net::ntoh(sa.u.in.sin_addr.s_addr);
port = net::ntoh(sa.u.in.sin_port);
}
+};
+
+struct ipv6_addr {
+ using ipv6_bytes = std::array<uint8_t, 16>;
+
+ ipv6_bytes ip;
+ uint16_t port;
+
+ ipv6_addr(const ipv6_bytes&, uint16_t port = 0);
+ ipv6_addr(uint16_t port = 0);
+ ipv6_addr(const std::string&);
+ ipv6_addr(const std::string&, uint16_t port);
+ ipv6_addr(const net::inet_address&, uint16_t = 0);
+ ipv6_addr(const ::in6_addr&, uint16_t = 0);
+ ipv6_addr(const ::sockaddr_in6&);

- ipv4_addr(socket_address &&sa) : ipv4_addr(sa) {}
+ bool is_ip_unspecified() const;
+ bool is_port_unspecified() const {
+ return port == 0;
+ }
};

}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -133,6 +133,10 @@ seastar::net::ipv6_address::ipv6_address(const
ipv6_bytes& in)
: ip(in)
{}

+seastar::net::ipv6_address::ipv6_address(const ipv6_addr& addr)
+ : ipv6_address(addr.ip)
+{}
+
seastar::net::ipv6_address::ipv6_address()
: ipv6_address(::in6addr_any)
{}
@@ -184,6 +188,48 @@ std::ostream& seastar::net::operator<<(std::ostream&
os, const ipv6_address& a)
return os << ::inet_ntop(AF_INET6, a.ip.data(), buffer,
sizeof(buffer));
}

+bool seastar::ipv6_addr::is_ip_unspecified() const {
+ return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b ==
0; });
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const
inet_address& addr) {
char buffer[64];

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:18 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Add ipv6 support to socket_address

---
diff --git a/include/seastar/net/socket_defs.hh
b/include/seastar/net/socket_defs.hh
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -28,24 +28,42 @@

namespace seastar {

+namespace net {
+class inet_address;
+}
+
struct ipv4_addr;
+struct ipv6_addr;

class socket_address {
public:
union {
::sockaddr_storage sas;
::sockaddr sa;
::sockaddr_in in;
+ ::sockaddr_in6 in6;
} u;
- socket_address(sockaddr_in sa) {
+ socket_address(const sockaddr_in& sa) {
u.in = sa;
}
+ socket_address(const sockaddr_in6& sa) {
+ u.in6 = sa;
+ }
socket_address(ipv4_addr);
+ socket_address(const ipv6_addr&);
+ socket_address(const net::inet_address&, uint16_t p = 0);
socket_address() = default;
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
+ ::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
const ::sockaddr& as_posix_sockaddr() const { return u.sa; }
const ::sockaddr_in& as_posix_sockaddr_in() const { return u.in; }
+ const ::sockaddr_in6& as_posix_sockaddr_in6() const { return u.in6; }
+
+ socket_address(uint32_t, uint16_t p = 0);
+
+ net::inet_address addr() const;
+ ::in_port_t port() const;

bool operator==(const socket_address&) const;
};
@@ -58,10 +76,6 @@ enum class transport {
};


-namespace net {
-class inet_address;
-}
-
struct ipv4_addr {
uint32_t ip;
uint16_t port;
@@ -72,10 +86,14 @@ struct ipv4_addr {
ipv4_addr(const std::string &addr);
ipv4_addr(const std::string &addr, uint16_t port);
ipv4_addr(const net::inet_address&, uint16_t);
+ ipv4_addr(const socket_address &);
+ ipv4_addr(const ::in_addr&, uint16_t = 0);

- ipv4_addr(const socket_address &sa) {
- ip = net::ntoh(sa.u.in.sin_addr.s_addr);
- port = net::ntoh(sa.u.in.sin_port);
+ bool is_ip_unspecified() const {
+ return ip == 0;
+ }
+ bool is_port_unspecified() const {
+ return port == 0;
}
};

@@ -92,11 +110,22 @@ struct ipv6_addr {
ipv6_addr(const net::inet_address&, uint16_t = 0);
ipv6_addr(const ::in6_addr&, uint16_t = 0);
ipv6_addr(const ::sockaddr_in6&);
+ ipv6_addr(const socket_address&);

bool is_ip_unspecified() const;
bool is_port_unspecified() const {
return port == 0;
}
};

+std::ostream& operator<<(std::ostream&, const ipv4_addr&);
+std::ostream& operator<<(std::ostream&, const ipv6_addr&);
+
+}
+
+namespace std {
+template<>
+struct hash<seastar::socket_address> {
+ size_t operator()(const seastar::socket_address&) const;
+};
}
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -230,6 +230,25 @@ bool seastar::ipv6_addr::is_ip_unspecified() const {
return std::all_of(ip.begin(), ip.end(), [](uint8_t b) { return b ==
0; });
}

+seastar::socket_address::socket_address(const net::inet_address& a,
uint16_t p)
+ : socket_address(a.is_ipv6() ? socket_address(ipv6_addr(a, p)) :
socket_address(ipv4_addr(a, p)))
+{}
+
+seastar::net::inet_address seastar::socket_address::addr() const {
+ switch (as_posix_sockaddr().sa_family) {
+ case AF_INET:
+ return net::inet_address(as_posix_sockaddr_in().sin_addr);
+ case AF_INET6:
+ return net::inet_address(as_posix_sockaddr_in6().sin6_addr);
+ default:
+ return net::inet_address();
+ }
+}
+
+::in_port_t seastar::socket_address::port() const {
+ return net::ntoh(u.in.sin_port);
+}
+
std::ostream& seastar::net::operator<<(std::ostream& os, const
inet_address& addr) {
char buffer[64];
return os << inet_ntop(int(addr.in_family()), addr.data(), buffer,
sizeof(buffer));
@@ -249,10 +268,28 @@ std::ostream& seastar::net::operator<<(std::ostream&
os, const inet_address::fam
return os;
}

-std::ostream& seastar::operator<<(std::ostream& os, const
seastar::socket_address& a) {
- return os <<
seastar::net::inet_address(a.as_posix_sockaddr_in().sin_addr)
- << ":" << ntohs(a.u.in.sin_port)
- ;
+std::ostream& seastar::operator<<(std::ostream& os, const socket_address&
a) {
+ auto addr = a.addr();
+ // CMH. maybe skip brackets for ipv4-mapped
+ auto bracket = addr.in_family() ==
seastar::net::inet_address::family::INET6;
+
+ if (bracket) {
+ os << '[';
+ }
+ os << addr;
+ if (bracket) {
+ os << ']';
+ }
+
+ return os << ':' << ntohs(a.u.in.sin_port);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv4_addr& a) {
+ return os << seastar::socket_address(a);
+}
+
+std::ostream& seastar::operator<<(std::ostream& os, const ipv6_addr& a) {
+ return os << seastar::socket_address(a);
}

size_t std::hash<seastar::net::inet_address>::operator()(const
seastar::net::inet_address& a) const {
@@ -266,6 +303,12 @@ size_t
std::hash<seastar::net::inet_address>::operator()(const seastar::net::ine
}
}

+size_t std::hash<seastar::socket_address>::operator()(const
seastar::socket_address& a) const {
+ auto h = std::hash<seastar::net::inet_address>()(a.addr());
+ boost::hash_combine(h, a.as_posix_sockaddr_in().sin_port);
+ return h;
+}
+
size_t std::hash<seastar::net::ipv6_address>::operator()(const
seastar::net::ipv6_address& a) const {
return boost::hash_range(a.ip.begin(), a.ip.end());
}
diff --git a/src/net/net.cc b/src/net/net.cc
--- a/src/net/net.cc
+++ b/src/net/net.cc
@@ -59,10 +59,15 @@ ipv4_addr::ipv4_addr(const std::string &addr) {
ipv4_addr::ipv4_addr(const std::string &addr, uint16_t port_) :
ip(boost::asio::ip::address_v4::from_string(addr).to_ulong()), port(port_)
{}

ipv4_addr::ipv4_addr(const net::inet_address& a, uint16_t port)
- : ipv4_addr([&a] {
- ::in_addr in = a;
- return net::ntoh(in.s_addr);
-}(), port)
+ : ipv4_addr(::in_addr(a), port)
+{}
+
+ipv4_addr::ipv4_addr(const socket_address &sa)
+ : ipv4_addr(sa.addr(), sa.port())
+{}
+
+ipv4_addr::ipv4_addr(const ::in_addr& in, uint16_t p)
+ : ip(net::ntoh(in.s_addr)), port(p)
{}

namespace net {
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -160,15 +160,43 @@ void server_socket::abort_accept() {
}

socket_address::socket_address(ipv4_addr addr)
- : socket_address(make_ipv4_address(addr))
-{}
+{
+ u.in.sin_family = AF_INET;
+ u.in.sin_port = htons(addr.port);
+ u.in.sin_addr.s_addr = htonl(addr.ip);
+}

+socket_address::socket_address(const ipv6_addr& addr)
+{
+ u.in6.sin6_family = AF_INET6;
+ u.in6.sin6_port = htons(addr.port);
+ std::copy(addr.ip.begin(), addr.ip.end(), u.in6.sin6_addr.s6_addr);
+}
+
+socket_address::socket_address(uint32_t ipv4, uint16_t p)
+ : socket_address(make_ipv4_address(ipv4, p))
+{}

bool socket_address::operator==(const socket_address& a) const {
- // TODO: handle ipv6
- return std::tie(u.in.sin_family, u.in.sin_port, u.in.sin_addr.s_addr)
- == std::tie(a.u.in.sin_family, a.u.in.sin_port,
- a.u.in.sin_addr.s_addr);
+ if (u.sa.sa_family != a.u.sa.sa_family) {
+ return false;
+ }
+ if (u.in.sin_port != a.u.in.sin_port) {
+ return false;
+ }
+ switch (u.sa.sa_family) {
+ case AF_INET:
+ return u.in.sin_addr.s_addr == a.u.in.sin_addr.s_addr;
+ case AF_INET6:
+ break;
+ default:
+ return false;
+ }
+

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:19 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Make socket_address default constructor ipv4 any

---
diff --git a/include/seastar/net/socket_defs.hh
b/include/seastar/net/socket_defs.hh
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -52,7 +52,7 @@ public:
socket_address(ipv4_addr);
socket_address(const ipv6_addr&);
socket_address(const net::inet_address&, uint16_t p = 0);
- socket_address() = default;
+ socket_address();
::sockaddr& as_posix_sockaddr() { return u.sa; }
::sockaddr_in& as_posix_sockaddr_in() { return u.in; }
::sockaddr_in6& as_posix_sockaddr_in6() { return u.in6; }
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -159,6 +159,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

+socket_address::socket_address()
+ : socket_address(ipv4_addr())

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:20 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Add socket address uint16_t port only constructor -> ipv4 0.0.0.0:port

---
diff --git a/include/seastar/net/socket_defs.hh
b/include/seastar/net/socket_defs.hh
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -49,6 +49,7 @@ public:
socket_address(const sockaddr_in6& sa) {
u.in6 = sa;
}
+ socket_address(uint16_t);
socket_address(ipv4_addr);
socket_address(const ipv6_addr&);
socket_address(const net::inet_address&, uint16_t p = 0);
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -163,6 +163,10 @@ socket_address::socket_address()
: socket_address(ipv4_addr())
{}

+socket_address::socket_address(uint16_t p)
+ : socket_address(ipv4_addr(p))

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:21 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

socket_address: Add != operator

---
diff --git a/include/seastar/net/socket_defs.hh
b/include/seastar/net/socket_defs.hh
--- a/include/seastar/net/socket_defs.hh
+++ b/include/seastar/net/socket_defs.hh
@@ -67,6 +67,9 @@ public:
::in_port_t port() const;

bool operator==(const socket_address&) const;
+ bool operator!=(const socket_address& a) const {
+ return !(*this == a);
+ }
};

std::ostream& operator<<(std::ostream&, const socket_address&);

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:22 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Cleanup and de-inline some helper functions

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:24 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

inet_address: Add wildcard constructor from family

Corresponding to AF_INET/AF_INET6 + zeroed addr

---
diff --git a/include/seastar/net/inet_address.hh
b/include/seastar/net/inet_address.hh
--- a/include/seastar/net/inet_address.hh
+++ b/include/seastar/net/inet_address.hh
@@ -56,6 +56,7 @@ private:
public:

inet_address();
+ inet_address(family);
inet_address(::in_addr i);
inet_address(::in6_addr i);
// NOTE: does _not_ resolve the address. Only parses
diff --git a/src/net/inet_address.cc b/src/net/inet_address.cc
--- a/src/net/inet_address.cc
+++ b/src/net/inet_address.cc
@@ -32,6 +32,12 @@ seastar::net::inet_address::inet_address()
: inet_address(::in6_addr{ 0, })
{}

+seastar::net::inet_address::inet_address(family f)
+ : _in_family(f)
+{
+ memset(&_in6, 0, sizeof(_in6));
+}
+
seastar::net::inet_address::inet_address(::in_addr i)
: _in_family(family::INET), _in(i) {
}

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:25 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

Posix-stack: Add ipv6 support for tcp

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -283,11 +283,7 @@ public:
virtual ~network_stack() {}
virtual server_socket listen(socket_address sa, listen_options opts) =
0;
// FIXME: local parameter assumes ipv4 for now, fix when adding other
AF
- future<connected_socket> connect(socket_address sa, socket_address
local = socket_address(::sockaddr_in{AF_INET, INADDR_ANY, {0}}), transport
proto = transport::TCP) {
- return do_with(socket(), [sa, local, proto](::seastar::socket& s) {
- return s.connect(sa, local, proto);
- });
- }
+ future<connected_socket> connect(socket_address sa, socket_address =
{}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
virtual future<> initialize() {
diff --git a/include/seastar/net/posix-stack.hh
b/include/seastar/net/posix-stack.hh
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -130,8 +130,8 @@ class posix_ap_server_socket_impl : public
server_socket_impl {
socket_address addr;
connection(pollable_fd xfd, socket_address xaddr) :
fd(std::move(xfd)), addr(xaddr) {}
};
- static thread_local std::unordered_map<::sockaddr_in,
promise<connected_socket, socket_address>> sockets;
- static thread_local std::unordered_multimap<::sockaddr_in, connection>
conn_q;
+ static thread_local std::unordered_map<socket_address,
promise<connected_socket, socket_address>> sockets;
+ static thread_local std::unordered_multimap<socket_address,
connection> conn_q;
socket_address _sa;
public:
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -234,7 +234,7 @@ posix_server_socket_impl<Transport>::abort_accept() {

template <transport Transport>
future<connected_socket, socket_address>
posix_ap_server_socket_impl<Transport>::accept() {
- auto conni = conn_q.find(_sa.as_posix_sockaddr_in());
+ auto conni = conn_q.find(_sa);
if (conni != conn_q.end()) {
connection c = std::move(conni->second);
conn_q.erase(conni);
@@ -247,7 +247,7 @@ future<connected_socket, socket_address>
posix_ap_server_socket_impl<Transport>:
}
} else {
try {
- auto i = sockets.emplace(std::piecewise_construct,
std::make_tuple(_sa.as_posix_sockaddr_in()), std::make_tuple());
+ auto i = sockets.emplace(std::piecewise_construct,
std::make_tuple(_sa), std::make_tuple());
assert(i.second);
return i.first->second.get_future();
} catch (...) {
@@ -259,7 +259,7 @@ future<connected_socket, socket_address>
posix_ap_server_socket_impl<Transport>:
template <transport Transport>
void
posix_ap_server_socket_impl<Transport>::abort_accept() {
- conn_q.erase(_sa.as_posix_sockaddr_in());
+ conn_q.erase(_sa);
auto i = sockets.find(_sa.as_posix_sockaddr_in());
if (i != sockets.end()) {
i->second.set_exception(std::system_error(ECONNABORTED,
std::system_category()));
@@ -287,7 +287,7 @@
posix_reuseport_server_socket_impl<Transport>::abort_accept() {
template <transport Transport>
void

posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address
sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
posix_ap_network_stack::listen(socket_address sa, listen_options opt) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -20,6 +20,7 @@
*/

#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>
#include <seastar/core/reactor.hh>

namespace seastar {
@@ -207,4 +208,14 @@ bool socket_address::operator==(const socket_address&
a) const {

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:26 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

UDP: redefine address used as socket_address

UPD interface/packets are hardcoded to use ipv4_addr as dest/source
addresses. Redefine this to instead use socket_address, which contains
all the multiplexing needed to handle optional ipv6.

Since socket_address also translated transparently to ipv4_addr,
existing programs should continue to work as before (more or less).

Adds actual ipv6 support to posix stack UDP.

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -83,8 +83,8 @@ class get_impl;
class udp_datagram_impl {
public:
virtual ~udp_datagram_impl() {};
- virtual ipv4_addr get_src() = 0;
- virtual ipv4_addr get_dst() = 0;
+ virtual socket_address get_src() = 0;
+ virtual socket_address get_dst() = 0;
virtual uint16_t get_dst_port() = 0;
virtual packet& get_data() = 0;
};
@@ -94,8 +94,8 @@ private:
std::unique_ptr<udp_datagram_impl> _impl;
public:
udp_datagram(std::unique_ptr<udp_datagram_impl>&& impl) :
_impl(std::move(impl)) {};
- ipv4_addr get_src() { return _impl->get_src(); }
- ipv4_addr get_dst() { return _impl->get_dst(); }
+ socket_address get_src() { return _impl->get_src(); }
+ socket_address get_dst() { return _impl->get_dst(); }
uint16_t get_dst_port() { return _impl->get_dst_port(); }
packet& get_data() { return _impl->get_data(); }
};
@@ -112,8 +112,8 @@ public:
udp_channel& operator=(udp_channel&&);

future<udp_datagram> receive();
- future<> send(ipv4_addr dst, const char* msg);
- future<> send(ipv4_addr dst, packet p);
+ future<> send(const socket_address& dst, const char* msg);
+ future<> send(const socket_address& dst, packet p);
bool is_closed() const;
/// Causes a pending receive() to complete (possibly with an exception)
void shutdown_input();
@@ -285,7 +285,7 @@ public:
// FIXME: local parameter assumes ipv4 for now, fix when adding other
AF
future<connected_socket> connect(socket_address sa, socket_address =
{}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr = {}) = 0;
+ virtual net::udp_channel make_udp_channel(const socket_address& = {})
= 0;
virtual future<> initialize() {
return make_ready_future();
}
diff --git a/include/seastar/net/posix-stack.hh
b/include/seastar/net/posix-stack.hh
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -175,7 +175,7 @@ public:
explicit posix_network_stack(boost::program_options::variables_map
opts) : _reuseport(engine().posix_reuseport_available()) {}
virtual server_socket listen(socket_address sa, listen_options opts)
override;
virtual ::seastar::socket socket() override;
- virtual net::udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual net::udp_channel make_udp_channel(const socket_address&)
override;
static future<std::unique_ptr<network_stack>>
create(boost::program_options::variables_map opts) {
return
make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new
posix_network_stack(opts)));
}
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -61,8 +61,8 @@ class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
virtual future<udp_datagram> receive() = 0;
- virtual future<> send(ipv4_addr dst, const char* msg) = 0;
- virtual future<> send(ipv4_addr dst, packet p) = 0;
+ virtual future<> send(const socket_address& dst, const char* msg) = 0;
+ virtual future<> send(const socket_address& dst, packet p) = 0;
virtual void shutdown_input() = 0;
virtual void shutdown_output() = 0;
virtual bool is_closed() const = 0;
diff --git a/src/net/native-stack.cc b/src/net/native-stack.cc
--- a/src/net/native-stack.cc
+++ b/src/net/native-stack.cc
@@ -151,7 +151,7 @@ class native_network_stack : public network_stack {
explicit native_network_stack(boost::program_options::variables_map
opts, std::shared_ptr<device> dev);
virtual server_socket listen(socket_address sa, listen_options opt)
override;
virtual ::seastar::socket socket() override;
- virtual udp_channel make_udp_channel(ipv4_addr addr) override;
+ virtual udp_channel make_udp_channel(const socket_address& addr)
override;
virtual future<> initialize() override;
static future<std::unique_ptr<network_stack>>
create(boost::program_options::variables_map opts) {
if (engine().cpu_id() == 0) {
@@ -169,7 +169,7 @@ class native_network_stack : public network_stack {
thread_local promise<std::unique_ptr<network_stack>>
native_network_stack::ready_promise;

udp_channel
-native_network_stack::make_udp_channel(ipv4_addr addr) {
+native_network_stack::make_udp_channel(const socket_address& addr) {
return _inet.get_udp().make_channel(addr);
}

diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -392,7 +392,10 @@ posix_ap_network_stack::listen(socket_address sa,
listen_options opt) {

struct cmsg_with_pktinfo {
struct cmsghdrcmh;
- struct in_pktinfo pktinfo;
+ union {
+ struct in_pktinfo pktinfo;
+ struct in6_pktinfo pkt6info;
+ };
};

class posix_udp_channel : public udp_channel_impl {
@@ -434,36 +437,36 @@ class posix_udp_channel : public udp_channel_impl {
_hdr.msg_namelen = sizeof(_dst.u.sas);
}

- void prepare(ipv4_addr dst, packet p) {
- _dst = make_ipv4_address(dst);
+ void prepare(const socket_address& dst, packet p) {
+ _dst = dst;
_p = std::move(p);
_iovecs = to_iovec(_p);
_hdr.msg_iov = _iovecs.data();
_hdr.msg_iovlen = _iovecs.size();
@@ -477,42 +480,51 @@ class posix_udp_channel : public udp_channel_impl {
virtual bool is_closed() const override { return _closed; }
};

-future<> posix_udp_channel::send(ipv4_addr dst, const char *message) {
+future<> posix_udp_channel::send(const socket_address& dst, const char
*message) {
auto len = strlen(message);
- return _fd->sendto(make_ipv4_address(dst), message, len)
+ return _fd->sendto(dst, message, len)
.then([len] (size_t size) { assert(size == len); });
}

-future<> posix_udp_channel::send(ipv4_addr dst, packet p) {
+future<> posix_udp_channel::send(const socket_address& dst, packet p) {
auto len = p.len();
_send.prepare(dst, std::move(p));
return _fd->sendmsg(&_send._hdr)
.then([len] (size_t size) { assert(size == len); });
}

udp_channel
-posix_network_stack::make_udp_channel(ipv4_addr addr) {
+posix_network_stack::make_udp_channel(const socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

class posix_datagram : public udp_datagram_impl {
private:
- ipv4_addr _src;
- ipv4_addr _dst;
+ socket_address _src;
+ socket_address _dst;
packet _p;
public:
- posix_datagram(ipv4_addr src, ipv4_addr dst, packet p) : _src(src),
_dst(dst), _p(std::move(p)) {}
- virtual ipv4_addr get_src() override { return _src; }
- virtual ipv4_addr get_dst() override { return _dst; }
- virtual uint16_t get_dst_port() override { return _dst.port; }
+ posix_datagram(const socket_address& src, const socket_address& dst,
packet p) : _src(src), _dst(dst), _p(std::move(p)) {}
+ virtual socket_address get_src() override { return _src; }
+ virtual socket_address get_dst() override { return _dst; }
+ virtual uint16_t get_dst_port() override { return _dst.port(); }
virtual packet& get_data() override { return _p; }
};

diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -41,12 +41,12 @@ future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}

-future<> net::udp_channel::send(ipv4_addr dst, const char* msg) {
- return _impl->send(std::move(dst), msg);
+future<> net::udp_channel::send(const socket_address& dst, const char*
msg) {
+ return _impl->send(dst, msg);
}

-future<> net::udp_channel::send(ipv4_addr dst, packet p) {
- return _impl->send(std::move(dst), std::move(p));
+future<> net::udp_channel::send(const socket_address& dst, packet p) {
+ return _impl->send(dst, std::move(p));
}

bool net::udp_channel::is_closed() const {
diff --git a/src/net/udp.cc b/src/net/udp.cc
--- a/src/net/udp.cc
+++ b/src/net/udp.cc

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:27 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

RPC: move log to cc file

---
diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -169,17 +169,11 @@ public:
_logger = std::move(l);
}

- void operator()(const client_info& info, id_type msg_id, const
sstring& str) const {
- log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " +
to_sstring(msg_id) + ": " + str);
- }
+ void operator()(const client_info& info, id_type msg_id, const
sstring& str) const;

- void operator()(const client_info& info, const sstring& str) const {
- log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
- }
+ void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)})
+ ": " + str);
- }
+ void operator()(ipv4_addr addr, const sstring& str) const;
};

class connection {
diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -5,6 +5,19 @@
namespace seastar {

namespace rpc {
+
+ void logger::operator()(const client_info& info, id_type msg_id, const
sstring& str) const {
+ log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " +
to_sstring(msg_id) + ": " + str);
+ }
+
+ void logger::operator()(const client_info& info, const sstring& str)
const {
+ log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ }
+
+ void logger::operator()(ipv4_addr addr, const sstring& str) const {
+ log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)})
+ ": " + str);
+ }

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:28 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

RCP: make rpc use socket_address to support ipv6

---
diff --git a/include/seastar/rpc/rpc.hh b/include/seastar/rpc/rpc.hh
--- a/include/seastar/rpc/rpc.hh
+++ b/include/seastar/rpc/rpc.hh
@@ -173,7 +173,7 @@ public:

void operator()(const client_info& info, const sstring& str) const;

- void operator()(ipv4_addr addr, const sstring& str) const;
+ void operator()(const socket_address& addr, const sstring& str) const;
};

class connection {
@@ -287,7 +287,7 @@ public:
}
xshard_connection_ptr get_stream(connection_id id) const;
void register_stream(connection_id id, xshard_connection_ptr c);
- virtual ipv4_addr peer_address() const = 0;
+ virtual socket_address peer_address() const = 0;

const logger& get_logger() const {
return _logger;
@@ -360,7 +360,7 @@ public:
};
private:
std::unordered_map<id_type, std::unique_ptr<reply_handler_base>>
_outstanding;
- ipv4_addr _server_addr;
+ socket_address _server_addr;
client_options _options;
compat::optional<shared_promise<>> _client_negotiated =
shared_promise<>();
weak_ptr<client> _parent; // for stream clients
@@ -386,8 +386,8 @@ public:
* @param addr the remote address identifying this client
* @param local the local address of this client
*/
- client(const logger& l, void* s, ipv4_addr addr, ipv4_addr local =
ipv4_addr());
- client(const logger& l, void* s, client_options options, ipv4_addr
addr, ipv4_addr local = ipv4_addr());
+ client(const logger& l, void* s, const socket_address& addr, const
socket_address& local = {});
+ client(const logger& l, void* s, client_options options, const
socket_address& addr, const socket_address& local = {});

/**
* Create client object which will attempt to connect to the remote
address using the
@@ -397,8 +397,8 @@ public:
* @param local the local address of this client
* @param socket the socket object use to connect to the remote address
*/
- client(const logger& l, void* s, socket socket, ipv4_addr addr,
ipv4_addr local = ipv4_addr());
- client(const logger& l, void* s, client_options options, socket
socket, ipv4_addr addr, ipv4_addr local = ipv4_addr());
+ client(const logger& l, void* s, socket socket, const socket_address&
addr, const socket_address& local = {});
+ client(const logger& l, void* s, client_options options, socket
socket, const socket_address& addr, const socket_address& local = {});

stats get_stats() const;
stats& get_stats_internal() {
@@ -410,7 +410,7 @@ public:
future<> stop();
void abort_all_streams();
void deregister_this_stream();
- ipv4_addr peer_address() const override {
+ socket_address peer_address() const override {
return _server_addr;
}
future<> await_connection() {
@@ -484,8 +484,8 @@ public:
stats& get_stats_internal() {
return _stats;
}
- ipv4_addr peer_address() const override {
- return ipv4_addr(_info.addr);
+ socket_address peer_address() const override {
+ return _info.addr;
}
// Resources will be released when this goes out of scope
future<resource_permit> wait_for_resources(size_t
memory_consumed, compat::optional<rpc_clock_type::time_point> timeout) {
@@ -518,8 +518,8 @@ private:
@@ -577,9 +577,9 @@ public:
* @param addr the remote address identifying this client
* @param local the local address of this client
*/
- client(protocol& p, ipv4_addr addr, ipv4_addr local =
ipv4_addr()) :
+ client(protocol& p, const socket_address& addr, const
socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, addr, local) {}
- client(protocol& p, client_options options, ipv4_addr addr,
ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, client_options options, const socket_address&
addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, options, addr,
local) {}

/**
@@ -590,9 +590,9 @@ public:
* @param local the local address of this client
* @param socket the socket object use to connect to the remote
address
*/
- client(protocol& p, socket socket, ipv4_addr addr, ipv4_addr local
= ipv4_addr()) :
+ client(protocol& p, socket socket, const socket_address& addr,
const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, std::move(socket),
addr, local) {}
- client(protocol& p, client_options options, socket socket,
ipv4_addr addr, ipv4_addr local = ipv4_addr()) :
+ client(protocol& p, client_options options, socket socket, const
socket_address& addr, const socket_address& local = {}) :
rpc::client(p.get_logger(), &p._serializer, options,
std::move(socket), addr, local) {}
};

diff --git a/src/rpc/rpc.cc b/src/rpc/rpc.cc
--- a/src/rpc/rpc.cc
+++ b/src/rpc/rpc.cc
@@ -7,15 +7,15 @@ namespace seastar {
namespace rpc {

void logger::operator()(const client_info& info, id_type msg_id, const
sstring& str) const {
- log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + " msg_id " +
to_sstring(msg_id) + ": " + str);
+ log(format("client {} msg_id {}: {}", info.addr, msg_id, str));
}

void logger::operator()(const client_info& info, const sstring& str)
const {
- log(to_sstring("client ") +
inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr) + ": " + str);
+ (*this)(info.addr, str);
}

- void logger::operator()(ipv4_addr addr, const sstring& str) const {
- log(to_sstring("client ") + inet_ntoa(in_addr{net::ntoh(addr.ip)})
+ ": " + str);
+ void logger::operator()(const socket_address& addr, const sstring&
str) const {

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:30 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

network_stack: Add ipv6 support query

While not 100% correct, since this should really be per interface etc,
it still allows us some info (hint hint tests)

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -290,6 +290,12 @@ public:
return make_ready_future();
}
virtual bool has_per_core_namespace() = 0;
+ // NOTE: this is not a correct query approach.
+ // This question should be per NIC, but we have no such
+ // abstraction, so for now this is "stack-wide"
+ virtual bool supports_ipv6() const {
+ return false;
+ }
};

}
diff --git a/include/seastar/net/posix-stack.hh
b/include/seastar/net/posix-stack.hh
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -180,6 +180,7 @@ public:
return
make_ready_future<std::unique_ptr<network_stack>>(std::unique_ptr<network_stack>(new
posix_network_stack(opts)));
}
virtual bool has_per_core_namespace() override { return _reuseport; };
+ bool supports_ipv6() const override;
};

class posix_ap_network_stack : public posix_network_stack {
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -498,6 +498,20 @@ posix_network_stack::make_udp_channel(const
socket_address& addr) {
return udp_channel(std::make_unique<posix_udp_channel>(addr));
}

+bool
+posix_network_stack::supports_ipv6() const {
+ static bool has_ipv6 = [] {
+ try {
+ posix_udp_channel c(ipv6_addr{});
+ c.close();
+ return true;
+ } catch (...) {}
+ return false;
+ }();
+
+ return has_ipv6;
+}
+
class posix_datagram : public udp_datagram_impl {
private:
socket_address _src;

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:31 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

udp_socket: Add local address accessor

It is somewhat useful to be able to query which address/port one got
when binding to wildcard.

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -111,6 +111,8 @@ public:
udp_channel(udp_channel&&);
udp_channel& operator=(udp_channel&&);

+ socket_address local_address() const;
+
future<udp_datagram> receive();
future<> send(const socket_address& dst, const char* msg);
future<> send(const socket_address& dst, packet p);
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -330,6 +330,10 @@ public:
void send(uint16_t src_port, ipv4_addr dst, packet &&p);
bool forward(forward_hash& out_hash_data, packet& p, size_t off)
override;
void set_queue_size(int size) { _queue_size = size; }
+
+ const ipv4& inet() const {
+ return _inet;
+ }
};

struct ip_hdr;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -60,6 +60,7 @@ public:
class udp_channel_impl {
public:
virtual ~udp_channel_impl() {};
+ virtual socket_address local_address() const = 0;
virtual future<udp_datagram> receive() = 0;
virtual future<> send(const socket_address& dst, const char* msg) = 0;
virtual future<> send(const socket_address& dst, packet p) = 0;
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -478,6 +478,9 @@ class posix_udp_channel : public udp_channel_impl {
_fd.reset();
}
virtual bool is_closed() const override { return _closed; }
+ socket_address local_address() const override {
+ return _address;
+ }
};

future<> posix_udp_channel::send(const socket_address& dst, const char
*message) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -37,6 +37,10 @@ net::udp_channel::~udp_channel()
net::udp_channel::udp_channel(udp_channel&&) = default;
net::udp_channel& net::udp_channel::operator=(udp_channel&&) = default;

+socket_address net::udp_channel::local_address() const {
+ return _impl->local_address();
+}
+
future<net::udp_datagram> net::udp_channel::receive() {
return _impl->receive();
}
diff --git a/src/net/udp.cc b/src/net/udp.cc
--- a/src/net/udp.cc
+++ b/src/net/udp.cc
@@ -21,6 +21,7 @@

#include <seastar/net/ip.hh>
#include <seastar/net/stack.hh>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -89,6 +90,10 @@ class native_channel : public udp_channel_impl {
close();
}

+ socket_address local_address() const override {
+ return socket_address(_proto.inet().host_address(), _reg.port());
+ }
+
virtual future<udp_datagram> receive() override {
return _state->_queue.pop_eventually();
}

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:32 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

native_stack: Make host_address const

---
diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -436,7 +436,7 @@ private:
public:
explicit ipv4(interface* netif);
void set_host_address(ipv4_address ip);
- ipv4_address host_address();
+ ipv4_address host_address() const;
void set_gw_address(ipv4_address ip);
ipv4_address gw_address() const;
void set_netmask_address(ipv4_address ip);
diff --git a/src/net/ip.cc b/src/net/ip.cc
--- a/src/net/ip.cc
+++ b/src/net/ip.cc

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:33 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

server_socket: Add local address accessor

Because sometimes it helps to query which address/port a wildcard bind
bound to.

---
diff --git a/include/seastar/net/api.hh b/include/seastar/net/api.hh
--- a/include/seastar/net/api.hh
+++ b/include/seastar/net/api.hh
@@ -271,6 +271,9 @@ public:
/// Current and future \ref accept() calls will terminate immediately
/// with an error.
void abort_accept();
+
+ /// Local bound address
+ socket_address local_address() const;
};
/// @}

diff --git a/include/seastar/net/ip.hh b/include/seastar/net/ip.hh
--- a/include/seastar/net/ip.hh
+++ b/include/seastar/net/ip.hh
@@ -195,6 +195,9 @@ public:
ipv4_l4(ipv4& inet) : _inet(inet) {}
void register_packet_provider(ipv4_traits::packet_provider_type func);
future<ethernet_address> get_l2_dst_address(ipv4_address to);
+ const ipv4& inet() const {
+ return _inet;
+ }
};

class ip_protocol {
diff --git a/include/seastar/net/posix-stack.hh
b/include/seastar/net/posix-stack.hh
--- a/include/seastar/net/posix-stack.hh
+++ b/include/seastar/net/posix-stack.hh
@@ -137,6 +137,9 @@ public:
explicit posix_ap_server_socket_impl(socket_address sa) : _sa(sa) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ socket_address local_address() const override {
+ return _sa;
+ }
static void move_connected_socket(socket_address sa, pollable_fd fd,
socket_address addr, conntrack::handle handle);
};
using posix_tcp_ap_server_socket_impl =
posix_ap_server_socket_impl<transport::TCP>;
@@ -152,6 +155,7 @@ public:
explicit posix_server_socket_impl(socket_address sa, pollable_fd lfd,
server_socket::load_balancing_algorithm lba) : _sa(sa),
_lfd(std::move(lfd)), _lba(lba) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_server_tcp_socket_impl =
posix_server_socket_impl<transport::TCP>;
using posix_server_sctp_socket_impl =
posix_server_socket_impl<transport::SCTP>;
@@ -164,6 +168,7 @@ public:
explicit posix_reuseport_server_socket_impl(socket_address sa,
pollable_fd lfd) : _sa(sa), _lfd(std::move(lfd)) {}
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};
using posix_reuseport_server_tcp_socket_impl =
posix_reuseport_server_socket_impl<transport::TCP>;
using posix_reuseport_server_sctp_socket_impl =
posix_reuseport_server_socket_impl<transport::SCTP>;
diff --git a/include/seastar/net/stack.hh b/include/seastar/net/stack.hh
--- a/include/seastar/net/stack.hh
+++ b/include/seastar/net/stack.hh
@@ -55,6 +55,7 @@ public:
virtual ~server_socket_impl() {}
virtual future<connected_socket, socket_address> accept() = 0;
virtual void abort_accept() = 0;
+ virtual socket_address local_address() const = 0;
};

class udp_channel_impl {
diff --git a/include/seastar/net/tcp.hh b/include/seastar/net/tcp.hh
--- a/include/seastar/net/tcp.hh
+++ b/include/seastar/net/tcp.hh
@@ -662,6 +662,9 @@ private:
semaphore _queue_space = {212992};
metrics::metric_groups _metrics;
public:
+ const inet_type& inet() const {
+ return _inet;
+ }
class connection {
lw_shared_ptr<tcb> _tcb;
public:
@@ -733,6 +736,13 @@ public:
bool full() { return _pending + _q.size() >= _q.max_size(); }
void inc_pending() { _pending++; }
void dec_pending() { _pending--; }
+
+ const tcp& get_tcp() const {
+ return _tcp;
+ }
+ uint16_t port() const {
+ return _port;
+ }
friend class tcp;
};
public:
diff --git a/src/net/native-stack-impl.hh b/src/net/native-stack-impl.hh
--- a/src/net/native-stack-impl.hh
+++ b/src/net/native-stack-impl.hh
@@ -24,6 +24,7 @@
#include <seastar/core/reactor.hh>
#include <seastar/net/stack.hh>
#include <iostream>
+#include <seastar/net/inet_address.hh>

namespace seastar {

@@ -47,6 +48,7 @@ public:
native_server_socket_impl(Protocol& proto, uint16_t port,
listen_options opt);
virtual future<connected_socket, socket_address> accept() override;
virtual void abort_accept() override;
+ virtual socket_address local_address() const override;
};

template <typename Protocol>
@@ -70,6 +72,11 @@ native_server_socket_impl<Protocol>::abort_accept() {
_listener.abort_accept();
}

+template <typename Protocol>
+socket_address native_server_socket_impl<Protocol>::local_address() const {
+ return
socket_address(_listener.get_tcp().inet().inet().host_address(),
_listener.port());
+}
+
// native_connected_socket_impl
template <typename Protocol>
class native_connected_socket_impl : public connected_socket_impl {
diff --git a/src/net/posix-stack.cc b/src/net/posix-stack.cc
--- a/src/net/posix-stack.cc
+++ b/src/net/posix-stack.cc
@@ -232,6 +232,11 @@ posix_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader();
}

+template <transport Transport>
+socket_address posix_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
future<connected_socket, socket_address>
posix_ap_server_socket_impl<Transport>::accept() {
auto conni = conn_q.find(_sa);
@@ -284,6 +289,11 @@
posix_reuseport_server_socket_impl<Transport>::abort_accept() {
_lfd.abort_reader();
}

+template <transport Transport>
+socket_address
posix_reuseport_server_socket_impl<Transport>::local_address() const {
+ return _lfd.get_file_desc().get_address();
+}
+
template <transport Transport>
void

posix_ap_server_socket_impl<Transport>::move_connected_socket(socket_address
sa, pollable_fd fd, socket_address addr, conntrack::handle cth) {
diff --git a/src/net/stack.cc b/src/net/stack.cc
--- a/src/net/stack.cc
+++ b/src/net/stack.cc
@@ -164,6 +164,10 @@ void server_socket::abort_accept() {
_aborted = true;
}

+socket_address server_socket::local_address() const {
+ return _ssi->local_address();
+}
+
socket_address::socket_address()
: socket_address(ipv4_addr())
{}
diff --git a/src/net/tls.cc b/src/net/tls.cc
--- a/src/net/tls.cc
+++ b/src/net/tls.cc
@@ -1132,6 +1132,9 @@ class server_session : public net::server_socket_impl
{
void abort_accept() override {
_sock.abort_accept();
}
+ socket_address local_address() const override {
+ return _sock.local_address();
+ }
private:
shared_ptr<server_credentials> _creds;
server_socket _sock;
diff --git a/tests/unit/loopback_socket.hh b/tests/unit/loopback_socket.hh
--- a/tests/unit/loopback_socket.hh
+++ b/tests/unit/loopback_socket.hh
@@ -191,6 +191,10 @@ public:
void abort_accept() override {

_pending->abort(std::make_exception_ptr(std::system_error(ECONNABORTED,
std::system_category())));
}
+ socket_address local_address() const override {

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 30, 2019, 7:47:35 AM1/30/19
to seastar-dev@googlegroups.com, Calle Wilund
From: Calle Wilund <ca...@scylladb.com>
Committer: Calle Wilund <ca...@scylladb.com>
Branch: master

ipv6_test: Add small ipv6 test

Borderline useless, but at least checks we can bind posix stack sockets
to ipv6.

---
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -294,6 +294,9 @@ seastar_add_test (httpd
httpd_test.cc
loopback_socket.hh)

+seastar_add_test (ipv6
+ SOURCES ipv6_test.cc)
+
seastar_add_test (json_formatter
SOURCES json_formatter_test.cc)

diff --git a/tests/unit/ipv6_test.cc b/tests/unit/ipv6_test.cc
--- a/tests/unit/ipv6_test.cc
+ return false;
+ }
Reply all
Reply to author
Forward
0 new messages