aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting')
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java147
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java23
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java4
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java22
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java12
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java1
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java198
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java317
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java1
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java32
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java (renamed from framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java)72
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java (renamed from framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java)29
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java1
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java85
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java12
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java30
16 files changed, 778 insertions, 208 deletions
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 36563f01..2c6412cf 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -20,10 +20,10 @@ import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
-import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
@@ -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;
@@ -58,12 +60,21 @@ public class ArpHandler {
/**
* Processes incoming ARP packets.
+ *
* If it is an ARP request to router itself or known hosts,
* then it sends ARP response.
* If it is an ARP request to unknown hosts in its own subnet,
* then it flood the ARP request to the ports.
* If it is an ARP response, then set a flow rule for the host
* and forward any IP packets to the host in the packet buffer to the host.
+ * <p>
+ * Note: We handles all ARP packet in, even for those ARP packets between
+ * hosts in the same subnet.
+ * For an ARP packet with broadcast destination MAC,
+ * some switches pipelines will send it to the controller due to table miss,
+ * other swithches will flood the packets directly in the data plane without
+ * packet in.
+ * We can deal with both cases.
*
* @param pkt incoming packet
*/
@@ -84,29 +95,56 @@ public class ArpHandler {
if (arp.getOpCode() == ARP.OP_REQUEST) {
handleArpRequest(deviceId, connectPoint, ethernet);
} else {
- srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
+ handleArpReply(deviceId, connectPoint, ethernet);
}
}
private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
ARP arpRequest = (ARP) payload.getPayload();
+ VlanId vlanId = VlanId.vlanId(payload.getVlanID());
HostId targetHostId = HostId.hostId(MacAddress.valueOf(
- arpRequest.getTargetHardwareAddress()));
+ arpRequest.getTargetHardwareAddress()),
+ vlanId);
- // ARP request for router
+ // ARP request for router. Send ARP reply.
if (isArpReqForRouter(deviceId, arpRequest)) {
Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
-
- sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress));
+ sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId);
} else {
Host targetHost = srManager.hostService.getHost(targetHostId);
- // ARP request for known hosts
+ // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
if (targetHost != null) {
- sendArpResponse(arpRequest, targetHost.mac());
+ removeVlanAndForward(payload, targetHost.location());
+ // ARP request for unknown host in the subnet. Flood in the subnet.
+ } else {
+ removeVlanAndFlood(payload, inPort);
+ }
+ }
+ }
+
+ private void handleArpReply(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
+ ARP arpReply = (ARP) payload.getPayload();
+ VlanId vlanId = VlanId.vlanId(payload.getVlanID());
+ HostId targetHostId = HostId.hostId(MacAddress.valueOf(
+ arpReply.getTargetHardwareAddress()),
+ vlanId);
- // ARP request for unknown host in the subnet
- } else if (isArpReqForSubnet(deviceId, arpRequest)) {
- flood(payload, inPort);
+ // ARP reply for router. Process all pending IP packets.
+ if (isArpReqForRouter(deviceId, arpReply)) {
+ Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress());
+ srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
+ } else {
+ Host targetHost = srManager.hostService.getHost(targetHostId);
+ // ARP reply for known hosts. Forward to the host.
+ if (targetHost != null) {
+ removeVlanAndForward(payload, targetHost.location());
+ // ARP reply for unknown host, Flood in the subnet.
+ } else {
+ // Don't flood to non-edge ports
+ if (vlanId.equals(VlanId.vlanId(srManager.ASSIGNED_VLAN_NO_SUBNET))) {
+ return;
+ }
+ removeVlanAndFlood(payload, inPort);
}
}
}
@@ -124,14 +162,6 @@ public class ArpHandler {
return false;
}
- private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) {
- return config.getSubnets(deviceId).stream()
- .anyMatch((prefix)->
- prefix.contains(Ip4Address.
- valueOf(arpRequest.
- getTargetProtocolAddress())));
- }
-
/**
* Sends an APR request for the target IP address to all ports except in-port.
*
@@ -140,9 +170,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)
@@ -161,11 +198,10 @@ public class ArpHandler {
.setSourceMACAddress(senderMacAddress)
.setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);
- flood(eth, inPort);
+ removeVlanAndFlood(eth, inPort);
}
- private void sendArpResponse(ARP arpRequest, MacAddress targetMac) {
-
+ private void sendArpResponse(ARP arpRequest, MacAddress targetMac, VlanId vlanId) {
ARP arpReply = new ARP();
arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
.setProtocolType(ARP.PROTO_TYPE_IP)
@@ -184,8 +220,9 @@ public class ArpHandler {
.setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
- HostId dstId = HostId.hostId(MacAddress.valueOf(
- arpReply.getTargetHardwareAddress()));
+ HostId dstId = HostId.hostId(
+ MacAddress.valueOf(arpReply.getTargetHardwareAddress()),
+ vlanId);
Host dst = srManager.hostService.getHost(dstId);
if (dst == null) {
log.warn("Cannot send ARP response to unknown device");
@@ -200,19 +237,51 @@ public class ArpHandler {
srManager.packetService.emit(packet);
}
- private void flood(Ethernet request, ConnectPoint inPort) {
- TrafficTreatment.Builder builder;
- ByteBuffer buf = ByteBuffer.wrap(request.serialize());
-
- for (Port port: srManager.deviceService.getPorts(inPort.deviceId())) {
- if (!port.number().equals(inPort.port()) &&
- port.number().toLong() > 0) {
- builder = DefaultTrafficTreatment.builder();
- builder.setOutput(port.number());
- srManager.packetService.emit(new DefaultOutboundPacket(inPort.deviceId(),
- builder.build(), buf));
+ /**
+ * Remove VLAN tag and flood to all ports in the same subnet.
+ *
+ * @param packet packet to be flooded
+ * @param inPort where the packet comes from
+ */
+ private void removeVlanAndFlood(Ethernet packet, ConnectPoint inPort) {
+ Ip4Address targetProtocolAddress = Ip4Address.valueOf(
+ ((ARP) packet.getPayload()).getTargetProtocolAddress()
+ );
+
+ srManager.deviceConfiguration.getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
+ if (subnet.contains(targetProtocolAddress)) {
+ ports.stream()
+ .filter(port -> port != inPort.port())
+ .forEach(port -> {
+ removeVlanAndForward(packet, new ConnectPoint(inPort.deviceId(), port));
+ });
}
- }
+ });
}
+ /**
+ * Remove VLAN tag and packet out to given port.
+ *
+ * Note: In current implementation, we expect all communication with
+ * end hosts within a subnet to be untagged.
+ * <p>
+ * For those pipelines that internally assigns a VLAN, the VLAN tag will be
+ * removed before egress.
+ * <p>
+ * For those pipelines that do not assign internal VLAN, the packet remains
+ * untagged.
+ *
+ * @param packet packet to be forwarded
+ * @param outPort where the packet should be forwarded
+ */
+ private void removeVlanAndForward(Ethernet packet, ConnectPoint outPort) {
+ packet.setEtherType(Ethernet.TYPE_ARP);
+ packet.setVlanID(Ethernet.VLAN_UNTAGGED);
+ ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
+
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ tbuilder.setOutput(outPort.port());
+ srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
+ tbuilder.build(), buf));
+ }
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index c4a91c75..a737339f 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -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);
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
index 8c6fbe8d..70161432 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
@@ -17,8 +17,6 @@
package org.onosproject.segmentrouting;
import java.util.List;
-import java.util.Objects;
-
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -96,7 +94,7 @@ public class DefaultTunnel implements Tunnel {
@Override
public int hashCode() {
- return Objects.hash(labelIds);
+ return labelIds.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index b3916b06..eb3b3fd5 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -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();
@@ -97,8 +105,17 @@ public class IcmpHandler {
}
}
+ /**
+ * Sends an ICMP reply message.
+ *
+ * Note: we assume that packets sending from the edge switches to the hosts
+ * have untagged VLAN.
+ * @param icmpRequest the original ICMP request
+ * @param outport the output port where the ICMP reply should be sent to
+ */
private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) {
-
+ // Note: We assume that packets arrive at the edge switches have
+ // untagged VLAN.
Ethernet icmpReplyEth = new Ethernet();
IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
@@ -121,7 +138,6 @@ public class IcmpHandler {
icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4);
icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress());
icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress());
- icmpReplyEth.setVlanID(icmpRequest.getVlanID());
Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress());
Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
index 14ce679b..b1682e77 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
@@ -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);
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
index 83cb7e86..0a4c26d9 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
@@ -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;
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index d46028e7..bc3ce8c6 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -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;
@@ -53,7 +55,6 @@ import java.util.concurrent.atomic.AtomicLong;
import static com.google.common.base.Preconditions.checkNotNull;
public class RoutingRulePopulator {
-
private static final Logger log = LoggerFactory
.getLogger(RoutingRulePopulator.class);
@@ -103,6 +104,46 @@ public class RoutingRulePopulator {
*/
public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
MacAddress hostMac, PortNumber outPort) {
+ log.debug("Populate IP table entry for host {} at {}:{}",
+ hostIp, deviceId, outPort);
+ ForwardingObjective.Builder fwdBuilder;
+ try {
+ fwdBuilder = getForwardingObjectiveBuilder(
+ deviceId, hostIp, hostMac, outPort);
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Aborting populateIpRuleForHost.");
+ return;
+ }
+ srManager.flowObjectiveService.
+ forward(deviceId, fwdBuilder.add(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)));
+ rulePopulationCounter.incrementAndGet();
+ }
+
+ public void revokeIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
+ MacAddress hostMac, PortNumber outPort) {
+ log.debug("Revoke IP table entry for host {} at {}:{}",
+ hostIp, deviceId, outPort);
+ ForwardingObjective.Builder fwdBuilder;
+ try {
+ fwdBuilder = getForwardingObjectiveBuilder(
+ deviceId, hostIp, hostMac, outPort);
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Aborting revokeIpRuleForHost.");
+ return;
+ }
+ srManager.flowObjectiveService.
+ forward(deviceId, fwdBuilder.remove(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)));
+ }
+
+ private ForwardingObjective.Builder getForwardingObjectiveBuilder(
+ DeviceId deviceId, Ip4Address hostIp,
+ MacAddress hostMac, PortNumber outPort)
+ throws DeviceConfigNotFoundException {
+ MacAddress deviceMac;
+ deviceMac = config.getDeviceMac(deviceId);
+
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
@@ -111,25 +152,16 @@ public class RoutingRulePopulator {
tbuilder.deferred()
.setEthDst(hostMac)
- .setEthSrc(config.getDeviceMac(deviceId))
+ .setEthSrc(deviceMac)
.setOutput(outPort);
TrafficTreatment treatment = tbuilder.build();
TrafficSelector selector = sbuilder.build();
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder().fromApp(srManager.appId).makePermanent()
+ return DefaultForwardingObjective.builder()
+ .fromApp(srManager.appId).makePermanent()
.withSelector(selector).withTreatment(treatment)
.withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
-
- log.debug("Installing IPv4 forwarding objective "
- + "for host {} in switch {}", hostIp, deviceId);
- srManager.flowObjectiveService.
- forward(deviceId,
- fwdBuilder.
- add(new SRObjectiveContext(deviceId,
- SRObjectiveContext.ObjectiveType.FORWARDING)));
- rulePopulationCounter.incrementAndGet();
}
/**
@@ -167,28 +199,34 @@ 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();
-
sbuilder.matchIPDst(ipPrefix);
sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+ TrafficSelector selector = sbuilder.build();
- NeighborSet ns = null;
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ NeighborSet ns;
+ TrafficTreatment treatment;
// If the next hop is the same as the final destination, then MPLS label
// is not set.
if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
- tbuilder.deferred().decNwTtl();
+ tbuilder.immediate().decNwTtl();
ns = new NeighborSet(nextHops);
+ treatment = tbuilder.build();
} else {
- tbuilder.deferred().copyTtlOut();
- ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
+ ns = new NeighborSet(nextHops, segmentId);
+ treatment = null;
}
- TrafficTreatment treatment = tbuilder.build();
- TrafficSelector selector = sbuilder.build();
-
if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
log.warn("No next objective in {} for ns: {}", deviceId, ns);
return false;
@@ -199,10 +237,12 @@ public class RoutingRulePopulator {
.fromApp(srManager.appId)
.makePermanent()
.nextStep(srManager.getNextObjectiveId(deviceId, ns))
- .withTreatment(treatment)
.withSelector(selector)
.withPriority(100)
.withFlag(ForwardingObjective.Flag.SPECIFIC);
+ if (treatment != null) {
+ fwdBuilder.withTreatment(treatment);
+ }
log.debug("Installing IPv4 forwarding objective "
+ "for router IP/subnet {} in switch {}",
ipPrefix,
@@ -227,19 +267,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 +311,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 +357,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 +388,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 +430,25 @@ 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 +473,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,16 +488,16 @@ 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();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(IpPrefix.valueOf(ipaddr,
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+ sbuilder.matchIPDst(IpPrefix.valueOf(ipaddr,
IpPrefix.MAX_INET_MASK_LENGTH));
- treatment.setOutput(PortNumber.CONTROLLER);
- puntIp.withSelector(selector.build());
- puntIp.withTreatment(treatment.build());
+ tbuilder.setOutput(PortNumber.CONTROLLER);
+ puntIp.withSelector(sbuilder.build());
+ puntIp.withTreatment(tbuilder.build());
puntIp.withFlag(Flag.VERSATILE)
.withPriority(HIGHEST_PRIORITY)
.makePermanent()
@@ -434,6 +510,48 @@ public class RoutingRulePopulator {
}
}
+ /**
+ * Populates a forwarding objective to send packets that miss other high
+ * priority Bridging Table entries to a group that contains all ports of
+ * its subnet.
+ *
+ * Note: We assume that packets sending from the edge switches to the hosts
+ * have untagged VLAN.
+ * The VLAN tag will be popped later in the flooding group.
+ *
+ * @param deviceId switch ID to set the rules
+ */
+ public void populateSubnetBroadcastRule(DeviceId deviceId) {
+ config.getSubnets(deviceId).forEach(subnet -> {
+ int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet);
+ VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet);
+
+ /* Driver should treat objective with MacAddress.NONE as the
+ * subnet broadcast rule
+ */
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ sbuilder.matchVlanId(vlanId);
+ sbuilder.matchEthDst(MacAddress.NONE);
+
+ ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
+ fob.withFlag(Flag.SPECIFIC)
+ .withSelector(sbuilder.build())
+ .nextStep(nextId)
+ .withPriority(5)
+ .fromApp(srManager.appId)
+ .makePermanent();
+
+ srManager.flowObjectiveService.forward(
+ deviceId,
+ fob.add(new SRObjectiveContext(
+ deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)
+ )
+ );
+ });
+ }
+
+
private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
Set<Link> links = srManager.linkService.getDeviceLinks(srcId);
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 9d60b279..84fe5168 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
@@ -33,11 +34,25 @@ import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.Event;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
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.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveContext;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+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;
@@ -137,11 +152,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private static ScheduledFuture<?> eventHandlerFuture = null;
private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
- private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
+ private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
+ new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
// Per device next objective ID store with (device id + neighbor set) as key
- private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore = null;
- private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null;
+ private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
+ nsNextObjStore = null;
+ private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
+ subnetNextObjStore = null;
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
// Per device, per-subnet assigned-vlans store, with (device id + subnet
@@ -168,6 +185,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
};
+ private final HostListener hostListener = new InternalHostListener();
+
private Object threadSchedulerLock = new Object();
private static int numOfEventsQueued = 0;
private static int numOfEventsExecuted = 0;
@@ -257,6 +276,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
cfgService.addListener(cfgListener);
cfgService.registerConfigFactory(cfgFactory);
+ hostService.addListener(hostListener);
+
processor = new InternalPacketProcessor();
linkListener = new InternalLinkListener();
deviceListener = new InternalDeviceListener();
@@ -553,7 +574,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,30 +620,43 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processDeviceAdded(Device device) {
log.debug("A new device with ID {} was added", device.id());
+ if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
+ log.warn("Device configuration uploading. Device {} will be "
+ + "processed after config completes.", device.id());
+ return;
+ }
// Irrespective of whether the local is a MASTER or not for this device,
// we need to create a SR-group-handler instance. This is because in a
// multi-instance setup, any instance can initiate forwarding/next-objectives
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
- DefaultGroupHandler groupHandler = DefaultGroupHandler.
- createGroupHandler(device.id(),
- appId,
- deviceConfiguration,
- linkService,
- flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore);
- 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
- // port addressing rules to the driver as well irrespective of whether
- // this instance is the master or not.
- defaultRoutingHandler.populatePortAddressingRules(device.id());
-
+ if (groupHandlerMap.get(device.id()) == null) {
+ 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
+ // port addressing rules to the driver as well irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+ }
if (mastershipService.isLocalMaster(device.id())) {
+ DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
+ routingRulePopulator.populateSubnetBroadcastRule(device.id());
}
}
@@ -660,22 +697,33 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
- DefaultGroupHandler groupHandler = DefaultGroupHandler
- .createGroupHandler(device.id(), appId,
- deviceConfiguration, linkService,
- flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore);
- 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
- // port addressing rules to the driver as well, irrespective of whether
- // this instance is the master or not.
- defaultRoutingHandler.populatePortAddressingRules(device.id());
+ if (groupHandlerMap.get(device.id()) == null) {
+ 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
+ // information to process rules (eg. Router IP/MAC); and so, we send
+ // port addressing rules to the driver as well, irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+ }
if (mastershipService.isLocalMaster(device.id())) {
+ DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
+ routingRulePopulator.populateSubnetBroadcastRule(device.id());
}
}
@@ -696,4 +744,205 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
}
}
+
+ private class InternalHostListener implements HostListener {
+ private ForwardingObjective.Builder getForwardingObjectiveBuilder(
+ MacAddress mac, VlanId vlanId, PortNumber port) {
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ sbuilder.matchEthDst(mac);
+ sbuilder.matchVlanId(vlanId);
+
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ // TODO Move popVlan from flow action to group action
+ tbuilder.immediate().popVlan();
+ tbuilder.immediate().setOutput(port);
+
+ return DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .withSelector(sbuilder.build())
+ .withTreatment(tbuilder.build())
+ .withPriority(100)
+ .fromApp(appId)
+ .makePermanent();
+ }
+
+ private void processHostAddedEvent(HostEvent event) {
+ MacAddress mac = event.subject().mac();
+ VlanId vlanId = event.subject().vlan();
+ DeviceId deviceId = event.subject().location().deviceId();
+ PortNumber port = event.subject().location().port();
+ Set<IpAddress> ips = event.subject().ipAddresses();
+ log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
+
+ // TODO Move bridging table population to a separate class
+ // Populate bridging table entry
+ ForwardingObjective.Builder fob =
+ getForwardingObjectiveBuilder(mac, vlanId, port);
+ flowObjectiveService.forward(deviceId, fob.add(
+ new BridgingTableObjectiveContext(mac, vlanId)
+ ));
+
+ // Populate IP table entry
+ ips.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.populateIpRuleForHost(
+ deviceId, ip.getIp4Address(), mac, port);
+ }
+ });
+ }
+
+ private void processHostRemoveEvent(HostEvent event) {
+ MacAddress mac = event.subject().mac();
+ VlanId vlanId = event.subject().vlan();
+ DeviceId deviceId = event.subject().location().deviceId();
+ PortNumber port = event.subject().location().port();
+ Set<IpAddress> ips = event.subject().ipAddresses();
+ log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
+
+ // Revoke bridging table entry
+ ForwardingObjective.Builder fob =
+ getForwardingObjectiveBuilder(mac, vlanId, port);
+ flowObjectiveService.forward(deviceId, fob.remove(
+ new BridgingTableObjectiveContext(mac, vlanId)
+ ));
+
+ // Revoke IP table entry
+ ips.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.revokeIpRuleForHost(
+ deviceId, ip.getIp4Address(), mac, port);
+ }
+ });
+ }
+
+ private void processHostMovedEvent(HostEvent event) {
+ MacAddress mac = event.subject().mac();
+ VlanId vlanId = event.subject().vlan();
+ DeviceId prevDeviceId = event.prevSubject().location().deviceId();
+ PortNumber prevPort = event.prevSubject().location().port();
+ Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
+ DeviceId newDeviceId = event.subject().location().deviceId();
+ PortNumber newPort = event.subject().location().port();
+ Set<IpAddress> newIps = event.subject().ipAddresses();
+ log.debug("Host {}/{} is moved from {}:{} to {}:{}",
+ mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
+
+ // Revoke previous bridging table entry
+ ForwardingObjective.Builder prevFob =
+ getForwardingObjectiveBuilder(mac, vlanId, prevPort);
+ flowObjectiveService.forward(prevDeviceId, prevFob.remove(
+ new BridgingTableObjectiveContext(mac, vlanId)
+ ));
+
+ // Revoke previous IP table entry
+ prevIps.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.revokeIpRuleForHost(
+ prevDeviceId, ip.getIp4Address(), mac, prevPort);
+ }
+ });
+
+ // Populate new bridging table entry
+ ForwardingObjective.Builder newFob =
+ getForwardingObjectiveBuilder(mac, vlanId, prevPort);
+ flowObjectiveService.forward(newDeviceId, newFob.add(
+ new BridgingTableObjectiveContext(mac, vlanId)
+ ));
+
+ // Populate new IP table entry
+ newIps.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.populateIpRuleForHost(
+ newDeviceId, ip.getIp4Address(), mac, newPort);
+ }
+ });
+ }
+
+ private void processHostUpdatedEvent(HostEvent event) {
+ MacAddress mac = event.subject().mac();
+ VlanId vlanId = event.subject().vlan();
+ DeviceId prevDeviceId = event.prevSubject().location().deviceId();
+ PortNumber prevPort = event.prevSubject().location().port();
+ Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
+ DeviceId newDeviceId = event.subject().location().deviceId();
+ PortNumber newPort = event.subject().location().port();
+ Set<IpAddress> newIps = event.subject().ipAddresses();
+ log.debug("Host {}/{} is updated", mac, vlanId);
+
+ // Revoke previous IP table entry
+ prevIps.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.revokeIpRuleForHost(
+ prevDeviceId, ip.getIp4Address(), mac, prevPort);
+ }
+ });
+
+ // Populate new IP table entry
+ newIps.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.populateIpRuleForHost(
+ newDeviceId, ip.getIp4Address(), mac, newPort);
+ }
+ });
+ }
+
+ @Override
+ public void event(HostEvent event) {
+ // Do not proceed without mastership
+ DeviceId deviceId = event.subject().location().deviceId();
+ if (!mastershipService.isLocalMaster(deviceId)) {
+ return;
+ }
+
+ switch (event.type()) {
+ case HOST_ADDED:
+ processHostAddedEvent(event);
+ break;
+ case HOST_MOVED:
+ processHostMovedEvent(event);
+ break;
+ case HOST_REMOVED:
+ processHostRemoveEvent(event);
+ break;
+ case HOST_UPDATED:
+ processHostUpdatedEvent(event);
+ break;
+ default:
+ log.warn("Unsupported host event type: {}", event.type());
+ break;
+ }
+ }
+ }
+
+ private static class BridgingTableObjectiveContext implements ObjectiveContext {
+ final MacAddress mac;
+ final VlanId vlanId;
+
+ BridgingTableObjectiveContext(MacAddress mac, VlanId vlanId) {
+ this.mac = mac;
+ this.vlanId = vlanId;
+ }
+
+ @Override
+ public void onSuccess(Objective objective) {
+ if (objective.op() == Objective.Operation.ADD) {
+ log.debug("Successfully populate bridging table entry for {}/{}",
+ mac, vlanId);
+ } else {
+ log.debug("Successfully revoke bridging table entry for {}/{}",
+ mac, vlanId);
+ }
+ }
+
+ @Override
+ public void onError(Objective objective, ObjectiveError error) {
+ if (objective.op() == Objective.Operation.ADD) {
+ log.debug("Fail to populate bridging table entry for {}/{}. {}",
+ mac, vlanId, error);
+ } else {
+ log.debug("Fail to revoke bridging table entry for {}/{}. {}",
+ mac, vlanId, error);
+ }
+ }
+ }
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
index 820bb40a..7d025c72 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
@@ -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;
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
new file mode 100644
index 00000000..ae156e60
--- /dev/null
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
@@ -0,0 +1,32 @@
+/*
+ * 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);
+ }
+}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 828c51ce..0ad00679 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -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;
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
index d28d38d5..a39c9567 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
@@ -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
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
index a5c1090f..33496bd7 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
@@ -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;
/**
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 69a0d86f..b394db5e 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -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,13 +220,12 @@ 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()
- .setMpls(MplsLabel.
- mplsLabel(ns.getEdgeLabel()));
+ .copyTtlOut()
+ .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
}
Integer nextId = nsNextObjStore.
@@ -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,11 +289,12 @@ 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()));
+ tBuilder.pushMpls()
+ .copyTtlOut()
+ .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
}
Integer nextId = nsNextObjStore.
@@ -432,7 +459,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,15 +522,24 @@ 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
- .getEdgeLabel()));
+ tBuilder.pushMpls()
+ .copyTtlOut()
+ .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
}
nextObjBuilder.addTreatment(tBuilder.build());
}
@@ -535,6 +579,7 @@ public class DefaultGroupHandler {
ports.forEach(port -> {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ tBuilder.popVlan();
tBuilder.setOutput(port);
nextObjBuilder.addTreatment(tBuilder.build());
});
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
index b009e869..8e1b6a8f 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
@@ -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;
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
index e47a6625..55142078 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
@@ -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()