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
18 #include <netinet/in.h>
20 #include "include/ceph_features.h"
21 #include "include/types.h"
22 #include "include/blobhash.h"
23 #include "include/encoding.h"
29 extern ostream
& operator<<(ostream
& out
, const sockaddr_storage
&ss
);
30 extern ostream
& operator<<(ostream
& out
, const sockaddr
*sa
);
32 typedef uint8_t entity_type_t
;
40 static const int TYPE_MON
= CEPH_ENTITY_TYPE_MON
;
41 static const int TYPE_MDS
= CEPH_ENTITY_TYPE_MDS
;
42 static const int TYPE_OSD
= CEPH_ENTITY_TYPE_OSD
;
43 static const int TYPE_CLIENT
= CEPH_ENTITY_TYPE_CLIENT
;
44 static const int TYPE_MGR
= CEPH_ENTITY_TYPE_MGR
;
46 static const int64_t NEW
= -1;
49 entity_name_t() : _type(0), _num(0) { }
50 entity_name_t(int t
, int64_t n
) : _type(t
), _num(n
) { }
51 explicit entity_name_t(const ceph_entity_name
&n
) :
52 _type(n
.type
), _num(n
.num
) { }
55 static entity_name_t
MON(int64_t i
=NEW
) { return entity_name_t(TYPE_MON
, i
); }
56 static entity_name_t
MDS(int64_t i
=NEW
) { return entity_name_t(TYPE_MDS
, i
); }
57 static entity_name_t
OSD(int64_t i
=NEW
) { return entity_name_t(TYPE_OSD
, i
); }
58 static entity_name_t
CLIENT(int64_t i
=NEW
) { return entity_name_t(TYPE_CLIENT
, i
); }
59 static entity_name_t
MGR(int64_t i
=NEW
) { return entity_name_t(TYPE_MGR
, i
); }
61 int64_t num() const { return _num
; }
62 int type() const { return _type
; }
63 const char *type_str() const {
64 return ceph_entity_type_name(type());
67 bool is_new() const { return num() < 0; }
69 bool is_client() const { return type() == TYPE_CLIENT
; }
70 bool is_mds() const { return type() == TYPE_MDS
; }
71 bool is_osd() const { return type() == TYPE_OSD
; }
72 bool is_mon() const { return type() == TYPE_MON
; }
73 bool is_mgr() const { return type() == TYPE_MGR
; }
75 operator ceph_entity_name() const {
76 ceph_entity_name n
= { _type
, init_le64(_num
) };
80 bool parse(const string
& s
) {
81 const char *start
= s
.c_str();
83 bool got
= parse(start
, &end
);
84 return got
&& end
== start
+ s
.length();
86 bool parse(const char *start
, char **end
) {
87 if (strstr(start
, "mon.") == start
) {
90 } else if (strstr(start
, "osd.") == start
) {
93 } else if (strstr(start
, "mds.") == start
) {
96 } else if (strstr(start
, "client.") == start
) {
99 } else if (strstr(start
, "mgr.") == start
) {
107 _num
= strtoll(start
, end
, 10);
108 if (*end
== NULL
|| *end
== start
)
113 DENC(entity_name_t
, v
, p
) {
117 void dump(Formatter
*f
) const;
119 static void generate_test_instances(list
<entity_name_t
*>& o
);
121 WRITE_CLASS_DENC(entity_name_t
)
123 inline bool operator== (const entity_name_t
& l
, const entity_name_t
& r
) {
124 return (l
.type() == r
.type()) && (l
.num() == r
.num()); }
125 inline bool operator!= (const entity_name_t
& l
, const entity_name_t
& r
) {
126 return (l
.type() != r
.type()) || (l
.num() != r
.num()); }
127 inline bool operator< (const entity_name_t
& l
, const entity_name_t
& r
) {
128 return (l
.type() < r
.type()) || (l
.type() == r
.type() && l
.num() < r
.num()); }
130 inline std::ostream
& operator<<(std::ostream
& out
, const entity_name_t
& addr
) {
131 //if (addr.is_namer()) return out << "namer";
132 if (addr
.is_new() || addr
.num() < 0)
133 return out
<< addr
.type_str() << ".?";
135 return out
<< addr
.type_str() << '.' << addr
.num();
137 inline std::ostream
& operator<<(std::ostream
& out
, const ceph_entity_name
& addr
) {
138 return out
<< *(const entity_name_t
*)&addr
;
142 template<> struct hash
< entity_name_t
>
144 size_t operator()( const entity_name_t
&m
) const
146 return rjhash32(m
.type() ^ m
.num());
152 * an entity's network address.
153 * includes a random value that prevents it from being reused.
154 * thus identifies a particular process instance.
158 #if defined(__linux__) || defined(DARWIN) || defined(__FreeBSD__)
160 * encode sockaddr.ss_family as network byte order
162 static inline void encode(const sockaddr_storage
& a
, bufferlist
& bl
) {
163 struct sockaddr_storage ss
= a
;
164 #if defined(DARWIN) || defined(__FreeBSD__)
165 unsigned short *ss_family
= reinterpret_cast<unsigned short*>(&ss
);
166 *ss_family
= htons(a
.ss_family
);
168 ss
.ss_family
= htons(ss
.ss_family
);
170 ::encode_raw(ss
, bl
);
172 static inline void decode(sockaddr_storage
& a
, bufferlist::iterator
& bl
) {
174 #if defined(DARWIN) || defined(__FreeBSD__)
175 unsigned short *ss_family
= reinterpret_cast<unsigned short *>(&a
);
176 a
.ss_family
= ntohs(*ss_family
);
179 a
.ss_family
= ntohs(a
.ss_family
);
184 // define a wire format for sockaddr that matches Linux's.
185 struct ceph_sockaddr_storage
{
187 __u8 __ss_padding
[128 - sizeof(__le16
)];
189 void encode(bufferlist
& bl
) const {
190 struct ceph_sockaddr_storage ss
= *this;
191 ss
.ss_family
= htons(ss
.ss_family
);
192 ::encode_raw(ss
, bl
);
195 void decode(bufferlist::iterator
& bl
) {
196 struct ceph_sockaddr_storage ss
;
197 ::decode_raw(ss
, bl
);
198 ss
.ss_family
= ntohs(ss
.ss_family
);
201 } __attribute__ ((__packed__
));
202 WRITE_CLASS_ENCODER(ceph_sockaddr_storage
)
204 struct entity_addr_t
{
207 TYPE_LEGACY
= 1, ///< legacy msgr1 protocol (ceph jewel and older)
208 TYPE_MSGR2
= 2, ///< msgr2 protocol (new in ceph kraken)
210 static const type_t TYPE_DEFAULT
= TYPE_LEGACY
;
211 static const char *get_type_name(int t
) {
213 case TYPE_NONE
: return "none";
214 case TYPE_LEGACY
: return "legacy";
215 case TYPE_MSGR2
: return "msgr2";
216 default: return "???";
228 entity_addr_t() : type(0), nonce(0) {
229 memset(&u
, 0, sizeof(u
));
231 entity_addr_t(__u32 _type
, __u32 _nonce
) : type(_type
), nonce(_nonce
) {
232 memset(&u
, 0, sizeof(u
));
234 explicit entity_addr_t(const ceph_entity_addr
&o
) {
237 memcpy(&u
, &o
.in_addr
, sizeof(u
));
238 #if !defined(__FreeBSD__)
239 u
.sa
.sa_family
= ntohs(u
.sa
.sa_family
);
243 uint32_t get_type() const { return type
; }
244 void set_type(uint32_t t
) { type
= t
; }
246 __u32
get_nonce() const { return nonce
; }
247 void set_nonce(__u32 n
) { nonce
= n
; }
249 int get_family() const {
250 return u
.sa
.sa_family
;
252 void set_family(int f
) {
256 sockaddr_in
&in4_addr() {
259 const sockaddr_in
&in4_addr() const{
262 sockaddr_in6
&in6_addr(){
265 const sockaddr_in6
&in6_addr() const{
268 const sockaddr
*get_sockaddr() const {
271 size_t get_sockaddr_len() const {
272 switch (u
.sa
.sa_family
) {
274 return sizeof(u
.sin
);
276 return sizeof(u
.sin6
);
280 bool set_sockaddr(const struct sockaddr
*sa
)
282 switch (sa
->sa_family
) {
284 memcpy(&u
.sin
, sa
, sizeof(u
.sin
));
287 memcpy(&u
.sin6
, sa
, sizeof(u
.sin6
));
295 sockaddr_storage
get_sockaddr_storage() const {
297 memcpy(&ss
, &u
, sizeof(u
));
298 memset((char*)&ss
+ sizeof(u
), 0, sizeof(ss
) - sizeof(u
));
302 void set_in4_quad(int pos
, int val
) {
303 u
.sin
.sin_family
= AF_INET
;
304 unsigned char *ipq
= (unsigned char*)&u
.sin
.sin_addr
.s_addr
;
307 void set_port(int port
) {
308 switch (u
.sa
.sa_family
) {
310 u
.sin
.sin_port
= htons(port
);
313 u
.sin6
.sin6_port
= htons(port
);
319 int get_port() const {
320 switch (u
.sa
.sa_family
) {
322 return ntohs(u
.sin
.sin_port
);
325 return ntohs(u
.sin6
.sin6_port
);
331 operator ceph_entity_addr() const {
335 a
.in_addr
= get_sockaddr_storage();
336 #if !defined(__FreeBSD__)
337 a
.in_addr
.ss_family
= htons(a
.in_addr
.ss_family
);
342 bool probably_equals(const entity_addr_t
&o
) const {
343 if (get_port() != o
.get_port())
345 if (get_nonce() != o
.get_nonce())
347 if (is_blank_ip() || o
.is_blank_ip())
349 if (memcmp(&u
, &o
.u
, sizeof(u
)) == 0)
354 bool is_same_host(const entity_addr_t
&o
) const {
355 if (u
.sa
.sa_family
!= o
.u
.sa
.sa_family
)
357 if (u
.sa
.sa_family
== AF_INET
)
358 return u
.sin
.sin_addr
.s_addr
== o
.u
.sin
.sin_addr
.s_addr
;
359 if (u
.sa
.sa_family
== AF_INET6
)
360 return memcmp(u
.sin6
.sin6_addr
.s6_addr
,
361 o
.u
.sin6
.sin6_addr
.s6_addr
,
362 sizeof(u
.sin6
.sin6_addr
.s6_addr
)) == 0;
366 bool is_blank_ip() const {
367 switch (u
.sa
.sa_family
) {
369 return u
.sin
.sin_addr
.s_addr
== INADDR_ANY
;
371 return memcmp(&u
.sin6
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
)) == 0;
378 switch (u
.sa
.sa_family
) {
387 bool parse(const char *s
, const char **end
= 0);
389 void decode_legacy_addr_after_marker(bufferlist::iterator
& bl
)
393 ::decode(marker
, bl
);
398 #if defined(__linux__) || defined(DARWIN) || defined(__FreeBSD__)
401 ceph_sockaddr_storage wireaddr
;
402 ::memset(&wireaddr
, '\0', sizeof(wireaddr
));
403 ::decode(wireaddr
, bl
);
404 unsigned copysize
= MIN(sizeof(wireaddr
), sizeof(ss
));
405 ::memcpy(&ss
, &wireaddr
, copysize
);
407 set_sockaddr((sockaddr
*)&ss
);
410 // Right now, these only deal with sockaddr_storage that have only family and content.
411 // Apparently on BSD there is also an ss_len that we need to handle; this requires
414 void encode(bufferlist
& bl
, uint64_t features
) const {
415 if ((features
& CEPH_FEATURE_MSG_ADDR2
) == 0) {
416 ::encode((__u32
)0, bl
);
418 sockaddr_storage ss
= get_sockaddr_storage();
419 #if defined(__linux__) || defined(DARWIN) || defined(__FreeBSD__)
422 ceph_sockaddr_storage wireaddr
;
423 ::memset(&wireaddr
, '\0', sizeof(wireaddr
));
424 unsigned copysize
= MIN(sizeof(wireaddr
), sizeof(ss
));
425 // ceph_sockaddr_storage is in host byte order
426 ::memcpy(&wireaddr
, &ss
, copysize
);
427 ::encode(wireaddr
, bl
);
431 ::encode((__u8
)1, bl
);
432 ENCODE_START(1, 1, bl
);
435 __u32 elen
= get_sockaddr_len();
438 #if (__FreeBSD__) || defined(__APPLE__)
439 __le16 ss_family
= u
.sa
.sa_family
;
440 ::encode(ss_family
, bl
);
441 bl
.append(u
.sa
.sa_data
,
442 elen
- sizeof(u
.sa
.sa_len
) - sizeof(u
.sa
.sa_family
));
444 bl
.append((char*)get_sockaddr(), elen
);
449 void decode(bufferlist::iterator
& bl
) {
451 ::decode(marker
, bl
);
453 decode_legacy_addr_after_marker(bl
);
457 throw buffer::malformed_input("entity_addr_t marker != 1");
464 #if defined(__FreeBSD__) || defined(__APPLE__)
467 if (elen
< sizeof(ss_family
)) {
468 throw buffer::malformed_input("elen smaller than family len");
470 ::decode(ss_family
, bl
);
471 u
.sa
.sa_family
= ss_family
;
472 elen
-= sizeof(ss_family
);
473 if (elen
> get_sockaddr_len() - sizeof(u
.sa
.sa_family
)) {
474 throw buffer::malformed_input("elen exceeds sockaddr len");
476 bl
.copy(elen
, u
.sa
.sa_data
);
478 if (elen
< sizeof(u
.sa
.sa_family
)) {
479 throw buffer::malformed_input("elen smaller than family len");
481 bl
.copy(sizeof(u
.sa
.sa_family
), (char*)&u
.sa
.sa_family
);
482 if (elen
> get_sockaddr_len()) {
483 throw buffer::malformed_input("elen exceeds sockaddr len");
485 elen
-= sizeof(u
.sa
.sa_family
);
486 bl
.copy(elen
, u
.sa
.sa_data
);
492 void dump(Formatter
*f
) const;
494 static void generate_test_instances(list
<entity_addr_t
*>& o
);
496 WRITE_CLASS_ENCODER_FEATURES(entity_addr_t
)
498 ostream
& operator<<(ostream
& out
, const entity_addr_t
&addr
);
500 inline bool operator==(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) == 0; }
501 inline bool operator!=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) != 0; }
502 inline bool operator<(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) < 0; }
503 inline bool operator<=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) <= 0; }
504 inline bool operator>(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) > 0; }
505 inline bool operator>=(const entity_addr_t
& a
, const entity_addr_t
& b
) { return memcmp(&a
, &b
, sizeof(a
)) >= 0; }
508 template<> struct hash
< entity_addr_t
>
510 size_t operator()( const entity_addr_t
& x
) const
513 return H((const char*)&x
, sizeof(x
));
518 struct entity_addrvec_t
{
519 vector
<entity_addr_t
> v
;
521 unsigned size() const { return v
.size(); }
522 bool empty() const { return v
.empty(); }
524 void encode(bufferlist
& bl
, uint64_t features
) const;
525 void decode(bufferlist::iterator
& bl
);
526 void dump(Formatter
*f
) const;
527 static void generate_test_instances(list
<entity_addrvec_t
*>& ls
);
529 WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t
);
532 * a particular entity instance
534 struct entity_inst_t
{
538 entity_inst_t(entity_name_t n
, const entity_addr_t
& a
) : name(n
), addr(a
) {}
539 // cppcheck-suppress noExplicitConstructor
540 entity_inst_t(const ceph_entity_inst
& i
) : name(i
.name
), addr(i
.addr
) { }
541 entity_inst_t(const ceph_entity_name
& n
, const ceph_entity_addr
&a
) : name(n
), addr(a
) {}
542 operator ceph_entity_inst() {
543 ceph_entity_inst i
= {name
, addr
};
547 void encode(bufferlist
& bl
, uint64_t features
) const {
549 ::encode(addr
, bl
, features
);
551 void decode(bufferlist::iterator
& bl
) {
556 void dump(Formatter
*f
) const;
557 static void generate_test_instances(list
<entity_inst_t
*>& o
);
559 WRITE_CLASS_ENCODER_FEATURES(entity_inst_t
)
562 inline bool operator==(const entity_inst_t
& a
, const entity_inst_t
& b
) {
563 return a
.name
== b
.name
&& a
.addr
== b
.addr
;
565 inline bool operator!=(const entity_inst_t
& a
, const entity_inst_t
& b
) {
566 return a
.name
!= b
.name
|| a
.addr
!= b
.addr
;
568 inline bool operator<(const entity_inst_t
& a
, const entity_inst_t
& b
) {
569 return a
.name
< b
.name
|| (a
.name
== b
.name
&& a
.addr
< b
.addr
);
571 inline bool operator<=(const entity_inst_t
& a
, const entity_inst_t
& b
) {
572 return a
.name
< b
.name
|| (a
.name
== b
.name
&& a
.addr
<= b
.addr
);
574 inline bool operator>(const entity_inst_t
& a
, const entity_inst_t
& b
) { return b
< a
; }
575 inline bool operator>=(const entity_inst_t
& a
, const entity_inst_t
& b
) { return b
<= a
; }
578 template<> struct hash
< entity_inst_t
>
580 size_t operator()( const entity_inst_t
& x
) const
582 static hash
< entity_name_t
> H
;
583 static hash
< entity_addr_t
> I
;
584 return H(x
.name
) ^ I(x
.addr
);
590 inline ostream
& operator<<(ostream
& out
, const entity_inst_t
&i
)
592 return out
<< i
.name
<< " " << i
.addr
;
594 inline ostream
& operator<<(ostream
& out
, const ceph_entity_inst
&i
)