blob: 1019c55340354e1c47c1a619d2dc4ecc7aa6dba8 [file] [log] [blame]
Georgios Katsikas70671b32018-07-02 18:47:27 +02001/*
2 * Copyright 2018 Open Networking Foundation
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
17package org.onosproject.drivers.server;
18
Georgios Katsikas70671b32018-07-02 18:47:27 +020019import org.onosproject.drivers.server.devices.nic.NicFlowRule;
20import org.onosproject.drivers.server.devices.nic.NicRxFilter.RxFilter;
21import org.onosproject.net.DeviceId;
Georgios Katsikas042a0fc2018-08-16 18:49:07 +020022import org.onosproject.net.driver.Driver;
23import org.onosproject.net.driver.DriverService;
Georgios Katsikas70671b32018-07-02 18:47:27 +020024import org.onosproject.net.flow.DefaultFlowEntry;
25import org.onosproject.net.flow.FlowEntry;
26import org.onosproject.net.flow.FlowRule;
27import org.onosproject.net.flow.FlowRuleProgrammable;
28import org.onosproject.net.flow.FlowRuleService;
29
Georgios Katsikas042a0fc2018-08-16 18:49:07 +020030import org.slf4j.Logger;
31
Georgios Katsikas13ccba62020-03-18 12:05:03 +010032import com.fasterxml.jackson.databind.JsonNode;
33import com.fasterxml.jackson.databind.ObjectMapper;
34import com.fasterxml.jackson.databind.node.ArrayNode;
35import com.fasterxml.jackson.databind.node.ObjectNode;
36import com.google.common.base.Strings;
37import com.google.common.collect.Sets;
38
Georgios Katsikas70671b32018-07-02 18:47:27 +020039import java.io.ByteArrayInputStream;
40import java.io.IOException;
41import java.io.InputStream;
42import java.util.Collection;
43import java.util.Collections;
Georgios Katsikas332985d2019-01-21 13:23:26 +010044import java.util.Iterator;
Georgios Katsikas042a0fc2018-08-16 18:49:07 +020045import java.util.List;
Georgios Katsikas70671b32018-07-02 18:47:27 +020046import java.util.Map;
47import java.util.Set;
48import java.util.concurrent.ConcurrentHashMap;
49import javax.ws.rs.ProcessingException;
50
51import static com.google.common.base.Preconditions.checkArgument;
52import static com.google.common.base.Preconditions.checkNotNull;
Georgios Katsikas13ccba62020-03-18 12:05:03 +010053import static org.onosproject.drivers.server.Constants.JSON;
54import static org.onosproject.drivers.server.Constants.MSG_DEVICE_ID_NULL;
Georgios Katsikas13ccba62020-03-18 12:05:03 +010055import static org.onosproject.drivers.server.Constants.PARAM_CPUS;
Georgios Katsikas1a64c3a2020-06-03 17:30:43 +020056import static org.onosproject.drivers.server.Constants.PARAM_ID;
57import static org.onosproject.drivers.server.Constants.PARAM_NAME;
Georgios Katsikas13ccba62020-03-18 12:05:03 +010058import static org.onosproject.drivers.server.Constants.PARAM_NICS;
59import static org.onosproject.drivers.server.Constants.PARAM_NIC_RX_FILTER;
60import static org.onosproject.drivers.server.Constants.PARAM_NIC_RX_FILTER_FD;
61import static org.onosproject.drivers.server.Constants.PARAM_NIC_RX_METHOD;
62import static org.onosproject.drivers.server.Constants.PARAM_RULES;
63import static org.onosproject.drivers.server.Constants.PARAM_RULE_CONTENT;
64import static org.onosproject.drivers.server.Constants.SLASH;
65import static org.onosproject.drivers.server.Constants.URL_RULE_MANAGEMENT;
Georgios Katsikas70671b32018-07-02 18:47:27 +020066import static org.slf4j.LoggerFactory.getLogger;
67
68/**
69 * Manages rules on commodity server devices, by
70 * converting ONOS FlowRule objetcs into
71 * network interface card (NIC) rules and vice versa.
72 */
Georgios Katsikas13ccba62020-03-18 12:05:03 +010073public class FlowRuleProgrammableServerImpl
74 extends BasicServerDriver
Georgios Katsikas70671b32018-07-02 18:47:27 +020075 implements FlowRuleProgrammable {
76
77 private final Logger log = getLogger(getClass());
78
79 /**
Georgios Katsikas042a0fc2018-08-16 18:49:07 +020080 * Driver's property to specify how many rules the controller can remove at once.
81 */
82 private static final String RULE_DELETE_BATCH_SIZE_PROPERTY = "ruleDeleteBatchSize";
Georgios Katsikas70671b32018-07-02 18:47:27 +020083
Georgios Katsikas13ccba62020-03-18 12:05:03 +010084 public FlowRuleProgrammableServerImpl() {
85 super();
86 log.debug("Started");
87 }
88
Georgios Katsikas70671b32018-07-02 18:47:27 +020089 @Override
90 public Collection<FlowEntry> getFlowEntries() {
Georgios Katsikas13ccba62020-03-18 12:05:03 +010091 DeviceId deviceId = getDeviceId();
92 checkNotNull(deviceId, MSG_DEVICE_ID_NULL);
Georgios Katsikas70671b32018-07-02 18:47:27 +020093
94 // Expected FlowEntries installed through ONOS
95 FlowRuleService flowService = getHandler().get(FlowRuleService.class);
96 Iterable<FlowEntry> flowEntries = flowService.getFlowEntries(deviceId);
97
98 // Hit the path that provides the server's flow rules
99 InputStream response = null;
100 try {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100101 response = getController().get(deviceId, URL_RULE_MANAGEMENT, JSON);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200102 } catch (ProcessingException pEx) {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200103 log.error("Failed to get NIC flow entries from device: {}", deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200104 return Collections.EMPTY_LIST;
105 }
106
107 // Load the JSON into objects
108 ObjectMapper mapper = new ObjectMapper();
109 ObjectNode objNode = null;
110 try {
111 Map<String, Object> jsonMap = mapper.readValue(response, Map.class);
112 JsonNode jsonNode = mapper.convertValue(jsonMap, JsonNode.class);
113 objNode = (ObjectNode) jsonNode;
114 } catch (IOException ioEx) {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200115 log.error("Failed to get NIC flow entries from device: {}", deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200116 return Collections.EMPTY_LIST;
117 }
118
119 if (objNode == null) {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200120 log.error("Failed to get NIC flow entries from device: {}", deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200121 return Collections.EMPTY_LIST;
122 }
123
124 JsonNode scsNode = objNode.path(PARAM_RULES);
125
126 // Here we store the trully installed rules
127 Collection<FlowEntry> actualFlowEntries =
128 Sets.<FlowEntry>newConcurrentHashSet();
129
130 for (JsonNode scNode : scsNode) {
131 String scId = get(scNode, PARAM_ID);
132 String rxFilter = get(
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100133 scNode.path(PARAM_NIC_RX_FILTER), PARAM_NIC_RX_METHOD);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200134
135 // Only Flow-based RxFilter is permitted
136 if (RxFilter.getByName(rxFilter) != RxFilter.FLOW) {
137 log.warn("Device with Rx filter {} is not managed by this driver",
138 rxFilter.toString().toUpperCase());
139 continue;
140 }
141
142 // Each device might have multiple NICs
143 for (JsonNode nicNode : scNode.path(PARAM_NICS)) {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200144 JsonNode cpusNode = nicNode.path(PARAM_CPUS);
145
146 // Each NIC can dispatch to multiple CPU cores
147 for (JsonNode cpuNode : cpusNode) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100148 String cpuId = get(cpuNode, PARAM_ID);
149 JsonNode rulesNode = cpuNode.path(PARAM_RULES);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200150
151 // Multiple rules might correspond to each CPU core
152 for (JsonNode ruleNode : rulesNode) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100153 long ruleId = ruleNode.path(PARAM_ID).asLong();
Georgios Katsikas70671b32018-07-02 18:47:27 +0200154 String ruleContent = get(ruleNode, PARAM_RULE_CONTENT);
155
156 // Search for this rule ID in ONOS's store
157 FlowRule r = findRuleInFlowEntries(flowEntries, ruleId);
158
159 // Local rule, not present in the controller => Ignore
160 if (r == null) {
161 continue;
162 // Rule trully present in the data plane => Add
163 } else {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200164 actualFlowEntries.add(new DefaultFlowEntry(
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100165 r, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
Georgios Katsikas70671b32018-07-02 18:47:27 +0200166 }
167 }
168 }
169 }
170 }
171
172 return actualFlowEntries;
173 }
174
175 @Override
176 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100177 DeviceId deviceId = getDeviceId();
178 checkNotNull(deviceId, MSG_DEVICE_ID_NULL);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200179
180 // Set of truly-installed rules to be reported
181 Set<FlowRule> installedRules = Sets.<FlowRule>newConcurrentHashSet();
182
183 // Splits the rule set into multiple ones, grouped by traffic class ID
184 Map<String, Set<FlowRule>> rulesPerTc = groupRules(rules);
185
186 // Install NIC rules on a per-traffic class basis
187 for (Map.Entry<String, Set<FlowRule>> entry : rulesPerTc.entrySet()) {
188 String tcId = entry.getKey();
189 Set<FlowRule> tcRuleSet = entry.getValue();
190
191 installedRules.addAll(
192 installNicFlowRules(deviceId, tcId, tcRuleSet)
193 );
194 }
195
196 return installedRules;
197 }
198
199 @Override
200 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100201 DeviceId deviceId = getDeviceId();
202 checkNotNull(deviceId, MSG_DEVICE_ID_NULL);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200203
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200204 int ruleDeleteBatchSize = getRuleDeleteBatchSizeProperty(deviceId);
205
Georgios Katsikas70671b32018-07-02 18:47:27 +0200206 // Set of truly-removed rules to be reported
207 Set<FlowRule> removedRules = Sets.<FlowRule>newConcurrentHashSet();
208
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200209 List<FlowRule> ruleList = (List) rules;
210 int ruleCount = rules.size();
211 int ruleStart = 0;
212 int processed = 0;
213 int batchNb = 1;
214 while (processed < ruleCount) {
215 String ruleIds = "";
216
217 for (int i = ruleStart; i < ruleCount; i++) {
218 // Batch completed
219 if (i >= (batchNb * ruleDeleteBatchSize)) {
220 break;
221 }
222
223 // TODO: Turn this string into a list and modify removeNicFlowRuleBatch()
224 // Create a comma-separated sequence of rule IDs
225 ruleIds += Long.toString(ruleList.get(i).id().value()) + ",";
226
227 processed++;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200228 }
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200229
230 // Remove last comma
231 ruleIds = ruleIds.substring(0, ruleIds.length() - 1);
232
233 // Remove the entire batch of rules at once
234 if (removeNicFlowRuleBatch(deviceId, ruleIds)) {
235 removedRules.addAll(ruleList.subList(ruleStart, processed));
236 }
237
238 // Prepare for the next batch (if any)
239 batchNb++;
240 ruleStart += ruleDeleteBatchSize;
241 }
Georgios Katsikas70671b32018-07-02 18:47:27 +0200242
243 return removedRules;
244 }
245
246 /**
247 * Groups a set of FlowRules by their traffic class ID.
248 *
249 * @param rules set of NIC rules to install
250 * @return a map of traffic class IDs to their set of NIC rules
251 */
252 private Map<String, Set<FlowRule>> groupRules(Collection<FlowRule> rules) {
253 Map<String, Set<FlowRule>> rulesPerTc =
254 new ConcurrentHashMap<String, Set<FlowRule>>();
255
256 rules.forEach(rule -> {
257 if (!(rule instanceof FlowEntry)) {
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100258 NicFlowRule nicRule = null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200259
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100260 // Only NicFlowRules are accepted
261 try {
262 nicRule = (NicFlowRule) rule;
263 } catch (ClassCastException cEx) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100264 log.warn("Skipping flow rule not crafted for NIC: {}", rule);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200265 }
266
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100267 if (nicRule != null) {
268 String tcId = nicRule.trafficClassId();
269
270 // Create a bucket of flow rules for this traffic class
271 if (!rulesPerTc.containsKey(tcId)) {
272 rulesPerTc.put(tcId, Sets.<FlowRule>newConcurrentHashSet());
273 }
274
275 Set<FlowRule> tcRuleSet = rulesPerTc.get(tcId);
276 tcRuleSet.add(nicRule);
277 }
Georgios Katsikas70671b32018-07-02 18:47:27 +0200278 }
279 });
280
281 return rulesPerTc;
282 }
283
284 /**
285 * Searches for a flow rule with certain ID.
286 *
287 * @param flowEntries a list of FlowEntries
288 * @param ruleId a desired rule ID
289 * @return a FlowRule that corresponds to the desired ID or null
290 */
291 private FlowRule findRuleInFlowEntries(
292 Iterable<FlowEntry> flowEntries, long ruleId) {
293 for (FlowEntry fe : flowEntries) {
294 if (fe.id().value() == ruleId) {
295 return (FlowRule) fe;
296 }
297 }
298
299 return null;
300 }
301
302 /**
303 * Installs a set of FlowRules of the same traffic class ID
304 * on a server device.
305 *
306 * @param deviceId target server device ID
307 * @param trafficClassId traffic class ID of the NIC rules
308 * @param rules set of NIC rules to install
309 * @return a set of successfully installed NIC rules
310 */
311 private Collection<FlowRule> installNicFlowRules(
312 DeviceId deviceId, String trafficClassId,
313 Collection<FlowRule> rules) {
Georgios Katsikas332985d2019-01-21 13:23:26 +0100314 int rulesToInstall = rules.size();
315 if (rulesToInstall == 0) {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200316 return Collections.EMPTY_LIST;
317 }
318
319 ObjectMapper mapper = new ObjectMapper();
320
321 // Create the object node to host the list of rules
322 ObjectNode scsObjNode = mapper.createObjectNode();
323
324 // Add the service chain's traffic class ID that requested these rules
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100325 scsObjNode.put(PARAM_ID, trafficClassId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200326
327 // Create the object node to host the Rx filter method
328 ObjectNode methodObjNode = mapper.createObjectNode();
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100329 methodObjNode.put(PARAM_NIC_RX_METHOD, PARAM_NIC_RX_FILTER_FD);
330 scsObjNode.put(PARAM_NIC_RX_FILTER, methodObjNode);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200331
332 // Map each core to an array of rule IDs and rules
333 Map<Long, ArrayNode> cpuObjSet =
334 new ConcurrentHashMap<Long, ArrayNode>();
335
Georgios Katsikas80e0b9f2018-07-21 20:29:18 +0200336 String nic = null;
Georgios Katsikas332985d2019-01-21 13:23:26 +0100337 Iterator<FlowRule> it = rules.iterator();
Georgios Katsikas70671b32018-07-02 18:47:27 +0200338
Georgios Katsikas332985d2019-01-21 13:23:26 +0100339 while (it.hasNext()) {
340 NicFlowRule nicRule = (NicFlowRule) it.next();
341 if (nicRule.isFullWildcard() && (rulesToInstall > 1)) {
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100342 log.warn("Skipping wildcard flow rule: {}", nicRule);
Georgios Katsikas332985d2019-01-21 13:23:26 +0100343 it.remove();
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100344 continue;
345 }
346
Georgios Katsikas70671b32018-07-02 18:47:27 +0200347 long coreIndex = nicRule.cpuCoreIndex();
348
349 // Keep the ID of the target NIC
Georgios Katsikas80e0b9f2018-07-21 20:29:18 +0200350 if (nic == null) {
351 nic = findNicInterfaceWithPort(deviceId, nicRule.interfaceNumber());
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200352 checkArgument(!Strings.isNullOrEmpty(nic),
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100353 "Attempted to install flow rules in an invalid NIC");
Georgios Katsikas70671b32018-07-02 18:47:27 +0200354 }
355
356 // Create a JSON array for this CPU core
357 if (!cpuObjSet.containsKey(coreIndex)) {
358 cpuObjSet.put(coreIndex, mapper.createArrayNode());
359 }
360
361 // The array of rules that corresponds to this CPU core
362 ArrayNode ruleArrayNode = cpuObjSet.get(coreIndex);
363
364 // Each rule has an ID and a content
365 ObjectNode ruleNode = mapper.createObjectNode();
Georgios Katsikas1a64c3a2020-06-03 17:30:43 +0200366 ruleNode.put(PARAM_ID, nicRule.id().value());
367 ruleNode.put(PARAM_RULE_CONTENT, nicRule.ruleBody());
Georgios Katsikas70671b32018-07-02 18:47:27 +0200368
369 ruleArrayNode.add(ruleNode);
370 }
371
Georgios Katsikas332985d2019-01-21 13:23:26 +0100372 if (rules.size() == 0) {
373 log.error("Failed to install {} NIC flow rules in device {}", rulesToInstall, deviceId);
374 return Collections.EMPTY_LIST;
375 }
376
Georgios Katsikas70671b32018-07-02 18:47:27 +0200377 ObjectNode nicObjNode = mapper.createObjectNode();
Georgios Katsikas1a64c3a2020-06-03 17:30:43 +0200378 nicObjNode.put(PARAM_NAME, nic);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200379
380 ArrayNode cpusArrayNode = nicObjNode.putArray(PARAM_CPUS);
381
382 // Convert the map of CPU cores to arrays of rules to JSON
383 for (Map.Entry<Long, ArrayNode> entry : cpuObjSet.entrySet()) {
384 long coreIndex = entry.getKey();
385 ArrayNode ruleArrayNode = entry.getValue();
386
387 ObjectNode cpuObjNode = mapper.createObjectNode();
Georgios Katsikas1a64c3a2020-06-03 17:30:43 +0200388 cpuObjNode.put(PARAM_ID, coreIndex);
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100389 cpuObjNode.putArray(PARAM_RULES).addAll(ruleArrayNode);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200390
391 cpusArrayNode.add(cpuObjNode);
392 }
393
394 scsObjNode.putArray(PARAM_NICS).add(nicObjNode);
395
396 // Create the object node to host all the data
397 ObjectNode sendObjNode = mapper.createObjectNode();
398 sendObjNode.putArray(PARAM_RULES).add(scsObjNode);
399
400 // Post the NIC rules to the server
401 int response = getController().post(
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100402 deviceId, URL_RULE_MANAGEMENT,
Georgios Katsikas70671b32018-07-02 18:47:27 +0200403 new ByteArrayInputStream(sendObjNode.toString().getBytes()), JSON);
404
405 // Upon an error, return an empty set of rules
406 if (!checkStatusCode(response)) {
Georgios Katsikas332985d2019-01-21 13:23:26 +0100407 log.error("Failed to install {} NIC flow rules in device {}", rules.size(), deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200408 return Collections.EMPTY_LIST;
409 }
410
Georgios Katsikas332985d2019-01-21 13:23:26 +0100411 log.info("Successfully installed {}/{} NIC flow rules in device {}",
412 rules.size(), rulesToInstall, deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200413
414 // .. or all of them
415 return rules;
416 }
417
418 /**
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200419 * Removes a batch of FlowRules from a server device
420 * using a single REST command.
Georgios Katsikas70671b32018-07-02 18:47:27 +0200421 *
422 * @param deviceId target server device ID
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200423 * @param ruleIds a batch of comma-separated NIC rule IDs to be removed
Georgios Katsikas70671b32018-07-02 18:47:27 +0200424 * @return boolean removal status
425 */
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200426 private boolean removeNicFlowRuleBatch(DeviceId deviceId, String ruleIds) {
Georgios Katsikas30bede52018-07-28 14:46:07 +0200427 int response = -1;
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200428 long ruleCount = ruleIds.chars().filter(ch -> ch == ',').count() + 1;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200429
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200430 // Try to remove the rules, although server might be unreachable
Georgios Katsikas30bede52018-07-28 14:46:07 +0200431 try {
432 response = getController().delete(deviceId,
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100433 URL_RULE_MANAGEMENT + SLASH + ruleIds, null, JSON);
Georgios Katsikas30bede52018-07-28 14:46:07 +0200434 } catch (Exception ex) {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200435 log.error("Failed to remove NIC flow rule batch with {} rules from device {}", ruleCount, deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200436 return false;
437 }
438
Georgios Katsikas30bede52018-07-28 14:46:07 +0200439 if (!checkStatusCode(response)) {
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200440 log.error("Failed to remove NIC flow rule batch with {} rules from device {}", ruleCount, deviceId);
Georgios Katsikas30bede52018-07-28 14:46:07 +0200441 return false;
442 }
Georgios Katsikas70671b32018-07-02 18:47:27 +0200443
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200444 log.info("Successfully removed NIC flow rule batch with {} rules from device {}", ruleCount, deviceId);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200445 return true;
446 }
447
Georgios Katsikas042a0fc2018-08-16 18:49:07 +0200448 /**
449 * Returns how many rules this driver can delete at once.
450 *
451 * @param deviceId the device's ID to delete rules from
452 * @return rule deletion batch size
453 */
454 private int getRuleDeleteBatchSizeProperty(DeviceId deviceId) {
455 Driver driver = getHandler().get(DriverService.class).getDriver(deviceId);
456 return Integer.parseInt(driver.getProperty(RULE_DELETE_BATCH_SIZE_PROPERTY));
457 }
458
Georgios Katsikas70671b32018-07-02 18:47:27 +0200459}