artdaq  v3_12_02
PortManager.cc
1 #include "artdaq/DAQdata/PortManager.hh"
2 #include "TRACE/tracemf.h"
3 #define TRACE_NAME "PortManager"
4 
5 #include "artdaq/DAQdata/Globals.hh"
7 
8 #include "fhiclcpp/ParameterSet.h"
9 
10 #include <cstdlib>
11 #include <sstream>
12 #include <string>
13 
15  : multicast_interface_address_()
16  , request_message_group_pattern_("227.128.PPP.SSS")
17  , routing_table_group_pattern_("227.129.PPP.SSS")
18  , multicast_transfer_group_pattern_("227.130.14.PPP")
19 {
20 }
21 
22 void artdaq::PortManager::UpdateConfiguration(fhicl::ParameterSet const& ps)
23 {
24  if (ps.has_key("artdaq_base_port"))
25  {
26  auto newVal = ps.get<int>("artdaq_base_port");
27  if (base_port_ != DEFAULT_BASE && base_port_ != newVal)
28  {
29  TLOG(TLVL_WARNING) << "Base port has changed! This may lead to misconfiguration and non-functional systems!";
30  }
31  base_port_ = newVal;
32  }
33  if (ps.has_key("ports_per_partition"))
34  {
35  auto newVal = ps.get<int>("ports_per_partition");
36  if (ports_per_partition_ != DEFAULT_PORTS_PER_PARTITION && ports_per_partition_ != newVal)
37  {
38  TLOG(TLVL_WARNING) << "Ports per Partition has changed! This may lead to misconfiguration and non-functional systems!";
39  }
40  ports_per_partition_ = newVal;
41  }
42 
43  auto bp = getenv("ARTDAQ_BASE_PORT"); // Environment overrides configuration
44  if (bp != nullptr)
45  {
46  try
47  {
48  auto bp_s = std::string(bp);
49  auto bp_tmp = std::stoi(bp_s, nullptr, 0);
50  if (bp_tmp < 1024 || bp_tmp > 32000)
51  {
52  TLOG(TLVL_ERROR) << "Base port specified in ARTDAQ_BASE_PORT is invalid! Ignoring...";
53  }
54  else
55  {
56  base_port_ = bp_tmp;
57  }
58  }
59  catch (const std::invalid_argument&)
60  {}
61  catch (const std::out_of_range&)
62  {}
63  }
64 
65  auto ppp = getenv("ARTDAQ_PORTS_PER_PARTITION"); // Environment overrides configuration
66  if (ppp != nullptr)
67  {
68  try
69  {
70  auto ppp_s = std::string(ppp);
71  auto ppp_tmp = std::stoi(ppp_s, nullptr, 0);
72  if (ppp_tmp < 0 || ppp_tmp > 32000)
73  {
74  TLOG(TLVL_ERROR) << "Ports per partition specified in ARTDAQ_PORTS_PER_PARTITION is invalid! Ignoring...";
75  }
76  else
77  {
78  ports_per_partition_ = ppp_tmp;
79  }
80  }
81  catch (const std::invalid_argument&)
82  {}
83  catch (const std::out_of_range&)
84  {}
85  }
86 
87  if (!base_configured_ && (base_port_ != DEFAULT_BASE || ports_per_partition_ != DEFAULT_PORTS_PER_PARTITION))
88  {
89  base_configured_ = true;
90  auto max_partitions = (65535 - base_port_) / ports_per_partition_;
91  TLOG(TLVL_INFO) << "Based on configuration, there can be " << max_partitions << " partitions of " << ports_per_partition_ << " ports each, starting at port " << base_port_;
92  if (GetPartitionNumber() > max_partitions)
93  {
94  TLOG(TLVL_ERROR) << "Currently-configured partition number is greater than the allowed number! The system WILL NOT WORK!";
95  exit(22);
96  }
97  }
98 
99  in_addr tmp_addr;
100  bool multicast_configured = false;
101  if (ps.has_key("multicast_output_interface"))
102  {
103  multicast_configured = GetIPOfInterface(ps.get<std::string>("multicast_output_interface"), tmp_addr) == 0;
104  }
105  else if (ps.has_key("multicast_output_network"))
106  {
107  multicast_configured = GetInterfaceForNetwork(ps.get<std::string>("multicast_output_network").c_str(), tmp_addr) == 0;
108  }
109  if (multicast_configured && multicasts_configured_ && tmp_addr.s_addr != multicast_interface_address_.s_addr)
110  {
111  TLOG(TLVL_WARNING) << "Multicast output address has changed! This may lead to misconfiguration and non-functional systems!";
112  }
113  else if (multicast_configured)
114  {
115  multicasts_configured_ = true;
116  multicast_interface_address_ = tmp_addr;
117  }
118 
119  if (ps.has_key("multicast_group_offset"))
120  {
121  auto newVal = ps.get<int>("multicast_group_offset");
122  if (multicast_group_offset_ != DEFAULT_MULTICAST_GROUP_OFFSET && multicast_group_offset_ != newVal)
123  {
124  TLOG(TLVL_WARNING) << "Multicast group offset (added to last part of group IP address) has changed! This may lead to misconfiguration and non-functional systems!";
125  }
126  multicast_group_offset_ = newVal;
127  }
128 
129  if (ps.has_key("routing_token_port_offset"))
130  {
131  auto newVal = ps.get<int>("routing_token_port_offset");
132  if (routing_tokens_configured_ && newVal != routing_token_offset_)
133  {
134  TLOG(TLVL_WARNING) << "Routing Token Port Offset has changed! This may lead to misconfiguration and non-functional systems!";
135  }
136 
137  routing_tokens_configured_ = true;
138  routing_token_offset_ = newVal;
139  }
140 
141  if (ps.has_key("routing_table_ack_port_offset"))
142  {
143  auto newVal = ps.get<int>("routing_table_ack_port_offset");
144  if (routing_acks_configured_ && newVal != routing_ack_offset_)
145  {
146  TLOG(TLVL_WARNING) << "Routing Table Acknowledgement Port Offset has changed! This may lead to misconfiguration and non-functional systems!";
147  }
148 
149  routing_acks_configured_ = true;
150  routing_ack_offset_ = newVal;
151  }
152 
153  if (ps.has_key("xmlrpc_port_offset"))
154  {
155  auto newVal = ps.get<int>("xmlrpc_port_offset");
156  if (xmlrpc_configured_ && newVal != xmlrpc_offset_)
157  {
158  TLOG(TLVL_WARNING) << "XMLRPC Port Offset has changed! This may lead to misconfiguration and non-functional systems!";
159  }
160 
161  xmlrpc_configured_ = true;
162  xmlrpc_offset_ = newVal;
163  }
164 
165  if (ps.has_key("tcp_socket_port_offset"))
166  {
167  auto newVal = ps.get<int>("tcp_socket_port_offset");
168  if (tcpsocket_configured_ && newVal != tcp_socket_offset_)
169  {
170  TLOG(TLVL_WARNING) << "TCPSocketTransfer Port Offset has changed! This may lead to misconfiguration and non-functional systems!";
171  }
172 
173  tcpsocket_configured_ = true;
174  tcp_socket_offset_ = newVal;
175  }
176 
177  if (ps.has_key("request_port"))
178  {
179  auto newVal = ps.get<int>("request_port");
180  if (request_port_configured_ && newVal != request_message_port_)
181  {
182  TLOG(TLVL_WARNING) << "Request Message Port has changed! This may lead to misconfiguration and non-functional systems!";
183  }
184 
185  request_port_configured_ = true;
186  request_message_port_ = newVal;
187  }
188 
189  if (ps.has_key("request_pattern"))
190  {
191  auto newVal = ps.get<std::string>("request_pattern");
192  if (request_pattern_configured_ && newVal != request_message_group_pattern_)
193  {
194  TLOG(TLVL_WARNING) << "Request Message Multicast Group Pattern has changed! This may lead to misconfiguration and non-functional systems!";
195  }
196 
197  request_pattern_configured_ = true;
198  request_message_group_pattern_ = newVal;
199  }
200 
201  if (ps.has_key("routing_table_port"))
202  {
203  auto newVal = ps.get<int>("routing_table_port");
204  if (routing_table_port_configured_ && newVal != routing_table_port_)
205  {
206  TLOG(TLVL_WARNING) << "Routing Table Port has changed! This may lead to misconfiguration and non-functional systems!";
207  }
208 
209  routing_table_port_configured_ = true;
210  routing_table_port_ = newVal;
211  }
212 
213  if (ps.has_key("routing_table_pattern"))
214  {
215  auto newVal = ps.get<std::string>("routing_table_pattern");
216  if (routing_table_pattern_configured_ && newVal != routing_table_group_pattern_)
217  {
218  TLOG(TLVL_WARNING) << "Routing Table Multicast Group Pattern has changed! This may lead to misconfiguration and non-functional systems!";
219  }
220 
221  routing_table_pattern_configured_ = true;
222  routing_table_group_pattern_ = newVal;
223  }
224 
225  if (ps.has_key("multicast_transfer_port_offset"))
226  {
227  auto newVal = ps.get<int>("multicast_transfer_port_offset");
228  if (multicast_transfer_port_configued_ && newVal != multicast_transfer_offset_)
229  {
230  TLOG(TLVL_WARNING) << "Multicast Transfer Port Offset has changed! This may lead to misconfiguration and non-functional systems!";
231  }
232 
233  multicast_transfer_port_configued_ = true;
234  multicast_transfer_offset_ = newVal;
235  }
236 
237  if (ps.has_key("multicast_transfer_pattern"))
238  {
239  auto newVal = ps.get<std::string>("multicast_transfer_pattern");
240  if (multicast_transfer_pattern_configured_ && newVal != multicast_transfer_group_pattern_)
241  {
242  TLOG(TLVL_WARNING) << "Multicast Transfer Multicast Group Pattern has changed! This may lead to misconfiguration and non-functional systems!";
243  }
244 
245  multicast_transfer_pattern_configured_ = true;
246  multicast_transfer_group_pattern_ = newVal;
247  }
248 }
249 
251 {
252  if (!routing_tokens_configured_)
253  {
254  TLOG(TLVL_INFO) << "Using default port range for Routing Tokens";
255  routing_tokens_configured_ = true;
256  }
257 
258  return base_port_ + routing_token_offset_ + (GetPartitionNumber() * ports_per_partition_) + subsystemID;
259 }
260 
262 {
263  if (!routing_acks_configured_)
264  {
265  TLOG(TLVL_INFO) << "Using default port range for Routing Table Acknowledgements";
266  routing_acks_configured_ = true;
267  }
268  return base_port_ + routing_ack_offset_ + (GetPartitionNumber() * ports_per_partition_) + subsystemID;
269 }
270 
272 {
273  if (!xmlrpc_configured_)
274  {
275  TLOG(TLVL_INFO) << "Using default port range for XMLRPC";
276  xmlrpc_configured_ = true;
277  }
278  return base_port_ + xmlrpc_offset_ + rank + (GetPartitionNumber() * ports_per_partition_);
279 }
280 
282 {
283  if (!tcpsocket_configured_)
284  {
285  TLOG(TLVL_INFO) << "Using default port range for TCPSocket Transfer";
286  tcpsocket_configured_ = true;
287  }
288  return base_port_ + tcp_socket_offset_ + (GetPartitionNumber() * ports_per_partition_) + rank;
289 }
290 
292 {
293  if (!request_port_configured_)
294  {
295  TLOG(TLVL_INFO) << "Using default port for Request Messages";
296  request_port_configured_ = true;
297  }
298  return request_message_port_;
299 }
300 
302 {
303  if (!request_pattern_configured_)
304  {
305  TLOG(TLVL_INFO) << "Using default address for Request Messages";
306  request_pattern_configured_ = true;
307  }
308 
309  return parse_pattern_(request_message_group_pattern_, subsystemID);
310 }
311 
313 {
314  if (!routing_table_port_configured_)
315  {
316  TLOG(TLVL_INFO) << "Using default port for Routing Tables";
317  routing_table_port_configured_ = true;
318  }
319 
320  return routing_table_port_;
321 }
322 
324 {
325  if (!routing_table_pattern_configured_)
326  {
327  TLOG(TLVL_INFO) << "Using default address for Routing Tables";
328  routing_table_pattern_configured_ = true;
329  }
330 
331  return parse_pattern_(routing_table_group_pattern_, subsystemID);
332 }
333 
335 {
336  if (!multicast_transfer_port_configued_)
337  {
338  TLOG(TLVL_INFO) << "Using default port for Multicast Transfer";
339  multicast_transfer_port_configued_ = true;
340  }
341 
342  return multicast_transfer_offset_ + rank;
343 }
344 
346 {
347  if (!multicast_transfer_pattern_configured_)
348  {
349  TLOG(TLVL_INFO) << "Using default address for Multicast Transfer";
350  multicast_transfer_pattern_configured_ = true;
351  }
352 
353  return parse_pattern_(multicast_transfer_group_pattern_);
354 }
355 
356 in_addr artdaq::PortManager::GetMulticastOutputAddress(const std::string& interface_name, const std::string& interface_address)
357 {
358  if (!multicasts_configured_)
359  {
360  if (interface_name.empty() && interface_address.empty())
361  {
362  TLOG(TLVL_INFO) << "Using default multicast output address (autodetected private interface)";
363  }
364  if (!interface_name.empty())
365  {
366  GetIPOfInterface(interface_name, multicast_interface_address_);
367  }
368  else if (!interface_address.empty())
369  {
370  GetInterfaceForNetwork(interface_address.c_str(), multicast_interface_address_);
371  }
372  else
373  {
374  AutodetectPrivateInterface(multicast_interface_address_);
375  }
376  multicasts_configured_ = true;
377  }
378  return multicast_interface_address_;
379 }
380 
381 std::string artdaq::PortManager::parse_pattern_(const std::string& pattern, int subsystemID, int rank)
382 {
383  std::istringstream f(pattern);
384  std::vector<int> address(4);
385  std::string s;
386 
387  while (getline(f, s, '.'))
388  {
389  if (s == "PPP")
390  {
391  address.push_back(GetPartitionNumber());
392  }
393  else if (s == "SSS")
394  {
395  address.push_back(subsystemID);
396  }
397  else if (s == "RRR")
398  {
399  address.push_back(rank);
400  }
401  else
402  {
403  address.push_back(stoi(s));
404  }
405  }
406 
407  if (address.size() != 4)
408  {
409  TLOG(TLVL_ERROR) << "Invalid address pattern!";
410  while (address.size() < 4) { address.push_back(0); }
411  }
412  address[3] += multicast_group_offset_;
413 
414  return std::to_string(address[0]) + "." + std::to_string(address[1]) + "." + std::to_string(address[2]) + "." + std::to_string(address[3]);
415 }
int GetRequestMessagePort()
Get the port that should be used for multicast request messages.
Definition: PortManager.cc:291
int GetIPOfInterface(const std::string &interface_name, in_addr &addr)
Get the IP address associated with a given interface name.
Definition: TCPConnect.cc:78
int GetMulticastTransferPort(int rank)
Get the multicast transfer port for the given rank.
Definition: PortManager.cc:334
int GetRoutingAckPort(int subsystemID=0)
Get the port that should be used for Routing Acknowledgements.
Definition: PortManager.cc:261
std::string GetRequestMessageGroupAddress(int subsystemID=0)
Get the multicast address for request messages.
Definition: PortManager.cc:301
in_addr GetMulticastOutputAddress(const std::string &interface_name="", const std::string &interface_address="")
Determine the output interface address, using the hints provided.
Definition: PortManager.cc:356
int GetInterfaceForNetwork(char const *host_in, in_addr &addr)
Convert an IP address to the network address of the interface sharing the subnet mask.
Definition: TCPConnect.cc:224
PortManager()
PortManager Construator.
Definition: PortManager.cc:14
int GetRoutingTokenPort(int subsystemID=0)
Get the port that should be used for Routing Tokens.
Definition: PortManager.cc:250
std::string GetMulticastTransferGroupAddress()
Get the multicast address for multicast transfers.
Definition: PortManager.cc:345
int GetXMLRPCPort(int rank)
Get the XMLRPC port for the given rank.
Definition: PortManager.cc:271
int AutodetectPrivateInterface(in_addr &addr)
Pick a private IP address on this host.
Definition: TCPConnect.cc:132
void UpdateConfiguration(fhicl::ParameterSet const &ps)
Override the default configuration.
Definition: PortManager.cc:22
int GetRoutingTablePort()
Get the port that should be used for multicast Routing Tables.
Definition: PortManager.cc:312
int GetTCPSocketTransferPort(int rank)
Get the TCP Socket transfer port for the given rank.
Definition: PortManager.cc:281
std::string GetRoutingTableGroupAddress(int subsystemID=0)
Get the multicast address for Routing Tables.
Definition: PortManager.cc:323