Hyunsun Moon
Committed by Gerrit Code Review

CORD-305 Added basic VTN rules for VMs with openstackswitching

Change-Id: I3eebc3c396b6657457363c183ca8c260b6bb8db4
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
33 33
34 <properties> 34 <properties>
35 <onos.app.name>org.onosproject.cordvtn</onos.app.name> 35 <onos.app.name>org.onosproject.cordvtn</onos.app.name>
36 + <onos.app.requires>
37 + org.onosproject.ovsdb,
38 + org.onosproject.openstackswitching
39 + </onos.app.requires>
36 </properties> 40 </properties>
37 41
38 <dependencies> 42 <dependencies>
...@@ -64,6 +68,11 @@ ...@@ -64,6 +68,11 @@
64 <artifactId>org.apache.karaf.shell.console</artifactId> 68 <artifactId>org.apache.karaf.shell.console</artifactId>
65 <version>3.0.3</version> 69 <version>3.0.3</version>
66 </dependency> 70 </dependency>
71 + <dependency>
72 + <groupId>org.onosproject</groupId>
73 + <artifactId>onos-app-openstackswitching-api</artifactId>
74 + <version>${project.version}</version>
75 + </dependency>
67 </dependencies> 76 </dependencies>
68 77
69 </project> 78 </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.cordvtn;
17 +
18 +import org.onlab.packet.Ip4Address;
19 +import org.onlab.util.ItemNotFoundException;
20 +import org.onosproject.core.ApplicationId;
21 +import org.onosproject.net.DeviceId;
22 +import org.onosproject.net.Port;
23 +import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
24 +import org.onosproject.net.driver.DefaultDriverData;
25 +import org.onosproject.net.driver.DefaultDriverHandler;
26 +import org.onosproject.net.driver.Driver;
27 +import org.onosproject.net.driver.DriverHandler;
28 +import org.onosproject.net.driver.DriverService;
29 +import org.onosproject.net.flow.DefaultTrafficSelector;
30 +import org.onosproject.net.flow.DefaultTrafficTreatment;
31 +import org.onosproject.net.flow.TrafficSelector;
32 +import org.onosproject.net.flow.TrafficTreatment;
33 +import org.onosproject.net.flow.instructions.ExtensionPropertyException;
34 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
35 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
36 +import org.onosproject.net.flowobjective.FlowObjectiveService;
37 +import org.onosproject.net.flowobjective.ForwardingObjective;
38 +import org.slf4j.Logger;
39 +
40 +import java.util.List;
41 +
42 +import static com.google.common.base.Preconditions.checkArgument;
43 +import static com.google.common.base.Preconditions.checkNotNull;
44 +import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
45 +import static org.slf4j.LoggerFactory.getLogger;
46 +
47 +/**
48 + * Populates rules for virtual tenant network.
49 + */
50 +public final class CordVtnRuleInstaller {
51 + protected final Logger log = getLogger(getClass());
52 +
53 + private static final int DEFAULT_PRIORITY = 5000;
54 +
55 + private final ApplicationId appId;
56 + private final FlowObjectiveService flowObjectiveService;
57 + private final DriverService driverService;
58 + private final String tunnelType;
59 +
60 + /**
61 + * Creates a new rule installer.
62 + *
63 + * @param appId application id
64 + * @param flowObjectiveService flow objective service
65 + * @param driverService driver service
66 + * @param tunnelType tunnel type
67 + */
68 + public CordVtnRuleInstaller(ApplicationId appId,
69 + FlowObjectiveService flowObjectiveService,
70 + DriverService driverService,
71 + String tunnelType) {
72 + this.appId = appId;
73 + this.flowObjectiveService = flowObjectiveService;
74 + this.driverService = driverService;
75 + this.tunnelType = checkNotNull(tunnelType);
76 + }
77 +
78 + /**
79 + * Installs flow rules for tunnel in traffic.
80 + *
81 + * @param deviceId device id to install flow rules
82 + * @param inPort in port
83 + * @param dstInfos list of destination info
84 + */
85 + public void installFlowRulesTunnelIn(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
86 + dstInfos.stream().forEach(dstInfo -> {
87 + ForwardingObjective.Builder fBuilder = vtnRulesSameNode(inPort, dstInfo);
88 + if (fBuilder != null) {
89 + flowObjectiveService.forward(deviceId, fBuilder.add());
90 + }
91 + });
92 + }
93 +
94 + /**
95 + * Installs flow rules for local in traffic.
96 + *
97 + * @param deviceId device id to install flow rules
98 + * @param inPort in port
99 + * @param dstInfos list of destination info
100 + */
101 + public void installFlowRulesLocalIn(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
102 + dstInfos.stream().forEach(dstInfo -> {
103 + ForwardingObjective.Builder fBuilder = isTunnelPort(dstInfo.output()) ?
104 + vtnRulesRemoteNode(deviceId, inPort, dstInfo) : vtnRulesSameNode(inPort, dstInfo);
105 +
106 + if (fBuilder != null) {
107 + flowObjectiveService.forward(deviceId, fBuilder.add());
108 + }
109 + });
110 + }
111 +
112 + /**
113 + * Uninstalls flow rules associated with a given port from a given device.
114 + *
115 + * @param deviceId device id
116 + * @param inPort port associated with removed host
117 + * @param dstInfos list of destination info
118 + */
119 + public void uninstallFlowRules(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
120 + dstInfos.stream().forEach(dstInfo -> {
121 + ForwardingObjective.Builder fBuilder = isTunnelPort(dstInfo.output()) ?
122 + vtnRulesRemoteNode(deviceId, inPort, dstInfo) : vtnRulesSameNode(inPort, dstInfo);
123 +
124 + if (fBuilder != null) {
125 + flowObjectiveService.forward(deviceId, fBuilder.remove());
126 + }
127 + });
128 + }
129 +
130 + /**
131 + * Returns forwarding objective builder to provision basic virtual tenant network.
132 + * This method cares for the traffics whose source and destination device is the same.
133 + *
134 + * @param inPort in port
135 + * @param dstInfo destination information
136 + * @return forwarding objective builder
137 + */
138 + private ForwardingObjective.Builder vtnRulesSameNode(Port inPort, DestinationInfo dstInfo) {
139 + checkArgument(inPort.element().id().equals(dstInfo.output().element().id()));
140 +
141 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
142 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
143 +
144 + sBuilder.matchInPort(inPort.number())
145 + .matchEthDst(dstInfo.mac());
146 + if (isTunnelPort(inPort)) {
147 + sBuilder.matchTunnelId(dstInfo.tunnelId());
148 + }
149 +
150 + tBuilder.setOutput(dstInfo.output().number());
151 +
152 + return DefaultForwardingObjective.builder()
153 + .withSelector(sBuilder.build())
154 + .withTreatment(tBuilder.build())
155 + .withPriority(DEFAULT_PRIORITY)
156 + .withFlag(ForwardingObjective.Flag.VERSATILE)
157 + .fromApp(appId)
158 + .makePermanent();
159 + }
160 +
161 + /**
162 + * Returns forwarding objective builder to provision basic virtual tenant network.
163 + * This method cares for the traffics whose source and destination is not the same.
164 + *
165 + * @param deviceId device id to install flow rules
166 + * @param inPort in port
167 + * @param dstInfo destination information
168 + * @return forwarding objective, or null if it fails to build it
169 + */
170 + private ForwardingObjective.Builder vtnRulesRemoteNode(DeviceId deviceId, Port inPort, DestinationInfo dstInfo) {
171 + checkArgument(isTunnelPort(dstInfo.output()));
172 +
173 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
174 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
175 +
176 + ExtensionTreatment extTreatment =
177 + getTunnelDstInstruction(deviceId, dstInfo.remoteIp().getIp4Address());
178 + if (extTreatment == null) {
179 + return null;
180 + }
181 +
182 + sBuilder.matchInPort(inPort.number())
183 + .matchEthDst(dstInfo.mac());
184 +
185 + tBuilder.extension(extTreatment, deviceId)
186 + .setTunnelId(dstInfo.tunnelId())
187 + .setOutput(dstInfo.output().number());
188 +
189 + return DefaultForwardingObjective.builder()
190 + .withSelector(sBuilder.build())
191 + .withTreatment(tBuilder.build())
192 + .withPriority(DEFAULT_PRIORITY)
193 + .withFlag(ForwardingObjective.Flag.VERSATILE)
194 + .fromApp(appId)
195 + .makePermanent();
196 + }
197 +
198 + /**
199 + * Checks if a given port is tunnel interface or not.
200 + * It assumes the tunnel interface contains tunnelType string in its name.
201 + *
202 + * @param port port
203 + * @return true if the port is tunnel interface, false otherwise.
204 + */
205 + private boolean isTunnelPort(Port port) {
206 + return port.annotations().value("portName").contains(tunnelType);
207 + }
208 +
209 + /**
210 + * Returns extension instruction to set tunnel destination.
211 + *
212 + * @param deviceId device id
213 + * @param remoteIp tunnel destination address
214 + * @return extension treatment or null if it fails to get instruction
215 + */
216 + private ExtensionTreatment getTunnelDstInstruction(DeviceId deviceId, Ip4Address remoteIp) {
217 + try {
218 + Driver driver = driverService.getDriver(deviceId);
219 + DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
220 + ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
221 +
222 + ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
223 + treatment.setPropertyValue("tunnelDst", remoteIp);
224 +
225 + return treatment;
226 + } catch (ItemNotFoundException | UnsupportedOperationException | ExtensionPropertyException e) {
227 + log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
228 + return null;
229 + }
230 + }
231 +}
1 +/*
2 + * Copyright 2014-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.cordvtn;
17 +
18 +import org.onlab.packet.IpAddress;
19 +import org.onlab.packet.MacAddress;
20 +import org.onosproject.net.Port;
21 +
22 +import java.util.List;
23 +
24 +import static com.google.common.base.Preconditions.checkNotNull;
25 +
26 +/**
27 + * Contains destination information.
28 + */
29 +public final class DestinationInfo {
30 +
31 + private final Port output;
32 + private final List<IpAddress> ip;
33 + private final MacAddress mac;
34 + private final IpAddress remoteIp;
35 + private final long tunnelId;
36 +
37 + /**
38 + * Creates a new destination information.
39 + *
40 + * @param output output port
41 + * @param ip destination ip address
42 + * @param mac destination mac address
43 + * @param remoteIp tunnel remote ip address
44 + * @param tunnelId segment id
45 + */
46 + public DestinationInfo(Port output, List<IpAddress> ip, MacAddress mac,
47 + IpAddress remoteIp, long tunnelId) {
48 + this.output = checkNotNull(output);
49 + this.ip = ip;
50 + this.mac = mac;
51 + this.remoteIp = remoteIp;
52 + this.tunnelId = tunnelId;
53 + }
54 +
55 + /**
56 + * Returns output port.
57 + *
58 + * @return port
59 + */
60 + public Port output() {
61 + return output;
62 + }
63 +
64 + /**
65 + * Returns destination ip addresses.
66 + *
67 + * @return list of ip address
68 + */
69 + public List<IpAddress> ip() {
70 + return ip;
71 + }
72 +
73 + /**
74 + * Returns destination mac address.
75 + *
76 + * @return mac address
77 + */
78 + public MacAddress mac() {
79 + return mac;
80 + }
81 +
82 + /**
83 + * Returns tunnel remote ip address.
84 + *
85 + * @return ip address
86 + */
87 + public IpAddress remoteIp() {
88 + return remoteIp;
89 + }
90 +
91 + /**
92 + * Returns tunnel id.
93 + *
94 + * @return tunnel id
95 + */
96 + public long tunnelId() {
97 + return tunnelId;
98 + }
99 +
100 + /**
101 + * Returns a new destination info builder.
102 + *
103 + * @return destination info builder
104 + */
105 + public static DestinationInfo.Builder builder(Port output) {
106 + return new Builder(output);
107 + }
108 +
109 + /**
110 + * DestinationInfo builder class.
111 + */
112 + public static final class Builder {
113 +
114 + private final Port output;
115 + private List<IpAddress> ip;
116 + private MacAddress mac;
117 + private IpAddress remoteIp;
118 + private long tunnelId;
119 +
120 + /**
121 + * Creates a new destination information builder.
122 + *
123 + * @param output output port
124 + */
125 + public Builder(Port output) {
126 + this.output = checkNotNull(output, "Output port cannot be null");
127 + }
128 +
129 + /**
130 + * Sets the destination ip address.
131 + *
132 + * @param ip ip address
133 + * @return destination info builder
134 + */
135 + public Builder setIp(List<IpAddress> ip) {
136 + this.ip = checkNotNull(ip, "IP cannot be null");
137 + return this;
138 + }
139 +
140 + /**
141 + * Sets the destination mac address.
142 + *
143 + * @param mac mac address
144 + * @return destination info builder
145 + */
146 + public Builder setMac(MacAddress mac) {
147 + this.mac = checkNotNull(mac, "MAC address cannot be null");
148 + return this;
149 + }
150 +
151 + /**
152 + * Sets the tunnel remote ip address.
153 + *
154 + * @param remoteIp ip address
155 + * @return destination info builder
156 + */
157 + public Builder setRemoteIp(IpAddress remoteIp) {
158 + this.remoteIp = checkNotNull(remoteIp, "Remote IP address cannot be null");
159 + return this;
160 + }
161 +
162 + /**
163 + * Sets the tunnel id.
164 + *
165 + * @param tunnelId tunnel id
166 + * @return destination info builder
167 + */
168 + public Builder setTunnelId(long tunnelId) {
169 + this.tunnelId = checkNotNull(tunnelId, "Tunnel ID cannot be null");
170 + return this;
171 + }
172 +
173 + /**
174 + * Build a destination information.
175 + *
176 + * @return destination info object
177 + */
178 + public DestinationInfo build() {
179 + return new DestinationInfo(this);
180 + }
181 + }
182 +
183 + private DestinationInfo(Builder builder) {
184 + output = builder.output;
185 + ip = builder.ip;
186 + mac = builder.mac;
187 + remoteIp = builder.remoteIp;
188 + tunnelId = builder.tunnelId;
189 + }
190 +}