乱七八糟的

/*
 * 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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值