blob: e6ed5bf50d1000c77c062587e8c8ad196ab22741 [file] [log] [blame]
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -07003 *
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 */
Hyunsun Moon05400872017-02-07 17:11:25 +090016package org.onosproject.openstacknetworking.impl;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070017
18import org.onlab.packet.Ip4Address;
sangho072c4dd2017-05-17 10:45:21 +090019import org.onlab.packet.IpAddress;
20import org.onosproject.core.ApplicationId;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070021import org.onosproject.net.Device;
22import org.onosproject.net.DeviceId;
sangho072c4dd2017-05-17 10:45:21 +090023import org.onosproject.net.behaviour.ExtensionSelectorResolver;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070024import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
25import org.onosproject.net.device.DeviceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070026import org.onosproject.net.flow.instructions.ExtensionPropertyException;
27import org.onosproject.net.flow.instructions.ExtensionTreatment;
sangho072c4dd2017-05-17 10:45:21 +090028import org.onosproject.net.driver.DriverHandler;
29import org.onosproject.net.driver.DriverService;
30import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
32import org.onosproject.net.flow.criteria.ExtensionSelector;
33import org.onosproject.net.flow.criteria.ExtensionSelectorType;
34import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
35import org.onosproject.net.flowobjective.DefaultForwardingObjective;
36import org.onosproject.net.flowobjective.FlowObjectiveService;
37import org.onosproject.net.flowobjective.ForwardingObjective;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070038import org.slf4j.Logger;
39
sangho072c4dd2017-05-17 10:45:21 +090040import java.util.ArrayList;
41import java.util.List;
42
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070043import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
44import static org.slf4j.LoggerFactory.getLogger;
45
46/**
47 * Provides common methods to help populating flow rules for SONA applications.
48 */
49public final class RulePopulatorUtil {
50
51 protected static final Logger log = getLogger(RulePopulatorUtil.class);
52
53 private static final String TUNNEL_DST = "tunnelDst";
sangho072c4dd2017-05-17 10:45:21 +090054 private static final String CT_FLAGS = "flags";
55 private static final String CT_ZONE = "zone";
56 private static final String CT_TABLE = "recircTable";
57 private static final String CT = "niciraCt";
58 private static final String CT_STATE = "ctState";
59 private static final String CT_STATE_MASK = "ctStateMask";
60 private static final String CT_PRESENT_FLAGS = "presentFlags";
61 private static final String CT_IPADDRESS_MIN = "ipAddressMin";
62 private static final String CT_IPADDRESS_MAX = "ipAddressMax";
63
64 private static final int ADDRESS_MIN_FLAG = 0;
65 private static final int ADDRESS_MAX_FLAG = 1;
66 private static final int PORT_MIN_FLAG = 2;
67 private static final int PORT_MAX_FLAG = 3;
68
69 // Refer to http://openvswitch.org/support/dist-docs/ovs-fields.7.txt for the values
70 public static final long CT_STATE_NONE = 0;
71 public static final long CT_STATE_NEW = 0x01;
72 public static final long CT_STATE_EST = 0x02;
73 public static final long CT_STATE_NOT_TRK = 0x20;
74 public static final long CT_STATE_TRK = 0x20;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070075
76 private RulePopulatorUtil() {
77 }
78
79 /**
sangho072c4dd2017-05-17 10:45:21 +090080 * Returns a builder for OVS Connection Tracking feature actions.
81 *
82 * @param ds DriverService
83 * @param id DeviceId
84 * @return a builder for OVS Connection Tracking feature actions
85 */
86 public static NiriraConnTrackTreatmentBuilder niciraConnTrackTreatmentBuilder(DriverService ds, DeviceId id) {
87 return new NiriraConnTrackTreatmentBuilder(ds, id);
88 }
89
90 /**
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070091 * Returns tunnel destination extension treatment object.
92 *
93 * @param deviceService driver service
94 * @param deviceId device id to apply this treatment
95 * @param remoteIp tunnel destination ip address
96 * @return extension treatment
97 */
98 public static ExtensionTreatment buildExtension(DeviceService deviceService,
99 DeviceId deviceId,
100 Ip4Address remoteIp) {
101 Device device = deviceService.getDevice(deviceId);
sangho072c4dd2017-05-17 10:45:21 +0900102 if (device != null && !device.is(ExtensionTreatmentResolver.class)) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700103 log.error("The extension treatment is not supported");
104 return null;
105 }
sangho072c4dd2017-05-17 10:45:21 +0900106
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700107 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
108 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
109 try {
110 treatment.setPropertyValue(TUNNEL_DST, remoteIp);
111 return treatment;
112 } catch (ExtensionPropertyException e) {
113 log.warn("Failed to get tunnelDst extension treatment for {}", deviceId);
114 return null;
115 }
116 }
sangho072c4dd2017-05-17 10:45:21 +0900117
118 /**
119 * Builds OVS ConnTrack matches.
120 *
121 * @param driverService driver service
122 * @param deviceId device ID
123 * @param ctState connection tracking sate masking value
124 * @param ctSateMask connection tracking sate masking value
125 * @return OVS ConnTrack extension match
126 */
127 public static ExtensionSelector buildCtExtensionSelector(DriverService driverService, DeviceId deviceId,
128 long ctState, long ctSateMask) {
129 DriverHandler handler = driverService.createHandler(deviceId);
130 ExtensionSelectorResolver esr = handler.behaviour(ExtensionSelectorResolver.class);
131
132 ExtensionSelector extensionSelector = esr.getExtensionSelector(
133 ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type());
134 try {
135 extensionSelector.setPropertyValue(CT_STATE, ctState);
136 extensionSelector.setPropertyValue(CT_STATE_MASK, ctSateMask);
137 } catch (Exception e) {
138 log.error("Failed to set nicira match CT state");
139 return null;
140 }
141
142 return extensionSelector;
143 }
144
145 /**
146 * Adds flow rules with the supplied information.
147 *
148 * @param flowObjectiveService flow objective service
149 * @param appId application id
150 * @param deviceId device id to remove this flow rule
151 * @param selector traffic selector
152 * @param treatment traffic treatment
153 * @param flag flag
154 * @param priority priority
155 * @param install populate flows if true, remove them otherwise
156 */
157 public static void setRule(FlowObjectiveService flowObjectiveService,
158 ApplicationId appId,
159 DeviceId deviceId,
160 TrafficSelector selector,
161 TrafficTreatment treatment,
162 ForwardingObjective.Flag flag,
163 int priority,
164 boolean install) {
165 ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
166 .withSelector(selector)
167 .withTreatment(treatment)
168 .withFlag(flag)
169 .withPriority(priority)
170 .fromApp(appId);
171
172 if (install) {
173 flowObjectiveService.forward(deviceId, foBuilder.add());
174 } else {
175 flowObjectiveService.forward(deviceId, foBuilder.remove());
176 }
177 }
178
179 /**
180 * Computes ConnTack State flag values.
181 *
182 * @param isTracking true for +trk, false for -trk
183 * @param isNew true for +new, false for nothing
184 * @param isEstablished true for +est, false for nothing
185 * @return ConnTrack State flags
186 */
187 public static long computeCtStateFlag(boolean isTracking, boolean isNew, boolean isEstablished) {
188 long ctMaskFlag = 0x00;
189
190 if (isTracking) {
191 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
192 }
193
194 if (isNew) {
195 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
196 ctMaskFlag = ctMaskFlag | CT_STATE_NEW;
197 }
198
199 if (isEstablished) {
200 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
201 ctMaskFlag = ctMaskFlag | CT_STATE_EST;
202 }
203
204 return ctMaskFlag;
205 }
206
207 /**
208 * Computes ConnTrack State mask values.
209 *
210 * @param isTracking true for setting +trk/-trk value, false for otherwise
211 * @param isNew true for setting +new value, false for otherwise
212 * @param isEstablished true for setting +est value, false for otherwise
213 * @return ConnTrack State Mask value
214 */
215 public static long computeCtMaskFlag(boolean isTracking, boolean isNew, boolean isEstablished) {
216 long ctMaskFlag = 0x00;
217
218 if (isTracking) {
219 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
220 }
221
222 if (isNew) {
223 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
224 ctMaskFlag = ctMaskFlag | CT_STATE_NEW;
225 }
226
227 if (isEstablished) {
228 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
229 ctMaskFlag = ctMaskFlag | CT_STATE_EST;
230 }
231
232 return ctMaskFlag;
233 }
234
235 /**
236 * Builder class for OVS Connection Tracking feature actions.
237 */
238 public static final class NiriraConnTrackTreatmentBuilder {
239
240 private DriverService driverService;
241 private DeviceId deviceId;
242 private IpAddress natAddress = null;
243 private int zone;
244 private boolean commit;
245 private short table = -1;
246 private boolean natAction;
247
248
249 private NiriraConnTrackTreatmentBuilder(DriverService driverService, DeviceId deviceId) {
250 this.driverService = driverService;
251 this.deviceId = deviceId;
252 }
253
254 /**
255 * Sets commit flag.
256 *
257 * @param c true if commit, false if not.
258 * @return NiriraConnTrackTreatmentBuilder object
259 */
260 public NiriraConnTrackTreatmentBuilder commit(boolean c) {
261 this.commit = c;
262 return this;
263 }
264
265 /**
266 * Sets zone number.
267 *
268 * @param z zone number
269 * @return NiriraConnTrackTreatmentBuilder object
270 */
271 public NiriraConnTrackTreatmentBuilder zone(int z) {
272 this.zone = z;
273 return this;
274 }
275
276 /**
277 * Sets recirculation table number.
278 *
279 * @param t table number to restart
280 * @return NiriraConnTrackTreatmentBuilder object
281 */
282 public NiriraConnTrackTreatmentBuilder table(short t) {
283 this.table = t;
284 return this;
285 }
286
287 /**
288 * Sets IP address for NAT.
289 *
290 * @param ip NAT IP address
291 * @return NiriraConnTrackTreatmentBuilder object
292 */
293 public NiriraConnTrackTreatmentBuilder natIp(IpAddress ip) {
294 this.natAddress = ip;
295 return this;
296 }
297
298 /**
299 * Sets the flag for NAT action.
300 *
301 * @param nat nat action is included if true, no nat action otherwise
302 * @return NiriraConnTrackTreatmentBuilder object
303 */
304 public NiriraConnTrackTreatmentBuilder natAction(boolean nat) {
305 this.natAction = nat;
306 return this;
307 }
308
309 /**
310 * Builds extension treatment for OVS ConnTack and NAT feature.
311 *
312 * @return ExtensionTreatment object
313 */
314 public ExtensionTreatment build() {
315 DriverHandler handler = driverService.createHandler(deviceId);
316 ExtensionTreatmentResolver etr = handler.behaviour(ExtensionTreatmentResolver.class);
317
318 ExtensionTreatment natTreatment
319 = etr.getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type());
320 try {
321 if (natAddress != null) {
322 natTreatment.setPropertyValue(CT_FLAGS, 1);
323 natTreatment.setPropertyValue(CT_PRESENT_FLAGS, buildPresentFlag(false, true));
324 natTreatment.setPropertyValue(CT_IPADDRESS_MIN, natAddress);
325 natTreatment.setPropertyValue(CT_IPADDRESS_MAX, natAddress);
326 } else {
327 natTreatment.setPropertyValue(CT_FLAGS, 0);
328 natTreatment.setPropertyValue(CT_PRESENT_FLAGS, 0);
329 }
330 } catch (Exception e) {
331 log.error("Failed to set NAT due to error : {}", e.getMessage());
332 return null;
333 }
334
335 ExtensionTreatment ctTreatment
336 = etr.getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type());
337 try {
338 List<ExtensionTreatment> nat = new ArrayList<>();
339 if (natAction) {
340 nat.add(natTreatment);
341 }
342 ctTreatment.setPropertyValue(CT_FLAGS, commit ? 1 : 0);
343 ctTreatment.setPropertyValue(CT_ZONE, zone);
344 ctTreatment.setPropertyValue(CT_TABLE, table > -1 ? table : 0xff);
345 ctTreatment.setPropertyValue("nestedActions", nat);
346 } catch (Exception e) {
347 log.error("Failed to set CT due to error : {}", e.getMessage());
348 return null;
349 }
350
351 return ctTreatment;
352 }
353
354 private int buildPresentFlag(boolean isPortPresent, boolean isAddressPresent) {
355
356 int presentFlag = 0;
357
358 if (isPortPresent) {
359 presentFlag = presentFlag | 1 << PORT_MIN_FLAG | 1 << PORT_MAX_FLAG;
360 }
361
362 if (isAddressPresent) {
363 presentFlag = 1 << ADDRESS_MIN_FLAG | 1 << ADDRESS_MAX_FLAG;
364 }
365
366 return presentFlag;
367 }
368 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700369}