From c540e36fe2e026e8103e891152750e1bda001105 Mon Sep 17 00:00:00 2001 From: Calle Wilund Date: Tue, 2 Apr 2019 12:54:58 +0000 Subject: [PATCH] gms::inet_address: Make serialization ipv6 aware Because inet_address was initially hardcoded to ipv4, its wire format is not very forward compatible. Since we potentially need to communicate with older version nodes, we manually define the new serial format for inet_address to be: ipv4: 4 bytes address ipv6: 4 bytes marker 0xffffffff (invalid address) 16 bytes data -> address --- gms/inet_address_serializer.hh | 68 ++++++++++++++++++++++++++++++++++ idl/gossip_digest.idl.hh | 4 -- message/messaging_service.cc | 1 + 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 gms/inet_address_serializer.hh diff --git a/gms/inet_address_serializer.hh b/gms/inet_address_serializer.hh new file mode 100644 index 0000000000..695203f924 --- /dev/null +++ b/gms/inet_address_serializer.hh @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 ScyllaDB + */ + +/* + * This file is part of Scylla. + * + * See the LICENSE.PROPRIETARY file in the top-level directory for licensing information. + */ + +#pragma once + +#include "inet_address.hh" +#include "serializer.hh" + +namespace ser { + +/** + * Manual definition of inet_address serialization. + * Because inet_address was initially hardcoded to + * ipv4, its wire format is not very forward compatible. + * + * Since we potentially need to communicate with older + * version nodes, we manually define the new serial format + * for inet_address to be: + * + * ipv4: 4 bytes address + * ipv6: 4 bytes marker 0xffffffff (invalid address) + * 16 bytes data -> address + * + * As long as we are restricted to ipv4 (config/user responsibility) + * we will be able to swap gossip with older nodes. Once the + * cluster is fully updated, user can enable ipv6 and we will be + * happy and addressing all the molecules. + * + */ +template<> +struct serializer { + template + static gms::inet_address read(Input& in) { + auto sz = deserialize(in, boost::type()); + if (sz == std::numeric_limits::max()) { + seastar::net::ipv6_address addr(deserialize(in, boost::type())); + return gms::inet_address(addr); + } + return gms::inet_address(sz); + } + template + static void write(Output& out, gms::inet_address v) { + auto& addr = v.addr(); + if (addr.is_ipv6()) { + serialize(out, std::numeric_limits::max()); + auto bv = v.bytes(); + out.write(reinterpret_cast(bv.data()), bv.size()); + } else { + uint32_t ip = addr.as_ipv4_address().ip; + // must write this little (or rather host) endian + serialize(out, ip); + } + } + template + static void skip(Input& v) { + read(v); + } +}; + + +} diff --git a/idl/gossip_digest.idl.hh b/idl/gossip_digest.idl.hh index a57ae6c980..c82928c804 100644 --- a/idl/gossip_digest.idl.hh +++ b/idl/gossip_digest.idl.hh @@ -38,10 +38,6 @@ enum class application_state:int { SUPPORTED_FEATURES }; -class inet_address final { - uint32_t raw_addr(); -}; - class versioned_value { sstring value; int version; diff --git a/message/messaging_service.cc b/message/messaging_service.cc index add6e70e3d..6dcdee7a5f 100644 --- a/message/messaging_service.cc +++ b/message/messaging_service.cc @@ -23,6 +23,7 @@ #include #include "gms/failure_detector.hh" #include "gms/gossiper.hh" +#include "gms/inet_address_serializer.hh" #include "service/storage_service.hh" #include "streaming/prepare_message.hh" #include "gms/gossip_digest_syn.hh"