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