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