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