sangho
Committed by Gerrit Code Review

ONOS-1521 : Supports Leaf-Spine topology (tested with 4 x 4 )

- Supports ECMPNotSupportedInTransitRouter option
- Adds Leaf-Spine config file
- Removes the temporary NetworkConfigHanlder class
- Removes the grouphandler dependency
- Removes the grouphandler app
Change-Id: I8c70e81bfb4062e251b25c0fa23ef2c92419a75c
......@@ -43,7 +43,7 @@ public class ArpHandler {
private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
private SegmentRoutingManager srManager;
private NetworkConfigHandler config;
private DeviceConfiguration config;
/**
* Creates an ArpHandler object.
......@@ -52,7 +52,7 @@ public class ArpHandler {
*/
public ArpHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.config = checkNotNull(srManager.networkConfigHandler);
this.config = checkNotNull(srManager.deviceConfiguration);
}
/**
......@@ -96,8 +96,8 @@ public class ArpHandler {
// ARP request for router
if (isArpReqForRouter(deviceId, arpRequest)) {
Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
sendArpResponse(arpRequest, config.getRouterMac(targetAddress));
sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress));
// ARP request for known hosts
} else if (srManager.hostService.getHost(targetHostId) != null) {
MacAddress targetMac = srManager.hostService.getHost(targetHostId).mac();
......@@ -111,7 +111,7 @@ public class ArpHandler {
private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) {
List<Ip4Address> gatewayIpAddresses = config.getGatewayIpAddress(deviceId);
List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
if (gatewayIpAddresses != null) {
Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest
.getTargetProtocolAddress());
......@@ -123,7 +123,7 @@ public class ArpHandler {
}
private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) {
return config.getSubnetInfo(deviceId).stream()
return config.getSubnets(deviceId).stream()
.anyMatch((prefix)->
prefix.contains(Ip4Address.
valueOf(arpRequest.
......@@ -139,9 +139,8 @@ public class ArpHandler {
*/
public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
byte[] senderMacAddress = config.getRouterMacAddress(deviceId).toBytes();
byte[] senderIpAddress = config.getRouterIpAddress(deviceId)
.getIp4Prefix().address().toOctets();
byte[] senderMacAddress = config.getDeviceMac(deviceId).toBytes();
byte[] senderIpAddress = config.getRouterIp(deviceId).toOctets();
ARP arpRequest = new ARP();
arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
......
......@@ -17,6 +17,7 @@ package org.onosproject.segmentrouting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.Device;
......@@ -41,8 +42,8 @@ public class DefaultRoutingHandler {
private SegmentRoutingManager srManager;
private RoutingRulePopulator rulePopulator;
private NetworkConfigHandler config;
private HashMap<DeviceId, ECMPShortestPathGraph> currentEcmpSpgMap;
private DeviceConfiguration config;
private Status populationStatus;
/**
......@@ -70,7 +71,7 @@ public class DefaultRoutingHandler {
public DefaultRoutingHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.rulePopulator = checkNotNull(srManager.routingRulePopulator);
this.config = checkNotNull(srManager.networkConfigHandler);
this.config = checkNotNull(srManager.deviceConfiguration);
this.populationStatus = Status.IDLE;
this.currentEcmpSpgMap = Maps.newHashMap();
}
......@@ -356,8 +357,8 @@ public class DefaultRoutingHandler {
// If both target switch and dest switch are edge routers, then set IP rule
// for both subnet and router IP.
if (config.isEdgeRouter(targetSw) && config.isEdgeRouter(destSw)) {
List<Ip4Prefix> subnets = config.getSubnetInfo(destSw);
if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) {
List<Ip4Prefix> subnets = config.getSubnets(destSw);
result = rulePopulator.populateIpRuleForSubnet(targetSw,
subnets,
destSw,
......@@ -366,29 +367,28 @@ public class DefaultRoutingHandler {
return false;
}
IpPrefix routerIp = config.getRouterIpAddress(destSw);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIp, destSw, nextHops);
Ip4Address routerIp = config.getRouterIp(destSw);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
// If the target switch is an edge router, then set IP rules for the router IP.
} else if (config.isEdgeRouter(targetSw)) {
IpPrefix routerIp = config.getRouterIpAddress(destSw);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIp, destSw, nextHops);
} else if (config.isEdgeDevice(targetSw)) {
Ip4Address routerIp = config.getRouterIp(destSw);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
// If the target switch is an transit router, then set MPLS rules only.
} else if (config.isTransitRouter(targetSw)) {
} else if (!config.isEdgeDevice(targetSw)) {
result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops);
if (!result) {
return false;
}
} else {
log.warn("The switch {} is neither an edge router nor a transit router.", targetSw);
return false;
}
return true;
......
......@@ -313,4 +313,31 @@ public class DeviceConfiguration implements DeviceProperties {
log.debug("Cannot find a router for {}", gatewayIpAddress);
return null;
}
/**
* Checks if the host is in the subnet defined in the router with the
* device ID given.
*
* @param deviceId device identification of the router
* @param hostIp host IP address to check
* @return true if the host is within the subnet of the router,
* false if no subnet is defined under the router or if the host is not
* within the subnet defined in the router
*/
public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
List<Ip4Prefix> subnets = getSubnets(deviceId);
if (subnets == null) {
return false;
}
for (Ip4Prefix subnet: subnets) {
if (subnet.contains(hostIp)) {
return true;
}
}
return false;
}
}
......
......@@ -39,7 +39,7 @@ public class IcmpHandler {
private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
private SegmentRoutingManager srManager;
private NetworkConfigHandler config;
private DeviceConfiguration config;
/**
* Creates an IcmpHandler object.
......@@ -48,7 +48,7 @@ public class IcmpHandler {
*/
public IcmpHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.config = checkNotNull(srManager.networkConfigHandler);
this.config = checkNotNull(srManager.deviceConfiguration);
}
/**
......@@ -69,8 +69,9 @@ public class IcmpHandler {
DeviceId deviceId = connectPoint.deviceId();
Ip4Address destinationAddress =
Ip4Address.valueOf(ipv4.getDestinationAddress());
List<Ip4Address> gatewayIpAddresses = config.getGatewayIpAddress(deviceId);
IpPrefix routerIpPrefix = config.getRouterIpAddress(deviceId);
List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
Ip4Address routerIp = config.getRouterIp(deviceId);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address();
// ICMP to the router IP or gateway IP
......@@ -122,8 +123,8 @@ public class IcmpHandler {
icmpReplyEth.setVlanID(icmpRequest.getVlanID());
Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress());
Ip4Address destRouterAddress = config.getDestinationRouterAddress(destIpAddress);
int sid = config.getMplsId(destRouterAddress);
Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
int sid = config.getSegmentId(destRouterAddress);
if (sid < 0) {
log.warn("Cannot find the Segment ID for {}", destAddress);
return;
......@@ -138,7 +139,7 @@ public class IcmpHandler {
IPv4 ipPacket = (IPv4) payload.getPayload();
Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
if (sid == -1 || config.getMplsId(payload.getDestinationMAC()) == sid ||
if (sid == -1 || config.getSegmentId(payload.getDestinationMAC()) == sid ||
config.inSameSubnet(outport.deviceId(), destIpAddress)) {
TrafficTreatment treatment = DefaultTrafficTreatment.builder().
setOutput(outport.port()).build();
......@@ -164,4 +165,6 @@ public class IcmpHandler {
srManager.packetService.emit(packet);
}
}
}
......
......@@ -39,7 +39,7 @@ public class IpHandler {
private static Logger log = LoggerFactory.getLogger(IpHandler.class);
private SegmentRoutingManager srManager;
private NetworkConfigHandler config;
private DeviceConfiguration config;
private ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>> ipPacketQueue;
/**
......@@ -49,7 +49,7 @@ public class IpHandler {
*/
public IpHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.config = checkNotNull(srManager.networkConfigHandler);
this.config = checkNotNull(srManager.deviceConfiguration);
ipPacketQueue = new ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>>();
}
......@@ -129,8 +129,7 @@ public class IpHandler {
for (Host dest: srManager.hostService.getHostsByIp(destIpAddress)) {
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(dest.mac());
eth.setSourceMACAddress(config.getRouterMacAddress(
deviceId));
eth.setSourceMACAddress(config.getDeviceMac(deviceId));
eth.setEtherType(Ethernet.TYPE_IPV4);
eth.setPayload(ipPacket);
......@@ -141,7 +140,9 @@ public class IpHandler {
srManager.packetService.emit(packet);
ipPacketQueue.get(destIpAddress).remove(ipPacket);
}
ipPacketQueue.get(destIpAddress).remove(ipPacket);
}
}
}
}
......
/*
* Copyright 2015 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.segmentrouting;
import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Set;
/**
* This class is temporary class and used only for test.
* It will be replaced with "real" Network Config Manager.
*
* TODO: Knock off this wrapper and directly use DeviceConfiguration class
*/
public class NetworkConfigHandler {
private static Logger log = LoggerFactory.getLogger(NetworkConfigHandler.class);
private SegmentRoutingManager srManager;
private DeviceConfiguration deviceConfig;
public NetworkConfigHandler(SegmentRoutingManager srManager,
DeviceConfiguration deviceConfig) {
this.srManager = srManager;
this.deviceConfig = deviceConfig;
}
public List<Ip4Address> getGatewayIpAddress(DeviceId deviceId) {
return this.deviceConfig.getSubnetGatewayIps(deviceId);
}
public IpPrefix getRouterIpAddress(DeviceId deviceId) {
return IpPrefix.valueOf(deviceConfig.getRouterIp(deviceId), 32);
}
public MacAddress getRouterMacAddress(DeviceId deviceId) {
return deviceConfig.getDeviceMac(deviceId);
}
public boolean inSameSubnet(DeviceId deviceId, Ip4Address destIp) {
List<Ip4Prefix> subnets = getSubnetInfo(deviceId);
if (subnets == null) {
return false;
}
return subnets.stream()
.anyMatch((subnet) -> subnet.contains(destIp));
}
public boolean inSameSubnet(Ip4Address address, int sid) {
DeviceId deviceId = deviceConfig.getDeviceId(sid);
if (deviceId == null) {
log.warn("Cannot find a device for SID {}", sid);
return false;
}
return inSameSubnet(deviceId, address);
}
public List<Ip4Prefix> getSubnetInfo(DeviceId deviceId) {
return deviceConfig.getSubnets(deviceId);
}
public int getMplsId(DeviceId deviceId) {
return deviceConfig.getSegmentId(deviceId);
}
public int getMplsId(MacAddress routerMac) {
return deviceConfig.getSegmentId(routerMac);
}
public int getMplsId(Ip4Address routerIpAddress) {
return deviceConfig.getSegmentId(routerIpAddress);
}
public boolean isEcmpNotSupportedInTransit(DeviceId deviceId) {
return false;
}
public boolean isTransitRouter(DeviceId deviceId) {
return !(deviceConfig.isEdgeDevice(deviceId));
}
public boolean isEdgeRouter(DeviceId deviceId) {
return deviceConfig.isEdgeDevice(deviceId);
}
private List<PortNumber> getPortsToNeighbors(DeviceId deviceId, List<DeviceId> fwdSws) {
List<PortNumber> portNumbers = Lists.newArrayList();
Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId);
for (Link link: links) {
for (DeviceId swId: fwdSws) {
if (link.dst().deviceId().equals(swId)) {
portNumbers.add(link.src().port());
break;
}
}
}
return portNumbers;
}
public List<PortNumber> getPortsToDevice(DeviceId deviceId) {
List<PortNumber> portNumbers = Lists.newArrayList();
Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId);
for (Link link: links) {
if (link.dst().deviceId().equals(deviceId)) {
portNumbers.add(link.src().port());
}
}
return portNumbers;
}
public Ip4Address getDestinationRouterAddress(Ip4Address destIpAddress) {
return deviceConfig.getRouterIpAddressForASubnetHost(destIpAddress);
}
public DeviceId getDeviceId(Ip4Address ip4Address) {
return deviceConfig.getDeviceId(ip4Address);
}
public MacAddress getRouterMac(Ip4Address targetAddress) {
return deviceConfig.getRouterMacForAGatewayIp(targetAddress);
}
}
......@@ -48,10 +48,9 @@ public class RoutingRulePopulator {
private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);
private final SegmentRoutingManager srManager;
private final NetworkConfigHandler config;
private AtomicLong rulePopulationCounter;
private SegmentRoutingManager srManager;
private DeviceConfiguration config;
/**
* Creates a RoutingRulePopulator object.
*
......@@ -59,7 +58,7 @@ public class RoutingRulePopulator {
*/
public RoutingRulePopulator(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.config = checkNotNull(srManager.networkConfigHandler);
this.config = checkNotNull(srManager.deviceConfiguration);
this.rulePopulationCounter = new AtomicLong(0);
}
......@@ -94,7 +93,7 @@ public class RoutingRulePopulator {
sbuilder.matchEthType(Ethernet.TYPE_IPV4);
tbuilder.setEthDst(hostMac)
.setEthSrc(config.getRouterMacAddress(deviceId))
.setEthSrc(config.getDeviceMac(deviceId))
.setOutput(outPort);
TrafficTreatment treatment = tbuilder.build();
......@@ -156,7 +155,7 @@ public class RoutingRulePopulator {
ns = new NeighborSet(nextHops);
} else {
tbuilder.copyTtlOut();
ns = new NeighborSet(nextHops, config.getMplsId(destSw));
ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
}
DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns);
......@@ -201,7 +200,7 @@ public class RoutingRulePopulator {
Collection<TrafficTreatment> treatments = new ArrayList<>();
// TODO Handle the case of Bos == false
sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getMplsId(destSwId)));
sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId)));
sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
//If the next hop is the destination router, do PHP
......@@ -262,15 +261,15 @@ public class RoutingRulePopulator {
tbuilder.decMplsTtl();
}
if (config.isEcmpNotSupportedInTransit(deviceId)
&& config.isTransitRouter(deviceId)) {
if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) {
Link link = selectOneLink(deviceId, nextHops);
DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
if (link == null) {
log.warn("No link from {} to {}", deviceId, nextHops);
return null;
}
tbuilder.setEthSrc(config.getRouterMacAddress(deviceId))
.setEthDst(config.getRouterMacAddress(link.dst().deviceId()))
tbuilder.setEthSrc(config.getDeviceMac(deviceId))
.setEthDst(config.getDeviceMac(nextHop))
.setOutput(link.src().port());
} else {
NeighborSet ns = new NeighborSet(nextHops);
......@@ -292,6 +291,12 @@ public class RoutingRulePopulator {
return tbuilder.build();
}
private boolean isECMPSupportedInTransitRouter() {
// TODO: remove this function when objectives subsystem is supported.
return false;
}
/**
* Populates VLAN flows rules.
* All packets are forwarded to TMAC table.
......@@ -327,7 +332,7 @@ public class RoutingRulePopulator {
// flow rule for IP packets
TrafficSelector selectorIp = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchEthDst(config.getRouterMacAddress(deviceId))
.matchEthDst(config.getDeviceMac(deviceId))
.build();
TrafficTreatment treatmentIp = DefaultTrafficTreatment.builder()
.transition(FlowRule.Type.IP)
......@@ -341,7 +346,7 @@ public class RoutingRulePopulator {
// flow rule for MPLS packets
TrafficSelector selectorMpls = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.MPLS_UNICAST)
.matchEthDst(config.getRouterMacAddress(deviceId))
.matchEthDst(config.getDeviceMac(deviceId))
.build();
TrafficTreatment treatmentMpls = DefaultTrafficTreatment.builder()
.transition(FlowRule.Type.MPLS)
......
......@@ -99,15 +99,14 @@ public class SegmentRoutingManager {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
protected NetworkConfigHandler networkConfigHandler = null;
protected ArpHandler arpHandler = null;
protected IcmpHandler icmpHandler = null;
protected IpHandler ipHandler = null;
protected RoutingRulePopulator routingRulePopulator = null;
protected ApplicationId appId;
protected DeviceConfiguration deviceConfiguration = null;
private DefaultRoutingHandler defaultRoutingHandler = null;
private DeviceConfiguration deviceConfiguration = null;
private InternalPacketProcessor processor = new InternalPacketProcessor();
private InternalEventHandler eventHandler = new InternalEventHandler();
......@@ -129,8 +128,6 @@ public class SegmentRoutingManager {
appId = coreService.registerApplication("org.onosproject.segmentrouting");
networkConfigService.init();
deviceConfiguration = new DeviceConfiguration(networkConfigService);
networkConfigHandler = new NetworkConfigHandler(this,
deviceConfiguration);
arpHandler = new ArpHandler(this);
icmpHandler = new IcmpHandler(this);
ipHandler = new IpHandler(this);
......@@ -150,8 +147,8 @@ public class SegmentRoutingManager {
appId, deviceConfiguration, linkService, groupService);
groupHandler.createGroups();
groupHandlerMap.put(device.id(), groupHandler);
log.debug("Initiating default group handling for {}", device.id());
defaultRoutingHandler.populateTtpRules(device.id());
log.debug("Initiating default group handling for {}", device.id());
} else {
log.debug("Activate: Local role {} "
+ "is not MASTER for device {}",
......@@ -162,7 +159,6 @@ public class SegmentRoutingManager {
}
defaultRoutingHandler.startPopulationProcess();
log.info("Started");
}
......