blob: f29ceecaa1c4ba3db0a4c72c3d9c9809039faa48 [file] [log] [blame]
Yi Tsengc927a062017-05-02 15:02:37 -07001/*
2 * Copyright 2017-present 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
17package org.onosproject.net.intent.impl.installer;
18
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.onosproject.net.flow.FlowRule;
25import org.onosproject.net.flow.FlowRuleOperations;
26import org.onosproject.net.flow.FlowRuleOperationsContext;
27import org.onosproject.net.flow.FlowRuleService;
28import org.onosproject.net.intent.FlowRuleIntent;
29import org.onosproject.net.intent.IntentInstallCoordinator;
30import org.onosproject.net.intent.IntentData;
31import org.onosproject.net.intent.IntentExtensionService;
32import org.onosproject.net.intent.IntentOperationContext;
33import org.onosproject.net.intent.IntentInstaller;
34import org.onosproject.net.intent.impl.IntentManager;
35import org.onosproject.net.intent.impl.ObjectiveTrackerService;
36import org.slf4j.Logger;
37
38import java.util.Collection;
39import java.util.Iterator;
40import java.util.List;
41import java.util.Optional;
42import java.util.Set;
43import static org.onosproject.net.intent.IntentInstaller.Direction.ADD;
44import static org.onosproject.net.intent.IntentInstaller.Direction.REMOVE;
45import static org.onosproject.net.intent.IntentState.INSTALLED;
46import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Installer for FlowRuleIntent.
50 */
51@Component(immediate = true)
52public class FlowRuleIntentInstaller implements IntentInstaller<FlowRuleIntent> {
53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 protected IntentExtensionService intentExtensionService;
55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected ObjectiveTrackerService trackerService;
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected IntentInstallCoordinator intentInstallCoordinator;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected FlowRuleService flowRuleService;
64
65 @Activate
66 public void activate() {
67 intentExtensionService.registerInstaller(FlowRuleIntent.class, this);
68 }
69
70 @Deactivate
71 public void deactivated() {
72 intentExtensionService.unregisterInstaller(FlowRuleIntent.class);
73 }
74
75 protected final Logger log = getLogger(IntentManager.class);
76
77 @Override
78 public void apply(IntentOperationContext<FlowRuleIntent> context) {
79 Optional<IntentData> toUninstall = context.toUninstall();
80 Optional<IntentData> toInstall = context.toInstall();
81
82 List<FlowRuleIntent> uninstallIntents = context.intentsToUninstall();
83 List<FlowRuleIntent> installIntents = context.intentsToInstall();
84
85 if (!toInstall.isPresent() && !toUninstall.isPresent()) {
86 intentInstallCoordinator.intentInstallSuccess(context);
87 return;
88 } else if (!toInstall.isPresent()) {
89 // Uninstall only
90 trackIntentResources(toUninstall.get(), uninstallIntents, REMOVE);
91 } else if (!toUninstall.isPresent()) {
92 // Install only
93 trackIntentResources(toInstall.get(), installIntents, ADD);
94 } else {
95 IntentData uninstall = toUninstall.get();
96 IntentData install = toInstall.get();
97
98 // Filter out same intents and intents with same flow rules
99 Iterator<FlowRuleIntent> iterator = installIntents.iterator();
100 while (iterator.hasNext()) {
101 FlowRuleIntent installIntent = iterator.next();
102 uninstallIntents.stream().filter(uIntent -> {
103 if (uIntent.equals(installIntent)) {
104 return true;
105 } else {
106 return !flowRuleIntentChanged(uIntent, installIntent);
107 }
108 }).findFirst().ifPresent(common -> {
109 uninstallIntents.remove(common);
110 if (INSTALLED.equals(uninstall.state())) {
111 // only remove the install intent if the existing
112 // intent (i.e. the uninstall one) is already
113 // installed or installing
114 iterator.remove();
115 }
116 });
117 }
118 trackIntentResources(uninstall, uninstallIntents, REMOVE);
119 trackIntentResources(install, installIntents, ADD);
120 }
121
122 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
123 builder.newStage();
124
125 toUninstall.ifPresent(intentData -> {
126 uninstallIntents.stream().map(FlowRuleIntent::flowRules)
127 .flatMap(Collection::stream).forEach(builder::remove);
128 });
129
130 toInstall.ifPresent(intentData -> {
131 installIntents.stream().map(FlowRuleIntent::flowRules)
132 .flatMap(Collection::stream).forEach(builder::add);
133 });
134
135 FlowRuleOperationsContext flowRuleOperationsContext = new FlowRuleOperationsContext() {
136 @Override
137 public void onSuccess(FlowRuleOperations ops) {
138 intentInstallCoordinator.intentInstallSuccess(context);
139 }
140
141 @Override
142 public void onError(FlowRuleOperations ops) {
143 intentInstallCoordinator.intentInstallFailed(context);
144 }
145 };
146
147 FlowRuleOperations operations = builder.build(flowRuleOperationsContext);
148
149
150 log.debug("applying intent {} -> {} with {} rules: {}",
151 toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
152 toInstall.map(x -> x.key().toString()).orElse("<empty>"),
153 operations.stages().stream().mapToLong(Set::size).sum(),
154 operations.stages());
155 flowRuleService.apply(operations);
156 }
157
158 /**
159 * Track or un-track network resource of a Intent and it's installable
160 * Intents.
161 *
162 * @param intentData the Intent data
163 * @param intentsToApply the list of flow rule Intents from the Intent
164 * @param direction the direction to determine track or un-track
165 */
166 private void trackIntentResources(IntentData intentData, List<FlowRuleIntent> intentsToApply, Direction direction) {
167 switch (direction) {
168 case ADD:
169 trackerService.addTrackedResources(intentData.key(), intentData.intent().resources());
170 intentsToApply.forEach(installable ->
171 trackerService.addTrackedResources(intentData.key(),
172 installable.resources()));
173 break;
174 default:
175 trackerService.removeTrackedResources(intentData.key(), intentData.intent().resources());
176 intentsToApply.forEach(installable ->
177 trackerService.removeTrackedResources(intentData.intent().key(),
178 installable.resources()));
179 break;
180 }
181 }
182
183 /**
184 * Determines whether there is any flow rule changed
185 * (i.e., different set of flow rules or different treatments)
186 * between FlowRuleIntents to be uninstalled and to be installed.
187 *
188 * @param uninstallIntent FlowRuleIntent to uninstall
189 * @param installIntent FlowRuleIntent to install
190 * @return true if flow rules which to be uninstalled contains all flow
191 * rules which to be installed; false otherwise
192 */
193 private boolean flowRuleIntentChanged(FlowRuleIntent uninstallIntent,
194 FlowRuleIntent installIntent) {
195 Collection<FlowRule> flowRulesToUninstall = uninstallIntent.flowRules();
196 Collection<FlowRule> flowRulesToInstall = installIntent.flowRules();
197
198 // Check if any flow rule changed
199 for (FlowRule flowRuleToInstall : flowRulesToInstall) {
200 if (flowRulesToUninstall.stream().noneMatch(flowRuleToInstall::exactMatch)) {
201 return true;
202 }
203 }
204 return false;
205 }
206
207}