Charles Chan
Committed by Ray Milkey

[CORD-313] Handles uncaught exceptions when device is not configured

Includes following minor changes
    - Move DeviceConfiguration and DeviceProperties to config package
    - Create DeviceConfigNotFoundException

Change-Id: I32455d88c712bb65cd7f71dab9472ae003303de2
Showing 15 changed files with 323 additions and 115 deletions
......@@ -31,6 +31,8 @@ import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.HostId;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -140,9 +142,16 @@ public class ArpHandler {
* @param inPort in-port
*/
public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
byte[] senderMacAddress = config.getDeviceMac(deviceId).toBytes();
byte[] senderIpAddress = config.getRouterIp(deviceId).toOctets();
byte[] senderMacAddress;
byte[] senderIpAddress;
try {
senderMacAddress = config.getDeviceMac(deviceId).toBytes();
senderIpAddress = config.getRouterIp(deviceId).toOctets();
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting sendArpRequest.");
return;
}
ARP arpRequest = new ARP();
arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
......
......@@ -23,6 +23,8 @@ import org.onlab.packet.IpPrefix;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -449,7 +451,20 @@ 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.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) {
boolean targetIsEdge;
boolean destIsEdge;
Ip4Address destRouterIp;
try {
targetIsEdge = config.isEdgeDevice(targetSw);
destIsEdge = config.isEdgeDevice(destSw);
destRouterIp = config.getRouterIp(destSw);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateEcmpRoutingRulePartial.");
return false;
}
if (targetIsEdge && destIsEdge) {
Set<Ip4Prefix> subnets = config.getSubnets(destSw);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
targetSw, destSw, subnets);
......@@ -461,7 +476,7 @@ public class DefaultRoutingHandler {
return false;
}
Ip4Address routerIp = config.getRouterIp(destSw);
Ip4Address routerIp = destRouterIp;
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
......@@ -471,8 +486,8 @@ public class DefaultRoutingHandler {
}
// If the target switch is an edge router, then set IP rules for the router IP.
} else if (config.isEdgeDevice(targetSw)) {
Ip4Address routerIp = config.getRouterIp(destSw);
} else if (targetIsEdge) {
Ip4Address routerIp = destRouterIp;
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
......
......@@ -28,6 +28,8 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -71,7 +73,13 @@ public class IcmpHandler {
Ip4Address destinationAddress =
Ip4Address.valueOf(ipv4.getDestinationAddress());
Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
Ip4Address routerIp = config.getRouterIp(deviceId);
Ip4Address routerIp;
try {
routerIp = config.getRouterIp(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processPacketIn.");
return;
}
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address();
......
......@@ -26,6 +26,8 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -127,13 +129,19 @@ public class IpHandler {
for (IPv4 ipPacket : ipPacketQueue.get(destIpAddress)) {
Ip4Address destAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
if (ipPacket != null && config.inSameSubnet(deviceId, destAddress)) {
if (config.inSameSubnet(deviceId, destAddress)) {
ipPacket.setTtl((byte) (ipPacket.getTtl() - 1));
ipPacket.setChecksum((short) 0);
for (Host dest: srManager.hostService.getHostsByIp(destIpAddress)) {
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(dest.mac());
eth.setSourceMACAddress(config.getDeviceMac(deviceId));
try {
eth.setSourceMACAddress(config.getDeviceMac(deviceId));
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage()
+ " Skipping forwardPackets for this destination.");
continue;
}
eth.setEtherType(Ethernet.TYPE_IPV4);
eth.setPayload(ipPacket);
......
......@@ -27,6 +27,7 @@ import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
......
......@@ -22,6 +22,8 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
......@@ -103,6 +105,14 @@ public class RoutingRulePopulator {
*/
public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
MacAddress hostMac, PortNumber outPort) {
MacAddress deviceMac;
try {
deviceMac = config.getDeviceMac(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateIpRuleForHost.");
return;
}
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
......@@ -111,7 +121,7 @@ public class RoutingRulePopulator {
tbuilder.deferred()
.setEthDst(hostMac)
.setEthSrc(config.getDeviceMac(deviceId))
.setEthSrc(deviceMac)
.setOutput(outPort);
TrafficTreatment treatment = tbuilder.build();
......@@ -167,6 +177,13 @@ public class RoutingRulePopulator {
public boolean populateIpRuleForRouter(DeviceId deviceId,
IpPrefix ipPrefix, DeviceId destSw,
Set<DeviceId> nextHops) {
int segmentId;
try {
segmentId = config.getSegmentId(destSw);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
return false;
}
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
......@@ -183,7 +200,7 @@ public class RoutingRulePopulator {
ns = new NeighborSet(nextHops);
} else {
tbuilder.deferred().copyTtlOut();
ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
ns = new NeighborSet(nextHops, segmentId);
}
TrafficTreatment treatment = tbuilder.build();
......@@ -227,19 +244,26 @@ public class RoutingRulePopulator {
*/
public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId,
Set<DeviceId> nextHops) {
int segmentId;
try {
segmentId = config.getSegmentId(destSwId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateMplsRule.");
return false;
}
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<>();
// TODO Handle the case of Bos == false
sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId)));
sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
// If the next hop is the destination router, do PHP
if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
log.debug("populateMplsRule: Installing MPLS forwarding objective for "
+ "label {} in switch {} with PHP",
config.getSegmentId(destSwId),
segmentId,
deviceId);
ForwardingObjective.Builder fwdObjBosBuilder =
......@@ -264,7 +288,7 @@ public class RoutingRulePopulator {
} else {
log.debug("Installing MPLS forwarding objective for "
+ "label {} in switch {} without PHP",
config.getSegmentId(destSwId),
segmentId,
deviceId);
ForwardingObjective.Builder fwdObjBosBuilder =
......@@ -310,9 +334,21 @@ public class RoutingRulePopulator {
Set<DeviceId> nextHops,
boolean phpRequired,
boolean isBos) {
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
.builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
boolean isEdge;
MacAddress srcMac;
MacAddress dstMac;
try {
isEdge = config.isEdgeDevice(deviceId);
srcMac = config.getDeviceMac(deviceId);
dstMac = config.getDeviceMac(nextHop);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting getMplsForwardingObjective");
return null;
}
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
......@@ -329,16 +365,15 @@ public class RoutingRulePopulator {
tbuilder.deferred().decMplsTtl();
}
if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) {
if (!isECMPSupportedInTransitRouter() && !isEdge) {
PortNumber port = selectOnePort(deviceId, nextHops);
DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
if (port == null) {
log.warn("No link from {} to {}", deviceId, nextHops);
return null;
}
tbuilder.deferred()
.setEthSrc(config.getDeviceMac(deviceId))
.setEthDst(config.getDeviceMac(nextHop))
.setEthSrc(srcMac)
.setEthDst(dstMac)
.setOutput(port);
fwdBuilder.withTreatment(tbuilder.build());
} else {
......@@ -372,15 +407,27 @@ public class RoutingRulePopulator {
public void populateRouterMacVlanFilters(DeviceId deviceId) {
log.debug("Installing per-port filtering objective for untagged "
+ "packets in device {}", deviceId);
MacAddress deviceMac;
try {
deviceMac = config.getDeviceMac(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateRouterMacVlanFilters.");
return;
}
for (Port port : srManager.deviceService.getPorts(deviceId)) {
if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
VlanId assignedVlan = (portSubnet == null)
? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
: srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
fob.withKey(Criteria.matchInPort(port.number()))
.addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId)))
.addCondition(Criteria.matchEthDst(deviceMac))
.addCondition(Criteria.matchVlanId(VlanId.NONE));
// vlan assignment is valid only if this instance is master
if (srManager.mastershipService.isLocalMaster(deviceId)) {
......@@ -405,6 +452,14 @@ public class RoutingRulePopulator {
* @param deviceId the switch dpid for the router
*/
public void populateRouterIpPunts(DeviceId deviceId) {
Ip4Address routerIp;
try {
routerIp = config.getRouterIp(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateRouterIpPunts.");
return;
}
if (!srManager.mastershipService.isLocalMaster(deviceId)) {
log.debug("Not installing port-IP punts - not the master for dev:{} ",
deviceId);
......@@ -412,7 +467,7 @@ public class RoutingRulePopulator {
}
ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder();
Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId));
allIps.add(config.getRouterIp(deviceId));
allIps.add(routerIp);
for (Ip4Address ipaddr : allIps) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
......
......@@ -38,6 +38,8 @@ import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
......@@ -553,7 +555,10 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processLinkAdded(Link link) {
log.debug("A new link {} was added", link.toString());
if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
log.warn("Source device of this link is not configured.");
return;
}
//Irrespective whether the local is a MASTER or not for this device,
//create group handler instance and push default TTP flow rules.
//Because in a multi-instance setup, instances can initiate
......@@ -596,7 +601,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processDeviceAdded(Device device) {
log.debug("A new device with ID {} was added", device.id());
if (deviceConfiguration == null) {
if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
log.warn("Device configuration uploading. Device {} will be "
+ "processed after config completes.", device.id());
return;
......@@ -608,14 +613,20 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
if (groupHandlerMap.get(device.id()) == null) {
DefaultGroupHandler groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
DefaultGroupHandler groupHandler;
try {
groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processDeviceAdded.");
return;
}
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
// information to process rules (eg. Router IP/MAC); and so, we send
......@@ -667,12 +678,20 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
if (groupHandlerMap.get(device.id()) == null) {
DefaultGroupHandler groupHandler = DefaultGroupHandler
.createGroupHandler(device.id(), appId,
deviceConfiguration, linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
DefaultGroupHandler groupHandler;
try {
groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting configureNetwork.");
return;
}
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
......
......@@ -18,6 +18,7 @@ package org.onosproject.segmentrouting;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.store.service.EventuallyConsistentMap;
......
/*
* Copyright 2014-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.config;
/**
* Signals that an error occurred during reading device configuration.
*/
public class DeviceConfigNotFoundException extends Exception {
/**
* Creates a new ConfigNotFoundException with the given message.
*
* @param message exception message
*/
public DeviceConfigNotFoundException(String message) {
super(message);
}
}
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting;
package org.onosproject.segmentrouting.config;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
......@@ -26,9 +26,7 @@ import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid;
import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.slf4j.Logger;
......@@ -126,23 +124,20 @@ public class DeviceConfiguration implements DeviceProperties {
});
}
/**
* Returns the Node segment id of a segment router.
*
* @param deviceId device identifier
* @return segment id
*/
@Override
public int getSegmentId(DeviceId deviceId) {
public boolean isConfigured(DeviceId deviceId) {
return deviceConfigMap.get(deviceId) != null;
}
@Override
public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
return srinfo.nodeSid;
} else {
log.warn("getSegmentId for device {} "
+ "throwing IllegalStateException "
+ "because device does not exist in config", deviceId);
throw new IllegalStateException();
String message = "getSegmentId fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
......@@ -180,71 +175,42 @@ public class DeviceConfiguration implements DeviceProperties {
return -1;
}
/**
* Returns the router mac of a segment router.
*
* @param deviceId device identifier
* @return router mac address
*/
@Override
public MacAddress getDeviceMac(DeviceId deviceId) {
public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
return srinfo.mac;
} else {
log.warn("getDeviceMac for device {} "
+ "throwing IllegalStateException "
+ "because device does not exist in config", deviceId);
throw new IllegalStateException();
String message = "getDeviceMac fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
/**
* Returns the router ip address of a segment router.
*
* @param deviceId device identifier
* @return router ip address
*/
public Ip4Address getRouterIp(DeviceId deviceId) {
@Override
public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
return srinfo.ip;
} else {
log.warn("getRouterIp for device {} "
+ "throwing IllegalStateException "
+ "because device does not exist in config", deviceId);
throw new IllegalStateException();
String message = "getRouterIp fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
/**
* Indicates if the segment router is a edge router or
* a core/backbone router.
*
* @param deviceId device identifier
* @return boolean
*/
@Override
public boolean isEdgeDevice(DeviceId deviceId) {
public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
return srinfo.isEdge;
} else {
log.warn("isEdgeDevice for device {} "
+ "throwing IllegalStateException "
+ "because device does not exist in config", deviceId);
throw new IllegalStateException();
String message = "isEdgeDevice fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
/**
* Returns the node segment ids of all configured segment routers.
*
* @return list of node segment ids
*/
@Override
public List<Integer> getAllDeviceSegmentIds() {
return allSegmentIds;
......
......@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.config;
import java.util.List;
import java.util.Map;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
......@@ -30,28 +31,48 @@ import org.onosproject.net.PortNumber;
*/
public interface DeviceProperties {
/**
* Checks if the device is configured.
*
* @param deviceId device identifier
* @return true if the device is configured
*/
boolean isConfigured(DeviceId deviceId);
/**
* Returns the segment id of a device to be used in group creation.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return segment id of a device
*/
int getSegmentId(DeviceId deviceId);
int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Returns the Mac address of a device to be used in group creation.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return mac address of a device
*/
MacAddress getDeviceMac(DeviceId deviceId);
MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Returns the router ip address of a segment router.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return router ip address
*/
Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Indicates whether a device is edge device or transit/core device.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return boolean
*/
boolean isEdgeDevice(DeviceId deviceId);
boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Returns all segment IDs to be considered in building auto
......
......@@ -24,6 +24,7 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.store.service.EventuallyConsistentMap;
/**
......
......@@ -48,6 +48,8 @@ import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
......@@ -63,9 +65,9 @@ public class DefaultGroupHandler {
protected final ApplicationId appId;
protected final DeviceProperties deviceConfig;
protected final List<Integer> allSegmentIds;
protected final int nodeSegmentId;
protected final boolean isEdgeRouter;
protected final MacAddress nodeMacAddr;
protected int nodeSegmentId = -1;
protected boolean isEdgeRouter = false;
protected MacAddress nodeMacAddr = null;
protected LinkService linkService;
protected FlowObjectiveService flowObjectiveService;
......@@ -99,10 +101,15 @@ public class DefaultGroupHandler {
this.appId = checkNotNull(appId);
this.deviceConfig = checkNotNull(config);
this.linkService = checkNotNull(linkService);
allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
nodeSegmentId = config.getSegmentId(deviceId);
isEdgeRouter = config.isEdgeDevice(deviceId);
nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
try {
this.nodeSegmentId = config.getSegmentId(deviceId);
this.isEdgeRouter = config.isEdgeDevice(deviceId);
this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage()
+ " Skipping value assignment in DefaultGroupHandler");
}
this.flowObjectiveService = flowObjService;
this.nsNextObjStore = nsNextObjStore;
this.subnetNextObjStore = subnetNextObjStore;
......@@ -122,6 +129,7 @@ public class DefaultGroupHandler {
* @param flowObjService flow objective service object
* @param nsNextObjStore NeighborSet next objective store map
* @param subnetNextObjStore subnet next objective store map
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return default group handler type
*/
public static DefaultGroupHandler createGroupHandler(DeviceId deviceId,
......@@ -133,7 +141,9 @@ public class DefaultGroupHandler {
NeighborSetNextObjectiveStoreKey,
Integer> nsNextObjStore,
EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
Integer> subnetNextObjStore) {
Integer> subnetNextObjStore)
throws DeviceConfigNotFoundException {
// handle possible exception in the caller
if (config.isEdgeDevice(deviceId)) {
return new DefaultEdgeGroupHandler(deviceId, appId, config,
linkService,
......@@ -176,6 +186,14 @@ public class DefaultGroupHandler {
return;
}
MacAddress dstMac;
try {
dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId());
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting linkUp.");
return;
}
log.debug("Device {} linkUp at local port {} to neighbor {}", deviceId,
newLink.src().port(), newLink.dst().deviceId());
addNeighborAtPort(newLink.dst().deviceId(),
......@@ -202,8 +220,7 @@ public class DefaultGroupHandler {
TrafficTreatment.Builder tBuilder =
DefaultTrafficTreatment.builder();
tBuilder.setOutput(newLink.src().port())
.setEthDst(deviceConfig.getDeviceMac(
newLink.dst().deviceId()))
.setEthDst(dstMac)
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls()
......@@ -242,6 +259,15 @@ public class DefaultGroupHandler {
log.warn("portDown: unknown port");
return;
}
MacAddress dstMac;
try {
dstMac = deviceConfig.getDeviceMac(portDeviceMap.get(port));
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting portDown.");
return;
}
log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
portDeviceMap.get(port));
/*Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(portDeviceMap
......@@ -263,8 +289,8 @@ public class DefaultGroupHandler {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
.builder();
tBuilder.setOutput(port)
.setEthDst(deviceConfig.getDeviceMac(portDeviceMap
.get(port))).setEthSrc(nodeMacAddr);
.setEthDst(dstMac)
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
.getEdgeLabel()));
......@@ -432,7 +458,15 @@ public class DefaultGroupHandler {
}
private boolean isSegmentIdSameAsNodeSegmentId(DeviceId deviceId, int sId) {
return (deviceConfig.getSegmentId(deviceId) == sId);
int segmentId;
try {
segmentId = deviceConfig.getSegmentId(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting isSegmentIdSameAsNodeSegmentId.");
return false;
}
return segmentId == sId;
}
protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(Set<DeviceId> neighbors) {
......@@ -487,11 +521,19 @@ public class DefaultGroupHandler {
return;
}
MacAddress deviceMac;
try {
deviceMac = deviceConfig.getDeviceMac(d);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting createGroupsFromNeighborsets.");
return;
}
for (PortNumber sp : devicePortMap.get(d)) {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
.builder();
tBuilder.setOutput(sp)
.setEthDst(deviceConfig.getDeviceMac(d))
.setEthDst(deviceMac)
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
......
......@@ -23,6 +23,8 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.store.service.EventuallyConsistentMap;
/**
......@@ -171,7 +173,15 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
if (deviceSubSet.size() > 1) {
boolean avoidEdgeRouterPairing = true;
for (DeviceId device : deviceSubSet) {
if (!deviceConfig.isEdgeDevice(device)) {
boolean isEdge;
try {
isEdge = deviceConfig.isEdgeDevice(device);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Skipping filterEdgeRouterOnlyPairings on this device.");
continue;
}
if (!isEdge) {
avoidEdgeRouterPairing = false;
break;
}
......
......@@ -24,8 +24,11 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onosproject.core.ApplicationId;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.net.DeviceId;
......@@ -105,11 +108,19 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
PolicyGroupIdentifier(id,
Collections.singletonList(param),
Collections.singletonList(bucketId));
MacAddress neighborEthDst;
try {
neighborEthDst = deviceConfig.getDeviceMac(neighbor);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage()
+ " Skipping createPolicyGroupChain for this label.");
continue;
}
TrafficTreatment.Builder tBuilder =
DefaultTrafficTreatment.builder();
tBuilder.setOutput(sp)
.setEthDst(deviceConfig.
getDeviceMac(neighbor))
.setEthDst(neighborEthDst)
.setEthSrc(nodeMacAddr)
.pushMpls()
.setMpls(MplsLabel.mplsLabel(label));
......@@ -168,14 +179,23 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
if (fullyResolved) {
List<GroupBucket> outBuckets = new ArrayList<>();
for (GroupBucketIdentifier bucketId:bucketIds) {
for (GroupBucketIdentifier bucketId : bucketIds) {
DeviceId neighbor = portDeviceMap.
get(bucketId.outPort());
MacAddress neighborEthDst;
try {
neighborEthDst = deviceConfig.getDeviceMac(neighbor);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage()
+ " Skipping createPolicyGroupChain for this bucketId.");
continue;
}
TrafficTreatment.Builder tBuilder =
DefaultTrafficTreatment.builder();
tBuilder.setOutput(bucketId.outPort())
.setEthDst(deviceConfig.
getDeviceMac(neighbor))
.setEthDst(neighborEthDst)
.setEthSrc(nodeMacAddr);
if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls()
......