]> git.proxmox.com Git - ceph.git/blame - ceph/src/msg/msg_types.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / msg / msg_types.h
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
7c673cae
FG
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
11fdf7f2 10 * License version 2.1, as published by the Free Software
7c673cae 11 * Foundation. See file COPYING.
11fdf7f2 12 *
7c673cae
FG
13 */
14
15#ifndef CEPH_MSG_TYPES_H
16#define CEPH_MSG_TYPES_H
17
11fdf7f2
TL
18#include <sstream>
19
7c673cae
FG
20#include <netinet/in.h>
21
22#include "include/ceph_features.h"
23#include "include/types.h"
24#include "include/blobhash.h"
25#include "include/encoding.h"
26
11fdf7f2
TL
27#define MAX_PORT_NUMBER 65535
28
7c673cae
FG
29namespace ceph {
30 class Formatter;
31}
32
9f95a23c
TL
33std::ostream& operator<<(std::ostream& out, const sockaddr_storage &ss);
34std::ostream& operator<<(std::ostream& out, const sockaddr *sa);
7c673cae
FG
35
36typedef uint8_t entity_type_t;
37
38class entity_name_t {
39public:
40 entity_type_t _type;
41 int64_t _num;
42
43public:
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;
49
50 static const int64_t NEW = -1;
51
52 // cons
53 entity_name_t() : _type(0), _num(0) { }
54 entity_name_t(int t, int64_t n) : _type(t), _num(n) { }
11fdf7f2 55 explicit entity_name_t(const ceph_entity_name &n) :
7c673cae
FG
56 _type(n.type), _num(n.num) { }
57
58 // static cons
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); }
11fdf7f2 64
7c673cae
FG
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());
69 }
70
71 bool is_new() const { return num() < 0; }
72
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; }
78
79 operator ceph_entity_name() const {
20effc67 80 ceph_entity_name n = { _type, ceph_le64(_num) };
7c673cae
FG
81 return n;
82 }
83
20effc67 84 bool parse(std::string_view s);
7c673cae
FG
85
86 DENC(entity_name_t, v, p) {
87 denc(v._type, p);
88 denc(v._num, p);
89 }
9f95a23c 90 void dump(ceph::Formatter *f) const;
7c673cae 91
9f95a23c 92 static void generate_test_instances(std::list<entity_name_t*>& o);
7c673cae
FG
93};
94WRITE_CLASS_DENC(entity_name_t)
95
11fdf7f2 96inline bool operator== (const entity_name_t& l, const entity_name_t& r) {
7c673cae 97 return (l.type() == r.type()) && (l.num() == r.num()); }
11fdf7f2 98inline bool operator!= (const entity_name_t& l, const entity_name_t& r) {
7c673cae 99 return (l.type() != r.type()) || (l.num() != r.num()); }
11fdf7f2 100inline bool operator< (const entity_name_t& l, const entity_name_t& r) {
7c673cae
FG
101 return (l.type() < r.type()) || (l.type() == r.type() && l.num() < r.num()); }
102
103inline std::ostream& operator<<(std::ostream& out, const entity_name_t& addr) {
104 //if (addr.is_namer()) return out << "namer";
105 if (addr.is_new() || addr.num() < 0)
106 return out << addr.type_str() << ".?";
107 else
108 return out << addr.type_str() << '.' << addr.num();
109}
110inline std::ostream& operator<<(std::ostream& out, const ceph_entity_name& addr) {
11fdf7f2 111 return out << entity_name_t{addr.type, static_cast<int64_t>(addr.num)};
7c673cae
FG
112}
113
114namespace std {
115 template<> struct hash< entity_name_t >
116 {
117 size_t operator()( const entity_name_t &m ) const
118 {
119 return rjhash32(m.type() ^ m.num());
120 }
121 };
122} // namespace std
123
7c673cae
FG
124// define a wire format for sockaddr that matches Linux's.
125struct ceph_sockaddr_storage {
eafe8130
TL
126 ceph_le16 ss_family;
127 __u8 __ss_padding[128 - sizeof(ceph_le16)];
7c673cae 128
9f95a23c 129 void encode(ceph::buffer::list& bl) const {
7c673cae
FG
130 struct ceph_sockaddr_storage ss = *this;
131 ss.ss_family = htons(ss.ss_family);
9f95a23c 132 ceph::encode_raw(ss, bl);
7c673cae
FG
133 }
134
9f95a23c 135 void decode(ceph::buffer::list::const_iterator& bl) {
7c673cae 136 struct ceph_sockaddr_storage ss;
9f95a23c 137 ceph::decode_raw(ss, bl);
7c673cae
FG
138 ss.ss_family = ntohs(ss.ss_family);
139 *this = ss;
140 }
141} __attribute__ ((__packed__));
142WRITE_CLASS_ENCODER(ceph_sockaddr_storage)
143
11fdf7f2
TL
144/*
145 * encode sockaddr.ss_family as network byte order
146 */
9f95a23c 147static inline void encode(const sockaddr_storage& a, ceph::buffer::list& bl) {
11fdf7f2
TL
148#if defined(__linux__)
149 struct sockaddr_storage ss = a;
150 ss.ss_family = htons(ss.ss_family);
9f95a23c 151 ceph::encode_raw(ss, bl);
11fdf7f2
TL
152#elif defined(__FreeBSD__) || defined(__APPLE__)
153 ceph_sockaddr_storage ss{};
154 auto src = (unsigned char const *)&a;
155 auto dst = (unsigned char *)&ss;
156 src += sizeof(a.ss_len);
157 ss.ss_family = a.ss_family;
158 src += sizeof(a.ss_family);
159 dst += sizeof(ss.ss_family);
160 const auto copy_size = std::min((unsigned char*)(&a + 1) - src,
161 (unsigned char*)(&ss + 1) - dst);
162 ::memcpy(dst, src, copy_size);
163 encode(ss, bl);
164#else
f67539c2 165 ceph_sockaddr_storage ss;
11fdf7f2 166 ::memset(&ss, '\0', sizeof(ss));
f67539c2 167 ::memcpy(&ss, &a, std::min(sizeof(ss), sizeof(a)));
11fdf7f2
TL
168 encode(ss, bl);
169#endif
170}
9f95a23c
TL
171static inline void decode(sockaddr_storage& a,
172 ceph::buffer::list::const_iterator& bl) {
11fdf7f2 173#if defined(__linux__)
9f95a23c 174 ceph::decode_raw(a, bl);
11fdf7f2
TL
175 a.ss_family = ntohs(a.ss_family);
176#elif defined(__FreeBSD__) || defined(__APPLE__)
177 ceph_sockaddr_storage ss{};
178 decode(ss, bl);
179 auto src = (unsigned char const *)&ss;
180 auto dst = (unsigned char *)&a;
181 a.ss_len = 0;
182 dst += sizeof(a.ss_len);
183 a.ss_family = ss.ss_family;
184 src += sizeof(ss.ss_family);
185 dst += sizeof(a.ss_family);
186 auto const copy_size = std::min((unsigned char*)(&ss + 1) - src,
187 (unsigned char*)(&a + 1) - dst);
188 ::memcpy(dst, src, copy_size);
189#else
190 ceph_sockaddr_storage ss{};
191 decode(ss, bl);
192 ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a)));
193#endif
194}
195
196/*
197 * an entity's network address.
198 * includes a random value that prevents it from being reused.
199 * thus identifies a particular process instance.
200 * ipv4 for now.
201 */
7c673cae
FG
202struct entity_addr_t {
203 typedef enum {
204 TYPE_NONE = 0,
205 TYPE_LEGACY = 1, ///< legacy msgr1 protocol (ceph jewel and older)
206 TYPE_MSGR2 = 2, ///< msgr2 protocol (new in ceph kraken)
11fdf7f2 207 TYPE_ANY = 3, ///< ambiguous
7c673cae 208 } type_t;
11fdf7f2
TL
209 static const type_t TYPE_DEFAULT = TYPE_MSGR2;
210 static std::string_view get_type_name(int t) {
7c673cae
FG
211 switch (t) {
212 case TYPE_NONE: return "none";
11fdf7f2
TL
213 case TYPE_LEGACY: return "v1";
214 case TYPE_MSGR2: return "v2";
215 case TYPE_ANY: return "any";
7c673cae
FG
216 default: return "???";
217 }
218 };
219
220 __u32 type;
221 __u32 nonce;
222 union {
223 sockaddr sa;
224 sockaddr_in sin;
225 sockaddr_in6 sin6;
226 } u;
227
11fdf7f2 228 entity_addr_t() : type(0), nonce(0) {
7c673cae
FG
229 memset(&u, 0, sizeof(u));
230 }
231 entity_addr_t(__u32 _type, __u32 _nonce) : type(_type), nonce(_nonce) {
232 memset(&u, 0, sizeof(u));
233 }
234 explicit entity_addr_t(const ceph_entity_addr &o) {
235 type = o.type;
236 nonce = o.nonce;
237 memcpy(&u, &o.in_addr, sizeof(u));
238#if !defined(__FreeBSD__)
239 u.sa.sa_family = ntohs(u.sa.sa_family);
240#endif
241 }
242
243 uint32_t get_type() const { return type; }
244 void set_type(uint32_t t) { type = t; }
11fdf7f2
TL
245 bool is_legacy() const { return type == TYPE_LEGACY; }
246 bool is_msgr2() const { return type == TYPE_MSGR2; }
247 bool is_any() const { return type == TYPE_ANY; }
7c673cae
FG
248
249 __u32 get_nonce() const { return nonce; }
250 void set_nonce(__u32 n) { nonce = n; }
251
252 int get_family() const {
253 return u.sa.sa_family;
254 }
255 void set_family(int f) {
256 u.sa.sa_family = f;
257 }
258
11fdf7f2
TL
259 bool is_ipv4() const {
260 return u.sa.sa_family == AF_INET;
261 }
262 bool is_ipv6() const {
263 return u.sa.sa_family == AF_INET6;
264 }
265
7c673cae
FG
266 sockaddr_in &in4_addr() {
267 return u.sin;
268 }
269 const sockaddr_in &in4_addr() const{
270 return u.sin;
271 }
272 sockaddr_in6 &in6_addr(){
273 return u.sin6;
274 }
275 const sockaddr_in6 &in6_addr() const{
276 return u.sin6;
277 }
278 const sockaddr *get_sockaddr() const {
279 return &u.sa;
280 }
281 size_t get_sockaddr_len() const {
282 switch (u.sa.sa_family) {
283 case AF_INET:
284 return sizeof(u.sin);
285 case AF_INET6:
286 return sizeof(u.sin6);
287 }
288 return sizeof(u);
289 }
290 bool set_sockaddr(const struct sockaddr *sa)
291 {
292 switch (sa->sa_family) {
293 case AF_INET:
11fdf7f2
TL
294 // pre-zero, since we're only copying a portion of the source
295 memset(&u, 0, sizeof(u));
7c673cae
FG
296 memcpy(&u.sin, sa, sizeof(u.sin));
297 break;
298 case AF_INET6:
11fdf7f2
TL
299 // pre-zero, since we're only copying a portion of the source
300 memset(&u, 0, sizeof(u));
7c673cae
FG
301 memcpy(&u.sin6, sa, sizeof(u.sin6));
302 break;
11fdf7f2
TL
303 case AF_UNSPEC:
304 memset(&u, 0, sizeof(u));
305 break;
7c673cae
FG
306 default:
307 return false;
308 }
309 return true;
310 }
311
312 sockaddr_storage get_sockaddr_storage() const {
313 sockaddr_storage ss;
314 memcpy(&ss, &u, sizeof(u));
315 memset((char*)&ss + sizeof(u), 0, sizeof(ss) - sizeof(u));
316 return ss;
317 }
318
319 void set_in4_quad(int pos, int val) {
320 u.sin.sin_family = AF_INET;
321 unsigned char *ipq = (unsigned char*)&u.sin.sin_addr.s_addr;
322 ipq[pos] = val;
323 }
324 void set_port(int port) {
325 switch (u.sa.sa_family) {
326 case AF_INET:
327 u.sin.sin_port = htons(port);
328 break;
329 case AF_INET6:
330 u.sin6.sin6_port = htons(port);
331 break;
332 default:
333 ceph_abort();
334 }
335 }
336 int get_port() const {
337 switch (u.sa.sa_family) {
338 case AF_INET:
339 return ntohs(u.sin.sin_port);
7c673cae
FG
340 case AF_INET6:
341 return ntohs(u.sin6.sin6_port);
7c673cae
FG
342 }
343 return 0;
344 }
345
346 operator ceph_entity_addr() const {
347 ceph_entity_addr a;
348 a.type = 0;
349 a.nonce = nonce;
350 a.in_addr = get_sockaddr_storage();
351#if !defined(__FreeBSD__)
352 a.in_addr.ss_family = htons(a.in_addr.ss_family);
353#endif
354 return a;
355 }
356
357 bool probably_equals(const entity_addr_t &o) const {
358 if (get_port() != o.get_port())
359 return false;
360 if (get_nonce() != o.get_nonce())
361 return false;
362 if (is_blank_ip() || o.is_blank_ip())
363 return true;
364 if (memcmp(&u, &o.u, sizeof(u)) == 0)
365 return true;
366 return false;
367 }
11fdf7f2 368
7c673cae
FG
369 bool is_same_host(const entity_addr_t &o) const {
370 if (u.sa.sa_family != o.u.sa.sa_family)
371 return false;
372 if (u.sa.sa_family == AF_INET)
373 return u.sin.sin_addr.s_addr == o.u.sin.sin_addr.s_addr;
374 if (u.sa.sa_family == AF_INET6)
375 return memcmp(u.sin6.sin6_addr.s6_addr,
376 o.u.sin6.sin6_addr.s6_addr,
377 sizeof(u.sin6.sin6_addr.s6_addr)) == 0;
378 return false;
379 }
380
381 bool is_blank_ip() const {
382 switch (u.sa.sa_family) {
383 case AF_INET:
384 return u.sin.sin_addr.s_addr == INADDR_ANY;
385 case AF_INET6:
386 return memcmp(&u.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0;
387 default:
388 return true;
389 }
390 }
391
392 bool is_ip() const {
393 switch (u.sa.sa_family) {
394 case AF_INET:
395 case AF_INET6:
396 return true;
397 default:
398 return false;
399 }
400 }
401
11fdf7f2 402 std::string ip_only_to_str() const;
7c673cae 403
11fdf7f2 404 std::string get_legacy_str() const {
9f95a23c 405 std::ostringstream ss;
11fdf7f2
TL
406 ss << get_sockaddr() << "/" << get_nonce();
407 return ss.str();
408 }
409
20effc67
TL
410 bool parse(const std::string_view s, int default_type=TYPE_DEFAULT);
411 bool parse(const char *s, const char **end = 0, int default_type=TYPE_DEFAULT);
11fdf7f2 412
9f95a23c 413 void decode_legacy_addr_after_marker(ceph::buffer::list::const_iterator& bl)
7c673cae 414 {
11fdf7f2 415 using ceph::decode;
7c673cae
FG
416 __u8 marker;
417 __u16 rest;
11fdf7f2
TL
418 decode(marker, bl);
419 decode(rest, bl);
420 decode(nonce, bl);
7c673cae 421 sockaddr_storage ss;
11fdf7f2 422 decode(ss, bl);
7c673cae 423 set_sockaddr((sockaddr*)&ss);
11fdf7f2
TL
424 if (get_family() == AF_UNSPEC) {
425 type = TYPE_NONE;
426 } else {
427 type = TYPE_LEGACY;
428 }
7c673cae
FG
429 }
430
431 // Right now, these only deal with sockaddr_storage that have only family and content.
432 // Apparently on BSD there is also an ss_len that we need to handle; this requires
433 // broader study
434
9f95a23c 435 void encode(ceph::buffer::list& bl, uint64_t features) const {
11fdf7f2 436 using ceph::encode;
7c673cae 437 if ((features & CEPH_FEATURE_MSG_ADDR2) == 0) {
11fdf7f2
TL
438 encode((__u32)0, bl);
439 encode(nonce, bl);
7c673cae 440 sockaddr_storage ss = get_sockaddr_storage();
11fdf7f2 441 encode(ss, bl);
7c673cae
FG
442 return;
443 }
11fdf7f2 444 encode((__u8)1, bl);
7c673cae 445 ENCODE_START(1, 1, bl);
11fdf7f2
TL
446 if (HAVE_FEATURE(features, SERVER_NAUTILUS)) {
447 encode(type, bl);
448 } else {
449 // map any -> legacy for old clients. this is primary for the benefit
f67539c2 450 // of OSDMap's blocklist, but is reasonable in general since any: is
11fdf7f2
TL
451 // meaningless for pre-nautilus clients or daemons.
452 auto t = type;
453 if (t == TYPE_ANY) {
454 t = TYPE_LEGACY;
455 }
456 encode(t, bl);
457 }
458 encode(nonce, bl);
7c673cae 459 __u32 elen = get_sockaddr_len();
eafe8130
TL
460#if (__FreeBSD__) || defined(__APPLE__)
461 elen -= sizeof(u.sa.sa_len);
462#endif
11fdf7f2 463 encode(elen, bl);
7c673cae 464 if (elen) {
eafe8130
TL
465 uint16_t ss_family = u.sa.sa_family;
466
11fdf7f2 467 encode(ss_family, bl);
eafe8130
TL
468 elen -= sizeof(u.sa.sa_family);
469 bl.append(u.sa.sa_data, elen);
7c673cae
FG
470 }
471 ENCODE_FINISH(bl);
472 }
9f95a23c 473 void decode(ceph::buffer::list::const_iterator& bl) {
11fdf7f2 474 using ceph::decode;
7c673cae 475 __u8 marker;
11fdf7f2 476 decode(marker, bl);
7c673cae
FG
477 if (marker == 0) {
478 decode_legacy_addr_after_marker(bl);
479 return;
480 }
481 if (marker != 1)
9f95a23c 482 throw ceph::buffer::malformed_input("entity_addr_t marker != 1");
7c673cae 483 DECODE_START(1, bl);
11fdf7f2
TL
484 decode(type, bl);
485 decode(nonce, bl);
7c673cae 486 __u32 elen;
11fdf7f2 487 decode(elen, bl);
7c673cae 488 if (elen) {
a8e16298
TL
489#if defined(__FreeBSD__) || defined(__APPLE__)
490 u.sa.sa_len = 0;
eafe8130
TL
491#endif
492 uint16_t ss_family;
a8e16298 493 if (elen < sizeof(ss_family)) {
f67539c2 494 throw ceph::buffer::malformed_input("elen smaller than family len");
a8e16298 495 }
11fdf7f2 496 decode(ss_family, bl);
a8e16298
TL
497 u.sa.sa_family = ss_family;
498 elen -= sizeof(ss_family);
499 if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) {
f67539c2 500 throw ceph::buffer::malformed_input("elen exceeds sockaddr len");
a8e16298
TL
501 }
502 bl.copy(elen, u.sa.sa_data);
7c673cae
FG
503 }
504 DECODE_FINISH(bl);
505 }
506
9f95a23c 507 void dump(ceph::Formatter *f) const;
7c673cae 508
9f95a23c 509 static void generate_test_instances(std::list<entity_addr_t*>& o);
7c673cae
FG
510};
511WRITE_CLASS_ENCODER_FEATURES(entity_addr_t)
512
9f95a23c 513std::ostream& operator<<(std::ostream& out, const entity_addr_t &addr);
7c673cae
FG
514
515inline bool operator==(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) == 0; }
516inline bool operator!=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) != 0; }
517inline bool operator<(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) < 0; }
518inline bool operator<=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) <= 0; }
519inline bool operator>(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) > 0; }
520inline bool operator>=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) >= 0; }
521
522namespace std {
9f95a23c
TL
523template<> struct hash<entity_addr_t> {
524 size_t operator()( const entity_addr_t& x ) const {
525 static blobhash H;
526 return H(&x, sizeof(x));
527 }
528};
7c673cae
FG
529} // namespace std
530
531struct entity_addrvec_t {
9f95a23c 532 std::vector<entity_addr_t> v;
7c673cae 533
11fdf7f2
TL
534 entity_addrvec_t() {}
535 explicit entity_addrvec_t(const entity_addr_t& a) : v({ a }) {}
536
7c673cae
FG
537 unsigned size() const { return v.size(); }
538 bool empty() const { return v.empty(); }
539
11fdf7f2 540 entity_addr_t legacy_addr() const {
f67539c2 541 return addr_of_type(entity_addr_t::TYPE_LEGACY);
11fdf7f2
TL
542 }
543 entity_addr_t as_legacy_addr() const {
544 for (auto& a : v) {
545 if (a.is_legacy()) {
546 return a;
547 }
548 if (a.is_any()) {
549 auto b = a;
550 b.set_type(entity_addr_t::TYPE_LEGACY);
551 return b;
552 }
553 }
554 // hrm... lie!
555 auto a = front();
556 a.set_type(entity_addr_t::TYPE_LEGACY);
557 return a;
558 }
559 entity_addr_t front() const {
560 if (!v.empty()) {
561 return v.front();
562 }
563 return entity_addr_t();
564 }
565 entity_addr_t legacy_or_front_addr() const {
566 for (auto& a : v) {
567 if (a.type == entity_addr_t::TYPE_LEGACY) {
568 return a;
569 }
570 }
f67539c2 571 return front();
11fdf7f2 572 }
9f95a23c 573 std::string get_legacy_str() const {
11fdf7f2
TL
574 return legacy_or_front_addr().get_legacy_str();
575 }
576
577 entity_addr_t msgr2_addr() const {
f67539c2 578 return addr_of_type(entity_addr_t::TYPE_MSGR2);
11fdf7f2
TL
579 }
580 bool has_msgr2() const {
581 for (auto& a : v) {
582 if (a.is_msgr2()) {
583 return true;
584 }
585 }
586 return false;
587 }
588
f67539c2
TL
589 entity_addr_t pick_addr(uint32_t type) const {
590 entity_addr_t picked_addr;
591 switch (type) {
592 case entity_addr_t::TYPE_LEGACY:
593 [[fallthrough]];
594 case entity_addr_t::TYPE_MSGR2:
595 picked_addr = addr_of_type(type);
596 break;
597 case entity_addr_t::TYPE_ANY:
598 return front();
599 default:
600 return {};
601 }
602 if (!picked_addr.is_blank_ip()) {
603 return picked_addr;
604 } else {
605 return addr_of_type(entity_addr_t::TYPE_ANY);
606 }
607 }
608
609 entity_addr_t addr_of_type(uint32_t type) const {
610 for (auto &a : v) {
611 if (a.type == type) {
612 return a;
613 }
614 }
615 return entity_addr_t();
616 }
617
11fdf7f2
TL
618 bool parse(const char *s, const char **end = 0);
619
9f95a23c 620 void get_ports(std::set<int> *ports) const {
11fdf7f2
TL
621 for (auto& a : v) {
622 ports->insert(a.get_port());
623 }
624 }
9f95a23c
TL
625 std::set<int> get_ports() const {
626 std::set<int> r;
11fdf7f2
TL
627 get_ports(&r);
628 return r;
629 }
630
9f95a23c
TL
631 void encode(ceph::buffer::list& bl, uint64_t features) const;
632 void decode(ceph::buffer::list::const_iterator& bl);
633 void dump(ceph::Formatter *f) const;
634 static void generate_test_instances(std::list<entity_addrvec_t*>& ls);
11fdf7f2
TL
635
636 bool legacy_equals(const entity_addrvec_t& o) const {
637 if (v == o.v) {
638 return true;
639 }
640 if (v.size() == 1 &&
641 front().is_legacy() &&
642 front() == o.legacy_addr()) {
643 return true;
644 }
645 if (o.v.size() == 1 &&
646 o.front().is_legacy() &&
647 o.front() == legacy_addr()) {
648 return true;
649 }
650 return false;
651 }
652
653 bool probably_equals(const entity_addrvec_t& o) const {
654 for (unsigned i = 0; i < v.size(); ++i) {
655 if (!v[i].probably_equals(o.v[i])) {
656 return false;
657 }
658 }
659 return true;
660 }
661 bool contains(const entity_addr_t& a) const {
662 for (auto& i : v) {
663 if (a == i) {
664 return true;
665 }
666 }
667 return false;
668 }
669 bool is_same_host(const entity_addr_t& a) const {
670 for (auto& i : v) {
671 if (i.is_same_host(a)) {
672 return true;
673 }
674 }
675 return false;
676 }
677
9f95a23c 678 friend std::ostream& operator<<(std::ostream& out, const entity_addrvec_t& av) {
11fdf7f2
TL
679 if (av.v.empty()) {
680 return out;
681 } else if (av.v.size() == 1) {
682 return out << av.v[0];
683 } else {
684 return out << av.v;
685 }
686 }
687
688 friend bool operator==(const entity_addrvec_t& l, const entity_addrvec_t& r) {
689 return l.v == r.v;
690 }
691 friend bool operator!=(const entity_addrvec_t& l, const entity_addrvec_t& r) {
692 return l.v != r.v;
693 }
694 friend bool operator<(const entity_addrvec_t& l, const entity_addrvec_t& r) {
695 return l.v < r.v; // see lexicographical_compare()
696 }
20effc67
TL
697 friend bool operator>(const entity_addrvec_t& l, const entity_addrvec_t& r) {
698 return l.v > r.v; // see lexicographical_compare()
699 }
7c673cae
FG
700};
701WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t);
702
11fdf7f2 703namespace std {
9f95a23c
TL
704template<> struct hash<entity_addrvec_t> {
705 size_t operator()( const entity_addrvec_t& x) const {
706 static blobhash H;
707 size_t r = 0;
708 for (auto& i : x.v) {
709 r += H((const char*)&i, sizeof(i));
11fdf7f2 710 }
9f95a23c
TL
711 return r;
712 }
713};
11fdf7f2
TL
714} // namespace std
715
7c673cae
FG
716/*
717 * a particular entity instance
718 */
719struct entity_inst_t {
720 entity_name_t name;
721 entity_addr_t addr;
722 entity_inst_t() {}
723 entity_inst_t(entity_name_t n, const entity_addr_t& a) : name(n), addr(a) {}
724 // cppcheck-suppress noExplicitConstructor
725 entity_inst_t(const ceph_entity_inst& i) : name(i.name), addr(i.addr) { }
726 entity_inst_t(const ceph_entity_name& n, const ceph_entity_addr &a) : name(n), addr(a) {}
727 operator ceph_entity_inst() {
728 ceph_entity_inst i = {name, addr};
729 return i;
730 }
731
9f95a23c 732 void encode(ceph::buffer::list& bl, uint64_t features) const {
11fdf7f2
TL
733 using ceph::encode;
734 encode(name, bl);
735 encode(addr, bl, features);
7c673cae 736 }
9f95a23c 737 void decode(ceph::buffer::list::const_iterator& bl) {
11fdf7f2
TL
738 using ceph::decode;
739 decode(name, bl);
740 decode(addr, bl);
7c673cae
FG
741 }
742
9f95a23c
TL
743 void dump(ceph::Formatter *f) const;
744 static void generate_test_instances(std::list<entity_inst_t*>& o);
7c673cae
FG
745};
746WRITE_CLASS_ENCODER_FEATURES(entity_inst_t)
747
748
11fdf7f2 749inline bool operator==(const entity_inst_t& a, const entity_inst_t& b) {
7c673cae
FG
750 return a.name == b.name && a.addr == b.addr;
751}
11fdf7f2 752inline bool operator!=(const entity_inst_t& a, const entity_inst_t& b) {
7c673cae
FG
753 return a.name != b.name || a.addr != b.addr;
754}
11fdf7f2 755inline bool operator<(const entity_inst_t& a, const entity_inst_t& b) {
7c673cae
FG
756 return a.name < b.name || (a.name == b.name && a.addr < b.addr);
757}
758inline bool operator<=(const entity_inst_t& a, const entity_inst_t& b) {
759 return a.name < b.name || (a.name == b.name && a.addr <= b.addr);
760}
761inline bool operator>(const entity_inst_t& a, const entity_inst_t& b) { return b < a; }
762inline bool operator>=(const entity_inst_t& a, const entity_inst_t& b) { return b <= a; }
763
764namespace std {
765 template<> struct hash< entity_inst_t >
766 {
767 size_t operator()( const entity_inst_t& x ) const
768 {
769 static hash< entity_name_t > H;
770 static hash< entity_addr_t > I;
771 return H(x.name) ^ I(x.addr);
772 }
773 };
774} // namespace std
775
776
9f95a23c 777inline std::ostream& operator<<(std::ostream& out, const entity_inst_t &i)
7c673cae
FG
778{
779 return out << i.name << " " << i.addr;
780}
9f95a23c 781inline std::ostream& operator<<(std::ostream& out, const ceph_entity_inst &i)
7c673cae
FG
782{
783 entity_inst_t n = i;
784 return out << n;
785}
786
787#endif