Committed by
Gerrit Code Review
ONOS-688 (ONOS-1835,1836,1837) :
- Implements features to create and remove tunnels and tunnel flow policies. - Implements REST API to create/show/delete tunnels and policies. - Supports only single instance for now. - Fix "apply" actions to "write" actions of all flow rules Change-Id: I3740ed82fed8eab4ab8b03839192da72d3e223f1
Showing
20 changed files
with
1542 additions
and
20 deletions
| ... | @@ -32,6 +32,96 @@ | ... | @@ -32,6 +32,96 @@ |
| 32 | 32 | ||
| 33 | <properties> | 33 | <properties> |
| 34 | <onos.app.name>org.onosproject.segmentrouting</onos.app.name> | 34 | <onos.app.name>org.onosproject.segmentrouting</onos.app.name> |
| 35 | + <web.context>/onos/segmentrouting</web.context> | ||
| 35 | </properties> | 36 | </properties> |
| 36 | 37 | ||
| 38 | + <dependencies> | ||
| 39 | + <dependency> | ||
| 40 | + <groupId>org.onosproject</groupId> | ||
| 41 | + <artifactId>onos-cli</artifactId> | ||
| 42 | + <version>${project.version}</version> | ||
| 43 | + </dependency> | ||
| 44 | + | ||
| 45 | + <dependency> | ||
| 46 | + <groupId>org.apache.karaf.shell</groupId> | ||
| 47 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
| 48 | + </dependency> | ||
| 49 | + <dependency> | ||
| 50 | + <groupId>org.onosproject</groupId> | ||
| 51 | + <artifactId>onos-rest</artifactId> | ||
| 52 | + <version>${project.version}</version> | ||
| 53 | + </dependency> | ||
| 54 | + <dependency> | ||
| 55 | + <groupId>org.onosproject</groupId> | ||
| 56 | + <artifactId>onlab-rest</artifactId> | ||
| 57 | + <version>${project.version}</version> | ||
| 58 | + </dependency> | ||
| 59 | + <dependency> | ||
| 60 | + <groupId>javax.ws.rs</groupId> | ||
| 61 | + <artifactId>jsr311-api</artifactId> | ||
| 62 | + <version>1.1.1</version> | ||
| 63 | + </dependency> | ||
| 64 | + <dependency> | ||
| 65 | + <groupId>com.sun.jersey</groupId> | ||
| 66 | + <artifactId>jersey-servlet</artifactId> | ||
| 67 | + </dependency> | ||
| 68 | + <dependency> | ||
| 69 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 70 | + <artifactId>jackson-databind</artifactId> | ||
| 71 | + </dependency> | ||
| 72 | + | ||
| 73 | + <dependency> | ||
| 74 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 75 | + <artifactId>jackson-annotations</artifactId> | ||
| 76 | + </dependency> | ||
| 77 | + | ||
| 78 | + <dependency> | ||
| 79 | + <groupId>org.osgi</groupId> | ||
| 80 | + <artifactId>org.osgi.compendium</artifactId> | ||
| 81 | + </dependency> | ||
| 82 | + <dependency> | ||
| 83 | + <groupId>org.osgi</groupId> | ||
| 84 | + <artifactId>org.osgi.core</artifactId> | ||
| 85 | + </dependency> | ||
| 86 | + </dependencies> | ||
| 87 | + | ||
| 88 | + <build> | ||
| 89 | + <plugins> | ||
| 90 | + <plugin> | ||
| 91 | + <groupId>org.apache.felix</groupId> | ||
| 92 | + <artifactId>maven-bundle-plugin</artifactId> | ||
| 93 | + <extensions>true</extensions> | ||
| 94 | + <configuration> | ||
| 95 | + <instructions> | ||
| 96 | + <_wab>src/main/webapp/</_wab> | ||
| 97 | + <Bundle-SymbolicName> | ||
| 98 | + ${project.groupId}.${project.artifactId} | ||
| 99 | + </Bundle-SymbolicName> | ||
| 100 | + <Import-Package> | ||
| 101 | + org.slf4j, | ||
| 102 | + org.osgi.framework, | ||
| 103 | + javax.ws.rs, | ||
| 104 | + javax.ws.rs.core, | ||
| 105 | + com.sun.jersey.api.core, | ||
| 106 | + com.sun.jersey.spi.container.servlet, | ||
| 107 | + com.sun.jersey.server.impl.container.servlet, | ||
| 108 | + com.fasterxml.jackson.databind, | ||
| 109 | + com.fasterxml.jackson.databind.node, | ||
| 110 | + com.fasterxml.jackson.core, | ||
| 111 | + org.apache.karaf.shell.commands, | ||
| 112 | + org.apache.commons.lang.math.*, | ||
| 113 | + com.google.common.*, | ||
| 114 | + org.onlab.packet.*, | ||
| 115 | + org.onlab.rest.*, | ||
| 116 | + org.onosproject.*, | ||
| 117 | + org.onlab.util.*, | ||
| 118 | + org.jboss.netty.util.* | ||
| 119 | + </Import-Package> | ||
| 120 | + <Web-ContextPath>${web.context}</Web-ContextPath> | ||
| 121 | + </instructions> | ||
| 122 | + </configuration> | ||
| 123 | + </plugin> | ||
| 124 | + </plugins> | ||
| 125 | + </build> | ||
| 126 | + | ||
| 37 | </project> | 127 | </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 | + | ||
| 17 | +package org.onosproject.segmentrouting; | ||
| 18 | + | ||
| 19 | +import org.onosproject.net.DeviceId; | ||
| 20 | +import org.onosproject.net.Link; | ||
| 21 | +import org.onosproject.segmentrouting.grouphandler.NeighborSet; | ||
| 22 | +import org.slf4j.Logger; | ||
| 23 | +import org.slf4j.LoggerFactory; | ||
| 24 | + | ||
| 25 | +import java.util.Collections; | ||
| 26 | +import java.util.HashSet; | ||
| 27 | +import java.util.List; | ||
| 28 | +import java.util.Set; | ||
| 29 | + | ||
| 30 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * Tunnel class. | ||
| 34 | + */ | ||
| 35 | +public class DefaultTunnel implements Tunnel { | ||
| 36 | + | ||
| 37 | + private static final Logger log = LoggerFactory | ||
| 38 | + .getLogger(DefaultTunnel.class); | ||
| 39 | + | ||
| 40 | + private final String tunnelId; | ||
| 41 | + private final List<Integer> labelIds; | ||
| 42 | + private final SegmentRoutingManager srManager; | ||
| 43 | + private final DeviceConfiguration config; | ||
| 44 | + | ||
| 45 | + private int groupId; | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * Creates a Tunnel reference. | ||
| 49 | + * | ||
| 50 | + * @param srm SegmentRoutingManager object | ||
| 51 | + * @param tid Tunnel ID | ||
| 52 | + * @param labelIds Label stack of the tunnel | ||
| 53 | + */ | ||
| 54 | + public DefaultTunnel(SegmentRoutingManager srm, String tid, | ||
| 55 | + List<Integer> labelIds) { | ||
| 56 | + this.srManager = checkNotNull(srm); | ||
| 57 | + this.tunnelId = checkNotNull(tid); | ||
| 58 | + this.labelIds = Collections.unmodifiableList(labelIds); | ||
| 59 | + this.config = srManager.deviceConfiguration; | ||
| 60 | + this.groupId = -1; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * Creates a Tunnel reference. | ||
| 65 | + * | ||
| 66 | + * @param tid Tunnel ID | ||
| 67 | + * @param labelIds Label stack of the tunnel | ||
| 68 | + */ | ||
| 69 | + public DefaultTunnel(String tid, List<Integer> labelIds) { | ||
| 70 | + this.srManager = null; | ||
| 71 | + this.tunnelId = checkNotNull(tid); | ||
| 72 | + this.labelIds = Collections.unmodifiableList(labelIds); | ||
| 73 | + this.config = null; | ||
| 74 | + this.groupId = -1; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Creates a new DefaultTunnel reference using the tunnel reference. | ||
| 79 | + * | ||
| 80 | + * @param tunnel DefaultTunnel reference | ||
| 81 | + */ | ||
| 82 | + public DefaultTunnel(DefaultTunnel tunnel) { | ||
| 83 | + this.srManager = tunnel.srManager; | ||
| 84 | + this.tunnelId = tunnel.tunnelId; | ||
| 85 | + this.labelIds = tunnel.labelIds; | ||
| 86 | + this.config = tunnel.config; | ||
| 87 | + this.groupId = tunnel.groupId; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + @Override | ||
| 91 | + public String id() { | ||
| 92 | + return this.tunnelId; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @Override | ||
| 96 | + public List<Integer> labelIds() { | ||
| 97 | + return this.labelIds; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Override | ||
| 101 | + public boolean create() { | ||
| 102 | + | ||
| 103 | + if (labelIds.isEmpty() || labelIds.size() < 3) { | ||
| 104 | + log.error("More than one router needs to specified to created a tunnel"); | ||
| 105 | + return false; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + groupId = createGroupsForTunnel(); | ||
| 109 | + if (groupId < 0) { | ||
| 110 | + log.error("Failed to create groups for the tunnel"); | ||
| 111 | + return false; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + return true; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + @Override | ||
| 118 | + public boolean remove() { | ||
| 119 | + | ||
| 120 | + DeviceId deviceId = config.getDeviceId(labelIds.get(0)); | ||
| 121 | + srManager.removeNextObjective(deviceId, groupId); | ||
| 122 | + | ||
| 123 | + return true; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @Override | ||
| 127 | + public int groupId() { | ||
| 128 | + return this.groupId; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + @Override | ||
| 132 | + public DeviceId source() { | ||
| 133 | + return config.getDeviceId(labelIds.get(0)); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + private int createGroupsForTunnel() { | ||
| 137 | + | ||
| 138 | + List<Integer> portNumbers; | ||
| 139 | + | ||
| 140 | + int groupId; | ||
| 141 | + | ||
| 142 | + DeviceId deviceId = config.getDeviceId(labelIds.get(0)); | ||
| 143 | + if (deviceId == null) { | ||
| 144 | + log.warn("No device found for SID {}", labelIds.get(0)); | ||
| 145 | + return -1; | ||
| 146 | + } | ||
| 147 | + Set<DeviceId> deviceIds = new HashSet<>(); | ||
| 148 | + int sid = labelIds.get(1); | ||
| 149 | + if (config.isAdjacencySid(deviceId, sid)) { | ||
| 150 | + portNumbers = config.getPortsForAdjacencySid(deviceId, sid); | ||
| 151 | + for (Link link: srManager.linkService.getDeviceEgressLinks(deviceId)) { | ||
| 152 | + for (Integer port: portNumbers) { | ||
| 153 | + if (link.src().port().toLong() == port) { | ||
| 154 | + deviceIds.add(link.dst().deviceId()); | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + } else { | ||
| 159 | + deviceIds.add(config.getDeviceId(sid)); | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + NeighborSet ns = new NeighborSet(deviceIds, labelIds.get(2)); | ||
| 163 | + groupId = srManager.getNextObjectiveId(deviceId, ns); | ||
| 164 | + | ||
| 165 | + return groupId; | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | +} |
| 1 | package org.onosproject.segmentrouting; | 1 | package org.onosproject.segmentrouting; |
| 2 | 2 | ||
| 3 | +import com.google.common.collect.Lists; | ||
| 3 | import org.onlab.packet.Ip4Address; | 4 | import org.onlab.packet.Ip4Address; |
| 4 | import org.onlab.packet.Ip4Prefix; | 5 | import org.onlab.packet.Ip4Prefix; |
| 5 | import org.onlab.packet.IpPrefix; | 6 | import org.onlab.packet.IpPrefix; |
| ... | @@ -44,6 +45,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -44,6 +45,7 @@ public class DeviceConfiguration implements DeviceProperties { |
| 44 | boolean isEdge; | 45 | boolean isEdge; |
| 45 | HashMap<PortNumber, Ip4Address> gatewayIps; | 46 | HashMap<PortNumber, Ip4Address> gatewayIps; |
| 46 | HashMap<PortNumber, Ip4Prefix> subnets; | 47 | HashMap<PortNumber, Ip4Prefix> subnets; |
| 48 | + List<SegmentRouterConfig.AdjacencySid> adjacencySids; | ||
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | /** | 51 | /** |
| ... | @@ -80,8 +82,10 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -80,8 +82,10 @@ public class DeviceConfiguration implements DeviceProperties { |
| 80 | info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()), | 82 | info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()), |
| 81 | Ip4Address.valueOf(gatewayIp)); | 83 | Ip4Address.valueOf(gatewayIp)); |
| 82 | } | 84 | } |
| 85 | + info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids(); | ||
| 83 | this.deviceConfigMap.put(info.deviceId, info); | 86 | this.deviceConfigMap.put(info.deviceId, info); |
| 84 | this.allSegmentIds.add(info.nodeSid); | 87 | this.allSegmentIds.add(info.nodeSid); |
| 88 | + | ||
| 85 | } | 89 | } |
| 86 | } | 90 | } |
| 87 | 91 | ||
| ... | @@ -352,4 +356,49 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -352,4 +356,49 @@ public class DeviceConfiguration implements DeviceProperties { |
| 352 | 356 | ||
| 353 | return false; | 357 | return false; |
| 354 | } | 358 | } |
| 359 | + | ||
| 360 | + /** | ||
| 361 | + * Returns the ports corresponding to the adjacency Sid given. | ||
| 362 | + * | ||
| 363 | + * @param deviceId device identification of the router | ||
| 364 | + * @param sid adjacency Sid | ||
| 365 | + * @return list of port numbers | ||
| 366 | + */ | ||
| 367 | + public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) { | ||
| 368 | + if (deviceConfigMap.get(deviceId) != null) { | ||
| 369 | + for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) { | ||
| 370 | + if (asid.getAdjSid() == sid) { | ||
| 371 | + return asid.getPorts(); | ||
| 372 | + } | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + return Lists.newArrayList(); | ||
| 377 | + } | ||
| 378 | + | ||
| 379 | + /** | ||
| 380 | + * Check if the Sid given is whether adjacency Sid of the router device or not. | ||
| 381 | + * | ||
| 382 | + * @param deviceId device identification of the router | ||
| 383 | + * @param sid Sid to check | ||
| 384 | + * @return true if the Sid given is the adjacency Sid of the device, | ||
| 385 | + * otherwise false | ||
| 386 | + */ | ||
| 387 | + public boolean isAdjacencySid(DeviceId deviceId, int sid) { | ||
| 388 | + if (deviceConfigMap.get(deviceId) != null) { | ||
| 389 | + if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) { | ||
| 390 | + return false; | ||
| 391 | + } else { | ||
| 392 | + for (SegmentRouterConfig.AdjacencySid asid: | ||
| 393 | + deviceConfigMap.get(deviceId).adjacencySids) { | ||
| 394 | + if (asid.getAdjSid() == sid) { | ||
| 395 | + return true; | ||
| 396 | + } | ||
| 397 | + } | ||
| 398 | + return false; | ||
| 399 | + } | ||
| 400 | + } | ||
| 401 | + | ||
| 402 | + return false; | ||
| 403 | + } | ||
| 355 | } | 404 | } | ... | ... |
| 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 | + | ||
| 17 | +package org.onosproject.segmentrouting; | ||
| 18 | + | ||
| 19 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * Interface for Segment Routing Policy. | ||
| 23 | + */ | ||
| 24 | +public interface Policy { | ||
| 25 | + /** | ||
| 26 | + * Enums for policy type. | ||
| 27 | + */ | ||
| 28 | + enum Type { | ||
| 29 | + // Tunnel flow policy type | ||
| 30 | + TUNNEL_FLOW, | ||
| 31 | + | ||
| 32 | + // Load balancing policy type | ||
| 33 | + LOADBALANCE, | ||
| 34 | + | ||
| 35 | + // policy to avoid specific routers or links | ||
| 36 | + AVOID, | ||
| 37 | + | ||
| 38 | + // Access Control policy type | ||
| 39 | + DENY | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Returns the policy ID. | ||
| 44 | + * | ||
| 45 | + * @return policy ID | ||
| 46 | + */ | ||
| 47 | + String id(); | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * Returns the traffic selector object. | ||
| 51 | + * | ||
| 52 | + * @return TrafficSelector object | ||
| 53 | + */ | ||
| 54 | + TrafficSelector selector(); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * Returns the priority of the policy. | ||
| 58 | + * | ||
| 59 | + * @return priority | ||
| 60 | + */ | ||
| 61 | + int priority(); | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * Returns the policy type. | ||
| 65 | + * | ||
| 66 | + * @return policy type | ||
| 67 | + */ | ||
| 68 | + Type type(); | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * Creates a policy. | ||
| 72 | + * | ||
| 73 | + * @return true if succeeds, false otherwise | ||
| 74 | + */ | ||
| 75 | + boolean create(); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Removes the policy. | ||
| 79 | + * | ||
| 80 | + * @return true if succeeds, false otherwise | ||
| 81 | + */ | ||
| 82 | + boolean remove(); | ||
| 83 | +} |
| 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 | + | ||
| 17 | +package org.onosproject.segmentrouting; | ||
| 18 | + | ||
| 19 | +import org.slf4j.Logger; | ||
| 20 | + | ||
| 21 | +import java.util.ArrayList; | ||
| 22 | +import java.util.HashMap; | ||
| 23 | +import java.util.List; | ||
| 24 | + | ||
| 25 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * Segment Routing Policy Handler. | ||
| 29 | + */ | ||
| 30 | +public class PolicyHandler { | ||
| 31 | + | ||
| 32 | + protected final Logger log = getLogger(getClass()); | ||
| 33 | + | ||
| 34 | + private final HashMap<String, Policy> policyMap; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * Creates a reference. | ||
| 38 | + */ | ||
| 39 | + public PolicyHandler() { | ||
| 40 | + policyMap = new HashMap<>(); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * Returns the policies. | ||
| 45 | + * | ||
| 46 | + * @return policy list | ||
| 47 | + */ | ||
| 48 | + public List<Policy> getPolicies() { | ||
| 49 | + List<Policy> policies = new ArrayList<>(); | ||
| 50 | + policyMap.values().forEach(policy -> policies.add( | ||
| 51 | + new TunnelPolicy((TunnelPolicy) policy))); | ||
| 52 | + | ||
| 53 | + return policies; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * Creates a policy using the policy information given. | ||
| 58 | + * | ||
| 59 | + * @param policy policy reference to create | ||
| 60 | + */ | ||
| 61 | + public void createPolicy(Policy policy) { | ||
| 62 | + policy.create(); | ||
| 63 | + policyMap.put(policy.id(), policy); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * Removes the policy given. | ||
| 68 | + * | ||
| 69 | + * @param policyInfo policy information to remove | ||
| 70 | + */ | ||
| 71 | + public void removePolicy(Policy policyInfo) { | ||
| 72 | + if (policyMap.get(policyInfo.id()) != null) { | ||
| 73 | + if (policyMap.get(policyInfo.id()).remove()) { | ||
| 74 | + policyMap.remove(policyInfo.id()); | ||
| 75 | + } else { | ||
| 76 | + log.error("Failed to remove the policy {}", policyInfo.id()); | ||
| 77 | + } | ||
| 78 | + } else { | ||
| 79 | + log.warn("Policy {} was not found", policyInfo.id()); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | +} |
| ... | @@ -98,7 +98,8 @@ public class RoutingRulePopulator { | ... | @@ -98,7 +98,8 @@ public class RoutingRulePopulator { |
| 98 | sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32)); | 98 | sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32)); |
| 99 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); | 99 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); |
| 100 | 100 | ||
| 101 | - tbuilder.setEthDst(hostMac) | 101 | + tbuilder.deferred() |
| 102 | + .setEthDst(hostMac) | ||
| 102 | .setEthSrc(config.getDeviceMac(deviceId)) | 103 | .setEthSrc(config.getDeviceMac(deviceId)) |
| 103 | .setOutput(outPort); | 104 | .setOutput(outPort); |
| 104 | 105 | ||
| ... | @@ -163,10 +164,10 @@ public class RoutingRulePopulator { | ... | @@ -163,10 +164,10 @@ public class RoutingRulePopulator { |
| 163 | // If the next hop is the same as the final destination, then MPLS label | 164 | // If the next hop is the same as the final destination, then MPLS label |
| 164 | // is not set. | 165 | // is not set. |
| 165 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { | 166 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { |
| 166 | - tbuilder.decNwTtl(); | 167 | + tbuilder.deferred().decNwTtl(); |
| 167 | ns = new NeighborSet(nextHops); | 168 | ns = new NeighborSet(nextHops); |
| 168 | } else { | 169 | } else { |
| 169 | - tbuilder.copyTtlOut(); | 170 | + tbuilder.deferred().copyTtlOut(); |
| 170 | ns = new NeighborSet(nextHops, config.getSegmentId(destSw)); | 171 | ns = new NeighborSet(nextHops, config.getSegmentId(destSw)); |
| 171 | } | 172 | } |
| 172 | 173 | ||
| ... | @@ -295,15 +296,15 @@ public class RoutingRulePopulator { | ... | @@ -295,15 +296,15 @@ public class RoutingRulePopulator { |
| 295 | 296 | ||
| 296 | if (phpRequired) { | 297 | if (phpRequired) { |
| 297 | log.debug("getMplsForwardingObjective: php required"); | 298 | log.debug("getMplsForwardingObjective: php required"); |
| 298 | - tbuilder.copyTtlIn(); | 299 | + tbuilder.deferred().copyTtlIn(); |
| 299 | if (isBos) { | 300 | if (isBos) { |
| 300 | - tbuilder.popMpls(Ethernet.TYPE_IPV4).decNwTtl(); | 301 | + tbuilder.deferred().popMpls(Ethernet.TYPE_IPV4).decNwTtl(); |
| 301 | } else { | 302 | } else { |
| 302 | - tbuilder.popMpls(Ethernet.MPLS_UNICAST).decMplsTtl(); | 303 | + tbuilder.deferred().popMpls(Ethernet.MPLS_UNICAST).decMplsTtl(); |
| 303 | } | 304 | } |
| 304 | } else { | 305 | } else { |
| 305 | log.debug("getMplsForwardingObjective: php not required"); | 306 | log.debug("getMplsForwardingObjective: php not required"); |
| 306 | - tbuilder.decMplsTtl(); | 307 | + tbuilder.deferred().decMplsTtl(); |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 309 | if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) { | 310 | if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) { |
| ... | @@ -313,7 +314,8 @@ public class RoutingRulePopulator { | ... | @@ -313,7 +314,8 @@ public class RoutingRulePopulator { |
| 313 | log.warn("No link from {} to {}", deviceId, nextHops); | 314 | log.warn("No link from {} to {}", deviceId, nextHops); |
| 314 | return null; | 315 | return null; |
| 315 | } | 316 | } |
| 316 | - tbuilder.setEthSrc(config.getDeviceMac(deviceId)) | 317 | + tbuilder.deferred() |
| 318 | + .setEthSrc(config.getDeviceMac(deviceId)) | ||
| 317 | .setEthDst(config.getDeviceMac(nextHop)) | 319 | .setEthDst(config.getDeviceMac(nextHop)) |
| 318 | .setOutput(port); | 320 | .setOutput(port); |
| 319 | fwdBuilder.withTreatment(tbuilder.build()); | 321 | fwdBuilder.withTreatment(tbuilder.build()); | ... | ... |
| ... | @@ -20,6 +20,7 @@ import org.apache.felix.scr.annotations.Component; | ... | @@ -20,6 +20,7 @@ import org.apache.felix.scr.annotations.Component; |
| 20 | import org.apache.felix.scr.annotations.Deactivate; | 20 | import org.apache.felix.scr.annotations.Deactivate; |
| 21 | import org.apache.felix.scr.annotations.Reference; | 21 | import org.apache.felix.scr.annotations.Reference; |
| 22 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 22 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 23 | +import org.apache.felix.scr.annotations.Service; | ||
| 23 | import org.onlab.packet.Ethernet; | 24 | import org.onlab.packet.Ethernet; |
| 24 | import org.onlab.packet.IPv4; | 25 | import org.onlab.packet.IPv4; |
| 25 | import org.onlab.util.KryoNamespace; | 26 | import org.onlab.util.KryoNamespace; |
| ... | @@ -60,6 +61,7 @@ import org.slf4j.LoggerFactory; | ... | @@ -60,6 +61,7 @@ import org.slf4j.LoggerFactory; |
| 60 | 61 | ||
| 61 | import java.net.URI; | 62 | import java.net.URI; |
| 62 | import java.util.HashSet; | 63 | import java.util.HashSet; |
| 64 | +import java.util.List; | ||
| 63 | import java.util.Map; | 65 | import java.util.Map; |
| 64 | import java.util.concurrent.ConcurrentHashMap; | 66 | import java.util.concurrent.ConcurrentHashMap; |
| 65 | import java.util.concurrent.ConcurrentLinkedQueue; | 67 | import java.util.concurrent.ConcurrentLinkedQueue; |
| ... | @@ -69,8 +71,9 @@ import java.util.concurrent.ScheduledFuture; | ... | @@ -69,8 +71,9 @@ import java.util.concurrent.ScheduledFuture; |
| 69 | import java.util.concurrent.TimeUnit; | 71 | import java.util.concurrent.TimeUnit; |
| 70 | 72 | ||
| 71 | @SuppressWarnings("ALL") | 73 | @SuppressWarnings("ALL") |
| 74 | +@Service | ||
| 72 | @Component(immediate = true) | 75 | @Component(immediate = true) |
| 73 | -public class SegmentRoutingManager { | 76 | +public class SegmentRoutingManager implements SegmentRoutingService { |
| 74 | 77 | ||
| 75 | private static Logger log = LoggerFactory | 78 | private static Logger log = LoggerFactory |
| 76 | .getLogger(SegmentRoutingManager.class); | 79 | .getLogger(SegmentRoutingManager.class); |
| ... | @@ -101,6 +104,7 @@ public class SegmentRoutingManager { | ... | @@ -101,6 +104,7 @@ public class SegmentRoutingManager { |
| 101 | 104 | ||
| 102 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 105 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 103 | protected MastershipService mastershipService; | 106 | protected MastershipService mastershipService; |
| 107 | + | ||
| 104 | protected ArpHandler arpHandler = null; | 108 | protected ArpHandler arpHandler = null; |
| 105 | protected IcmpHandler icmpHandler = null; | 109 | protected IcmpHandler icmpHandler = null; |
| 106 | protected IpHandler ipHandler = null; | 110 | protected IpHandler ipHandler = null; |
| ... | @@ -108,7 +112,10 @@ public class SegmentRoutingManager { | ... | @@ -108,7 +112,10 @@ public class SegmentRoutingManager { |
| 108 | protected ApplicationId appId; | 112 | protected ApplicationId appId; |
| 109 | protected DeviceConfiguration deviceConfiguration = null; | 113 | protected DeviceConfiguration deviceConfiguration = null; |
| 110 | 114 | ||
| 115 | + | ||
| 111 | private DefaultRoutingHandler defaultRoutingHandler = null; | 116 | private DefaultRoutingHandler defaultRoutingHandler = null; |
| 117 | + private TunnelHandler tunnelHandler = null; | ||
| 118 | + private PolicyHandler policyHandler = null; | ||
| 112 | private InternalPacketProcessor processor = new InternalPacketProcessor(); | 119 | private InternalPacketProcessor processor = new InternalPacketProcessor(); |
| 113 | private InternalEventHandler eventHandler = new InternalEventHandler(); | 120 | private InternalEventHandler eventHandler = new InternalEventHandler(); |
| 114 | 121 | ||
| ... | @@ -165,6 +172,8 @@ public class SegmentRoutingManager { | ... | @@ -165,6 +172,8 @@ public class SegmentRoutingManager { |
| 165 | ipHandler = new IpHandler(this); | 172 | ipHandler = new IpHandler(this); |
| 166 | routingRulePopulator = new RoutingRulePopulator(this); | 173 | routingRulePopulator = new RoutingRulePopulator(this); |
| 167 | defaultRoutingHandler = new DefaultRoutingHandler(this); | 174 | defaultRoutingHandler = new DefaultRoutingHandler(this); |
| 175 | + tunnelHandler = new TunnelHandler(); | ||
| 176 | + policyHandler = new PolicyHandler(); | ||
| 168 | 177 | ||
| 169 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); | 178 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); |
| 170 | linkService.addListener(new InternalLinkListener()); | 179 | linkService.addListener(new InternalLinkListener()); |
| ... | @@ -187,6 +196,7 @@ public class SegmentRoutingManager { | ... | @@ -187,6 +196,7 @@ public class SegmentRoutingManager { |
| 187 | 196 | ||
| 188 | defaultRoutingHandler.startPopulationProcess(); | 197 | defaultRoutingHandler.startPopulationProcess(); |
| 189 | log.info("Started"); | 198 | log.info("Started"); |
| 199 | + | ||
| 190 | } | 200 | } |
| 191 | 201 | ||
| 192 | @Deactivate | 202 | @Deactivate |
| ... | @@ -196,6 +206,51 @@ public class SegmentRoutingManager { | ... | @@ -196,6 +206,51 @@ public class SegmentRoutingManager { |
| 196 | log.info("Stopped"); | 206 | log.info("Stopped"); |
| 197 | } | 207 | } |
| 198 | 208 | ||
| 209 | + | ||
| 210 | + @Override | ||
| 211 | + public List<Tunnel> getTunnels() { | ||
| 212 | + return tunnelHandler.getTunnels(); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + @Override | ||
| 216 | + public void createTunnel(Tunnel tunnel) { | ||
| 217 | + tunnelHandler.createTunnel(tunnel); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + @Override | ||
| 221 | + public void removeTunnel(Tunnel tunnel) { | ||
| 222 | + for (Policy policy: policyHandler.getPolicies()) { | ||
| 223 | + if (policy.type() == Policy.Type.TUNNEL_FLOW) { | ||
| 224 | + TunnelPolicy tunnelPolicy = (TunnelPolicy) policy; | ||
| 225 | + if (tunnelPolicy.tunnelId().equals(tunnel.id())) { | ||
| 226 | + log.warn("Cannot remove the tunnel used by a policy"); | ||
| 227 | + return; | ||
| 228 | + } | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + tunnelHandler.removeTunnel(tunnel); | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + @Override | ||
| 235 | + public void removePolicy(Policy policy) { | ||
| 236 | + policyHandler.removePolicy(policy); | ||
| 237 | + | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + @Override | ||
| 241 | + public void createPolicy(Policy policy) { | ||
| 242 | + policyHandler.createPolicy(policy); | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + @Override | ||
| 246 | + public List<Policy> getPolicies() { | ||
| 247 | + return policyHandler.getPolicies(); | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + public Tunnel getTunnel(String tunnelId) { | ||
| 251 | + return tunnelHandler.getTunnel(tunnelId); | ||
| 252 | + } | ||
| 253 | + | ||
| 199 | /** | 254 | /** |
| 200 | * Returns the GrouopKey object for the device and the NighborSet given. | 255 | * Returns the GrouopKey object for the device and the NighborSet given. |
| 201 | * | 256 | * |
| ... | @@ -211,6 +266,12 @@ public class SegmentRoutingManager { | ... | @@ -211,6 +266,12 @@ public class SegmentRoutingManager { |
| 211 | return null; | 266 | return null; |
| 212 | } | 267 | } |
| 213 | 268 | ||
| 269 | + /** | ||
| 270 | + * | ||
| 271 | + * @param deviceId | ||
| 272 | + * @param ns | ||
| 273 | + * @return | ||
| 274 | + */ | ||
| 214 | public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) { | 275 | public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) { |
| 215 | 276 | ||
| 216 | if (groupHandlerMap.get(deviceId) != null) { | 277 | if (groupHandlerMap.get(deviceId) != null) { |
| ... | @@ -223,6 +284,16 @@ public class SegmentRoutingManager { | ... | @@ -223,6 +284,16 @@ public class SegmentRoutingManager { |
| 223 | } | 284 | } |
| 224 | } | 285 | } |
| 225 | 286 | ||
| 287 | + /** | ||
| 288 | + * | ||
| 289 | + * @param deviceId | ||
| 290 | + * @param objectiveId | ||
| 291 | + * @return | ||
| 292 | + */ | ||
| 293 | + public boolean removeNextObjective(DeviceId deviceId, int objectiveId) { | ||
| 294 | + return groupHandlerMap.get(deviceId).removeGroup(objectiveId); | ||
| 295 | + } | ||
| 296 | + | ||
| 226 | private class InternalPacketProcessor implements PacketProcessor { | 297 | private class InternalPacketProcessor implements PacketProcessor { |
| 227 | 298 | ||
| 228 | @Override | 299 | @Override |
| ... | @@ -295,7 +366,7 @@ public class SegmentRoutingManager { | ... | @@ -295,7 +366,7 @@ public class SegmentRoutingManager { |
| 295 | } | 366 | } |
| 296 | 367 | ||
| 297 | log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents, | 368 | log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents, |
| 298 | - numOfHandlerScheduled); | 369 | + numOfHandlerScheduled); |
| 299 | 370 | ||
| 300 | } | 371 | } |
| 301 | 372 | ||
| ... | @@ -403,4 +474,7 @@ public class SegmentRoutingManager { | ... | @@ -403,4 +474,7 @@ public class SegmentRoutingManager { |
| 403 | groupHandler.portDown(port.number()); | 474 | groupHandler.portDown(port.number()); |
| 404 | } | 475 | } |
| 405 | } | 476 | } |
| 477 | + | ||
| 478 | + | ||
| 479 | + | ||
| 406 | } | 480 | } | ... | ... |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.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 java.util.List; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * Segment Routing Service for REST API. | ||
| 22 | + */ | ||
| 23 | +public interface SegmentRoutingService { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * Returns all tunnels. | ||
| 27 | + * | ||
| 28 | + * @return list of tunnels | ||
| 29 | + */ | ||
| 30 | + List<Tunnel> getTunnels(); | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Creates a tunnel. | ||
| 34 | + * | ||
| 35 | + * @param tunnel tunnel reference to create | ||
| 36 | + */ | ||
| 37 | + void createTunnel(Tunnel tunnel); | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * Returns all policies. | ||
| 41 | + * | ||
| 42 | + * @return list of policy | ||
| 43 | + */ | ||
| 44 | + List<Policy> getPolicies(); | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * Creates a policy. | ||
| 48 | + * | ||
| 49 | + * @param policy policy reference to create | ||
| 50 | + */ | ||
| 51 | + void createPolicy(Policy policy); | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * Removes a tunnel. | ||
| 55 | + * | ||
| 56 | + * @param tunnel tunnel reference to remove | ||
| 57 | + */ | ||
| 58 | + void removeTunnel(Tunnel tunnel); | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * Removes a policy. | ||
| 62 | + * | ||
| 63 | + * @param policy policy reference to remove | ||
| 64 | + */ | ||
| 65 | + void removePolicy(Policy policy); | ||
| 66 | +} |
| 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 | + | ||
| 17 | +package org.onosproject.segmentrouting; | ||
| 18 | + | ||
| 19 | +import org.onosproject.net.DeviceId; | ||
| 20 | + | ||
| 21 | +import java.util.List; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Tunnel interface. | ||
| 25 | + */ | ||
| 26 | +public interface Tunnel { | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * Returns the tunnel ID. | ||
| 30 | + * | ||
| 31 | + * @return tunnel ID | ||
| 32 | + */ | ||
| 33 | + String id(); | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * Returns Segment IDs for the tunnel including source and destination. | ||
| 37 | + * | ||
| 38 | + * @return List of Node ID | ||
| 39 | + */ | ||
| 40 | + List<Integer> labelIds(); | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Creates a tunnel. | ||
| 44 | + * | ||
| 45 | + * @return true if succeeds, false otherwise | ||
| 46 | + */ | ||
| 47 | + boolean create(); | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * Removes the tunnel. | ||
| 51 | + * | ||
| 52 | + * @return true if succeeds, false otherwise. | ||
| 53 | + */ | ||
| 54 | + boolean remove(); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * Returns the group ID for the tunnel. | ||
| 58 | + * | ||
| 59 | + * @return group ID | ||
| 60 | + */ | ||
| 61 | + int groupId(); | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * Returns the source device Id of the tunnel. | ||
| 65 | + * | ||
| 66 | + * @return source device Id | ||
| 67 | + */ | ||
| 68 | + DeviceId source(); | ||
| 69 | +} |
| 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.slf4j.Logger; | ||
| 19 | + | ||
| 20 | +import java.util.ArrayList; | ||
| 21 | +import java.util.List; | ||
| 22 | +import java.util.HashMap; | ||
| 23 | + | ||
| 24 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * Tunnel Handler. | ||
| 28 | + */ | ||
| 29 | +public class TunnelHandler { | ||
| 30 | + protected final Logger log = getLogger(getClass()); | ||
| 31 | + | ||
| 32 | + private final HashMap<String, Tunnel> tunnelMap; | ||
| 33 | + | ||
| 34 | + public TunnelHandler() { | ||
| 35 | + tunnelMap = new HashMap<>(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * Creates a tunnel. | ||
| 40 | + * | ||
| 41 | + * @param tunnel tunnel reference to create a tunnel | ||
| 42 | + */ | ||
| 43 | + public void createTunnel(Tunnel tunnel) { | ||
| 44 | + tunnel.create(); | ||
| 45 | + tunnelMap.put(tunnel.id(), tunnel); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * Removes the tunnel with the tunnel ID given. | ||
| 50 | + * | ||
| 51 | + * @param tunnelInfo tunnel information to delete tunnels | ||
| 52 | + */ | ||
| 53 | + public void removeTunnel(Tunnel tunnelInfo) { | ||
| 54 | + | ||
| 55 | + Tunnel tunnel = tunnelMap.get(tunnelInfo.id()); | ||
| 56 | + if (tunnel != null) { | ||
| 57 | + tunnel.remove(); | ||
| 58 | + tunnelMap.remove(tunnel.id()); | ||
| 59 | + } else { | ||
| 60 | + log.warn("No tunnel found for tunnel ID {}", tunnelInfo.id()); | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * Returns the tunnel with the tunnel ID given. | ||
| 66 | + * | ||
| 67 | + * @param tid Tunnel ID | ||
| 68 | + * @return Tunnel reference | ||
| 69 | + */ | ||
| 70 | + public Tunnel getTunnel(String tid) { | ||
| 71 | + return tunnelMap.get(tid); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + /** | ||
| 75 | + * Returns all tunnels. | ||
| 76 | + * | ||
| 77 | + * @return list of Tunnels | ||
| 78 | + */ | ||
| 79 | + public List<Tunnel> getTunnels() { | ||
| 80 | + List<Tunnel> tunnels = new ArrayList<>(); | ||
| 81 | + tunnelMap.values().forEach(tunnel -> tunnels.add( | ||
| 82 | + new DefaultTunnel((DefaultTunnel) tunnel))); | ||
| 83 | + | ||
| 84 | + return tunnels; | ||
| 85 | + } | ||
| 86 | +} |
| 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 | + | ||
| 17 | +package org.onosproject.segmentrouting; | ||
| 18 | + | ||
| 19 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 20 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
| 21 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 22 | + | ||
| 23 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Tunnel Policy. | ||
| 27 | + */ | ||
| 28 | +public final class TunnelPolicy implements Policy { | ||
| 29 | + | ||
| 30 | + private final SegmentRoutingManager srManager; | ||
| 31 | + private final Type type; | ||
| 32 | + private final String id; | ||
| 33 | + private final TrafficSelector selector; | ||
| 34 | + private final int priority; | ||
| 35 | + private final String tunnelId; | ||
| 36 | + | ||
| 37 | + private TunnelPolicy(SegmentRoutingManager srm, String policyId, Type type, | ||
| 38 | + TrafficSelector selector, int priority, String tunnelId) { | ||
| 39 | + this.srManager = srm; | ||
| 40 | + this.id = checkNotNull(policyId); | ||
| 41 | + this.type = type; | ||
| 42 | + this.tunnelId = tunnelId; | ||
| 43 | + this.priority = priority; | ||
| 44 | + this.selector = selector; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * Creates a TunnelPolicy reference. | ||
| 49 | + * | ||
| 50 | + * @param p TunnelPolicy reference | ||
| 51 | + */ | ||
| 52 | + public TunnelPolicy(TunnelPolicy p) { | ||
| 53 | + this.srManager = p.srManager; | ||
| 54 | + this.id = p.id; | ||
| 55 | + this.type = p.type; | ||
| 56 | + this.tunnelId = p.tunnelId; | ||
| 57 | + this.priority = p.priority; | ||
| 58 | + this.selector = p.selector; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * Creates a TunnelPolicy reference. | ||
| 63 | + * | ||
| 64 | + * @param p TunnelPolicy reference | ||
| 65 | + */ | ||
| 66 | + public TunnelPolicy(SegmentRoutingManager srm, TunnelPolicy p) { | ||
| 67 | + this.srManager = srm; | ||
| 68 | + this.id = p.id; | ||
| 69 | + this.type = p.type; | ||
| 70 | + this.tunnelId = p.tunnelId; | ||
| 71 | + this.priority = p.priority; | ||
| 72 | + this.selector = p.selector; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + /** | ||
| 76 | + * Returns the TunnelPolicy builder reference. | ||
| 77 | + * | ||
| 78 | + * @return TunnelPolicy builder | ||
| 79 | + */ | ||
| 80 | + public static TunnelPolicy.Builder builder() { | ||
| 81 | + return new Builder(); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @Override | ||
| 85 | + public String id() { | ||
| 86 | + return this.id; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @Override | ||
| 90 | + public TrafficSelector selector() { | ||
| 91 | + return selector; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + public int priority() { | ||
| 96 | + return priority; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @Override | ||
| 100 | + public Type type() { | ||
| 101 | + return type; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + @Override | ||
| 105 | + public boolean create() { | ||
| 106 | + | ||
| 107 | + Tunnel tunnel = srManager.getTunnel(tunnelId); | ||
| 108 | + | ||
| 109 | + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective | ||
| 110 | + .builder() | ||
| 111 | + .fromApp(srManager.appId) | ||
| 112 | + .makePermanent() | ||
| 113 | + .nextStep(tunnel.groupId()) | ||
| 114 | + .withPriority(priority) | ||
| 115 | + .withSelector(selector) | ||
| 116 | + .withFlag(ForwardingObjective.Flag.VERSATILE); | ||
| 117 | + | ||
| 118 | + srManager.flowObjectiveService.forward(tunnel.source(), fwdBuilder.add()); | ||
| 119 | + | ||
| 120 | + return true; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + @Override | ||
| 124 | + public boolean remove() { | ||
| 125 | + | ||
| 126 | + Tunnel tunnel = srManager.getTunnel(tunnelId); | ||
| 127 | + | ||
| 128 | + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective | ||
| 129 | + .builder() | ||
| 130 | + .fromApp(srManager.appId) | ||
| 131 | + .makePermanent() | ||
| 132 | + .withSelector(selector) | ||
| 133 | + .withPriority(priority) | ||
| 134 | + .nextStep(tunnel.groupId()) | ||
| 135 | + .withFlag(ForwardingObjective.Flag.VERSATILE); | ||
| 136 | + | ||
| 137 | + srManager.flowObjectiveService.forward(tunnel.source(), fwdBuilder.remove()); | ||
| 138 | + | ||
| 139 | + return true; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * Returns the tunnel ID of the policy. | ||
| 144 | + * | ||
| 145 | + * @return Tunnel ID | ||
| 146 | + */ | ||
| 147 | + public String tunnelId() { | ||
| 148 | + return this.tunnelId; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + /** | ||
| 152 | + * Tunnel Policy Builder. | ||
| 153 | + */ | ||
| 154 | + public static final class Builder { | ||
| 155 | + | ||
| 156 | + private SegmentRoutingManager srManager; | ||
| 157 | + private String id; | ||
| 158 | + private Type type; | ||
| 159 | + private TrafficSelector selector; | ||
| 160 | + private int priority; | ||
| 161 | + private String tunnelId; | ||
| 162 | + | ||
| 163 | + /** | ||
| 164 | + * Sets the policy Id. | ||
| 165 | + * | ||
| 166 | + * @param id policy Id | ||
| 167 | + * @return Builder object | ||
| 168 | + */ | ||
| 169 | + public Builder setPolicyId(String id) { | ||
| 170 | + this.id = id; | ||
| 171 | + | ||
| 172 | + return this; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * Sets the policy type. | ||
| 177 | + * | ||
| 178 | + * @param type policy type | ||
| 179 | + * @return Builder object | ||
| 180 | + */ | ||
| 181 | + public Builder setType(Type type) { | ||
| 182 | + this.type = type; | ||
| 183 | + | ||
| 184 | + return this; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + /** | ||
| 188 | + * Sets the TrafficSelector. | ||
| 189 | + * | ||
| 190 | + * @param selector TrafficSelector | ||
| 191 | + * @return Builder object | ||
| 192 | + */ | ||
| 193 | + public Builder setSelector(TrafficSelector selector) { | ||
| 194 | + this.selector = selector; | ||
| 195 | + | ||
| 196 | + return this; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * Sets the priority of the policy. | ||
| 201 | + * | ||
| 202 | + * @param p priority | ||
| 203 | + * @return Builder object | ||
| 204 | + */ | ||
| 205 | + public Builder setPriority(int p) { | ||
| 206 | + this.priority = p; | ||
| 207 | + | ||
| 208 | + return this; | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + /** | ||
| 212 | + * Sets the tunnel Id. | ||
| 213 | + * | ||
| 214 | + * @param tunnelId tunnel Id | ||
| 215 | + * @return Builder object | ||
| 216 | + */ | ||
| 217 | + public Builder setTunnelId(String tunnelId) { | ||
| 218 | + this.tunnelId = tunnelId; | ||
| 219 | + | ||
| 220 | + return this; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + /** | ||
| 224 | + * Sets the Segment Routing Manager reference. | ||
| 225 | + * | ||
| 226 | + * @param srm Segment Routing Manager reference | ||
| 227 | + * @return Builder object | ||
| 228 | + */ | ||
| 229 | + public Builder setManager(SegmentRoutingManager srm) { | ||
| 230 | + this.srManager = srm; | ||
| 231 | + | ||
| 232 | + return this; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + /** | ||
| 236 | + * Builds the policy. | ||
| 237 | + * | ||
| 238 | + * @return Tunnel Policy reference | ||
| 239 | + */ | ||
| 240 | + public Policy build() { | ||
| 241 | + return new TunnelPolicy(srManager, id, type, selector, priority, tunnelId); | ||
| 242 | + } | ||
| 243 | + } | ||
| 244 | +} |
| ... | @@ -24,6 +24,7 @@ import java.util.Collections; | ... | @@ -24,6 +24,7 @@ import java.util.Collections; |
| 24 | import java.util.HashMap; | 24 | import java.util.HashMap; |
| 25 | import java.util.HashSet; | 25 | import java.util.HashSet; |
| 26 | import java.util.List; | 26 | import java.util.List; |
| 27 | +import java.util.Map; | ||
| 27 | import java.util.Random; | 28 | import java.util.Random; |
| 28 | import java.util.Set; | 29 | import java.util.Set; |
| 29 | import java.util.stream.Collectors; | 30 | import java.util.stream.Collectors; |
| ... | @@ -418,7 +419,12 @@ public class DefaultGroupHandler { | ... | @@ -418,7 +419,12 @@ public class DefaultGroupHandler { |
| 418 | return nsSegmentIds; | 419 | return nsSegmentIds; |
| 419 | } | 420 | } |
| 420 | 421 | ||
| 421 | - protected void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) { | 422 | + /** |
| 423 | + * Creates Groups from a set of NeighborSet given. | ||
| 424 | + * | ||
| 425 | + * @param nsSet a set of NeighborSet | ||
| 426 | + */ | ||
| 427 | + public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) { | ||
| 422 | for (NeighborSet ns : nsSet) { | 428 | for (NeighborSet ns : nsSet) { |
| 423 | int nextId = flowObjectiveService.allocateNextId(); | 429 | int nextId = flowObjectiveService.allocateNextId(); |
| 424 | NextObjective.Builder nextObjBuilder = DefaultNextObjective | 430 | NextObjective.Builder nextObjBuilder = DefaultNextObjective |
| ... | @@ -451,7 +457,7 @@ public class DefaultGroupHandler { | ... | @@ -451,7 +457,7 @@ public class DefaultGroupHandler { |
| 451 | NextObjective nextObj = nextObjBuilder.add(); | 457 | NextObjective nextObj = nextObjBuilder.add(); |
| 452 | flowObjectiveService.next(deviceId, nextObj); | 458 | flowObjectiveService.next(deviceId, nextObj); |
| 453 | log.debug("createGroupsFromNeighborsets: Submited " | 459 | log.debug("createGroupsFromNeighborsets: Submited " |
| 454 | - + "next objective {} in device {}", | 460 | + + "next objective {} in device {}", |
| 455 | nextId, deviceId); | 461 | nextId, deviceId); |
| 456 | nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns), | 462 | nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns), |
| 457 | nextId); | 463 | nextId); |
| ... | @@ -462,4 +468,29 @@ public class DefaultGroupHandler { | ... | @@ -462,4 +468,29 @@ public class DefaultGroupHandler { |
| 462 | return new DefaultGroupKey(kryo.build().serialize(obj)); | 468 | return new DefaultGroupKey(kryo.build().serialize(obj)); |
| 463 | } | 469 | } |
| 464 | 470 | ||
| 471 | + /** | ||
| 472 | + * Removes groups for the next objective ID given. | ||
| 473 | + * | ||
| 474 | + * @param objectiveId next objective ID to remove | ||
| 475 | + * @return true if succeeds, false otherwise | ||
| 476 | + */ | ||
| 477 | + public boolean removeGroup(int objectiveId) { | ||
| 478 | + | ||
| 479 | + if (nsNextObjStore.containsValue(objectiveId)) { | ||
| 480 | + NextObjective.Builder nextObjBuilder = DefaultNextObjective | ||
| 481 | + .builder().withId(objectiveId) | ||
| 482 | + .withType(NextObjective.Type.HASHED).fromApp(appId); | ||
| 483 | + NextObjective nextObjective = nextObjBuilder.remove(); | ||
| 484 | + flowObjectiveService.next(deviceId, nextObjective); | ||
| 485 | + | ||
| 486 | + for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) { | ||
| 487 | + if (entry.getValue().equals(objectiveId)) { | ||
| 488 | + nsNextObjStore.remove(entry.getKey()); | ||
| 489 | + break; | ||
| 490 | + } | ||
| 491 | + } | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + return false; | ||
| 495 | + } | ||
| 465 | } | 496 | } | ... | ... |
| 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.web; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.Ethernet; | ||
| 19 | +import org.onlab.packet.IpPrefix; | ||
| 20 | +import org.onosproject.cli.net.IpProtocol; | ||
| 21 | +import org.onosproject.codec.CodecContext; | ||
| 22 | +import org.onosproject.codec.JsonCodec; | ||
| 23 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 24 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
| 25 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 26 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 27 | +import org.onosproject.net.flow.criteria.IPCriterion; | ||
| 28 | +import org.onosproject.net.flow.criteria.IPProtocolCriterion; | ||
| 29 | +import org.onosproject.segmentrouting.Policy; | ||
| 30 | +import org.onosproject.segmentrouting.TunnelPolicy; | ||
| 31 | + | ||
| 32 | +public final class PolicyCodec extends JsonCodec<Policy> { | ||
| 33 | + | ||
| 34 | + // JSON field names | ||
| 35 | + private static final String POLICY_ID = "policy_id"; | ||
| 36 | + private static final String PRIORITY = "priority"; | ||
| 37 | + private static final String TYPE = "policy_type"; | ||
| 38 | + private static final String TUNNEL_ID = "tunnel_id"; | ||
| 39 | + private static final String DST_IP = "dst_ip"; | ||
| 40 | + private static final String SRC_IP = "src_ip"; | ||
| 41 | + private static final String PROTO_TYPE = "proto_type"; | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public ObjectNode encode(Policy policy, CodecContext context) { | ||
| 45 | + final ObjectNode result = context.mapper().createObjectNode() | ||
| 46 | + .put(POLICY_ID, policy.id()); | ||
| 47 | + | ||
| 48 | + result.put(PRIORITY, policy.priority()); | ||
| 49 | + result.put(TYPE, policy.type().toString()); | ||
| 50 | + | ||
| 51 | + if (policy.selector().getCriterion(Criterion.Type.IPV4_DST) != null) { | ||
| 52 | + IPCriterion criterion = (IPCriterion) policy.selector().getCriterion( | ||
| 53 | + Criterion.Type.IPV4_DST); | ||
| 54 | + result.put(DST_IP, criterion.ip().toString()); | ||
| 55 | + } | ||
| 56 | + if (policy.selector().getCriterion(Criterion.Type.IPV4_SRC) != null) { | ||
| 57 | + IPCriterion criterion = (IPCriterion) policy.selector().getCriterion( | ||
| 58 | + Criterion.Type.IPV4_SRC); | ||
| 59 | + result.put(SRC_IP, criterion.ip().toString()); | ||
| 60 | + } | ||
| 61 | + if (policy.selector().getCriterion(Criterion.Type.IP_PROTO) != null) { | ||
| 62 | + IPProtocolCriterion protocolCriterion = | ||
| 63 | + (IPProtocolCriterion) policy.selector().getCriterion(Criterion.Type.IP_PROTO); | ||
| 64 | + result.put(PROTO_TYPE, protocolCriterion.toString()); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + if (policy.type() == Policy.Type.TUNNEL_FLOW) { | ||
| 68 | + result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId()); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + return result; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @Override | ||
| 75 | + public Policy decode(ObjectNode json, CodecContext context) { | ||
| 76 | + | ||
| 77 | + String pid = json.path(POLICY_ID).asText(); | ||
| 78 | + String type = json.path(TYPE).asText(); | ||
| 79 | + int priority = json.path(PRIORITY).asInt(); | ||
| 80 | + String dstIp = json.path(DST_IP).asText(); | ||
| 81 | + String srcIp = json.path(SRC_IP).asText(); | ||
| 82 | + String tunnelId = json.path(TUNNEL_ID).asText(); | ||
| 83 | + String protoType = json.path(PROTO_TYPE).asText(); | ||
| 84 | + | ||
| 85 | + if (tunnelId != null) { | ||
| 86 | + TrafficSelector.Builder tsb = DefaultTrafficSelector.builder(); | ||
| 87 | + tsb.matchEthType(Ethernet.TYPE_IPV4); | ||
| 88 | + if (dstIp != null && !dstIp.isEmpty()) { | ||
| 89 | + tsb.matchIPDst(IpPrefix.valueOf(dstIp)); | ||
| 90 | + } | ||
| 91 | + if (srcIp != null && !srcIp.isEmpty()) { | ||
| 92 | + tsb.matchIPSrc(IpPrefix.valueOf(srcIp)); | ||
| 93 | + } | ||
| 94 | + if (protoType != null && !protoType.isEmpty()) { | ||
| 95 | + Short ipProto = Short.valueOf(IpProtocol.valueOf(protoType).value()); | ||
| 96 | + tsb.matchIPProtocol(ipProto.byteValue()); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid); | ||
| 100 | + if (tunnelId != null) { | ||
| 101 | + tpb.setTunnelId(tunnelId); | ||
| 102 | + } | ||
| 103 | + if (!json.path(PRIORITY).isMissingNode()) { | ||
| 104 | + tpb.setPriority(priority); | ||
| 105 | + } | ||
| 106 | + if (!json.path(TYPE).isMissingNode()) { | ||
| 107 | + tpb.setType(Policy.Type.valueOf(type)); | ||
| 108 | + } | ||
| 109 | + tpb.setSelector(tsb.build()); | ||
| 110 | + | ||
| 111 | + return tpb.build(); | ||
| 112 | + } else { | ||
| 113 | + // TODO: handle more policy types | ||
| 114 | + return null; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.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.web; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | + | ||
| 21 | +import org.onosproject.rest.AbstractWebResource; | ||
| 22 | +import org.onosproject.segmentrouting.Policy; | ||
| 23 | +import org.onosproject.segmentrouting.SegmentRoutingManager; | ||
| 24 | +import org.onosproject.segmentrouting.SegmentRoutingService; | ||
| 25 | +import org.onosproject.segmentrouting.TunnelPolicy; | ||
| 26 | + | ||
| 27 | +import javax.ws.rs.Consumes; | ||
| 28 | +import javax.ws.rs.DELETE; | ||
| 29 | +import javax.ws.rs.GET; | ||
| 30 | +import javax.ws.rs.POST; | ||
| 31 | +import javax.ws.rs.Path; | ||
| 32 | +import javax.ws.rs.Produces; | ||
| 33 | +import javax.ws.rs.core.MediaType; | ||
| 34 | +import javax.ws.rs.core.Response; | ||
| 35 | +import java.io.IOException; | ||
| 36 | +import java.io.InputStream; | ||
| 37 | +import java.util.List; | ||
| 38 | + | ||
| 39 | +@Path("policy") | ||
| 40 | +public class PolicyWebResource extends AbstractWebResource { | ||
| 41 | + | ||
| 42 | + private static final PolicyCodec POLICY_CODEC = new PolicyCodec(); | ||
| 43 | + | ||
| 44 | + @GET | ||
| 45 | + @Produces(MediaType.APPLICATION_JSON) | ||
| 46 | + public Response getPolicy() { | ||
| 47 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 48 | + List<Policy> policies = srService.getPolicies(); | ||
| 49 | + ObjectNode result = new ObjectMapper().createObjectNode(); | ||
| 50 | + result.set("policy", new PolicyCodec().encode(policies, this)); | ||
| 51 | + | ||
| 52 | + return ok(result.toString()).build(); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @POST | ||
| 56 | + @Consumes(MediaType.APPLICATION_JSON) | ||
| 57 | + public Response createPolicy(InputStream input) throws IOException { | ||
| 58 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 59 | + ObjectNode policyJson = (ObjectNode) mapper.readTree(input); | ||
| 60 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 61 | + Policy policyInfo = POLICY_CODEC.decode(policyJson, this); | ||
| 62 | + if (policyInfo.type() == Policy.Type.TUNNEL_FLOW) { | ||
| 63 | + TunnelPolicy policy = new TunnelPolicy((SegmentRoutingManager) srService, (TunnelPolicy) policyInfo); | ||
| 64 | + srService.createPolicy(policy); | ||
| 65 | + | ||
| 66 | + return Response.ok().build(); | ||
| 67 | + } else { | ||
| 68 | + return Response.serverError().build(); | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @DELETE | ||
| 73 | + @Consumes(MediaType.APPLICATION_JSON) | ||
| 74 | + public Response removePolicy(InputStream input) throws IOException { | ||
| 75 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 76 | + ObjectNode policyJson = (ObjectNode) mapper.readTree(input); | ||
| 77 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 78 | + Policy policyInfo = POLICY_CODEC.decode(policyJson, this); | ||
| 79 | + // TODO: Check the result | ||
| 80 | + srService.removePolicy(policyInfo); | ||
| 81 | + return Response.ok().build(); | ||
| 82 | + | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | +} |
| 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.web; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 20 | +import org.onosproject.codec.CodecContext; | ||
| 21 | +import org.onosproject.codec.JsonCodec; | ||
| 22 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 23 | +import org.onosproject.segmentrouting.DefaultTunnel; | ||
| 24 | +import org.onosproject.segmentrouting.Tunnel; | ||
| 25 | + | ||
| 26 | +import java.util.ArrayList; | ||
| 27 | +import java.util.List; | ||
| 28 | + | ||
| 29 | +public final class TunnelCodec extends JsonCodec<Tunnel> { | ||
| 30 | + | ||
| 31 | + // JSON field names | ||
| 32 | + private static final String TUNNEL_ID = "tunnel_id"; | ||
| 33 | + private static final String GROUP_ID = "group_id"; | ||
| 34 | + private static final String LABEL_PATH = "label_path"; | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public ObjectNode encode(Tunnel tunnel, CodecContext context) { | ||
| 38 | + final ObjectNode result = context.mapper().createObjectNode() | ||
| 39 | + .put(TUNNEL_ID, tunnel.id()); | ||
| 40 | + | ||
| 41 | + result.put(GROUP_ID, tunnel.groupId()); | ||
| 42 | + | ||
| 43 | + final ArrayNode jsonLabelIds = result.putArray(LABEL_PATH); | ||
| 44 | + | ||
| 45 | + tunnel.labelIds().forEach(label -> jsonLabelIds.add(label.intValue())); | ||
| 46 | + | ||
| 47 | + return result; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public DefaultTunnel decode(ObjectNode json, CodecContext context) { | ||
| 52 | + | ||
| 53 | + String tid = json.path(TUNNEL_ID).asText(); | ||
| 54 | + List<Integer> labels = new ArrayList<>(); | ||
| 55 | + | ||
| 56 | + if (!json.path(LABEL_PATH).isMissingNode()) { | ||
| 57 | + ArrayNode labelArray = (ArrayNode) json.path(LABEL_PATH); | ||
| 58 | + for (JsonNode o : labelArray) { | ||
| 59 | + labels.add(o.asInt()); | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return new DefaultTunnel(tid, labels); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.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.web; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | + | ||
| 21 | +import org.onosproject.rest.AbstractWebResource; | ||
| 22 | +import org.onosproject.segmentrouting.DefaultTunnel; | ||
| 23 | +import org.onosproject.segmentrouting.SegmentRoutingManager; | ||
| 24 | +import org.onosproject.segmentrouting.SegmentRoutingService; | ||
| 25 | +import org.onosproject.segmentrouting.Tunnel; | ||
| 26 | + | ||
| 27 | +import javax.ws.rs.Consumes; | ||
| 28 | +import javax.ws.rs.DELETE; | ||
| 29 | +import javax.ws.rs.GET; | ||
| 30 | +import javax.ws.rs.POST; | ||
| 31 | +import javax.ws.rs.Path; | ||
| 32 | +import javax.ws.rs.Produces; | ||
| 33 | +import javax.ws.rs.core.MediaType; | ||
| 34 | +import javax.ws.rs.core.Response; | ||
| 35 | +import java.io.IOException; | ||
| 36 | +import java.io.InputStream; | ||
| 37 | +import java.util.List; | ||
| 38 | + | ||
| 39 | +@Path("tunnel") | ||
| 40 | +public class TunnelWebResource extends AbstractWebResource { | ||
| 41 | + | ||
| 42 | + private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec(); | ||
| 43 | + | ||
| 44 | + @GET | ||
| 45 | + @Produces(MediaType.APPLICATION_JSON) | ||
| 46 | + public Response getTunnel() { | ||
| 47 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 48 | + List<Tunnel> tunnels = srService.getTunnels(); | ||
| 49 | + ObjectNode result = new ObjectMapper().createObjectNode(); | ||
| 50 | + result.set("tunnel", new TunnelCodec().encode(tunnels, this)); | ||
| 51 | + | ||
| 52 | + return ok(result.toString()).build(); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @POST | ||
| 56 | + @Consumes(MediaType.APPLICATION_JSON) | ||
| 57 | + public Response createTunnel(InputStream input) throws IOException { | ||
| 58 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 59 | + ObjectNode tunnelJson = (ObjectNode) mapper.readTree(input); | ||
| 60 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 61 | + Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this); | ||
| 62 | + Tunnel tunnel = new DefaultTunnel((SegmentRoutingManager) srService, | ||
| 63 | + tunnelInfo.id(), tunnelInfo.labelIds()); | ||
| 64 | + srService.createTunnel(tunnel); | ||
| 65 | + | ||
| 66 | + return Response.ok().build(); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @DELETE | ||
| 70 | + @Consumes(MediaType.APPLICATION_JSON) | ||
| 71 | + public Response removeTunnel(InputStream input) throws IOException { | ||
| 72 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 73 | + ObjectNode tunnelJson = (ObjectNode) mapper.readTree(input); | ||
| 74 | + SegmentRoutingService srService = get(SegmentRoutingService.class); | ||
| 75 | + Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this); | ||
| 76 | + srService.removeTunnel(tunnelInfo); | ||
| 77 | + | ||
| 78 | + return Response.ok().build(); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | +} |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!-- | ||
| 3 | + ~ Copyright 2015 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 | + --> | ||
| 17 | +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" | ||
| 18 | + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
| 19 | + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
| 20 | + id="ONOS" version="2.5"> | ||
| 21 | + <display-name>Segment Routing REST API v1.0</display-name> | ||
| 22 | + | ||
| 23 | + <servlet> | ||
| 24 | + <servlet-name>JAX-RS Service</servlet-name> | ||
| 25 | + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> | ||
| 26 | + <init-param> | ||
| 27 | + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> | ||
| 28 | + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value> | ||
| 29 | + </init-param> | ||
| 30 | + <init-param> | ||
| 31 | + <param-name>com.sun.jersey.config.property.classnames</param-name> | ||
| 32 | + <param-value> | ||
| 33 | + org.onosproject.segmentrouting.web.TunnelWebResource, | ||
| 34 | + org.onosproject.segmentrouting.web.PolicyWebResource | ||
| 35 | + </param-value> | ||
| 36 | + </init-param> | ||
| 37 | + <load-on-startup>1</load-on-startup> | ||
| 38 | + </servlet> | ||
| 39 | + | ||
| 40 | + <servlet-mapping> | ||
| 41 | + <servlet-name>JAX-RS Service</servlet-name> | ||
| 42 | + <url-pattern>/*</url-pattern> | ||
| 43 | + </servlet-mapping> | ||
| 44 | +</web-app> |
| ... | @@ -195,7 +195,6 @@ public final class DefaultNextObjective implements NextObjective { | ... | @@ -195,7 +195,6 @@ public final class DefaultNextObjective implements NextObjective { |
| 195 | checkNotNull(appId, "Must supply an application id"); | 195 | checkNotNull(appId, "Must supply an application id"); |
| 196 | checkNotNull(id, "id cannot be null"); | 196 | checkNotNull(id, "id cannot be null"); |
| 197 | checkNotNull(type, "The type cannot be null"); | 197 | checkNotNull(type, "The type cannot be null"); |
| 198 | - checkArgument(!treatments.isEmpty(), "Must have at least one treatment"); | ||
| 199 | 198 | ||
| 200 | return new DefaultNextObjective(id, treatments, appId, type, Operation.REMOVE); | 199 | return new DefaultNextObjective(id, treatments, appId, type, Operation.REMOVE); |
| 201 | } | 200 | } | ... | ... |
| ... | @@ -49,6 +49,7 @@ import org.onosproject.net.flow.criteria.Criterion; | ... | @@ -49,6 +49,7 @@ import org.onosproject.net.flow.criteria.Criterion; |
| 49 | import org.onosproject.net.flow.criteria.EthCriterion; | 49 | import org.onosproject.net.flow.criteria.EthCriterion; |
| 50 | import org.onosproject.net.flow.criteria.EthTypeCriterion; | 50 | import org.onosproject.net.flow.criteria.EthTypeCriterion; |
| 51 | import org.onosproject.net.flow.criteria.IPCriterion; | 51 | import org.onosproject.net.flow.criteria.IPCriterion; |
| 52 | +import org.onosproject.net.flow.criteria.IPProtocolCriterion; | ||
| 52 | import org.onosproject.net.flow.criteria.MplsCriterion; | 53 | import org.onosproject.net.flow.criteria.MplsCriterion; |
| 53 | import org.onosproject.net.flow.criteria.PortCriterion; | 54 | import org.onosproject.net.flow.criteria.PortCriterion; |
| 54 | import org.onosproject.net.flow.criteria.VlanIdCriterion; | 55 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
| ... | @@ -215,7 +216,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -215,7 +216,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 215 | public void next(NextObjective nextObjective) { | 216 | public void next(NextObjective nextObjective) { |
| 216 | 217 | ||
| 217 | if (nextObjective.op() == Objective.Operation.REMOVE) { | 218 | if (nextObjective.op() == Objective.Operation.REMOVE) { |
| 218 | - if (nextObjective.next() == null) { | 219 | + if (nextObjective.next().isEmpty()) { |
| 219 | removeGroup(nextObjective); | 220 | removeGroup(nextObjective); |
| 220 | } else { | 221 | } else { |
| 221 | removeBucketFromGroup(nextObjective); | 222 | removeBucketFromGroup(nextObjective); |
| ... | @@ -369,8 +370,89 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -369,8 +370,89 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 371 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | 372 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { |
| 372 | - fail(fwd, ObjectiveError.UNSUPPORTED); | 373 | + log.debug("Processing versatile forwarding objective"); |
| 373 | - return Collections.emptySet(); | 374 | + TrafficSelector selector = fwd.selector(); |
| 375 | + | ||
| 376 | + EthTypeCriterion ethType = | ||
| 377 | + (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | ||
| 378 | + if (ethType == null) { | ||
| 379 | + log.error("Versatile forwarding objective must include ethType"); | ||
| 380 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 381 | + return Collections.emptySet(); | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + TrafficSelector.Builder filteredSelectorBuilder = | ||
| 385 | + DefaultTrafficSelector.builder(); | ||
| 386 | + if (ethType.ethType() == Ethernet.TYPE_IPV4) { | ||
| 387 | + IPCriterion ipSrc = (IPCriterion) selector | ||
| 388 | + .getCriterion(Criterion.Type.IPV4_SRC); | ||
| 389 | + IPCriterion ipDst = (IPCriterion) selector | ||
| 390 | + .getCriterion(Criterion.Type.IPV4_DST); | ||
| 391 | + IPProtocolCriterion ipProto = (IPProtocolCriterion) selector | ||
| 392 | + .getCriterion(Criterion.Type.IP_PROTO); | ||
| 393 | + | ||
| 394 | + filteredSelectorBuilder | ||
| 395 | + .matchEthType(Ethernet.TYPE_IPV4); | ||
| 396 | + | ||
| 397 | + if (ipSrc != null) { | ||
| 398 | + filteredSelectorBuilder.matchIPSrc(ipSrc.ip()); | ||
| 399 | + } | ||
| 400 | + if (ipDst != null) { | ||
| 401 | + filteredSelectorBuilder.matchIPDst(ipDst.ip()); | ||
| 402 | + } | ||
| 403 | + if (ipProto != null) { | ||
| 404 | + filteredSelectorBuilder.matchIPProtocol( | ||
| 405 | + Short.valueOf(ipProto.protocol()).byteValue()); | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + log.debug("processing IPv4 specific forwarding objective"); | ||
| 409 | + } else { | ||
| 410 | + log.warn("VERSATILE forwarding objective does not support {} yet.", | ||
| 411 | + ethType.ethType()); | ||
| 412 | + return Collections.emptySet(); | ||
| 413 | + } | ||
| 414 | + | ||
| 415 | + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment | ||
| 416 | + .builder(); | ||
| 417 | + treatmentBuilder.wipeDeferred(); | ||
| 418 | + | ||
| 419 | + if (fwd.nextId() != null) { | ||
| 420 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
| 421 | + | ||
| 422 | + if (next != null) { | ||
| 423 | + GroupKey key = appKryo.deserialize(next.data()); | ||
| 424 | + | ||
| 425 | + Group group = groupService.getGroup(deviceId, key); | ||
| 426 | + | ||
| 427 | + if (group == null) { | ||
| 428 | + log.warn("The group left!"); | ||
| 429 | + fail(fwd, ObjectiveError.GROUPMISSING); | ||
| 430 | + return Collections.emptySet(); | ||
| 431 | + } | ||
| 432 | + treatmentBuilder.deferred().group(group.id()); | ||
| 433 | + log.debug("Adding OUTGROUP action"); | ||
| 434 | + } | ||
| 435 | + } else { | ||
| 436 | + log.warn("VERSATILE forwarding objective need next objective ID."); | ||
| 437 | + return Collections.emptySet(); | ||
| 438 | + } | ||
| 439 | + | ||
| 440 | + TrafficSelector filteredSelector = filteredSelectorBuilder.build(); | ||
| 441 | + TrafficTreatment treatment = treatmentBuilder.build(); | ||
| 442 | + | ||
| 443 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
| 444 | + .fromApp(fwd.appId()).withPriority(fwd.priority()) | ||
| 445 | + .forDevice(deviceId).withSelector(filteredSelector) | ||
| 446 | + .withTreatment(treatment); | ||
| 447 | + | ||
| 448 | + if (fwd.permanent()) { | ||
| 449 | + ruleBuilder.makePermanent(); | ||
| 450 | + } else { | ||
| 451 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + ruleBuilder.forTable(aclTableId); | ||
| 455 | + return Collections.singletonList(ruleBuilder.build()); | ||
| 374 | } | 456 | } |
| 375 | 457 | ||
| 376 | protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | 458 | protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { |
| ... | @@ -434,7 +516,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -434,7 +516,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 434 | fail(fwd, ObjectiveError.GROUPMISSING); | 516 | fail(fwd, ObjectiveError.GROUPMISSING); |
| 435 | return Collections.emptySet(); | 517 | return Collections.emptySet(); |
| 436 | } | 518 | } |
| 437 | - treatmentBuilder.group(group.id()); | 519 | + treatmentBuilder.deferred().group(group.id()); |
| 438 | log.debug("Adding OUTGROUP action"); | 520 | log.debug("Adding OUTGROUP action"); |
| 439 | } else { | 521 | } else { |
| 440 | log.warn("processSpecific: No associated next objective object"); | 522 | log.warn("processSpecific: No associated next objective object"); | ... | ... |
providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
| ... | @@ -104,12 +104,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder { | ... | @@ -104,12 +104,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder { |
| 104 | List<OFInstruction> instructions = Lists.newLinkedList(); | 104 | List<OFInstruction> instructions = Lists.newLinkedList(); |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | - if (immediateActions.size() > 0) { | ||
| 108 | - instructions.add(factory().instructions().applyActions(immediateActions)); | ||
| 109 | - } | ||
| 110 | if (treatment.clearedDeferred()) { | 107 | if (treatment.clearedDeferred()) { |
| 111 | instructions.add(factory().instructions().clearActions()); | 108 | instructions.add(factory().instructions().clearActions()); |
| 112 | } | 109 | } |
| 110 | + if (immediateActions.size() > 0) { | ||
| 111 | + instructions.add(factory().instructions().applyActions(immediateActions)); | ||
| 112 | + } | ||
| 113 | if (deferredActions.size() > 0) { | 113 | if (deferredActions.size() > 0) { |
| 114 | instructions.add(factory().instructions().writeActions(deferredActions)); | 114 | instructions.add(factory().instructions().writeActions(deferredActions)); |
| 115 | } | 115 | } | ... | ... |
-
Please register or login to post a comment