}
// bind
- err = msgr->bindv(bind_addrs);
+ err = msgr->bindv(bind_addrs, public_addrs);
if (err < 0) {
derr << "unable to bind monitor to " << bind_addrs << dendl;
prefork.exit(1);
}
- // if the public and bind addr are different set the msgr addr
- // to the public one, now that the bind is complete.
- if (public_addrs != bind_addrs) {
- msgr->set_addrs(public_addrs);
- }
-
if (g_conf()->daemonize) {
global_init_postfork_finish(g_ceph_context);
prefork.daemonize();
return r;
}
-int Messenger::bindv(const entity_addrvec_t& addrs)
+int Messenger::bindv(const entity_addrvec_t& bind_addrs,
+ std::optional<entity_addrvec_t> public_addrs)
{
- return bind(addrs.legacy_addr());
+ return bind(bind_addrs.legacy_addr(), std::move(public_addrs));
}
#ifndef CEPH_MESSENGER_H
#define CEPH_MESSENGER_H
-#include <map>
#include <deque>
+#include <map>
+#include <optional>
#include <errno.h>
#include <sstream>
* @param addr The address to use as a template.
*/
virtual bool set_addr_unknowns(const entity_addrvec_t &addrs) = 0;
- /**
- * set the address for this Messenger. This is useful if the Messenger
- * binds to a specific address but advertises a different address on the
- * the network.
- *
- * @param addr The address to use.
- */
- virtual void set_addrs(const entity_addrvec_t &addr) = 0;
+
/// Get the default send priority.
int get_default_send_priority() { return default_send_priority; }
/**
* in an unspecified order.
*
* @param bind_addr The address to bind to.
+ * @patam public_addrs The addresses to announce over the network
* @return 0 on success, or -1 on error, or -errno if
* we can be more specific about the failure.
*/
- virtual int bind(const entity_addr_t& bind_addr) = 0;
+ virtual int bind(const entity_addr_t& bind_addr,
+ std::optional<entity_addrvec_t> public_addrs=std::nullopt) = 0;
- virtual int bindv(const entity_addrvec_t& addrs);
+ virtual int bindv(const entity_addrvec_t& bind_addrs,
+ std::optional<entity_addrvec_t> public_addrs=std::nullopt);
/**
* This function performs a full restart of the Messenger component,
stack->ready();
if (pending_bind) {
- int err = bindv(pending_bind_addrs);
+ int err = bindv(pending_bind_addrs, saved_public_addrs);
if (err) {
lderr(cct) << __func__ << " postponed bind failed" << dendl;
ceph_abort();
return 0;
}
-int AsyncMessenger::bind(const entity_addr_t &bind_addr)
+int AsyncMessenger::bind(const entity_addr_t &bind_addr,
+ std::optional<entity_addrvec_t> public_addrs)
{
- ldout(cct,10) << __func__ << " " << bind_addr << dendl;
+ ldout(cct, 10) << __func__ << " " << bind_addr
+ << " public " << public_addrs << dendl;
// old bind() can take entity_addr_t(). new bindv() can take a
// 0.0.0.0-like address but needs type and family to be set.
auto a = bind_addr;
a.set_family(AF_INET);
}
}
- return bindv(entity_addrvec_t(a));
+ return bindv(entity_addrvec_t(a), public_addrs);
}
-int AsyncMessenger::bindv(const entity_addrvec_t &bind_addrs)
+int AsyncMessenger::bindv(const entity_addrvec_t &bind_addrs,
+ std::optional<entity_addrvec_t> public_addrs)
{
lock.lock();
return -1;
}
- ldout(cct,10) << __func__ << " " << bind_addrs << dendl;
+ ldout(cct, 10) << __func__ << " " << bind_addrs
+ << " public " << public_addrs << dendl;
+ if (public_addrs && bind_addrs != public_addrs) {
+ // for the sake of rebind() and the is-not-ready case let's
+ // store public_addrs. there is no point in that if public
+ // addrs are indifferent from bind_addrs.
+ saved_public_addrs = std::move(public_addrs);
+ }
if (!stack->is_ready()) {
ldout(cct, 10) << __func__ << " Network Stack is not ready for bind yet - postponed" << dendl;
entity_addrvec_t newaddrs = *my_addrs;
for (auto& a : newaddrs.v) {
a.set_nonce(nonce);
+ if (saved_public_addrs) {
+ // transplantate network layer addresses while keeping ports
+ // (as they can be figured out by msgr from the allowed range [1])
+ // unless they are explicitly specified (NATing both IP/port?)
+ //
+ // [1]: the low-level `Processor::bind` scans for free ports in
+ // a range controlled by ms_bind_port_min and ms_bind_port_max
+ const auto& public_addr =
+ saved_public_addrs->addr_of_type(a.get_type());
+ const auto public_port = public_addr.get_port();
+ const auto bound_port = a.get_port();
+ a.set_sockaddr(public_addr.get_sockaddr());
+ a.set_port(public_port == 0 ? bound_port : public_port);
+ }
}
set_myaddrs(newaddrs);
return ret;
}
-void AsyncMessenger::set_addrs(const entity_addrvec_t &addrs)
-{
- std::lock_guard l{lock};
- auto t = addrs;
- for (auto& a : t.v) {
- a.set_nonce(nonce);
- }
- set_myaddrs(t);
- _init_local_connection();
-}
-
void AsyncMessenger::shutdown_connections(bool queue_reset)
{
ldout(cct,1) << __func__ << " " << dendl;
#define CEPH_ASYNCMESSENGER_H
#include <map>
+#include <optional>
#include "include/types.h"
#include "include/xlist.h"
* @{
*/
bool set_addr_unknowns(const entity_addrvec_t &addr) override;
- void set_addrs(const entity_addrvec_t &addrs) override;
int get_dispatch_queue_len() override {
return dispatch_queue.get_queue_len();
cluster_protocol = p;
}
- int bind(const entity_addr_t& bind_addr) override;
+ int bind(const entity_addr_t& bind_addr,
+ std::optional<entity_addrvec_t> public_addrs=std::nullopt) override;
int rebind(const std::set<int>& avoid_ports) override;
- int bindv(const entity_addrvec_t& bind_addrs) override;
+ int bindv(const entity_addrvec_t& bind_addrs,
+ std::optional<entity_addrvec_t> public_addrs=std::nullopt) override;
int client_bind(const entity_addr_t& bind_addr) override;
bool need_addr = true;
/**
- * set to bind addresses if bind was called before NetworkStack was ready to
- * bind
+ * set to bind addresses if bind or bindv were called before NetworkStack
+ * was ready to bind
*/
entity_addrvec_t pending_bind_addrs;
+ /**
+ * set to public addresses (those announced by the msgr's protocols).
+ * they are stored to handle the cases when either:
+ * a) bind or bindv were called before NetworkStack was ready to bind,
+ * b) rebind is called down the road.
+ */
+ std::optional<entity_addrvec_t> saved_public_addrs;
+
/**
* false; set to true if a pending bind exists
*/