2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.vpnservice.natservice.internal;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Comparator;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
19 import java.util.TreeSet;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitchesBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.common.base.Optional;
39 public class NAPTSwitchSelector {
40 private static final Logger LOG = LoggerFactory.getLogger(NAPTSwitchSelector.class);
42 private DataBroker dataBroker;
43 public NAPTSwitchSelector(DataBroker dataBroker) {
44 this.dataBroker = dataBroker;
47 BigInteger selectNewNAPTSwitch(String routerName) {
48 LOG.info("NAT Service : Select a new NAPT switch for router {}", routerName);
49 Map<BigInteger, Integer> naptSwitchWeights = constructNAPTSwitches();
50 List<BigInteger> routerSwitches = getDpnsForVpn(routerName);
51 if(routerSwitches.isEmpty()) {
52 LOG.debug("NAT Service : No dpns that are part of router {}", routerName);
53 LOG.warn("NAT Service : NAPT switch selection stopped due to no dpns scenario for router {}", routerName);
54 return BigInteger.ZERO;
57 Set<SwitchWeight> switchWeights = new TreeSet<>();
58 for(BigInteger dpn : routerSwitches) {
59 if(naptSwitchWeights.get(dpn) != null) {
60 switchWeights.add(new SwitchWeight(dpn, naptSwitchWeights.get(dpn)));
62 switchWeights.add(new SwitchWeight(dpn, 0));
66 BigInteger primarySwitch;
68 if(!switchWeights.isEmpty()) {
70 LOG.debug("NAT Service : Current switch weights for router {} - {}", routerName, switchWeights);
72 Iterator<SwitchWeight> it = switchWeights.iterator();
73 List<RouterToNaptSwitch> routerToNaptSwitchList = new ArrayList<>();
74 RouterToNaptSwitchBuilder routerToNaptSwitchBuilder = new RouterToNaptSwitchBuilder().setRouterName(routerName);
75 if ( switchWeights.size() == 1 )
77 SwitchWeight singleSwitchWeight = null;
78 while(it.hasNext() ) {
79 singleSwitchWeight = it.next();
81 primarySwitch = singleSwitchWeight.getSwitch();
82 routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch);
83 routerToNaptSwitchList.add(routerToNaptSwitchBuilder.build());
84 NaptSwitches naptSwitches = new NaptSwitchesBuilder().setRouterToNaptSwitch(routerToNaptSwitchList).build();
85 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(), naptSwitches);
87 LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container for single switch" );
92 SwitchWeight firstSwitchWeight = null;
93 while(it.hasNext() ) {
94 firstSwitchWeight = it.next();
96 primarySwitch = firstSwitchWeight.getSwitch();
97 routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch);
98 routerToNaptSwitchList.add(routerToNaptSwitchBuilder.build());
99 NaptSwitches naptSwitches = new NaptSwitchesBuilder().setRouterToNaptSwitch(routerToNaptSwitchList).build();
100 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(), naptSwitches);
102 LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container");
103 return primarySwitch;
107 primarySwitch = BigInteger.ZERO;
109 LOG.debug("NAT Service : switchWeights empty, primarySwitch: {} ", primarySwitch);
110 return primarySwitch;
116 private Map<BigInteger, Integer> constructNAPTSwitches() {
117 Optional<NaptSwitches> optNaptSwitches = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier());
118 Map<BigInteger, Integer> switchWeights = new HashMap<>();
120 if(optNaptSwitches.isPresent()) {
121 NaptSwitches naptSwitches = optNaptSwitches.get();
122 List<RouterToNaptSwitch> routerToNaptSwitches = naptSwitches.getRouterToNaptSwitch();
124 for(RouterToNaptSwitch naptSwitch : routerToNaptSwitches) {
125 BigInteger primarySwitch = naptSwitch.getPrimarySwitchId();
127 Integer weight = switchWeights.get(primarySwitch);
129 switchWeights.put(primarySwitch, 1);
131 switchWeights.put(primarySwitch, ++weight);
135 return switchWeights;
138 private InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
139 return InstanceIdentifier.create(NaptSwitches.class);
142 public List<BigInteger> getDpnsForVpn(String routerName ) {
143 LOG.debug( "getVpnToDpnList called for RouterName {}", routerName );
145 InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
146 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(routerName))
149 List<BigInteger> dpnsInVpn = new ArrayList<>();
150 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
152 if(vpnInstanceOpData.isPresent()) {
153 LOG.debug( "NATService : getVpnToDpnList able to fetch vpnInstanceOpData" );
154 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get();
155 List<VpnToDpnList> vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList();
156 if(vpnDpnList != null) {
157 for(VpnToDpnList vpnToDpn: vpnDpnList) {
158 dpnsInVpn.add(vpnToDpn.getDpnId());
163 LOG.debug( "getVpnToDpnList returning vpnDpnList {}", dpnsInVpn);
167 private static class SwitchWeight implements Comparable<SwitchWeight>
169 private BigInteger swich;
172 public SwitchWeight( BigInteger swich, int weight )
175 this.weight = weight;
179 public int hashCode() {
180 final int prime = 31;
182 result = prime * result + ((swich == null) ? 0 : swich.hashCode());
187 public boolean equals(Object obj) {
192 if (getClass() != obj.getClass())
194 SwitchWeight other = (SwitchWeight) obj;
196 if (other.swich != null)
198 } else if (!swich.equals(other.swich))
203 public BigInteger getSwitch() {
207 public int getWeight() {
211 public void incrementWeight() {
216 public int compareTo(SwitchWeight o) {
217 return o.getWeight() - weight;