/*
* Copyright (c) 2013 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
*
* 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.sdnplatform.netvirt.virtualrouting.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.sdnplatform.devicemanager.IDevice;
import org.sdnplatform.devicemanager.SwitchPort;
import org.sdnplatform.netvirt.virtualrouting.GatewayNode;
import org.sdnplatform.netvirt.virtualrouting.IGatewayPool;
import org.sdnplatform.routing.Route;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GatewayPoolImpl implements IGatewayPool {
protected static final Logger logger =
LoggerFactory.getLogger(GatewayPoolImpl.class);
private String name;
private Map<String, GatewayNode> gatewayNodeMap;
private VirtualRouterManager vRtrManager;
@Override
public String getName() {
return name;
}
@Override
public void addGatewayNode(String ip) {
GatewayNode gwNode = new GatewayNode(ip);
gatewayNodeMap.put(ip, gwNode);
}
@Override
public void removeGatewayNode(String ip) {
if (gatewayNodeMap.containsKey(ip)) {
gatewayNodeMap.remove(ip);
}
}
@Override
public Map<String, GatewayNode> getGatewayNodes() {
return Collections.unmodifiableMap(gatewayNodeMap);
}
/**
* @param sp An array of switch-port tuples
* @return a map of cluster id --> switch ports for the given switch port
* array
*/
private Map<Long, SwitchPort> getSwitchPortMap(SwitchPort[] sp) {
Map<Long, SwitchPort> resultMap = new HashMap<Long, SwitchPort>();
for(int i=0; i < sp.length; i++) {
long l2id = vRtrManager.getTopology().getL2DomainId(sp[i].getSwitchDPID());
resultMap.put(l2id, sp[i]);
}
return resultMap;
}
@Override
public GatewayNode getOptimalGatewayNodeInfo(IDevice srcDevice,
Short vlan) {
GatewayNode optimalGatewayNode = null;
int hopsToOptimalGatewayNode = Integer.MAX_VALUE;
SwitchPort[] sdAPs = srcDevice.getAttachmentPoints();
Map<Long, SwitchPort> sdMap = getSwitchPortMap(sdAPs);
for (GatewayNode node : getGatewayNodes().values()) {
if (node.getIp() == 0) {
logger.warn("GW Pool {} node ip is zero", this.getName());
continue;
}
IDevice gatewayDevice = vRtrManager.findDevice(null,
srcDevice.getEntityClass(),
0L,
(vlan != null) ? vlan.shortValue() : 0,
node.getIp());
if (gatewayDevice == null) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to get dev for {}", node);
}
continue;
}
SwitchPort[] gdAPs = gatewayDevice.getAttachmentPoints();
Map<Long, SwitchPort> gdMap = getSwitchPortMap(gdAPs);
/*
* Add route hops for each openflow cluster that is in the path.
* TODO, now there isn't a way to tell which clusters are in the
* path.
* For now, we compare the sum of routeHops for all clusters.
* Initialize the numHops to MAX to assume there is no route
*/
int numHops = Integer.MAX_VALUE;
for (long l2id : sdMap.keySet()) {
int hopsInCluster = 0;
SwitchPort srcDap = sdMap.get(l2id);
SwitchPort dstDap = gdMap.get(l2id);
if (dstDap == null) {
if (logger.isTraceEnabled()) {
logger.trace("{} not seen on l2id {}",
node, l2id);
}
continue;
}
if (srcDap.equals(dstDap)) {
hopsInCluster = 0;
} else {
Route route = vRtrManager.getRoutingService().
getRoute(srcDap.getSwitchDPID(),
(short)srcDap.getPort(),
dstDap.getSwitchDPID(),
(short)dstDap.getPort(),
0);
if (route != null && route.getPath() != null) {
hopsInCluster = route.getPath().size();
}
}
if (numHops == Integer.MAX_VALUE) {
numHops = hopsInCluster;
} else {
numHops += hopsInCluster;
}
} // while through clusters
if (numHops < hopsToOptimalGatewayNode) {
// Found a better service node
hopsToOptimalGatewayNode = numHops;
optimalGatewayNode = new GatewayNode(node.getIp(), gatewayDevice);
} else if (numHops != Integer.MAX_VALUE &&
numHops == hopsToOptimalGatewayNode) {
// Equal distance, then pick the node with smaller ip
if (node.getIp() < optimalGatewayNode.getIp()) {
optimalGatewayNode = new GatewayNode(node.getIp(), gatewayDevice);
}
}
}
return optimalGatewayNode;
}
public GatewayPoolImpl(String name, VirtualRouterManager vRtrManager) {
super();
this.name = name;
this.gatewayNodeMap = new HashMap<String, GatewayNode>();
this.vRtrManager = vRtrManager;
}
}