Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
do not throw signal from sg_platf
[simgrid.git] / src / kernel / routing / ClusterZone.cpp
1 /* Copyright (c) 2009-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "simgrid/kernel/routing/ClusterZone.hpp"
7 #include "simgrid/kernel/routing/NetPoint.hpp"
8 #include "simgrid/kernel/routing/RoutedZone.hpp"
9 #include "src/surf/network_interface.hpp"
10 #include "src/surf/xml/platf_private.hpp" // FIXME: RouteCreationArgs and friends
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster, surf, "Routing part of surf");
13
14 /* This routing is specifically setup to represent clusters, aka homogeneous sets of machines
15  * Note that a router is created, easing the interconnection with the rest of the world. */
16
17 namespace simgrid {
18 namespace kernel {
19 namespace routing {
20 ClusterZone::ClusterZone(const std::string& name) : NetZoneImpl(name) {}
21
22 void ClusterZone::set_loopback()
23 {
24   if (not has_loopback_) {
25     num_links_per_node_++;
26     has_loopback_ = true;
27   }
28 }
29
30 void ClusterZone::set_limiter()
31 {
32   if (not has_limiter_) {
33     num_links_per_node_++;
34     has_limiter_ = true;
35   }
36 }
37
38 void ClusterZone::add_private_link_at(unsigned int position, std::pair<resource::LinkImpl*, resource::LinkImpl*> link)
39 {
40   private_links_.insert({position, link});
41 }
42
43 void ClusterZone::get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* route, double* lat)
44 {
45   XBT_VERB("cluster getLocalRoute from '%s'[%u] to '%s'[%u]", src->get_cname(), src->id(), dst->get_cname(), dst->id());
46   xbt_assert(not private_links_.empty(),
47              "Cluster routing: no links attached to the source node - did you use host_link tag?");
48
49   if ((src->id() == dst->id()) && has_loopback_) {
50     if (src->is_router()) {
51       XBT_WARN("Routing from a cluster private router to itself is meaningless");
52     } else {
53       std::pair<resource::LinkImpl*, resource::LinkImpl*> info = private_links_.at(node_pos(src->id()));
54       route->link_list.push_back(info.first);
55       if (lat)
56         *lat += info.first->get_latency();
57     }
58     return;
59   }
60
61   if (not src->is_router()) { // No private link for the private router
62     if (has_limiter_) {       // limiter for sender
63       std::pair<resource::LinkImpl*, resource::LinkImpl*> info = private_links_.at(node_pos_with_loopback(src->id()));
64       route->link_list.push_back(info.first);
65     }
66
67     std::pair<resource::LinkImpl*, resource::LinkImpl*> info =
68         private_links_.at(node_pos_with_loopback_limiter(src->id()));
69     if (info.first) { // link up
70       route->link_list.push_back(info.first);
71       if (lat)
72         *lat += info.first->get_latency();
73     }
74   }
75
76   if (backbone_) {
77     route->link_list.push_back(backbone_);
78     if (lat)
79       *lat += backbone_->get_latency();
80   }
81
82   if (not dst->is_router()) { // No specific link for router
83     std::pair<resource::LinkImpl*, resource::LinkImpl*> info =
84         private_links_.at(node_pos_with_loopback_limiter(dst->id()));
85
86     if (info.second) { // link down
87       route->link_list.push_back(info.second);
88       if (lat)
89         *lat += info.second->get_latency();
90     }
91     if (has_limiter_) { // limiter for receiver
92       info = private_links_.at(node_pos_with_loopback(dst->id()));
93       route->link_list.push_back(info.first);
94     }
95   }
96 }
97
98 void ClusterZone::get_graph(const s_xbt_graph_t* graph, std::map<std::string, xbt_node_t, std::less<>>* nodes,
99                             std::map<std::string, xbt_edge_t, std::less<>>* edges)
100 {
101   xbt_assert(router_,
102              "Malformed cluster. This may be because your platform file is a hypergraph while it must be a graph.");
103
104   /* create the router */
105   xbt_node_t routerNode = new_xbt_graph_node(graph, router_->get_cname(), nodes);
106
107   xbt_node_t backboneNode = nullptr;
108   if (backbone_) {
109     backboneNode = new_xbt_graph_node(graph, backbone_->get_cname(), nodes);
110     new_xbt_graph_edge(graph, routerNode, backboneNode, edges);
111   }
112
113   for (auto const& src : get_vertices()) {
114     if (not src->is_router()) {
115       xbt_node_t previous = new_xbt_graph_node(graph, src->get_cname(), nodes);
116
117       std::pair<resource::LinkImpl*, resource::LinkImpl*> info = private_links_.at(src->id());
118
119       if (info.first) { // link up
120         xbt_node_t current = new_xbt_graph_node(graph, info.first->get_cname(), nodes);
121         new_xbt_graph_edge(graph, previous, current, edges);
122
123         if (backbone_) {
124           new_xbt_graph_edge(graph, current, backboneNode, edges);
125         } else {
126           new_xbt_graph_edge(graph, current, routerNode, edges);
127         }
128       }
129
130       if (info.second) { // link down
131         xbt_node_t current = new_xbt_graph_node(graph, info.second->get_cname(), nodes);
132         new_xbt_graph_edge(graph, previous, current, edges);
133
134         if (backbone_) {
135           new_xbt_graph_edge(graph, current, backboneNode, edges);
136         } else {
137           new_xbt_graph_edge(graph, current, routerNode, edges);
138         }
139       }
140     }
141   }
142 }
143
144 void ClusterZone::create_links_for_node(const ClusterCreationArgs* cluster, int id, int /*rank*/, unsigned int position)
145 {
146   std::string link_id = cluster->id + "_link_" + std::to_string(id);
147
148   const s4u::Link* linkUp;
149   const s4u::Link* linkDown;
150   if (cluster->sharing_policy == simgrid::s4u::Link::SharingPolicy::SPLITDUPLEX) {
151     linkUp   = create_link(link_id + "_UP", std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
152     linkDown = create_link(link_id + "_DOWN", std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
153   } else {
154     linkUp   = create_link(link_id, std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
155     linkDown = linkUp;
156   }
157   private_links_.insert({position, {linkUp->get_impl(), linkDown->get_impl()}});
158 }
159
160 void ClusterZone::set_gateway(unsigned int position, NetPoint* gateway)
161 {
162   xbt_assert(not gateway || not gateway->is_netzone(), "ClusterZone: gateway cannot be another netzone %s",
163              gateway->get_cname());
164   gateways_[position] = gateway;
165 }
166
167 NetPoint* ClusterZone::get_gateway(unsigned int position)
168 {
169   NetPoint* res = nullptr;
170   auto it       = gateways_.find(position);
171   if (it != gateways_.end()) {
172     res = it->second;
173   }
174   return res;
175 }
176
177 void ClusterZone::fill_leaf_from_cb(unsigned int position, const std::vector<unsigned int>& dimensions,
178                                     const std::function<s4u::ClusterNetPointCb>& set_netpoint_cb,
179                                     const std::function<s4u::ClusterLinkCb>& set_loopback_cb,
180                                     const std::function<s4u::ClusterLinkCb>& set_limiter_cb, NetPoint** node_netpoint,
181                                     s4u::Link** lb_link, s4u::Link** limiter_link)
182 {
183   xbt_assert(node_netpoint, "Invalid node_netpoint parameter");
184   xbt_assert(lb_link, "Invalid lb_link parameter");
185   xbt_assert(limiter_link, "Invalid limiter_link paramater");
186   *lb_link      = nullptr;
187   *limiter_link = nullptr;
188
189   // auxiliary function to get dims from index
190   auto index_to_dims = [&dimensions](int index) {
191     std::vector<unsigned int> dims_array(dimensions.size());
192     for (unsigned long i = dimensions.size() - 1; i != 0; --i) {
193       if (index <= 0) {
194         break;
195       }
196       unsigned int value = index % dimensions[i];
197       dims_array[i]      = value;
198       index              = (index / dimensions[i]);
199     }
200     return dims_array;
201   };
202
203   kernel::routing::NetPoint* netpoint = nullptr;
204   kernel::routing::NetPoint* gw       = nullptr;
205   auto dims                           = index_to_dims(position);
206   std::tie(netpoint, gw)              = set_netpoint_cb(get_iface(), dims, position);
207   xbt_assert(netpoint, "set_netpoint(elem=%u): Invalid netpoint (nullptr)", position);
208   if (netpoint->is_netzone()) {
209     xbt_assert(gw && not gw->is_netzone(),
210                "set_netpoint(elem=%u): Netpoint (%s) is a netzone, but gateway (%s) is invalid", position,
211                netpoint->get_cname(), gw ? gw->get_cname() : "nullptr");
212   } else {
213     xbt_assert(not gw, "set_netpoint: Netpoint (%s) isn't netzone, gateway must be nullptr", netpoint->get_cname());
214   }
215   // setting gateway
216   set_gateway(position, gw);
217
218   if (set_loopback_cb) {
219     s4u::Link* loopback = set_loopback_cb(get_iface(), dims, position);
220     xbt_assert(loopback, "set_loopback: Invalid loopback link (nullptr) for element %u", position);
221     set_loopback();
222     add_private_link_at(node_pos(netpoint->id()), {loopback->get_impl(), loopback->get_impl()});
223     *lb_link = loopback;
224   }
225
226   if (set_limiter_cb) {
227     s4u::Link* limiter = set_limiter_cb(get_iface(), dims, position);
228     xbt_assert(limiter, "set_limiter: Invalid limiter link (nullptr) for element %u", position);
229     set_limiter();
230     add_private_link_at(node_pos_with_loopback(netpoint->id()), {limiter->get_impl(), limiter->get_impl()});
231     *limiter_link = limiter;
232   }
233   *node_netpoint = netpoint;
234 }
235
236 } // namespace routing
237 } // namespace kernel
238
239 namespace s4u {
240 NetZone* create_cluster_zone(const std::string& name)
241 {
242   return (new kernel::routing::ClusterZone(name))->get_iface();
243 }
244 } // namespace s4u
245
246 } // namespace simgrid