]>
git.proxmox.com Git - ceph.git/blob - ceph/src/msg/msg_types.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #ifndef CEPH_MSG_TYPES_H
16 #define CEPH_MSG_TYPES_H
20 #include <netinet/in.h>
22 #include "include/ceph_features.h"
23 #include "include/types.h"
24 #include "include/blobhash.h"
25 #include "include/encoding.h"
27 #define MAX_PORT_NUMBER 65535
33 extern ostream
& operator<<(ostream
& out
, const sockaddr_storage
&ss
);
34 extern ostream
& operator<<(ostream
& out
, const sockaddr
*sa
);
36 typedef uint8_t entity_type_t
;
44 static const int TYPE_MON
= CEPH_ENTITY_TYPE_MON
;
45 static const int TYPE_MDS
= CEPH_ENTITY_TYPE_MDS
;
46 static const int TYPE_OSD
= CEPH_ENTITY_TYPE_OSD
;
47 static const int TYPE_CLIENT
= CEPH_ENTITY_TYPE_CLIENT
;
48 static const int TYPE_MGR
= CEPH_ENTITY_TYPE_MGR
;
50 static const int64_t NEW
= -1;
53 entity_name_t() : _type(0), _num(0) { }
54 entity_name_t(int t
, int64_t n
) : _type(t
), _num(n
) { }
55 explicit entity_name_t(const ceph_entity_name
&n
) :
56 _type(n
.type
), _num(n
.num
) { }
59 static entity_name_t
MON(int64_t i
=NEW
) { return entity_name_t(TYPE_MON
, i
); }
60 static entity_name_t
MDS(int64_t i
=NEW
) { return entity_name_t(TYPE_MDS
, i
); }
61 static entity_name_t
OSD(int64_t i
=NEW
) { return entity_name_t(TYPE_OSD
, i
); }
62 static entity_name_t
CLIENT(int64_t i
=NEW
) { return entity_name_t(TYPE_CLIENT
, i
); }
63 static entity_name_t
MGR(int64_t i
=NEW
) { return entity_name_t(TYPE_MGR
, i
); }
65 int64_t num() const { return _num
; }
66 int type() const { return _type
; }
67 const char *type_str() const {
68 return ceph_entity_type_name(type());
71 bool is_new() const { return num() < 0; }
73 bool is_client() const { return type() == TYPE_CLIENT
; }
74 bool is_mds() const { return type() == TYPE_MDS
; }
75 bool is_osd() const { return type() == TYPE_OSD
; }
76 bool is_mon() const { return type() == TYPE_MON
; }
77 bool is_mgr() const { return type() == TYPE_MGR
; }
79 operator ceph_entity_name() const {
80 ceph_entity_name n
= { _type
, init_le64(_num
) };
84 bool parse(const string
& s
) {
85 const char *start
= s
.c_str();
87 bool got
= parse(start
, &end
);
88 return got
&& end
== start
+ s
.length();
90 bool parse(const char *start
, char **end
) {
91 if (strstr(start
, "mon.") == start
) {
94 } else if (strstr(start
, "osd.") == start
) {
97 } else if (strstr(start
, "mds.") == start
) {
100 } else if (strstr(start
, "client.") == start
) {
103 } else if (strstr(start
, "mgr.") == start
) {
111 _num
= strtoll(start
, end
, 10);
112 if (*end
== NULL
|| *end
== start
)
117 DENC(entity_name_t
, v
, p
) {
121 void dump(Formatter
*f
) const;
123 static void generate_test_instances(list
<entity_name_t
*>& o
);
125 WRITE_CLASS_DENC(entity_name_t
)
127 inline bool operator== (const entity_name_t
& l
, const entity_name_t
& r
) {
128 return (l
.type() == r
.type()) && (l
.num() == r
.num()); }
129 inline bool operator!= (const entity_name_t
& l
, const entity_name_t
& r
) {
130 return (l
.type() != r
.type()) || (l
.num() != r
.num()); }
131 inline bool operator< (const entity_name_t
& l
, const entity_name_t
& r
) {
132 return (l
.type() < r
.type()) || (l
.type() == r
.type() && l
.num() < r
.num()); }
134 inline std::ostream
& operator<<(std::ostream
& out
, const entity_name_t
& addr
) {
135 //if (addr.is_namer()) return out << "namer";
136 if (addr
.is_new() || addr
.num() < 0)
137 return out
<< addr
.type_str() << ".?";
139 return out
<< addr
.type_str() << '.' << addr
.num();
141 inline std::ostream
& operator<<(std::ostream
& out
, const ceph_entity_name
& addr
) {
142 return out
<< entity_name_t
{addr
.type
, static_cast<int64_t>(addr
.num
)};
146 template<> struct hash
< entity_name_t
>
148 size_t operator()( const entity_name_t
&m
) const
150 return rjhash32(m
.type() ^ m
.num());
155 // define a wire format for sockaddr that matches Linux's.
156 struct ceph_sockaddr_storage
{
158 __u8 __ss_padding
[128 - sizeof(__le16
)];
160 void encode(bufferlist
& bl
) const {
161 struct ceph_sockaddr_storage ss
= *this;
162 ss
.ss_family
= htons(ss
.ss_family
);
163 ::encode_raw(ss
, bl
);
166 void decode(bufferlist::const_iterator
& bl
) {
167 struct ceph_sockaddr_storage ss
;
168 ::decode_raw(ss
, bl
);
169 ss
.ss_family
= ntohs(ss
.ss_family
);
172 } __attribute__ ((__packed__
));
173 WRITE_CLASS_ENCODER(ceph_sockaddr_storage
)
176 * encode sockaddr.ss_family as network byte order
178 static inline void encode(const sockaddr_storage
& a
, bufferlist
& bl
) {
179 #if defined(__linux__)
180 struct sockaddr_storage ss
= a
;
181 ss
.ss_family
= htons(ss
.ss_family
);
182 ::encode_raw(ss
, bl
);
183 #elif defined(__FreeBSD__) || defined(__APPLE__)
184 ceph_sockaddr_storage ss
{};
185 auto src
= (unsigned char const *)&a
;
186 auto dst
= (unsigned char *)&ss
;
187 src
+= sizeof(a
.ss_len
);
188 ss
.ss_family
= a
.ss_family
;
189 src
+= sizeof(a
.ss_family
);
190 dst
+= sizeof(ss
.ss_family
);
191 const auto copy_size
= std::min((unsigned char*)(&a
+ 1) - src
,
192 (unsigned char*)(&ss
+ 1) - dst
);
193 ::memcpy(dst
, src
, copy_size
);
196 ceph_sockaddr_storage ss
{};
197 ::memset(&ss
, '\0', sizeof(ss
));
198 ::memcpy(&wireaddr
, &ss
, std::min(sizeof(ss
), sizeof(a
)));
202 static inline void decode(sockaddr_storage
& a
, bufferlist::const_iterator
& bl
) {
203 #if defined(__linux__)
205 a
.ss_family
= ntohs(a
.ss_family
);
206 #elif defined(__FreeBSD__) || defined(__APPLE__)
207 ceph_sockaddr_storage ss
{};
209 auto src
= (unsigned char const *)&ss
;
210 auto dst
= (unsigned char *)&a
;
212 dst
+= sizeof(a
.ss_len
);
213 a
.ss_family
= ss
.ss_family
;
214 src
+= sizeof(ss
.ss_family
);
215 dst
+= sizeof(a
.ss_family
);
216 auto const copy_size
= std::min((unsigned char*)(&ss
+ 1) - src
,
217 (unsigned char*)(&a
+ 1) - dst
);
218 ::memcpy(dst
, src
, copy_size
);
220 ceph_sockaddr_storage ss
{};
222 ::memcpy(&a
, &ss
, std::min(sizeof(ss
), sizeof(a
)));
227 * an entity's network address.
228 * includes a random value that prevents it from being reused.
229 * thus identifies a particular process instance.
232 struct entity_addr_t
{
235 TYPE_LEGACY
= 1, ///< legacy msgr1 protocol (ceph jewel and older)
236 TYPE_MSGR2
= 2, ///< msgr2 protocol (new in ceph kraken)
237 TYPE_ANY
= 3, ///< ambiguous
239 static const type_t TYPE_DEFAULT
= TYPE_MSGR2
;
240 static std::string_view
get_type_name(int t
) {
242 case TYPE_NONE
: return "none";
243 case TYPE_LEGACY
: return "v1";
244 case TYPE_MSGR2
: return "v2";
245 case TYPE_ANY
: return "any";
246 default: return "???";
258 entity_addr_t() : type(0), nonce(0) {
259 memset(&u
, 0, sizeof(u
));
261 entity_addr_t(__u32 _type
, __u32 _nonce
) : type(_type
), nonce(_nonce
) {
262 memset(&u
, 0, sizeof(u
));
264 explicit entity_addr_t(const ceph_entity_addr
&o
) {
267 memcpy(&u
, &o
.in_addr
, sizeof(u
));
268 #if !defined(__FreeBSD__)
269 u
.sa
.sa_family
= ntohs(u
.sa
.sa_family
);
273 uint32_t get_type() const { return type
; }
274 void set_type(uint32_t t
) { type
= t
; }
275 bool is_legacy() const { return type
== TYPE_LEGACY
; }
276 bool is_msgr2() const { return type
== TYPE_MSGR2
; }
277 bool is_any() const { return type
== TYPE_ANY
; }
279 __u32
get_nonce() const { return nonce
; }
280 void set_nonce(__u32 n
) { nonce
= n
; }
282 int get_family() const {
283 return u
.sa
.sa_family
;
285 void set_family(int f
) {
289 bool is_ipv4() const {
290 return u
.sa
.sa_family
== AF_INET
;
292 bool is_ipv6() const {
293 return u
.sa
.sa_family
== AF_INET6
;
296 sockaddr_in
&in4_addr() {
299 const sockaddr_in
&in4_addr() const{
302 sockaddr_in6
&in6_addr(){
305 const sockaddr_in6
&in6_addr() const{
308 const sockaddr
*get_sockaddr() const {
311 size_t get_sockaddr_len() const {
312 switch (u
.sa
.sa_family
) {
314 return sizeof(u
.sin
);
316 return sizeof(u
.sin6
);
320 bool set_sockaddr(const struct sockaddr
*sa
)
322 switch (sa
->sa_family
) {
324 // pre-zero, since we're only copying a portion of the source
325 memset(&u
, 0, sizeof(u
));
326 memcpy(&u
.sin
, sa
, sizeof(u
.sin
));
329 // pre-zero, since we're only copying a portion of the source
330 memset(&u
, 0, sizeof(u
));
331 memcpy(&u
.sin6
, sa
, sizeof(u
.sin6
));
334 memset(&u
, 0, sizeof(u
));
342 sockaddr_storage
get_sockaddr_storage() const {
344 memcpy(&ss
, &u
, sizeof(u
));
345 memset((char*)&ss
+ sizeof(u
), 0, sizeof(ss
) - sizeof(u
));
349 void set_in4_quad(int pos
, int val
) {
350 u
.sin
.sin_family
= AF_INET
;
351 unsigned char *ipq
= (unsigned char*)&u
.sin
.sin_addr
.s_addr
;
354 void set_port(int port
) {
355 switch (u
.sa
.sa_family
) {
357 u
.sin
.sin_port
= htons(port
);
360 u
.sin6
.sin6_port
= htons(port
);
366 int get_port() const {
367 switch (u
.sa
.sa_family
) {
369 return ntohs(u
.sin
.sin_port
);
372 return ntohs(u
.sin6
.sin6_port
);
378 operator ceph_entity_addr() const {
382 a
.in_addr
= get_sockaddr_storage();
383 #if !defined(__FreeBSD__)
384 a
.in_addr
.ss_family
= htons(a
.in_addr
.ss_family
);
389 bool probably_equals(const entity_addr_t
&o
) const {
390 if (get_port() != o
.get_port())
392 if (get_nonce() != o
.get_nonce())
394 if (is_blank_ip() || o
.is_blank_ip())
396 if (memcmp(&u
, &o
.u
, sizeof(u
)) == 0)
401 bool is_same_host(const entity_addr_t
&o
) const {
402 if (u
.sa
.sa_family
!= o
.u
.sa
.sa_family
)
404 if (u
.sa
.sa_family
== AF_INET
)
405 return u
.sin
.sin_addr
.s_addr
== o
.u
.sin
.sin_addr
.s_addr
;
406 if (u
.sa
.sa_family
== AF_INET6
)
407 return memcmp(u
.sin6
.sin6_addr
.s6_addr
,
408 o
.u
.sin6
.sin6_addr
.s6_addr
,
409 sizeof(u
.sin6
.sin6_addr
.s6_addr
)) == 0;
413 bool is_blank_ip() const {
414 switch (u
.sa
.sa_family
) {
416 return u
.sin
.sin_addr
.s_addr
== INADDR_ANY
;
418 return memcmp(&u
.sin6
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
)) == 0;
425 switch (u
.sa
.sa_family
) {
434 std::string
ip_only_to_str() const;
436 std::string
get_legacy_str() const {
438 ss
<< get_sockaddr() << "/" << get_nonce();
442 bool parse(const char *s
, const char **end
= 0, int type
=0);
444 void decode_legacy_addr_after_marker(bufferlist::const_iterator
& bl
)
454 set_sockaddr((sockaddr
*)&ss
);
455 if (get_family() == AF_UNSPEC
) {
462 // Right now, these only deal with sockaddr_storage that have only family and content.
463 // Apparently on BSD there is also an ss_len that we need to handle; this requires
466 void encode(bufferlist
& bl
, uint64_t features
) const {
468 if ((features
& CEPH_FEATURE_MSG_ADDR2
) == 0) {
469 encode((__u32
)0, bl
);
471 sockaddr_storage ss
= get_sockaddr_storage();
476 ENCODE_START(1, 1, bl
);
477 if (HAVE_FEATURE(features
, SERVER_NAUTILUS
)) {
480 // map any -> legacy for old clients. this is primary for the benefit
481 // of OSDMap's blacklist, but is reasonable in general since any: is
482 // meaningless for pre-nautilus clients or daemons.
490 __u32 elen
= get_sockaddr_len();
493 #if (__FreeBSD__) || defined(__APPLE__)
494 __le16 ss_family
= u
.sa
.sa_family
;
495 encode(ss_family
, bl
);
496 bl
.append(u
.sa
.sa_data
,
497 elen
- sizeof(u
.sa
.sa_len
) - sizeof(u
.sa
.sa_family
));
499 bl
.append((char*)get_sockaddr(), elen
);
504 void decode(bufferlist::const_iterator
& bl
) {
509 decode_legacy_addr_after_marker(bl
);
513 throw buffer::malformed_input("entity_addr_t marker != 1");
520 #if defined(__FreeBSD__) || defined(__APPLE__)
523 if (elen
< sizeof(ss_family
)) {
524 throw buffer::malformed_input("elen smaller than family len");
526 decode(ss_family
, bl
);
527 u
.sa
.sa_family
= ss_family
;
528 elen
-= sizeof(ss_family
);
529 if (elen
> get_sockaddr_len() - sizeof(u
.sa
.sa_family
)) {
530 throw buffer::malformed_input("elen exceeds sockaddr len");
532 bl
.copy(elen
, u
.sa
.sa_data
);
534 if (elen
< sizeof(u
.sa
.sa_family
)) {
535 throw buffer::malformed_input("elen smaller than family len");
537 bl
.copy(sizeof(u
.sa
.sa_family
), (char*)&u
.sa
.sa_family
);
538 if (elen
> get_sockaddr_len()) {
539 throw buffer::malformed_input("elen exceeds sockaddr len");
541 elen
-= sizeof(u
.sa
.sa_family
);
542 bl
.copy(elen
, u
.sa
.sa_data
);
548 void dump(Formatter
*f
) const;
550 static void generate_test_instances(list
<entity_addr_t
*>& o
);
552 WRITE_CLASS_ENCODER_FEATURES(entity_addr_t
)
554 ostream
& operator<<(ostream
& out
, const entity_addr_t
&addr
);
556 inline bool operator==(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) == 0; }
557 inline bool operator!=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) != 0; }
558 inline bool operator<(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) < 0; }
559 inline bool operator<=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) <= 0; }
560 inline bool operator>(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) > 0; }
561 inline bool operator>=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) >= 0; }
564 template<> struct hash
< entity_addr_t
>
566 size_t operator()( const entity_addr_t
& x
) const
569 return H((const char*)&x
, sizeof(x
));
574 struct entity_addrvec_t
{
575 vector
<entity_addr_t
> v
;
577 entity_addrvec_t() {}
578 explicit entity_addrvec_t(const entity_addr_t
& a
) : v({ a
}) {}
580 unsigned size() const { return v
.size(); }
581 bool empty() const { return v
.empty(); }
583 entity_addr_t
legacy_addr() const {
585 if (a
.type
== entity_addr_t::TYPE_LEGACY
) {
589 return entity_addr_t();
591 entity_addr_t
as_legacy_addr() const {
598 b
.set_type(entity_addr_t::TYPE_LEGACY
);
604 a
.set_type(entity_addr_t::TYPE_LEGACY
);
607 entity_addr_t
front() const {
611 return entity_addr_t();
613 entity_addr_t
legacy_or_front_addr() const {
615 if (a
.type
== entity_addr_t::TYPE_LEGACY
) {
622 return entity_addr_t();
624 string
get_legacy_str() const {
625 return legacy_or_front_addr().get_legacy_str();
628 entity_addr_t
msgr2_addr() const {
630 if (a
.type
== entity_addr_t::TYPE_MSGR2
) {
634 return entity_addr_t();
636 bool has_msgr2() const {
645 bool parse(const char *s
, const char **end
= 0);
647 void get_ports(set
<int> *ports
) const {
649 ports
->insert(a
.get_port());
652 set
<int> get_ports() const {
658 void encode(bufferlist
& bl
, uint64_t features
) const;
659 void decode(bufferlist::const_iterator
& bl
);
660 void dump(Formatter
*f
) const;
661 static void generate_test_instances(list
<entity_addrvec_t
*>& ls
);
663 bool legacy_equals(const entity_addrvec_t
& o
) const {
668 front().is_legacy() &&
669 front() == o
.legacy_addr()) {
672 if (o
.v
.size() == 1 &&
673 o
.front().is_legacy() &&
674 o
.front() == legacy_addr()) {
680 bool probably_equals(const entity_addrvec_t
& o
) const {
681 for (unsigned i
= 0; i
< v
.size(); ++i
) {
682 if (!v
[i
].probably_equals(o
.v
[i
])) {
688 bool contains(const entity_addr_t
& a
) const {
696 bool is_same_host(const entity_addr_t
& a
) const {
698 if (i
.is_same_host(a
)) {
705 friend ostream
& operator<<(ostream
& out
, const entity_addrvec_t
& av
) {
708 } else if (av
.v
.size() == 1) {
709 return out
<< av
.v
[0];
715 friend bool operator==(const entity_addrvec_t
& l
, const entity_addrvec_t
& r
) {
718 friend bool operator!=(const entity_addrvec_t
& l
, const entity_addrvec_t
& r
) {
721 friend bool operator<(const entity_addrvec_t
& l
, const entity_addrvec_t
& r
) {
722 return l
.v
< r
.v
; // see lexicographical_compare()
725 WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t
);
728 template<> struct hash
< entity_addrvec_t
>
730 size_t operator()( const entity_addrvec_t
& x
) const
734 for (auto& i
: x
.v
) {
735 r
+= H((const char*)&i
, sizeof(i
));
743 * a particular entity instance
745 struct entity_inst_t
{
749 entity_inst_t(entity_name_t n
, const entity_addr_t
& a
) : name(n
), addr(a
) {}
750 // cppcheck-suppress noExplicitConstructor
751 entity_inst_t(const ceph_entity_inst
& i
) : name(i
.name
), addr(i
.addr
) { }
752 entity_inst_t(const ceph_entity_name
& n
, const ceph_entity_addr
&a
) : name(n
), addr(a
) {}
753 operator ceph_entity_inst() {
754 ceph_entity_inst i
= {name
, addr
};
758 void encode(bufferlist
& bl
, uint64_t features
) const {
761 encode(addr
, bl
, features
);
763 void decode(bufferlist::const_iterator
& bl
) {
769 void dump(Formatter
*f
) const;
770 static void generate_test_instances(list
<entity_inst_t
*>& o
);
772 WRITE_CLASS_ENCODER_FEATURES(entity_inst_t
)
775 inline bool operator==(const entity_inst_t
& a
, const entity_inst_t
& b
) {
776 return a
.name
== b
.name
&& a
.addr
== b
.addr
;
778 inline bool operator!=(const entity_inst_t
& a
, const entity_inst_t
& b
) {
779 return a
.name
!= b
.name
|| a
.addr
!= b
.addr
;
781 inline bool operator<(const entity_inst_t
& a
, const entity_inst_t
& b
) {
782 return a
.name
< b
.name
|| (a
.name
== b
.name
&& a
.addr
< b
.addr
);
784 inline bool operator<=(const entity_inst_t
& a
, const entity_inst_t
& b
) {
785 return a
.name
< b
.name
|| (a
.name
== b
.name
&& a
.addr
<= b
.addr
);
787 inline bool operator>(const entity_inst_t
& a
, const entity_inst_t
& b
) { return b
< a
; }
788 inline bool operator>=(const entity_inst_t
& a
, const entity_inst_t
& b
) { return b
<= a
; }
791 template<> struct hash
< entity_inst_t
>
793 size_t operator()( const entity_inst_t
& x
) const
795 static hash
< entity_name_t
> H
;
796 static hash
< entity_addr_t
> I
;
797 return H(x
.name
) ^ I(x
.addr
);
803 inline ostream
& operator<<(ostream
& out
, const entity_inst_t
&i
)
805 return out
<< i
.name
<< " " << i
.addr
;
807 inline ostream
& operator<<(ostream
& out
, const ceph_entity_inst
&i
)