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