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.netvirt.natservice.internal;
10 import com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
17 import java.util.TreeSet;
18 import javax.annotation.Nonnull;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
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.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 public class NAPTSwitchSelector {
34 private static final Logger LOG = LoggerFactory.getLogger(NAPTSwitchSelector.class);
35 private final DataBroker dataBroker;
38 public NAPTSwitchSelector(final DataBroker dataBroker) {
39 this.dataBroker = dataBroker;
42 BigInteger selectNewNAPTSwitch(String routerName) {
43 LOG.info("selectNewNAPTSwitch : Select a new NAPT switch for router {}", routerName);
44 Map<BigInteger, Integer> naptSwitchWeights = constructNAPTSwitches();
45 List<BigInteger> routerSwitches = getDpnsForVpn(routerName);
46 if (routerSwitches == null || routerSwitches.isEmpty()) {
47 LOG.warn("selectNewNAPTSwitch : Delaying NAPT switch selection due to no dpns scenario for router {}",
49 return BigInteger.ZERO;
52 Set<SwitchWeight> switchWeights = new TreeSet<>();
53 for (BigInteger dpn : routerSwitches) {
54 if (naptSwitchWeights.get(dpn) != null) {
55 switchWeights.add(new SwitchWeight(dpn, naptSwitchWeights.get(dpn)));
57 switchWeights.add(new SwitchWeight(dpn, 0));
61 BigInteger primarySwitch;
63 if (!switchWeights.isEmpty()) {
65 LOG.debug("selectNewNAPTSwitch : Current switch weights for router {} - {}", routerName, switchWeights);
67 Iterator<SwitchWeight> it = switchWeights.iterator();
68 RouterToNaptSwitchBuilder routerToNaptSwitchBuilder =
69 new RouterToNaptSwitchBuilder().setRouterName(routerName);
70 if (switchWeights.size() == 1) {
71 SwitchWeight singleSwitchWeight = null;
72 while (it.hasNext()) {
73 singleSwitchWeight = it.next();
75 primarySwitch = singleSwitchWeight.getSwitch();
76 RouterToNaptSwitch id = routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch).build();
78 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
79 getNaptSwitchesIdentifier(routerName), id);
81 LOG.debug("selectNewNAPTSwitch : successful addition of RouterToNaptSwitch to napt-switches container "
82 + "for single switch");
85 SwitchWeight firstSwitchWeight = null;
86 while (it.hasNext()) {
87 firstSwitchWeight = it.next();
89 primarySwitch = firstSwitchWeight.getSwitch();
90 RouterToNaptSwitch id = routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch).build();
92 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
93 getNaptSwitchesIdentifier(routerName), id);
95 LOG.debug("selectNewNAPTSwitch : successful addition of RouterToNaptSwitch to napt-switches container");
99 primarySwitch = BigInteger.ZERO;
101 LOG.debug("selectNewNAPTSwitch : switchWeights empty, primarySwitch: {} ", primarySwitch);
102 return primarySwitch;
106 private Map<BigInteger, Integer> constructNAPTSwitches() {
107 Optional<NaptSwitches> optNaptSwitches =
108 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
109 Map<BigInteger, Integer> switchWeights = new HashMap<>();
111 if (optNaptSwitches.isPresent()) {
112 NaptSwitches naptSwitches = optNaptSwitches.get();
113 List<RouterToNaptSwitch> routerToNaptSwitches = naptSwitches.getRouterToNaptSwitch();
115 for (RouterToNaptSwitch naptSwitch : routerToNaptSwitches) {
116 BigInteger primarySwitch = naptSwitch.getPrimarySwitchId();
118 Integer weight = switchWeights.get(primarySwitch);
119 if (weight == null) {
120 switchWeights.put(primarySwitch, 1);
122 switchWeights.put(primarySwitch, ++weight);
126 return switchWeights;
129 private InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
130 return InstanceIdentifier.create(NaptSwitches.class);
133 private InstanceIdentifier<RouterToNaptSwitch> getNaptSwitchesIdentifier(String routerName) {
134 return InstanceIdentifier.builder(NaptSwitches.class)
135 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
138 public List<BigInteger> getDpnsForVpn(String routerName) {
139 LOG.debug("getDpnsForVpn: called for RouterName {}", routerName);
140 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
142 if (bgpVpnId != NatConstants.INVALID_ID) {
143 return NatUtil.getDpnsForRouter(dataBroker, routerName);
145 return NatUtil.getDpnsForRouter(dataBroker, routerName);
148 private static class SwitchWeight implements Comparable<SwitchWeight> {
149 private BigInteger swich;
152 SwitchWeight(BigInteger swich, int weight) {
154 this.weight = weight;
158 public int hashCode() {
159 final int prime = 31;
161 result = prime * result + ((swich == null) ? 0 : swich.hashCode());
166 public boolean equals(Object obj) {
173 if (getClass() != obj.getClass()) {
176 SwitchWeight other = (SwitchWeight) obj;
178 if (other.swich != null) {
181 } else if (!swich.equals(other.swich)) {
187 public BigInteger getSwitch() {
191 public int getWeight() {
195 public void incrementWeight() {
200 public int compareTo(@Nonnull SwitchWeight switchWeight) {
201 return switchWeight.getWeight() - weight;