X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=inline;f=natservice%2Fnatservice-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2Fnatservice%2Finternal%2FNAPTSwitchSelector.java;fp=natservice%2Fnatservice-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2Fnatservice%2Finternal%2FNAPTSwitchSelector.java;h=b7fd7d311e6b3b510337c1039212034c06ff2286;hb=45320706157e8500aaa5e085d05ad4373c289d5f;hp=0000000000000000000000000000000000000000;hpb=5d9a52407447e8656f58ff5df8612dc59afe1508;p=vpnservice.git diff --git a/natservice/natservice-impl/src/main/java/org/opendaylight/vpnservice/natservice/internal/NAPTSwitchSelector.java b/natservice/natservice-impl/src/main/java/org/opendaylight/vpnservice/natservice/internal/NAPTSwitchSelector.java new file mode 100644 index 00000000..b7fd7d31 --- /dev/null +++ b/natservice/natservice-impl/src/main/java/org/opendaylight/vpnservice/natservice/internal/NAPTSwitchSelector.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.natservice.internal; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitchesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +public class NAPTSwitchSelector { + private static final Logger LOG = LoggerFactory.getLogger(NAPTSwitchSelector.class); + + private DataBroker dataBroker; + public NAPTSwitchSelector(DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + BigInteger selectNewNAPTSwitch(String routerName) { + LOG.info("NAT Service : Select a new NAPT switch for router {}", routerName); + Map naptSwitchWeights = constructNAPTSwitches(); + List routerSwitches = getDpnsForVpn(routerName); + if(routerSwitches.isEmpty()) { + LOG.debug("NAT Service : No dpns that are part of router {}", routerName); + LOG.warn("NAT Service : NAPT switch selection stopped due to no dpns scenario for router {}", routerName); + return BigInteger.ZERO; + } + + Set switchWeights = new TreeSet<>(); + for(BigInteger dpn : routerSwitches) { + if(naptSwitchWeights.get(dpn) != null) { + switchWeights.add(new SwitchWeight(dpn, naptSwitchWeights.get(dpn))); + } else { + switchWeights.add(new SwitchWeight(dpn, 0)); + } + } + + BigInteger primarySwitch; + + if(!switchWeights.isEmpty()) { + + LOG.debug("NAT Service : Current switch weights for router {} - {}", routerName, switchWeights); + + Iterator it = switchWeights.iterator(); + List routerToNaptSwitchList = new ArrayList<>(); + RouterToNaptSwitchBuilder routerToNaptSwitchBuilder = new RouterToNaptSwitchBuilder().setRouterName(routerName); + if ( switchWeights.size() == 1 ) + { + SwitchWeight singleSwitchWeight = null; + while(it.hasNext() ) { + singleSwitchWeight = it.next(); + } + primarySwitch = singleSwitchWeight.getSwitch(); + routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch); + routerToNaptSwitchList.add(routerToNaptSwitchBuilder.build()); + NaptSwitches naptSwitches = new NaptSwitchesBuilder().setRouterToNaptSwitch(routerToNaptSwitchList).build(); + MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(), naptSwitches); + + LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container for single switch" ); + return primarySwitch; + } + else + { + SwitchWeight firstSwitchWeight = null; + while(it.hasNext() ) { + firstSwitchWeight = it.next(); + } + primarySwitch = firstSwitchWeight.getSwitch(); + routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch); + routerToNaptSwitchList.add(routerToNaptSwitchBuilder.build()); + NaptSwitches naptSwitches = new NaptSwitchesBuilder().setRouterToNaptSwitch(routerToNaptSwitchList).build(); + MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(), naptSwitches); + + LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container"); + return primarySwitch; + } + } else { + + primarySwitch = BigInteger.ZERO; + + LOG.debug("NAT Service : switchWeights empty, primarySwitch: {} ", primarySwitch); + return primarySwitch; + } + + + } + + private Map constructNAPTSwitches() { + Optional optNaptSwitches = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier()); + Map switchWeights = new HashMap<>(); + + if(optNaptSwitches.isPresent()) { + NaptSwitches naptSwitches = optNaptSwitches.get(); + List routerToNaptSwitches = naptSwitches.getRouterToNaptSwitch(); + + for(RouterToNaptSwitch naptSwitch : routerToNaptSwitches) { + BigInteger primarySwitch = naptSwitch.getPrimarySwitchId(); + //update weight + Integer weight = switchWeights.get(primarySwitch); + if(weight == null) { + switchWeights.put(primarySwitch, 1); + } else { + switchWeights.put(primarySwitch, ++weight); + } + } + } + return switchWeights; + } + + private InstanceIdentifier getNaptSwitchesIdentifier() { + return InstanceIdentifier.create(NaptSwitches.class); + } + + public List getDpnsForVpn(String routerName ) { + LOG.debug( "getVpnToDpnList called for RouterName {}", routerName ); + + InstanceIdentifier id = InstanceIdentifier.builder(VpnInstanceOpData.class) + .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(routerName)) + .build(); + + List dpnsInVpn = new ArrayList<>(); + Optional vpnInstanceOpData = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); + + if(vpnInstanceOpData.isPresent()) { + LOG.debug( "NATService : getVpnToDpnList able to fetch vpnInstanceOpData" ); + VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get(); + List vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList(); + if(vpnDpnList != null) { + for(VpnToDpnList vpnToDpn: vpnDpnList) { + dpnsInVpn.add(vpnToDpn.getDpnId()); + } + } + } + + LOG.debug( "getVpnToDpnList returning vpnDpnList {}", dpnsInVpn); + return dpnsInVpn; + } + + private static class SwitchWeight implements Comparable + { + private BigInteger swich; + private int weight; + + public SwitchWeight( BigInteger swich, int weight ) + { + this.swich = swich; + this.weight = weight; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((swich == null) ? 0 : swich.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SwitchWeight other = (SwitchWeight) obj; + if (swich == null) { + if (other.swich != null) + return false; + } else if (!swich.equals(other.swich)) + return false; + return true; + } + + public BigInteger getSwitch() { + return swich; + } + + public int getWeight() { + return weight; + } + + public void incrementWeight() { + ++ weight; + } + + @Override + public int compareTo(SwitchWeight o) { + return o.getWeight() - weight; + } + } +}