use quantifiable_derive::Quantifiable;use super::prelude::*;
use crate::matrix::Matrix;
use super::dragonfly::{Arrangement,ArrangementPoint,ArrangementSize,Palmtree,new_arrangement};
use crate::config_parser::ConfigurationValue;
use crate::match_object_panic;
#[derive(Quantifiable)]
#[derive(Debug)]
pub struct Megafly
{
servers_per_leaf: usize,
group_size: usize,
global_ports_per_spine: usize,
number_of_groups: usize,
global_arrangement: Box<dyn Arrangement>,
distance_matrix:Matrix<u8>,
}
impl Topology for Megafly
{
fn num_routers(&self) -> usize
{
self.number_of_groups * self.group_size * 2
}
fn num_servers(&self) -> usize
{
self.number_of_groups * self.group_size * self.servers_per_leaf
}
fn neighbour(&self, router_index:usize, port: usize) -> (Location,usize)
{
let (router_local,router_global,level_index)=self.unpack(router_index);
match level_index
{
0 => {
if port < self.group_size
{
(Location::RouterPort{router_index:self.pack((port,router_global,1)),router_port:router_local},0)
}
else
{
let port_offset = port - self.group_size;
(Location::ServerPort(router_index*self.servers_per_leaf + port_offset),2)
}
},
1 => {
if port < self.group_size
{
(Location::RouterPort{router_index:self.pack((port,router_global,0)),router_port:router_local},0)
}
else
{
let port_offset = port - self.group_size;
let point = ArrangementPoint {
group_index: router_global,
group_offset: router_local,
port_index: port_offset,
};
let target_point = self.global_arrangement.map(point);
let target_global = target_point.group_index;
let target_local = target_point.group_offset;
let target_port = self.group_size + target_point.port_index;
(Location::RouterPort{router_index:self.pack((target_local,target_global,1)),router_port:target_port},1)
}
},
_ => unreachable!("level must be 0 or 1"),
}
}
fn server_neighbour(&self, server_index:usize) -> (Location,usize)
{
let degree = self.group_size; (Location::RouterPort{
router_index: server_index/self.servers_per_leaf,
router_port: degree + server_index%self.servers_per_leaf,
},2)
}
fn diameter(&self) -> usize
{
3
}
fn distance(&self,origin:usize,destination:usize) -> usize
{
(*self.distance_matrix.get(origin,destination)).into()
}
fn amount_shortest_paths(&self,_origin:usize,_destination:usize) -> usize
{
todo!()
}
fn average_amount_shortest_paths(&self) -> f32
{
todo!()
}
fn maximum_degree(&self) -> usize
{
self.group_size + self.global_ports_per_spine
}
fn minimum_degree(&self) -> usize
{
self.group_size
}
fn degree(&self, router_index: usize) -> usize
{
let (_router_local,_router_global,level_index)=self.unpack(router_index);
match level_index
{
0 => self.group_size,
1 => self.group_size + self.global_ports_per_spine,
_ => unreachable!(),
}
}
fn ports(&self, router_index: usize) -> usize
{
let (_router_local,_router_global,level_index)=self.unpack(router_index);
match level_index
{
0 => self.group_size + self.servers_per_leaf,
1 => self.group_size + self.global_ports_per_spine,
_ => unreachable!(),
}
}
fn cartesian_data(&self) -> Option<&CartesianData>
{
todo!()
}
fn coordinated_routing_record(&self, _coordinates_a:&[usize], _coordinates_b:&[usize], _rng: Option<&mut StdRng>)->Vec<i32>
{
todo!()
}
fn is_direction_change(&self, _router_index:usize, _input_port: usize, _output_port: usize) -> bool
{
todo!()
}
fn up_down_distance(&self,_origin:usize,_destination:usize) -> Option<(usize,usize)>
{
todo!()
}
}
impl Megafly
{
pub fn new(arg:TopologyBuilderArgument) -> Megafly
{
let mut global_ports_per_spine=None;
let mut servers_per_leaf=None;
let mut group_size=None;
let mut number_of_groups=None;
let mut global_arrangement=None;
match_object_panic!(arg.cv,"Megafly",value,
"global_ports_per_spine" => global_ports_per_spine=Some(value.as_f64().expect("bad value for global_ports_per_spine")as usize),
"servers_per_leaf" => servers_per_leaf=Some(value.as_f64().expect("bad value for servers_per_leaf")as usize),
"group_size" => group_size=Some(value.as_f64().expect("bad value for group_size")as usize),
"number_of_groups" => number_of_groups=Some(value.as_f64().expect("bad value for number_of_groups")as usize),
"global_arrangement" => global_arrangement=Some(new_arrangement(value.into())),
);
let global_ports_per_spine=global_ports_per_spine.expect("There were no global_ports_per_spine");
let servers_per_leaf=servers_per_leaf.expect("There were no servers_per_leaf");
let group_size=group_size.expect("There were no group_size");
let number_of_groups=number_of_groups.expect("There were no number_of_groups");
let mut global_arrangement = global_arrangement.unwrap_or_else(||Box::new(Palmtree::default()));
global_arrangement.initialize(ArrangementSize{
number_of_groups,
group_size,
number_of_ports: global_ports_per_spine,
lag: 1usize,
},arg.rng);
let mut topo=Megafly{
global_ports_per_spine,
servers_per_leaf,
global_arrangement,
group_size,
number_of_groups,
distance_matrix:Matrix::constant(0,0,0),
};
let (distance_matrix,_amount_matrix)=topo.compute_amount_shortest_paths();
topo.distance_matrix=distance_matrix.map(|x|*x as u8);
topo
}
fn unpack(&self, router_index: usize) -> (usize,usize,usize)
{
let size = self.number_of_groups * self.group_size;
let level_index = router_index / size;
let level_offset = router_index % size;
let group_index = level_offset / self.group_size;
let group_offset = level_offset % self.group_size;
( group_offset, group_index, level_index )
}
fn pack(&self, coordinates:(usize,usize,usize)) -> usize
{
let (group_offset, group_index, level_index) = coordinates;
let level_offset = group_offset + group_index*self.group_size;
level_offset + level_index*self.group_size*self.number_of_groups
}
}