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> | ... | ... |
apps/segmentrouting/pom.xml
0 → 100644
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 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
0 → 100644
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 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
0 → 100644
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 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java
0 → 100644
This diff is collapsed. Click to expand it.
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 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/NetworkConfigHandler.java
0 → 100644
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 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
0 → 100644
This diff is collapsed. Click to expand it.
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
0 → 100644
This diff is collapsed. Click to expand it.
... | @@ -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")) { | ... | ... |
This diff is collapsed. Click to expand it.
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 | +} |
-
Please register or login to post a comment