sangho
Committed by Gerrit Code Review

ONOS-686, 687, 1344 : The first commit for the Segment Routing application

 - ICMP/ARP/IP handlers are implemented as a part of the application for now
 - Default routing and link add/failure/recovery are also supprted
 - Temporary NetworkConfigHandler, which is hardcoded to support only 6 router FISH topology, is used for test
 - Some fixes on GroupHanlder app to support transit routers
 - Supports multi-instance (tested with two instances)

Change-Id: Idfa67903e59e1c4cac4da430f89cd4c50e821420
Showing 19 changed files with 1344 additions and 11 deletions
...@@ -152,11 +152,13 @@ public class DefaultGroupHandler { ...@@ -152,11 +152,13 @@ public class DefaultGroupHandler {
152 * @param newLink new neighbor link 152 * @param newLink new neighbor link
153 */ 153 */
154 public void linkUp(Link newLink) { 154 public void linkUp(Link newLink) {
155 +
155 if (newLink.type() != Link.Type.DIRECT) { 156 if (newLink.type() != Link.Type.DIRECT) {
156 log.warn("linkUp: unknown link type"); 157 log.warn("linkUp: unknown link type");
157 return; 158 return;
158 } 159 }
159 160
161 +
160 if (!newLink.src().deviceId().equals(deviceId)) { 162 if (!newLink.src().deviceId().equals(deviceId)) {
161 log.warn("linkUp: deviceId{} doesn't match with link src{}", 163 log.warn("linkUp: deviceId{} doesn't match with link src{}",
162 deviceId, 164 deviceId,
...@@ -307,13 +309,11 @@ public class DefaultGroupHandler { ...@@ -307,13 +309,11 @@ public class DefaultGroupHandler {
307 309
308 List<Integer> nsSegmentIds = new ArrayList<Integer>(); 310 List<Integer> nsSegmentIds = new ArrayList<Integer>();
309 311
310 - // Add one entry for "no label" (-1) to the list if 312 + // Always pair up with no edge label
311 - // dpid list has not more than one node/neighbor as 313 + //If (neighbors.size() == 1) {
312 - // there will never be a case a packet going to more than one 314 + nsSegmentIds.add(-1);
313 - // neighbor without a label at an edge router 315 + //}
314 - if (neighbors.size() == 1) { 316 +
315 - nsSegmentIds.add(-1);
316 - }
317 // Filter out SegmentIds matching with the 317 // Filter out SegmentIds matching with the
318 // nodes in the combo 318 // nodes in the combo
319 for (Integer sId : allSegmentIds) { 319 for (Integer sId : allSegmentIds) {
...@@ -405,7 +405,8 @@ public class DefaultGroupHandler { ...@@ -405,7 +405,8 @@ public class DefaultGroupHandler {
405 } 405 }
406 } 406 }
407 407
408 - protected GroupKey getGroupKey(Object obj) { 408 + public GroupKey getGroupKey(Object obj) {
409 return new DefaultGroupKey(kryo.build().serialize(obj)); 409 return new DefaultGroupKey(kryo.build().serialize(obj));
410 } 410 }
411 +
411 } 412 }
......
...@@ -90,6 +90,7 @@ public class DefaultGroupHandlerApp { ...@@ -90,6 +90,7 @@ public class DefaultGroupHandlerApp {
90 public void activate() { 90 public void activate() {
91 appId = coreService.registerApplication("org.onosproject.defaultgrouphandler"); 91 appId = coreService.registerApplication("org.onosproject.defaultgrouphandler");
92 log.info("DefaultGroupHandlerApp Activating"); 92 log.info("DefaultGroupHandlerApp Activating");
93 +
93 deviceService.addListener(deviceListener); 94 deviceService.addListener(deviceListener);
94 linkService.addListener(linkListener); 95 linkService.addListener(linkListener);
95 for (Device device: deviceService.getDevices()) { 96 for (Device device: deviceService.getDevices()) {
...@@ -111,6 +112,7 @@ public class DefaultGroupHandlerApp { ...@@ -111,6 +112,7 @@ public class DefaultGroupHandlerApp {
111 device.id()); 112 device.id());
112 } 113 }
113 } 114 }
115 +
114 log.info("Activated"); 116 log.info("Activated");
115 } 117 }
116 118
......
...@@ -138,7 +138,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { ...@@ -138,7 +138,8 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
138 Set<DeviceId> updatedNeighbors) { 138 Set<DeviceId> updatedNeighbors) {
139 Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors); 139 Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
140 140
141 - Set<DeviceId> tmp = updatedNeighbors; 141 + Set<DeviceId> tmp = new HashSet<DeviceId>();
142 + tmp.addAll(updatedNeighbors);
142 tmp.remove(impactedNeighbor); 143 tmp.remove(impactedNeighbor);
143 Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp); 144 Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
144 145
......
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
45 <module>reactive-routing</module> 45 <module>reactive-routing</module>
46 <module>bgprouter</module> 46 <module>bgprouter</module>
47 <module>test</module> 47 <module>test</module>
48 + <module>grouphandler</module>
49 + <module>segmentrouting</module>
48 </modules> 50 </modules>
49 51
50 <properties> 52 <properties>
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
17 + <modelVersion>4.0.0</modelVersion>
18 + <parent>
19 + <artifactId>onos-apps</artifactId>
20 + <groupId>org.onosproject</groupId>
21 + <version>1.2.0-SNAPSHOT</version>
22 + </parent>
23 +
24 + <artifactId>onos-app-segmentrouting</artifactId>
25 + <packaging>bundle</packaging>
26 +
27 + <description>ONOS OSGi bundle archetype</description>
28 + <url>http://onosproject.org</url>
29 +
30 + <dependencies>
31 + <dependency>
32 + <groupId>org.onosproject</groupId>
33 + <artifactId>onos-app-grouphandler</artifactId>
34 + <version>1.2.0-SNAPSHOT</version>
35 + </dependency>
36 + </dependencies>
37 +
38 +</project>
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.segmentrouting;
17 +
18 +import org.onlab.packet.ARP;
19 +import org.onlab.packet.Ethernet;
20 +import org.onlab.packet.Ip4Address;
21 +import org.onlab.packet.IpAddress;
22 +import org.onlab.packet.IpPrefix;
23 +import org.onlab.packet.MacAddress;
24 +import org.onosproject.net.ConnectPoint;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.Host;
27 +import org.onosproject.net.Port;
28 +import org.onosproject.net.PortNumber;
29 +import org.onosproject.net.flow.DefaultTrafficTreatment;
30 +import org.onosproject.net.flow.TrafficTreatment;
31 +import org.onosproject.net.packet.DefaultOutboundPacket;
32 +import org.onosproject.net.packet.InboundPacket;
33 +import org.onosproject.net.HostId;
34 +import org.onosproject.net.packet.OutboundPacket;
35 +import org.slf4j.Logger;
36 +import org.slf4j.LoggerFactory;
37 +
38 +import java.nio.ByteBuffer;
39 +
40 +import static com.google.common.base.Preconditions.checkNotNull;
41 +
42 +public class ArpHandler {
43 +
44 + private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
45 +
46 + private SegmentRoutingManager srManager;
47 + private NetworkConfigHandler config;
48 +
49 + /**
50 + * Creates an ArpHandler object.
51 + *
52 + * @param srManager SegmentRoutingManager object
53 + */
54 + public ArpHandler(SegmentRoutingManager srManager) {
55 + this.srManager = srManager;
56 + this.config = checkNotNull(srManager.networkConfigHandler);
57 + }
58 +
59 + /**
60 + * Processes incoming ARP packets.
61 + * If it is an ARP request to router itself or known hosts,
62 + * then it sends ARP response.
63 + * If it is an ARP request to unknown hosts in its own subnet,
64 + * then it flood the ARP request to the ports.
65 + * If it is an ARP response, then set a flow rule for the host
66 + * and forward any IP packets to the host in the packet buffer to the host.
67 + *
68 + * @param pkt incoming packet
69 + */
70 + public void processPacketIn(InboundPacket pkt) {
71 +
72 + Ethernet ethernet = pkt.parsed();
73 + ARP arp = (ARP) ethernet.getPayload();
74 +
75 + ConnectPoint connectPoint = pkt.receivedFrom();
76 + PortNumber inPort = connectPoint.port();
77 + DeviceId deviceId = connectPoint.deviceId();
78 + byte[] senderMacAddressByte = arp.getSenderHardwareAddress();
79 + Ip4Address hostIpAddress = Ip4Address.valueOf(arp.getSenderProtocolAddress());
80 +
81 + srManager.routingRulePopulator.populateIpRuleForHost(deviceId, hostIpAddress, MacAddress.
82 + valueOf(senderMacAddressByte), inPort);
83 +
84 + if (arp.getOpCode() == ARP.OP_REQUEST) {
85 + handleArpRequest(deviceId, connectPoint, ethernet);
86 + } else {
87 + srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
88 + }
89 + }
90 +
91 + private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
92 +
93 + ARP arpRequest = (ARP) payload.getPayload();
94 + HostId targetHostId = HostId.hostId(MacAddress.valueOf(
95 + arpRequest.getTargetHardwareAddress()));
96 +
97 + // ARP request for router
98 + if (isArpReqForRouter(deviceId, arpRequest)) {
99 + Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
100 + sendArpResponse(arpRequest, config.getRouterMac(targetAddress));
101 +
102 + // ARP request for known hosts
103 + } else if (srManager.hostService.getHost(targetHostId) != null) {
104 + MacAddress targetMac = srManager.hostService.getHost(targetHostId).mac();
105 + sendArpResponse(arpRequest, targetMac);
106 +
107 + // ARP request for unknown host in the subnet
108 + } else if (isArpReqForSubnet(deviceId, arpRequest)) {
109 + flood(payload, inPort);
110 + }
111 + }
112 +
113 +
114 + private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) {
115 + Ip4Address gatewayIpAddress = config.getGatewayIpAddress(deviceId);
116 + if (gatewayIpAddress != null) {
117 + Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest
118 + .getTargetProtocolAddress());
119 + if (gatewayIpAddress.equals(targetProtocolAddress)) {
120 + return true;
121 + }
122 + }
123 + return false;
124 + }
125 +
126 + private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) {
127 + String subnetInfo = config.getSubnetInfo(deviceId);
128 + if (subnetInfo != null) {
129 + IpPrefix prefix = IpPrefix.valueOf(subnetInfo);
130 + if (prefix.contains(Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()))) {
131 + return true;
132 + }
133 + }
134 +
135 + return false;
136 + }
137 +
138 + /**
139 + * Sends an APR request for the target IP address to all ports except in-port.
140 + *
141 + * @param deviceId Switch device ID
142 + * @param targetAddress target IP address for ARP
143 + * @param inPort in-port
144 + */
145 + public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
146 +
147 + byte[] senderMacAddress = config.getRouterMacAddress(deviceId).toBytes();
148 + byte[] senderIpAddress = config.getRouterIpAddress(deviceId)
149 + .getIp4Prefix().address().toOctets();
150 +
151 + ARP arpRequest = new ARP();
152 + arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
153 + .setProtocolType(ARP.PROTO_TYPE_IP)
154 + .setHardwareAddressLength(
155 + (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
156 + .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
157 + .setOpCode(ARP.OP_REQUEST)
158 + .setSenderHardwareAddress(senderMacAddress)
159 + .setTargetHardwareAddress(MacAddress.ZERO.toBytes())
160 + .setSenderProtocolAddress(senderIpAddress)
161 + .setTargetProtocolAddress(targetAddress.toOctets());
162 +
163 + Ethernet eth = new Ethernet();
164 + eth.setDestinationMACAddress(MacAddress.BROADCAST.toBytes())
165 + .setSourceMACAddress(senderMacAddress)
166 + .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);
167 +
168 + flood(eth, inPort);
169 + }
170 +
171 + private void sendArpResponse(ARP arpRequest, MacAddress targetMac) {
172 +
173 + ARP arpReply = new ARP();
174 + arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
175 + .setProtocolType(ARP.PROTO_TYPE_IP)
176 + .setHardwareAddressLength(
177 + (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
178 + .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
179 + .setOpCode(ARP.OP_REPLY)
180 + .setSenderHardwareAddress(targetMac.toBytes())
181 + .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
182 + .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
183 + .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
184 +
185 + Ethernet eth = new Ethernet();
186 + eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
187 + .setSourceMACAddress(targetMac.toBytes())
188 + .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
189 +
190 +
191 + HostId dstId = HostId.hostId(MacAddress.valueOf(
192 + arpReply.getTargetHardwareAddress()));
193 + Host dst = srManager.hostService.getHost(dstId);
194 + if (dst == null) {
195 + log.warn("Cannot send ARP response to unknown device");
196 + return;
197 + }
198 +
199 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().
200 + setOutput(dst.location().port()).build();
201 + OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
202 + treatment, ByteBuffer.wrap(eth.serialize()));
203 +
204 + srManager.packetService.emit(packet);
205 + }
206 +
207 + private void flood(Ethernet request, ConnectPoint inPort) {
208 + TrafficTreatment.Builder builder;
209 + ByteBuffer buf = ByteBuffer.wrap(request.serialize());
210 +
211 + for (Port port: srManager.deviceService.getPorts(inPort.deviceId())) {
212 + if (!port.number().equals(inPort.port()) &&
213 + port.number().toLong() > 0) {
214 + builder = DefaultTrafficTreatment.builder();
215 + builder.setOutput(port.number());
216 + srManager.packetService.emit(new DefaultOutboundPacket(inPort.deviceId(),
217 + builder.build(), buf));
218 + }
219 + }
220 + }
221 +
222 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.segmentrouting;
17 +
18 +import org.onlab.packet.IpPrefix;
19 +import org.onosproject.net.Device;
20 +import org.onosproject.net.DeviceId;
21 +import org.onosproject.net.MastershipRole;
22 +import org.onosproject.net.flow.FlowRule;
23 +import org.slf4j.Logger;
24 +import org.slf4j.LoggerFactory;
25 +
26 +import java.util.ArrayList;
27 +import java.util.HashMap;
28 +import java.util.HashSet;
29 +import java.util.Set;
30 +
31 +import static com.google.common.base.Preconditions.checkNotNull;
32 +
33 +public class DefaultRoutingHandler {
34 +
35 + private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class);
36 +
37 + private SegmentRoutingManager srManager;
38 + private RoutingRulePopulator rulePopulator;
39 + private NetworkConfigHandler config;
40 + private Status populationStatus;
41 +
42 + /**
43 + * Represents the default routing population status.
44 + */
45 + public enum Status {
46 + // population process is not started yet.
47 + IDLE,
48 +
49 + // population process started.
50 + STARTED,
51 +
52 + // population process was aborted due to errors, mostly for groups not found.
53 + ABORTED,
54 +
55 + // population process was finished successfully.
56 + SUCCEEDED
57 + }
58 +
59 + /**
60 + * Creates a DefaultRoutingHandler object.
61 + *
62 + * @param srManager SegmentRoutingManager object
63 + */
64 + public DefaultRoutingHandler(SegmentRoutingManager srManager) {
65 + this.srManager = srManager;
66 + this.rulePopulator = checkNotNull(srManager.routingRulePopulator);
67 + this.config = checkNotNull(srManager.networkConfigHandler);
68 + this.populationStatus = Status.IDLE;
69 + }
70 +
71 + /**
72 + * Populates all routing rules to all connected routers, including default
73 + * routing rules, adjacency rules, and policy rules if any.
74 + *
75 + * @return true if it succeeds in populating all rules, otherwise false
76 + */
77 + public boolean populateAllRoutingRules() {
78 +
79 + populationStatus = Status.STARTED;
80 + log.info("Starts to populate routing rules");
81 +
82 + for (Device sw : srManager.deviceService.getDevices()) {
83 + if (srManager.mastershipService.
84 + getLocalRole(sw.id()) != MastershipRole.MASTER) {
85 + continue;
86 + }
87 +
88 + ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw.id(), srManager);
89 + if (!populateEcmpRoutingRules(sw, ecmpSPG)) {
90 + populationStatus = Status.ABORTED;
91 + log.debug("Abort routing rule population");
92 + return false;
93 + }
94 +
95 + // TODO: Set adjacency routing rule for all switches
96 + }
97 +
98 + populationStatus = Status.SUCCEEDED;
99 + log.info("Completes routing rule population");
100 + return true;
101 + }
102 +
103 + private boolean populateEcmpRoutingRules(Device sw,
104 + ECMPShortestPathGraph ecmpSPG) {
105 +
106 + HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
107 + ecmpSPG.getAllLearnedSwitchesAndVia();
108 + for (Integer itrIdx : switchVia.keySet()) {
109 + HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
110 + switchVia.get(itrIdx);
111 + for (DeviceId targetSw : swViaMap.keySet()) {
112 + DeviceId destSw = sw.id();
113 + Set<DeviceId> nextHops = new HashSet<>();
114 +
115 + for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
116 + if (via.isEmpty()) {
117 + nextHops.add(destSw);
118 + } else {
119 + nextHops.add(via.get(0));
120 + }
121 + }
122 + if (!populateEcmpRoutingRulePartial(targetSw, destSw, nextHops)) {
123 + return false;
124 + }
125 + }
126 + }
127 +
128 + return true;
129 + }
130 +
131 + private boolean populateEcmpRoutingRulePartial(DeviceId targetSw, DeviceId destSw,
132 + Set<DeviceId> nextHops) {
133 + boolean result;
134 +
135 + if (nextHops.isEmpty()) {
136 + nextHops.add(destSw);
137 + }
138 +
139 + // If both target switch and dest switch are edge routers, then set IP rule
140 + // for both subnet and router IP.
141 + if (config.isEdgeRouter(targetSw) && config.isEdgeRouter(destSw)) {
142 + String subnets = config.getSubnetInfo(destSw);
143 + result = rulePopulator.populateIpRuleForSubnet(targetSw, subnets, destSw, nextHops);
144 + if (!result) {
145 + return false;
146 + }
147 +
148 + IpPrefix routerIp = config.getRouterIpAddress(destSw);
149 + result = rulePopulator.populateIpRuleForRouter(targetSw, routerIp, destSw, nextHops);
150 + if (!result) {
151 + return false;
152 + }
153 +
154 + // If the target switch is an edge router, then set IP rules for the router IP.
155 + } else if (config.isEdgeRouter(targetSw)) {
156 + IpPrefix routerIp = config.getRouterIpAddress(destSw);
157 + result = rulePopulator.populateIpRuleForRouter(targetSw, routerIp, destSw, nextHops);
158 + if (!result) {
159 + return false;
160 + }
161 +
162 + // If the target switch is an transit router, then set MPLS rules only.
163 + } else if (config.isTransitRouter(targetSw)) {
164 + result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops);
165 + if (!result) {
166 + return false;
167 + }
168 + } else {
169 + log.warn("The switch {} is neither an edge router nor a transit router.", targetSw);
170 + return false;
171 + }
172 +
173 + return true;
174 + }
175 +
176 + /**
177 + * Populates table miss entries for all tables, and pipeline rules for
178 + * VLAN and TACM tables.
179 + *
180 + * @param deviceId Switch ID to set the rules
181 + */
182 + public void populateTtpRules(DeviceId deviceId) {
183 +
184 + rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.VLAN,
185 + true, false, false, FlowRule.Type.DEFAULT);
186 + rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.ETHER,
187 + true, false, false, FlowRule.Type.DEFAULT);
188 + rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.IP,
189 + false, true, true, FlowRule.Type.ACL);
190 + rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.MPLS,
191 + false, true, true, FlowRule.Type.ACL);
192 + rulePopulator.populateTableMissEntry(deviceId, FlowRule.Type.ACL,
193 + false, false, false, FlowRule.Type.DEFAULT);
194 +
195 + rulePopulator.populateTableVlan(deviceId);
196 + rulePopulator.populateTableTMac(deviceId);
197 + }
198 +
199 + /**
200 + * Start the flow rule population process if it was never started.
201 + * The process finishes successfully when all flow rules are set and
202 + * stops with ABORTED status when any groups required for flows is not
203 + * set yet.
204 + */
205 + public void startPopulationProcess() {
206 + synchronized (populationStatus) {
207 + if (populationStatus == Status.IDLE ||
208 + populationStatus == Status.SUCCEEDED) {
209 + populationStatus = Status.STARTED;
210 + populateAllRoutingRules();
211 + }
212 + }
213 + }
214 +
215 + /**
216 + * Resume the flow rule population process if it was aborted for any reason.
217 + * Mostly the process is aborted when the groups required are not set yet.
218 + */
219 + public void resumePopulationProcess() {
220 + synchronized (populationStatus) {
221 + if (populationStatus == Status.ABORTED) {
222 + populationStatus = Status.STARTED;
223 + // TODO: we need to restart from the point aborted instead of restarting.
224 + populateAllRoutingRules();
225 + }
226 + }
227 + }
228 +}
1 +package org.onosproject.segmentrouting;
2 +
3 +import org.onlab.packet.Ip4Address;
4 +import org.onlab.packet.MacAddress;
5 +import org.onosproject.grouphandler.DeviceProperties;
6 +import org.onosproject.net.DeviceId;
7 +import org.slf4j.Logger;
8 +import org.slf4j.LoggerFactory;
9 +
10 +import java.util.Arrays;
11 +import java.util.HashMap;
12 +import java.util.List;
13 +import java.util.Map;
14 +
15 +public class DeviceConfiguration implements DeviceProperties {
16 +
17 + private static final Logger log = LoggerFactory
18 + .getLogger(DeviceConfiguration.class);
19 + private final List<Integer> allSegmentIds =
20 + Arrays.asList(101, 102, 103, 104, 105, 106);
21 + private HashMap<DeviceId, Integer> deviceSegmentIdMap =
22 + new HashMap<DeviceId, Integer>() {
23 + {
24 + put(DeviceId.deviceId("of:0000000000000001"), 101);
25 + put(DeviceId.deviceId("of:0000000000000002"), 102);
26 + put(DeviceId.deviceId("of:0000000000000003"), 103);
27 + put(DeviceId.deviceId("of:0000000000000004"), 104);
28 + put(DeviceId.deviceId("of:0000000000000005"), 105);
29 + put(DeviceId.deviceId("of:0000000000000006"), 106);
30 + }
31 + };
32 + private final HashMap<DeviceId, MacAddress> deviceMacMap =
33 + new HashMap<DeviceId, MacAddress>() {
34 + {
35 + put(DeviceId.deviceId("of:0000000000000001"),
36 + MacAddress.valueOf("00:00:00:00:00:01"));
37 + put(DeviceId.deviceId("of:0000000000000002"),
38 + MacAddress.valueOf("00:00:00:00:00:02"));
39 + put(DeviceId.deviceId("of:0000000000000003"),
40 + MacAddress.valueOf("00:00:00:00:00:03"));
41 + put(DeviceId.deviceId("of:0000000000000004"),
42 + MacAddress.valueOf("00:00:00:00:00:04"));
43 + put(DeviceId.deviceId("of:0000000000000005"),
44 + MacAddress.valueOf("00:00:00:00:00:05"));
45 + put(DeviceId.deviceId("of:0000000000000006"),
46 + MacAddress.valueOf("00:00:00:00:00:06"));
47 + }
48 + };
49 +
50 + private final HashMap<DeviceId, Ip4Address> deviceIpMap =
51 + new HashMap<DeviceId, Ip4Address>() {
52 + {
53 + put(DeviceId.deviceId("of:0000000000000001"),
54 + Ip4Address.valueOf("192.168.0.1"));
55 + put(DeviceId.deviceId("of:0000000000000002"),
56 + Ip4Address.valueOf("192.168.0.2"));
57 + put(DeviceId.deviceId("of:0000000000000003"),
58 + Ip4Address.valueOf("192.168.0.3"));
59 + put(DeviceId.deviceId("of:0000000000000004"),
60 + Ip4Address.valueOf("192.168.0.4"));
61 + put(DeviceId.deviceId("of:0000000000000005"),
62 + Ip4Address.valueOf("192.168.0.5"));
63 + put(DeviceId.deviceId("of:0000000000000006"),
64 + Ip4Address.valueOf("192.168.0.6"));
65 + }
66 + };
67 +
68 + @Override
69 + public int getSegmentId(DeviceId deviceId) {
70 + if (deviceSegmentIdMap.get(deviceId) != null) {
71 + log.debug("getSegmentId for device{} is {}",
72 + deviceId,
73 + deviceSegmentIdMap.get(deviceId));
74 + return deviceSegmentIdMap.get(deviceId);
75 + } else {
76 + throw new IllegalStateException();
77 + }
78 + }
79 +
80 +
81 + @Override
82 + public MacAddress getDeviceMac(DeviceId deviceId) {
83 + if (deviceMacMap.get(deviceId) != null) {
84 + log.debug("getDeviceMac for device{} is {}",
85 + deviceId,
86 + deviceMacMap.get(deviceId));
87 + return deviceMacMap.get(deviceId);
88 + } else {
89 + throw new IllegalStateException();
90 + }
91 + }
92 +
93 +
94 + @Override
95 + public boolean isEdgeDevice(DeviceId deviceId) {
96 + if (deviceId.equals(DeviceId.deviceId("of:0000000000000001"))
97 + || deviceId.equals(DeviceId.deviceId("of:0000000000000006"))) {
98 + return true;
99 + }
100 +
101 + return false;
102 + }
103 +
104 + @Override
105 + public List<Integer> getAllDeviceSegmentIds() {
106 + return allSegmentIds;
107 + }
108 +
109 +
110 + /**
111 + * Returns Segment ID for the router with the MAC address given.
112 + *
113 + * @param targetMac Mac address for the router
114 + * @return Segment ID for the router with the MAC address
115 + */
116 + public int getSegmentId(MacAddress targetMac) {
117 + for (Map.Entry<DeviceId, MacAddress> entry: deviceMacMap.entrySet()) {
118 + if (entry.getValue().equals(targetMac)) {
119 + return deviceSegmentIdMap.get(entry.getKey());
120 + }
121 + }
122 +
123 + return -1;
124 + }
125 +
126 + /**
127 + * Returns Segment ID for the router withe IP address given.
128 + *
129 + * @param targetAddress IP address of the router
130 + * @return Segment ID for the router with the IP address
131 + */
132 + public int getSegmentId(Ip4Address targetAddress) {
133 + for (Map.Entry<DeviceId, Ip4Address> entry: deviceIpMap.entrySet()) {
134 + if (entry.getValue().equals(targetAddress)) {
135 + return deviceSegmentIdMap.get(entry.getKey());
136 + }
137 + }
138 +
139 + return -1;
140 + }
141 +
142 + /**
143 + * Returns Router IP address for the router with the device ID given.
144 + *
145 + * @param deviceId device ID of the router
146 + * @return IP address of the router
147 + */
148 + public Ip4Address getRouterIp(DeviceId deviceId) {
149 + if (deviceIpMap.get(deviceId) != null) {
150 + log.debug("getDeviceIp for device{} is {}",
151 + deviceId,
152 + deviceIpMap.get(deviceId));
153 + return deviceIpMap.get(deviceId);
154 + } else {
155 + throw new IllegalStateException();
156 + }
157 + }
158 +
159 + /**
160 + * Returns the Device ID of the router with the Segment ID given.
161 + *
162 + * @param sid Segment ID of the router
163 + * @return Device ID of the router
164 + */
165 + public DeviceId getDeviceId(int sid) {
166 + for (Map.Entry<DeviceId, Integer> entry: deviceSegmentIdMap.entrySet()) {
167 + if (entry.getValue() == sid) {
168 + return entry.getKey();
169 + }
170 + }
171 +
172 + return null;
173 + }
174 +
175 + /**
176 + * Returns the Device ID of the router with the IP address given.
177 + *
178 + * @param ipAddress IP address of the router
179 + * @return Device ID of the router
180 + */
181 + public DeviceId getDeviceId(Ip4Address ipAddress) {
182 + for (Map.Entry<DeviceId, Ip4Address> entry: deviceIpMap.entrySet()) {
183 + if (entry.getValue().equals(ipAddress)) {
184 + return entry.getKey();
185 + }
186 + }
187 +
188 + return null;
189 + }
190 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.segmentrouting;
17 +
18 +import java.nio.ByteBuffer;
19 +
20 +import org.onlab.packet.Ethernet;
21 +import org.onlab.packet.ICMP;
22 +import org.onlab.packet.IPv4;
23 +import org.onlab.packet.Ip4Address;
24 +import org.onlab.packet.IpPrefix;
25 +import org.onlab.packet.MPLS;
26 +import org.onosproject.net.ConnectPoint;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.flow.DefaultTrafficTreatment;
29 +import org.onosproject.net.flow.TrafficTreatment;
30 +import org.onosproject.net.packet.DefaultOutboundPacket;
31 +import org.onosproject.net.packet.InboundPacket;
32 +import org.onosproject.net.packet.OutboundPacket;
33 +import org.slf4j.Logger;
34 +import org.slf4j.LoggerFactory;
35 +
36 +import static com.google.common.base.Preconditions.checkNotNull;
37 +
38 +public class IcmpHandler {
39 +
40 + private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
41 + private SegmentRoutingManager srManager;
42 + private NetworkConfigHandler config;
43 +
44 + /**
45 + * Creates an IcmpHandler object.
46 + *
47 + * @param srManager SegmentRoutingManager object
48 + */
49 + public IcmpHandler(SegmentRoutingManager srManager) {
50 + this.srManager = srManager;
51 + this.config = checkNotNull(srManager.networkConfigHandler);
52 + }
53 +
54 + /**
55 + * Process incoming ICMP packet.
56 + * If it is an ICMP request to router or known host, then sends an ICMP response.
57 + * If it is an ICMP packet to known host and forward the packet to the host.
58 + * If it is an ICMP packet to unknown host in a subnet, then sends an ARP request
59 + * to the subnet.
60 + *
61 + * @param pkt
62 + */
63 + public void processPacketIn(InboundPacket pkt) {
64 +
65 + Ethernet ethernet = pkt.parsed();
66 + IPv4 ipv4 = (IPv4) ethernet.getPayload();
67 +
68 + ConnectPoint connectPoint = pkt.receivedFrom();
69 + DeviceId deviceId = connectPoint.deviceId();
70 + Ip4Address destinationAddress =
71 + Ip4Address.valueOf(ipv4.getDestinationAddress());
72 + Ip4Address gatewayIpAddress = config.getGatewayIpAddress(deviceId);
73 + IpPrefix routerIpPrefix = config.getRouterIpAddress(deviceId);
74 + Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address();
75 +
76 + // ICMP to the router IP or gateway IP
77 + if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST &&
78 + (destinationAddress.equals(routerIpAddress) ||
79 + gatewayIpAddress.equals(destinationAddress))) {
80 + sendICMPResponse(ethernet, connectPoint);
81 + // TODO: do we need to set the flow rule again ??
82 +
83 + // ICMP for any known host
84 + } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
85 + srManager.ipHandler.forwardPackets(deviceId, destinationAddress);
86 +
87 + // ICMP for an unknown host in the subnet of the router
88 + } else if (config.inSameSubnet(deviceId, destinationAddress)) {
89 + srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint);
90 +
91 + // ICMP for an unknown host
92 + } else {
93 + log.debug("ICMP request for unknown host {} ", destinationAddress);
94 + // Do nothing
95 + }
96 + }
97 +
98 + private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) {
99 +
100 + Ethernet icmpReplyEth = new Ethernet();
101 +
102 + IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
103 + IPv4 icmpReplyIpv4 = new IPv4();
104 +
105 + int destAddress = icmpRequestIpv4.getDestinationAddress();
106 + icmpReplyIpv4.setDestinationAddress(icmpRequestIpv4.getSourceAddress());
107 + icmpReplyIpv4.setSourceAddress(destAddress);
108 + icmpReplyIpv4.setTtl((byte) 64);
109 + icmpReplyIpv4.setChecksum((short) 0);
110 +
111 + ICMP icmpReply = (ICMP) icmpRequestIpv4.getPayload().clone();
112 + icmpReply.setIcmpType(ICMP.TYPE_ECHO_REPLY);
113 + icmpReply.setIcmpCode(ICMP.SUBTYPE_ECHO_REPLY);
114 + icmpReply.setChecksum((short) 0);
115 +
116 + icmpReplyIpv4.setPayload(icmpReply);
117 +
118 + icmpReplyEth.setPayload(icmpReplyIpv4);
119 + icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4);
120 + icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress());
121 + icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress());
122 + icmpReplyEth.setVlanID(icmpRequest.getVlanID());
123 +
124 + Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress());
125 + Ip4Address destRouterAddress = config.getDestinationRouterAddress(destIpAddress);
126 + int sid = config.getMplsId(destRouterAddress);
127 + if (sid < 0) {
128 + log.warn("Cannot find the Segment ID for {}", destAddress);
129 + return;
130 + }
131 +
132 + sendPacketOut(outport, icmpReplyEth, sid);
133 +
134 + }
135 +
136 + private void sendPacketOut(ConnectPoint outport, Ethernet payload, int sid) {
137 +
138 + IPv4 ipPacket = (IPv4) payload.getPayload();
139 + Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
140 +
141 + if (sid == -1 || config.getMplsId(payload.getDestinationMAC()) == sid ||
142 + config.inSameSubnet(outport.deviceId(), destIpAddress)) {
143 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().
144 + setOutput(outport.port()).build();
145 + OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
146 + treatment, ByteBuffer.wrap(payload.serialize()));
147 + srManager.packetService.emit(packet);
148 + } else {
149 + log.warn("Send a MPLS packet as a ICMP response");
150 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
151 + .setOutput(outport.port())
152 + .build();
153 +
154 + payload.setEtherType(Ethernet.MPLS_UNICAST);
155 + MPLS mplsPkt = new MPLS();
156 + mplsPkt.setLabel(sid);
157 + mplsPkt.setTtl(((IPv4) payload.getPayload()).getTtl());
158 + mplsPkt.setPayload(payload.getPayload());
159 + payload.setPayload(mplsPkt);
160 +
161 + OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
162 + treatment, ByteBuffer.wrap(payload.serialize()));
163 +
164 + srManager.packetService.emit(packet);
165 + }
166 + }
167 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.segmentrouting;
17 +
18 +import org.onlab.packet.Ethernet;
19 +import org.onlab.packet.IPv4;
20 +import org.onlab.packet.Ip4Address;
21 +import org.onosproject.net.ConnectPoint;
22 +import org.onosproject.net.DeviceId;
23 +import org.onosproject.net.Host;
24 +import org.onosproject.net.flow.DefaultTrafficTreatment;
25 +import org.onosproject.net.flow.TrafficTreatment;
26 +import org.onosproject.net.packet.DefaultOutboundPacket;
27 +import org.onosproject.net.packet.InboundPacket;
28 +import org.onosproject.net.packet.OutboundPacket;
29 +import org.slf4j.Logger;
30 +import org.slf4j.LoggerFactory;
31 +
32 +import java.nio.ByteBuffer;
33 +import java.util.concurrent.ConcurrentHashMap;
34 +import java.util.concurrent.ConcurrentLinkedQueue;
35 +
36 +import static com.google.common.base.Preconditions.checkNotNull;
37 +
38 +public class IpHandler {
39 +
40 + private static Logger log = LoggerFactory.getLogger(IpHandler.class);
41 + private SegmentRoutingManager srManager;
42 + private NetworkConfigHandler config;
43 + private ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>> ipPacketQueue;
44 +
45 + /**
46 + * Creates an IpHandler object.
47 + *
48 + * @param srManager SegmentRoutingManager object
49 + */
50 + public IpHandler(SegmentRoutingManager srManager) {
51 + this.srManager = srManager;
52 + this.config = checkNotNull(srManager.networkConfigHandler);
53 + ipPacketQueue = new ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>>();
54 + }
55 +
56 + /**
57 + * Processes incoming IP packets.
58 + *
59 + * If it is an IP packet for known host, then forward it to the host.
60 + * If it is an IP packet for unknown host in subnet, then send an ARP request
61 + * to the subnet.
62 + *
63 + * @param pkt incoming packet
64 + */
65 + public void processPacketIn(InboundPacket pkt) {
66 + Ethernet ethernet = pkt.parsed();
67 + IPv4 ipv4 = (IPv4) ethernet.getPayload();
68 +
69 + ConnectPoint connectPoint = pkt.receivedFrom();
70 + DeviceId deviceId = connectPoint.deviceId();
71 + Ip4Address destinationAddress =
72 + Ip4Address.valueOf(ipv4.getDestinationAddress());
73 +
74 + // IP packet for know hosts
75 + if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
76 + forwardPackets(deviceId, destinationAddress);
77 +
78 + // IP packet for unknown host in the subnet of the router
79 + } else if (config.inSameSubnet(deviceId, destinationAddress)) {
80 + srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint);
81 +
82 + // IP packets for unknown host
83 + } else {
84 + log.debug("ICMP request for unknown host {} which is not in the subnet",
85 + destinationAddress);
86 + // Do nothing
87 + }
88 + }
89 +
90 + /**
91 + * Adds the IP packet to a buffer.
92 + * The packets are forwarded to corresponding destination when the destination
93 + * MAC address is known via ARP response.
94 + *
95 + * @param ipPacket IP packet to add to the buffer
96 + */
97 + public void addToPacketBuffer(IPv4 ipPacket) {
98 +
99 + // Better not buffer TPC packets due to out-of-order packet transfer
100 + if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) {
101 + return;
102 + }
103 +
104 + Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
105 +
106 + if (ipPacketQueue.get(destIpAddress) == null) {
107 + ConcurrentLinkedQueue<IPv4> queue = new ConcurrentLinkedQueue<IPv4>();
108 + queue.add(ipPacket);
109 + ipPacketQueue.put(destIpAddress, queue);
110 + } else {
111 + ipPacketQueue.get(destIpAddress).add(ipPacket);
112 + }
113 + }
114 +
115 + /**
116 + * Forwards IP packets in the buffer to the destination IP address.
117 + * It is called when the controller finds the destination MAC address
118 + * via ARP responsees.
119 + *
120 + * @param deviceId switch device ID
121 + * @param destIpAddress destination IP address
122 + */
123 + public void forwardPackets(DeviceId deviceId, Ip4Address destIpAddress) {
124 + for (IPv4 ipPacket : ipPacketQueue.get(destIpAddress)) {
125 + Ip4Address destAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
126 + if (ipPacket != null && config.inSameSubnet(deviceId, destAddress)) {
127 + ipPacket.setTtl((byte) (ipPacket.getTtl() - 1));
128 + ipPacket.setChecksum((short) 0);
129 + for (Host dest: srManager.hostService.getHostsByIp(destIpAddress)) {
130 + Ethernet eth = new Ethernet();
131 + eth.setDestinationMACAddress(dest.mac());
132 + eth.setSourceMACAddress(config.getRouterMacAddress(
133 + deviceId));
134 + eth.setEtherType(Ethernet.TYPE_IPV4);
135 + eth.setPayload(ipPacket);
136 +
137 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().
138 + setOutput(dest.location().port()).build();
139 + OutboundPacket packet = new DefaultOutboundPacket(deviceId,
140 + treatment, ByteBuffer.wrap(eth.serialize()));
141 + srManager.packetService.emit(packet);
142 + }
143 + }
144 + }
145 + }
146 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.segmentrouting;
17 +
18 +import com.google.common.collect.Lists;
19 +import org.onlab.packet.Ip4Address;
20 +import org.onlab.packet.Ip4Prefix;
21 +import org.onlab.packet.IpPrefix;
22 +import org.onlab.packet.MacAddress;
23 +import org.onosproject.net.DeviceId;
24 +import org.onosproject.net.Link;
25 +import org.onosproject.net.PortNumber;
26 +import org.slf4j.Logger;
27 +import org.slf4j.LoggerFactory;
28 +
29 +import java.net.URI;
30 +import java.util.List;
31 +import java.util.Set;
32 +
33 +/**
34 + * This class is temporary class and used only for test.
35 + * It will be replaced with "real" Network Config Manager.
36 + */
37 +
38 +public class NetworkConfigHandler {
39 +
40 + private static Logger log = LoggerFactory.getLogger(NetworkConfigHandler.class);
41 + private SegmentRoutingManager srManager;
42 + private DeviceConfiguration deviceConfig = new DeviceConfiguration();
43 +
44 + public NetworkConfigHandler(SegmentRoutingManager srManager) {
45 + this.srManager = srManager;
46 + }
47 +
48 + public Ip4Address getGatewayIpAddress(DeviceId deviceId) {
49 +
50 + if (deviceId.uri().equals(URI.create("of:0000000000000001"))) {
51 + return Ip4Address.valueOf("10.0.1.128");
52 + } else if (deviceId.uri().equals(URI.create("of:0000000000000006"))) {
53 + return Ip4Address.valueOf("7.7.7.128");
54 + }
55 +
56 + log.warn("No gateway Ip address was found for {}", deviceId);
57 + return Ip4Address.valueOf("0.0.0.0");
58 + }
59 +
60 + public IpPrefix getRouterIpAddress(DeviceId deviceId) {
61 +
62 + return IpPrefix.valueOf(deviceConfig.getRouterIp(deviceId), 32);
63 + }
64 +
65 + public MacAddress getRouterMacAddress(DeviceId deviceId) {
66 + return deviceConfig.getDeviceMac(deviceId);
67 + }
68 +
69 + public boolean inSameSubnet(DeviceId deviceId, Ip4Address destIp) {
70 +
71 + String subnetInfo = getSubnetInfo(deviceId);
72 + if (subnetInfo == null) {
73 + return false;
74 + }
75 +
76 + IpPrefix prefix = IpPrefix.valueOf(subnetInfo);
77 + if (prefix.contains(destIp)) {
78 + return true;
79 + }
80 +
81 + return false;
82 + }
83 +
84 + public boolean inSameSubnet(Ip4Address address, int sid) {
85 + DeviceId deviceId = deviceConfig.getDeviceId(sid);
86 + if (deviceId == null) {
87 + log.warn("Cannot find a device for SID {}", sid);
88 + return false;
89 + }
90 +
91 + String subnetInfo = getSubnetInfo(deviceId);
92 + if (subnetInfo == null) {
93 + log.warn("Cannot find the subnet info for {}", deviceId);
94 + return false;
95 + }
96 +
97 + Ip4Prefix subnet = Ip4Prefix.valueOf(subnetInfo);
98 + if (subnet.contains(address)) {
99 + return true;
100 + }
101 +
102 + return false;
103 +
104 + }
105 +
106 + public String getSubnetInfo(DeviceId deviceId) {
107 + // TODO : supports multiple subnet
108 + if (deviceId.uri().equals(URI.create("of:0000000000000001"))) {
109 + return "10.0.1.1/24";
110 + } else if (deviceId.uri().equals(URI.create("of:0000000000000006"))) {
111 + return "7.7.7.7/24";
112 + } else {
113 + log.error("Switch {} is not an edge router", deviceId);
114 + return null;
115 + }
116 + }
117 +
118 + public int getMplsId(DeviceId deviceId) {
119 + return deviceConfig.getSegmentId(deviceId);
120 + }
121 +
122 + public int getMplsId(MacAddress mac) {
123 + return deviceConfig.getSegmentId(mac);
124 + }
125 +
126 + public int getMplsId(Ip4Address address) {
127 + return deviceConfig.getSegmentId(address);
128 + }
129 +
130 + public boolean isEcmpNotSupportedInTransit(DeviceId deviceId) {
131 + return false;
132 + }
133 +
134 + public boolean isTransitRouter(DeviceId deviceId) {
135 + return true;
136 + }
137 +
138 +
139 + public boolean isEdgeRouter(DeviceId deviceId) {
140 + if (deviceId.uri().equals(URI.create("of:0000000000000001"))
141 + || deviceId.uri().equals(URI.create("of:0000000000000006"))) {
142 + return true;
143 + }
144 +
145 + return false;
146 + }
147 +
148 + private List<PortNumber> getPortsToNeighbors(DeviceId deviceId, List<DeviceId> fwdSws) {
149 +
150 + List<PortNumber> portNumbers = Lists.newArrayList();
151 +
152 + Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId);
153 + for (Link link: links) {
154 + for (DeviceId swId: fwdSws) {
155 + if (link.dst().deviceId().equals(swId)) {
156 + portNumbers.add(link.src().port());
157 + break;
158 + }
159 + }
160 + }
161 +
162 + return portNumbers;
163 + }
164 +
165 + public List<PortNumber> getPortsToDevice(DeviceId deviceId) {
166 + List<PortNumber> portNumbers = Lists.newArrayList();
167 +
168 + Set<Link> links = srManager.linkService.getDeviceEgressLinks(deviceId);
169 + for (Link link: links) {
170 + if (link.dst().deviceId().equals(deviceId)) {
171 + portNumbers.add(link.src().port());
172 + }
173 + }
174 +
175 + return portNumbers;
176 + }
177 +
178 +
179 + public Ip4Address getDestinationRouterAddress(Ip4Address destIpAddress) {
180 + // TODO: need to check the subnet info
181 + if (destIpAddress.toString().equals("10.0.1.1")) {
182 + return Ip4Address.valueOf("192.168.0.1");
183 + } else if (destIpAddress.toString().equals("7.7.7.7")) {
184 + return Ip4Address.valueOf("192.168.0.6");
185 + } else {
186 + log.warn("No router was found for {}", destIpAddress);
187 + return null;
188 + }
189 +
190 + }
191 +
192 + public DeviceId getDeviceId(Ip4Address ip4Address) {
193 + return deviceConfig.getDeviceId(ip4Address);
194 + }
195 +
196 + public MacAddress getRouterMac(Ip4Address targetAddress) {
197 + if (targetAddress.toString().equals("10.0.1.128")) {
198 + return MacAddress.valueOf("00:00:00:00:00:01");
199 + } else if (targetAddress.toString().equals("7.7.7.128")) {
200 + return MacAddress.valueOf("00:00:00:00:00:06");
201 + } else {
202 + log.warn("Cannot find a router for {}", targetAddress);
203 + return null;
204 + }
205 + }
206 +}
...@@ -345,7 +345,8 @@ public final class KryoNamespaces { ...@@ -345,7 +345,8 @@ public final class KryoNamespaces {
345 MplsLabelResourceAllocation.class, 345 MplsLabelResourceAllocation.class,
346 MplsLabelResourceRequest.class, 346 MplsLabelResourceRequest.class,
347 MplsLabel.class, 347 MplsLabel.class,
348 - org.onlab.packet.MplsLabel.class 348 + org.onlab.packet.MplsLabel.class,
349 + org.onlab.packet.MPLS.class
349 ) 350 )
350 351
351 .build(); 352 .build();
......
...@@ -285,4 +285,18 @@ ...@@ -285,4 +285,18 @@
285 <bundle>mvn:org.onosproject/onos-app-calendar/@ONOS-VERSION</bundle> 285 <bundle>mvn:org.onosproject/onos-app-calendar/@ONOS-VERSION</bundle>
286 </feature> 286 </feature>
287 287
288 + <feature name="onos-app-grouphandler" version="@FEATURE-VERSION"
289 + description="Group Handler Sample App">
290 + <feature>onos-api</feature>
291 + <bundle>mvn:org.onosproject/onos-app-grouphandler/@ONOS-VERSION</bundle>
292 + </feature>
293 +
294 + <feature name="onos-app-segmentrouting" version="@FEATURE-VERSION"
295 + description="Segment routing application">
296 + <feature>onos-api</feature>
297 + <bundle>mvn:org.onosproject/onos-app-segmentrouting/@ONOS-VERSION</bundle>
298 + <bundle>mvn:org.onosproject/onos-app-grouphandler/@ONOS-VERSION</bundle>
299 + </feature>
300 +
301 +
288 </features> 302 </features>
......
...@@ -70,7 +70,7 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { ...@@ -70,7 +70,7 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory {
70 if (vendor.startsWith("Stanford University, Ericsson Research and CPqD Research") 70 if (vendor.startsWith("Stanford University, Ericsson Research and CPqD Research")
71 && 71 &&
72 hw.startsWith("OpenFlow 1.3 Reference Userspace Switch")) { 72 hw.startsWith("OpenFlow 1.3 Reference Userspace Switch")) {
73 - return new OFSwitchImplCPqD13(dpid, desc); 73 + return new OFSwitchImplSpringOpenTTP(dpid, desc);
74 } 74 }
75 75
76 if (hw.startsWith("Open vSwitch")) { 76 if (hw.startsWith("Open vSwitch")) {
......
1 +package org.onlab.packet;
2 +
3 +import java.nio.ByteBuffer;
4 +import java.util.HashMap;
5 +import java.util.Map;
6 +
7 +public class MPLS extends BasePacket {
8 + public static final int ADDRESS_LENGTH = 4;
9 + public static final byte PROTOCOL_IPV4 = 0x1;
10 + public static final byte PROTOCOL_MPLS = 0x6;
11 + public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
12 +
13 + static {
14 + PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
15 + PROTOCOL_CLASS_MAP.put(PROTOCOL_IPV4, IPv4.class);
16 + PROTOCOL_CLASS_MAP.put(PROTOCOL_MPLS, MPLS.class);
17 + }
18 +
19 + protected int label; //20bits
20 + protected byte bos; //1bit
21 + protected byte ttl; //8bits
22 + protected byte protocol;
23 +
24 + /**
25 + * Default constructor that sets the version to 4.
26 + */
27 + public MPLS() {
28 + super();
29 + this.bos = 1;
30 + this.protocol = PROTOCOL_IPV4;
31 + }
32 +
33 + @Override
34 + public byte[] serialize() {
35 + byte[] payloadData = null;
36 + if (payload != null) {
37 + payload.setParent(this);
38 + payloadData = payload.serialize();
39 + }
40 +
41 + byte[] data = new byte[(4 + ((payloadData != null) ? payloadData.length : 0)) ];
42 + ByteBuffer bb = ByteBuffer.wrap(data);
43 +
44 + bb.putInt(((this.label & 0x000fffff) << 12) | ((this.bos & 0x1) << 8 | (this.ttl & 0xff)));
45 + if (payloadData != null) {
46 + bb.put(payloadData);
47 + }
48 +
49 + return data;
50 + }
51 +
52 + @Override
53 + public IPacket deserialize(byte[] data, int offset, int length) {
54 + ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
55 +
56 + int mplsheader = bb.getInt();
57 + this.label = ((mplsheader & 0xfffff000) >> 12);
58 + this.bos = (byte) ((mplsheader & 0x00000100) >> 8);
59 + this.bos = (byte) (mplsheader & 0x000000ff);
60 + this.protocol = (this.bos == 1) ? PROTOCOL_IPV4 : PROTOCOL_MPLS;
61 +
62 + IPacket payload;
63 + if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
64 + Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
65 + try {
66 + payload = clazz.newInstance();
67 + } catch (Exception e) {
68 + throw new RuntimeException("Error parsing payload for MPLS packet", e);
69 + }
70 + } else {
71 + payload = new Data();
72 + }
73 + this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
74 + this.payload.setParent(this);
75 +
76 + return this;
77 + }
78 +
79 + /**
80 + * Returns the MPLS label.
81 + *
82 + * @return MPLS label
83 + */
84 + public int getLabel() {
85 + return label;
86 + }
87 +
88 + /**
89 + * Sets the MPLS label.
90 + *
91 + * @param label
92 + */
93 + public void setLabel(int label) {
94 + this.label = label;
95 + }
96 +
97 + /**
98 + * Returns the MPLS TTL of the packet.
99 + *
100 + * @return MPLS TTL of the packet
101 + */
102 + public byte getTtl() {
103 + return ttl;
104 + }
105 +
106 + /**
107 + * Sets the MPLS TTL of the packet.
108 + *
109 + * @param ttl MPLS TTL
110 + */
111 + public void setTtl(byte ttl) {
112 + this.ttl = ttl;
113 + }
114 +
115 +}