/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.self_reshape_network;
import org.onosproject.self_reshape_network.impl.*;
import org.onosproject.self_reshape_network.intf.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IpPrefix;
import org.onosproject.common.DefaultTopology;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onlab.graph.ScalarWeight;
import org.onlab.graph.Weight;
import org.onosproject.incubator.net.PortStatisticsService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultEdgeLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.EdgeLink;
import org.onosproject.net.ElementId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import static org.onosproject.net.device.DeviceEvent.Type.*;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onlab.packet.IpAddress;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.TpPort;
import org.onlab.packet.MacAddress;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.DefaultTopologyVertex;
//import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.MetricLinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.net.topology.TopologyVertex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Skeletal ONOS application component.
*
* author: wangxueqing
*/
@Component(immediate = true)
@Service
public class Self_reshape_network implements SelfReshapeService {
private final Logger log = LoggerFactory.getLogger(getClass());
//private final LoadBalanceRouting routing = new LoadBalanceRouting();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private PortStatisticsService portStatisticsService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private IntentService intentService;
private ApplicationId appId;
private ConcurrentMap<Set<Criterion>, Intent> intentMap = new ConcurrentHashMap<>();
private InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
//*wangxueqing
private RequestMonitor requestmonitor = new RequestMonitor();
@Activate
protected void activate() {
//intentMap.clear();
appId = coreService.registerApplication("org.onosproject.selfreshapenetwork");
requestmonitor.addListener();
//packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
//packetService.requestPackets(DefaultTrafficSelector.builder()
// .matchEthType(Ethernet.TYPE_IPV4).build(),
// PacketPriority.REACTIVE, appId);
log.info("Started");
}
@Deactivate
protected void deactivate() {
// packetService.removeProcessor(packetProcessor);
// packetService.cancelPackets(DefaultTrafficSelector.builder()
// .matchEthType(Ethernet.TYPE_IPV4).build(),
//PacketPriority.REACTIVE, appId);
// intentMap.values().forEach(intent -> {
// intentService.withdraw(intent);
// intentService.purge(intent);
// });
// intentMap.clear();
log.info("Stopped");
}
@Override
public Set<Path> getLoadBalancePaths(ElementId src, ElementId dst) {
return routing.getLoadBalancePaths(src, dst);
}
@Override
public Set<Path> getLoadBalancePaths(Topology topo, ElementId src, ElementId dst) {
return routing.getLoadBalancePaths(topo, src, dst);
}
//流表下发测试函数,当前拓扑中的交换机都发一遍
@Override
public void testInstallRules() {
int src_ip_0 = 10;
int src_ip_1 = 0;
int src_ip_2 = 0;
int src_ip_3 = 1;
int des_ip_0 = 10;
int des_ip_1 = 0;
int des_ip_2 = 0;
int des_ip_3 = 2;
byte[] ip = {(byte) src_ip_0, (byte) src_ip_1, (byte) src_ip_2, (byte) src_ip_3};
IpAddress src_ip = IpAddress.valueOf(IpAddress.Version.INET, ip);
hostService.startMonitoringIp(src_ip);
Set<Host> src_host = hostService.getHostsByIp(src_ip);
Host src_1=null;
Host des_1=null;
if(!src_host.isEmpty()) {
Iterator<Host> srchost = src_host.iterator();
src_1 = srchost.next();
}
else{
System.out.println("host with the src ip address is null!");
}
byte[] ips = {(byte) des_ip_0, (byte) des_ip_1, (byte) des_ip_2, (byte) des_ip_3};
IpAddress des_ip = IpAddress.valueOf(IpAddress.Version.INET, ips);
hostService.startMonitoringIp(des_ip);
Set<Host> des_host = hostService.getHostsByIp(des_ip);
if(!des_host.isEmpty()) {
Iterator<Host> deshost = des_host.iterator();
des_1 = deshost.next();
}
else{
System.out.println("host with the dest ip address is null!");
}
MacAddress src_mac = src_1.mac();
MacAddress des_mac = des_1.mac();
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
TrafficSelector selector = selectorBuilder.matchEthSrc(src_mac)
.matchEthDst(des_mac).matchEthType(Ethernet.TYPE_IPV4)
.matchIPSrc(Ip4Prefix.valueOf(src_ip, Ip4Prefix.MAX_MASK_LENGTH))
.matchIPDst(Ip4Prefix.valueOf(des_ip, Ip4Prefix.MAX_MASK_LENGTH))
.matchIPProtocol(org.onlab.packet.IPv4.PROTOCOL_UDP).build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setEthDst(des_mac)
.build();
Iterator<Device> devices = deviceService.getDevices(Device.Type.SWITCH).iterator();
while (devices.hasNext()) {
Device device = devices.next();
DeviceId deviceId = device.id(); //log.info(deviceId.toString());
installRule(selector, treatment, deviceId, 7777);
}
}
/* * 制定流表规则,比较重要的部分有两个: * 一个是selector,用来指定源目的 ip,源目的mac,源目的port * 另一个treatment,用来说明怎么处理包,丢弃还是转发,从哪儿转发 * 再有就是确定优先级,然后发到哪个设备上 */
private void installRule(TrafficSelector selector, TrafficTreatment treatment , DeviceId deviceId, int priority ){
ForwardingObjective.Builder forwardingObjectiveBuilder = DefaultForwardingObjective.builder();
forwardingObjectiveBuilder
.withFlag(ForwardingObjective.Flag. VERSATILE)
.withSelector( selector) .withTreatment( treatment)
.withPriority( priority) .makePermanent() .fromApp( appId);
flowObjectiveService.forward(deviceId , forwardingObjectiveBuilder .add());
}
@Override
public String collaboratingload(JsonNode request,Set<String> serverip){
//===========get all server DC sources================
Host dc1=null;
Host dc2=null;
Host dc3=null;
Host src=null;
HostId srcId=null;
//set key:value
Map<HostId,IpAddress> map=new HashMap<HostId,IpAddress>();
HostId[] dchosts=new HostId[3];
IpAddress src_ip = IpAddress.valueOf("10.0.0.1");
hostService.startMonitoringIp(src_ip);
Set<Host> src_host = hostService.getHostsByIp(src_ip);
//byte[] dc1byte = {(byte) 10, (byte) 0, (byte) 0, (byte) 2};
//IpAddress dc1_ip = IpAddress.valueOf(IpAddress.Version.INET, dc1byte);
Iterator<String> server=serverip.iterator();
if(server.hasNext())
{
IpAddress dc1_ip = IpAddress.valueOf(server.next());
hostService.startMonitoringIp(dc1_ip);
Set<Host> dc1_host = hostService.getHostsByIp(dc1_ip);
if(!dc1_host.isEmpty()) {
//Iterator<Host> dc1host = dc1_host.iterator();
// dc1 = dc1host.next();
dc1=dc1_host.iterator().next();
MacAddress dc1_mac = dc1.mac();
dchosts[0] = HostId.hostId(dc1_mac);
map.put(dchosts[0],dc1_ip);
}
else{
System.out.println("dc1 is null!");
}
}
//byte[] dc2byte = {(byte) 10, (byte) 0, (byte) 0, (byte) 3};
//IpAddress dc2_ip = IpAddress.valueOf(IpAddress.Version.INET, dc2byte);
if(server.hasNext()){
IpAddress dc2_ip = IpAddress.valueOf(server.next());
hostService.startMonitoringIp(dc2_ip);
Set<Host> dc2_host = hostService.getHostsByIp(dc2_ip);
if(!dc2_host.isEmpty()) {
//Iterator<Host> dc2host = dc2_host.iterator();
//dc2 = dc2host.next();
dc2=dc2_host.iterator().next();
MacAddress dc2_mac = dc2.mac();
dchosts[1] = HostId.hostId(dc2_mac);
map.put(dchosts[1],dc2_ip);
}
else{
System.out.println("dc2 is null!");
}
}
if(server.hasNext()){
IpAddress dc3_ip = IpAddress.valueOf(server.next());
hostService.startMonitoringIp(dc3_ip);
Set<Host> dc3_host = hostService.getHostsByIp(dc3_ip);
if(!dc3_host.isEmpty()) { ;
dc3=dc3_host.iterator().next();
MacAddress dc3_mac = dc3.mac();
dchosts[2] = HostId.hostId(dc3_mac);
map.put(dchosts[2],dc3_ip);
}
else{
System.out.println("dc3 is null!");
}
}
if(!src_host.isEmpty()) {
src = src_host.iterator().next();
MacAddress src_mac = src.mac();
srcId=HostId.hostId(src_mac);
map.put(srcId,src_ip);
}
else{
System.out.println("host with the src ip address is null!");
}
//1-2 2-3
// Path path1to2 = getLoadBalancePaths(srcId, dchosts[0]).iterator().next();
// Path path2to3 = getLoadBalancePaths(dchosts[0], dchosts[1]).iterator().next();
/* log.info("\n------ Path Info ------\n{}",
path1to2.links().toString().replace("Default", "\n"));
log.info("\n------ Path Rest Bandwidth------\n{}",
path1to2.weight());
log.info("\n------ Path Info ------\n{}",
path2to3.links().toString().replace("Default", "\n"));
log.info("\n------ Path Rest Bandwidth------\n{}",
path2to3.weight());*/
//====================getbestLoadBalance===================
Set<Path> paths=new HashSet<>();
for(int i=0;i<dchosts.length;i++){
Set<Path> availablepath = getLoadBalancePaths(srcId, dchosts[i]);
if(!availablepath.isEmpty()) {
Iterator<Path> path_ = availablepath.iterator();
Path path = path_.next();
paths.add(path);
}
}
LoadBalanceRouting r1=new LoadBalanceRouting();
Path result=r1.selectRoute(paths);
//HostId resultdstid=DefaultPath.destination(result.links()).hostId();
log.info("\n------ Path Info ------\n{}",
result.links().toString().replace("Default", "\n"));
log.info("\n------ Dst Info ------\n{}",
result.dst().hostId());
System.out.println("Dst server: "+ map.get(result.dst().hostId()));
String dstipaddress = map.get(result.dst().hostId()).toString();
//for(int i=0;i<dchosts.length)
// result.dst.hostId().equals()''
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPSrc(IpPrefix.valueOf("10.0.0.1/32"))
.matchIPDst(IpPrefix.valueOf(map.get(result.dst().hostId()),32))
.build();
PathIntent pathIntent = PathIntent.builder()
.path(result)
.appId(appId)
.priority(45678)
.selector(selector)
.treatment(DefaultTrafficTreatment.emptyTreatment())
.build();
intentService.submit(pathIntent);
intentMap.put(selector.criteria(), pathIntent);
return dstipaddress;
}
private class InternalPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
if (context.isHandled()) {
return;
}
Ethernet pkt = context.inPacket().parsed();
if (pkt.getEtherType() == Ethernet.TYPE_IPV4) {
HostId srcHostId = HostId.hostId(pkt.getSourceMAC());
HostId dstHostId = HostId.hostId(pkt.getDestinationMAC());
//entry to getLoadBalance algorithm
Set<Path> paths = getLoadBalancePaths(srcHostId, dstHostId);
if (paths.isEmpty()) {
log.warn("paths is Empty !!! no Path is available");
context.block();
return;
}
IPv4 ipPkt = (IPv4) pkt.getPayload();
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPSrc(IpPrefix.valueOf(ipPkt.getSourceAddress(), 32))
.matchIPDst(IpPrefix.valueOf(ipPkt.getDestinationAddress(), 32))
.build();
boolean isContain;
// synchronized (intentMap) {
isContain = intentMap.containsKey(selector.criteria());
// }
if (isContain) {
context.block();
return;
}
Path result = paths.iterator().next();
log.info("\n------ Mao Path Info ------\nSrc:{}, Dst:{}\n{}",
IpPrefix.valueOf(ipPkt.getSourceAddress(), 32).toString(),
IpPrefix.valueOf(ipPkt.getDestinationAddress(), 32),
result.links().toString().replace("Default", "\n"));
PathIntent pathIntent = PathIntent.builder()
.path(result)
.appId(appId)
.priority(65432)
.selector(selector)
.treatment(DefaultTrafficTreatment.emptyTreatment())
.build();
intentService.submit(pathIntent);
// synchronized (intentMap) {
intentMap.put(selector.criteria(), pathIntent);
// }
context.block();
}
}
}
/**
* Load Balance Routing Module.
*
* author: Jianwei Mao
*/
public class LoadBalanceRouting {
//=================== Start =====================
private final ProviderId routeProviderId = new ProviderId("FNL", "Mao");
private final BandwidthLinkWeight bandwidthLinkWeightTool = new BandwidthLinkWeight();
/**
* Compatible Entry of routing function.
*
* @param src
* @param dst
* @return empty Set if
* 1. no path found
* 2. given srcHost or dstHost is not discovered by ONOS
* 3. given srcDevice and dstDevice are identical one.
*/
public Set<Path> getLoadBalancePaths(ElementId src, ElementId dst) {
Topology currentTopo = topologyService.currentTopology();
return getLoadBalancePaths(currentTopo, src, dst);
}
/**
* Core Entry of routing function.
*
* @param topo
* @param src
* @param dst
* @return empty Set if
* 1. no path found
* 2. given srcHost or dstHost is not discovered by ONOS
* 3. given srcDevice and dstDevice are identical one.
*/
public Set<Path> getLoadBalancePaths(Topology topo, ElementId src, ElementId dst) {
if (src instanceof DeviceId && dst instanceof DeviceId) {
// no need to create edge link.
// --- Three Step by Mao. ---
//---------------------dst erect Set<DeviceId>------------------------
Set<List<TopologyEdge>> allRoutes = findAllRoutes(topo, (DeviceId) src, (DeviceId) dst);
Set<Path> allPaths = calculateRoutesCost(allRoutes);
Path linkPath = selectRoute(allPaths);
//use Set to be compatible with ONOS API
return linkPath != null ? ImmutableSet.of(linkPath) : ImmutableSet.of();
} else if (src instanceof HostId && dst instanceof HostId) {
Host srcHost = hostService.getHost((HostId) src);
Host dstHost = hostService.getHost((HostId) dst);
if (srcHost == null || dstHost == null) {
log.warn("Generate whole path but found null, hostSrc:{}, hostDst:{}", srcHost, dstHost);
return ImmutableSet.of();
}
EdgeLink srcLink = getEdgeLink(srcHost, true);
EdgeLink dstLink = getEdgeLink(dstHost, false);
// --- Four Step by Mao. ---
Set<List<TopologyEdge>> allRoutes = findAllRoutes(topo, srcLink.dst().deviceId(), dstLink.src().deviceId());
Set<Path> allPaths = calculateRoutesCost(allRoutes);
Path linkPath = selectRoute(allPaths);
Path wholePath = buildWholePath(srcLink, dstLink, linkPath);
Weight buildwp= ScalarWeight.toWeight(buildWholePath(srcLink, dstLink, linkPath).cost());
Weight wp=ScalarWeight.toWeight(wholePath.cost());
//use Set to be compatible with ONOS API
return wholePath != null ? ImmutableSet.of(wholePath) : ImmutableSet.of();
} else {
//use Set to be compatible with ONOS API
return ImmutableSet.of();
}
}
/**
* Generate EdgeLink which is between Host and Device.
* Tool for getLoadBalancePaths().
*
* @param host
* @param isIngress whether it is Ingress to Device or not.
* @return
*/
public EdgeLink getEdgeLink(Host host, boolean isIngress) {
return new DefaultEdgeLink(routeProviderId, new ConnectPoint(host.id(), PortNumber.portNumber(0)),
host.location(), isIngress);
}
//=================== Step One: Find routes =====================
/**
* Entry for find all Paths between Src and Dst.
* By Mao.
*
* @param src Src of Path.
* @param dst Dst of Path.
* @param topo Topology, MUST be an Object of DefaultTopology now.
*/
public Set<List<TopologyEdge>> findAllRoutes(Topology topo, DeviceId src, DeviceId dst) {
if (!(topo instanceof DefaultTopology)) {
log.error("topology is not the object of DefaultTopology.");
return ImmutableSet.of();
}
Set<List<TopologyEdge>> graghResult = new HashSet<>();
dfsFindAllRoutes(new DefaultTopologyVertex(src), new DefaultTopologyVertex(dst),
new ArrayList<>(), new ArrayList<>(),
((DefaultTopology) topo).getGraph(), graghResult);
return graghResult;
}
/**
* Get all possible path between Src and Dst using DFS, by Mao.
* DFS Core, Recursion Part.
*
* @param src Source point per Recursion
* @param dst Final Objective
* @param passedLink dynamic, record passed links in real time
* @param passedDevice dynamic, record entered devices in real time, to avoid loop
* @param topoGraph represent the whole world
* @param result Set of all Paths.
* @return no use.
*/
public void dfsFindAllRoutes(TopologyVertex src,
TopologyVertex dst,
List<TopologyEdge> passedLink,
List<TopologyVertex> passedDevice,
TopologyGraph topoGraph,
Set<List<TopologyEdge>> result) {
if (src.equals(dst)) {
return;
}
passedDevice.add(src);
Set<TopologyEdge> egressSrc = topoGraph.getEdgesFrom(src);
egressSrc.forEach(egress -> {
TopologyVertex vertexDst = egress.dst();
if (vertexDst.equals(dst)) {
//Gain a Path
passedLink.add(egress);
result.add(ImmutableList.copyOf(passedLink.iterator()));
passedLink.remove(egress);
} else if (!passedDevice.contains(vertexDst)) {
//DFS into
passedLink.add(egress);
dfsFindAllRoutes(vertexDst, dst, passedLink, passedDevice, topoGraph, result);
passedLink.remove(egress);
} else {
//means - passedDevice.contains(vertexDst)
//We hit a loop, NOT go into
}
});
passedDevice.remove(src);
}
/**
* Parse several TopologyEdge(s) to one Path.
* Tool for findAllPaths.
*/
public List<Link> parseEdgeToLink(List<TopologyEdge> edges) {
List<Link> links = new ArrayList<>();
edges.forEach(edge -> links.add(edge.link()));
return links;
}
//=================== Step Two: Calculate Cost =====================
public Set<Path> calculateRoutesCost(Set<List<TopologyEdge>> routes) {
Set<Path> paths = new HashSet<>();
routes.forEach(route -> {
double cost = maxLinkWeight(route);
paths.add(parseEdgeToPath(route, cost));
});
return paths;
}
/**
* A strategy to calculate the weight of one path.
*/
public double maxLinkWeight(List<TopologyEdge> edges) {
Weight weight = ScalarWeight.toWeight(0);
for (TopologyEdge edge : edges) {
Weight linkWeight = bandwidthLinkWeightTool.weight(edge);
weight = linkWeight.compareTo(weight) > 0 ? linkWeight : weight;
}
return ((ScalarWeight)weight).value();
}
/**
* Parse several TopologyEdge(s) to one Path.
* Tool for calculateRoutesWeight().
*/
public Path parseEdgeToPath(List<TopologyEdge> edges, double cost) {
ArrayList links = new ArrayList();
edges.forEach(edge -> links.add(edge.link()));
return new DefaultPath(routeProviderId, links, ScalarWeight.toWeight(cost));
}
//=================== Step Three: Select one route(Path) =====================
public Path selectRoute(Set<Path> paths) {
if (paths.size() < 1) {
return null;
}
return getMinHopPath(getMinCostPath(new ArrayList(paths)));
}
/**
* A strategy to select one best Path.
*
* @return whose max cost of all links is least.
*/
public List<Path> getMinCostPath(List<Path> paths) {
final double measureTolerance = 0.05; // 0.05% represent 5M(10G), 12.5M(25G), 50M(100G)
//Sort by Cost in order
paths.sort((p1, p2) -> p1.cost() > p2.cost() ? 1 : (p1.cost() < p2.cost() ? -1 : 0));
// get paths with similar lowest cost within measureTolerance range.
List<Path> minCostPaths = new ArrayList<>();
Path result = paths.get(0);
minCostPaths.add(result);
for (int i = 1, pathCount = paths.size(); i < pathCount; i++) {
Path temp = paths.get(i);
if (temp.cost() - result.cost() < measureTolerance) {
minCostPaths.add(temp);
}
}
return minCostPaths;
}
/**
* A strategy to select one best Path.
*
* @return whose count of all links is least.
*/
public Path getMinHopPath(List<Path> paths) {
Path result = paths.get(0);
for (int i = 1, pathCount = paths.size(); i < pathCount; i++) {
Path temp = paths.get(i);
result = result.links().size() > temp.links().size() ? temp : result;
}
return result;
}
//=================== Step Four: Build the whole Path =====================
/**
* @param srcLink
* @param dstLink
* @param linkPath
* @return At least, Path will include two edge links.
*/
public Path buildWholePath(EdgeLink srcLink, EdgeLink dstLink, Path linkPath) {
if (linkPath == null && !(srcLink.dst().deviceId().equals(dstLink.src().deviceId()))) {
log.warn("no available Path is found!");
return null;
}
return buildEdgeToEdgePath(srcLink, dstLink, linkPath);
}
/**
* Produces a direct edge-to-edge path.
*
* @param srcLink
* @param dstLink
* @param linkPath
* @return
*/
public Path buildEdgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path linkPath) {
List<Link> links = Lists.newArrayListWithCapacity(2);
Weight cost = ScalarWeight.toWeight(0);
// now, the cost of edge link is 0.
links.add(srcLink);
if (linkPath != null) {
links.addAll(linkPath.links());
cost=cost.merge(linkPath.weight());
}
links.add(dstLink);
return new DefaultPath(routeProviderId, links, cost);
}
//=================== The End =====================
}
/**
* Tool for calculating weight value for each Link(TopologyEdge).
*
* author: Jianwei Mao
*/
public class BandwidthLinkWeight extends MetricLinkWeight {
private static final double LINK_WEIGHT_IDLE = 0;
private static final double LINK_WEIGHT_DOWN = 100.0;
private static final double LINK_WEIGHT_FULL = 100.0;
@Override
public Weight getInitialWeight() {
return ScalarWeight.toWeight(LINK_WEIGHT_IDLE);
}
@Override
public Weight getNonViableWeight() {
return ScalarWeight.toWeight(LINK_WEIGHT_DOWN);
}
//FIXME - Bata1: Here, assume the edge is the inter-demain link
@Override
public Weight weight(TopologyEdge edge) {
if (edge.link().state() == Link.State.INACTIVE) {
return ScalarWeight.toWeight(LINK_WEIGHT_DOWN);
}
long linkWireSpeed = getLinkWireSpeed(edge.link());
//FIXME - Bata1: Here, assume the value in the map is the rest bandwidth of inter-demain link
long interLinkRestBandwidth = linkWireSpeed - getLinkLoadSpeed(edge.link());
if (interLinkRestBandwidth <= 0) {
return ScalarWeight.toWeight(LINK_WEIGHT_FULL);
}
//restBandwidthPersent
return ScalarWeight.toWeight(100 - interLinkRestBandwidth * 1.0 / linkWireSpeed * 100);
//return ScalarWeight.toWeight(interLinkRestBandwidth);
}
public long getLinkWireSpeed(Link link) {
long srcSpeed = getPortWireSpeed(link.src());
long dstSpeed = getPortWireSpeed(link.dst());
return Math.min(srcSpeed, dstSpeed);
}
public long getLinkLoadSpeed(Link link) {
long srcSpeed = getPortLoadSpeed(link.src());
long dstSpeed = getPortLoadSpeed(link.dst());
return Math.max(srcSpeed, dstSpeed);
}
/**
* Unit: bps.
*
* @param port
* @return
*/
public long getPortLoadSpeed(ConnectPoint port) {
//data source: Bps
return portStatisticsService.load(port).rate() * 8;
}
/**
* Unit bps.
*
* @param port
* @return
*/
public long getPortWireSpeed(ConnectPoint port) {
assert port.elementId() instanceof DeviceId;
//data source: Mbps
return deviceService.getPort(port.deviceId(), port.port()).portSpeed() * 1000000;
}
}
}
乱七八糟的
最新推荐文章于 2023-06-02 14:27:41 发布