blob: c4cd4b2fa664aea4816fb5ec828b36d71f0148e0 [file] [log] [blame]
Anton Chigrinbf14b372019-01-14 17:29:56 +02001/*
2 * Copyright 2019-present 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 */
16package org.onosproject.openflow.controller.impl;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.Map;
22import java.util.Set;
23import java.util.Collections;
24import java.util.stream.Collectors;
25import com.google.common.collect.Maps;
26import com.google.common.collect.Sets;
27import com.google.common.collect.ImmutableSet;
28
29import org.osgi.service.component.annotations.Activate;
30import org.osgi.service.component.annotations.Component;
31import org.osgi.service.component.annotations.Deactivate;
32import org.osgi.service.component.annotations.Reference;
33import org.osgi.service.component.annotations.ReferenceCardinality;
34import org.onosproject.event.ListenerRegistry;
35import org.onosproject.net.DeviceId;
36import org.onosproject.openflow.controller.OpenFlowClassifier;
37import org.onosproject.openflow.controller.OpenFlowClassifierConfig;
38import org.onosproject.openflow.controller.OpenFlowEvent;
39import org.onosproject.openflow.controller.OpenFlowListener;
40import org.onosproject.openflow.controller.OpenFlowService;
41import org.slf4j.Logger;
42
43import org.onosproject.net.config.ConfigFactory;
44import org.onosproject.net.config.NetworkConfigService;
45import org.onosproject.net.config.NetworkConfigRegistry;
46import org.onosproject.net.config.NetworkConfigListener;
47import org.onosproject.net.config.NetworkConfigEvent;
48import static org.onosproject.net.config.basics.SubjectFactories.DEVICE_SUBJECT_FACTORY;
49
50/**
51 * Manages the inventory of OpenFlow Classifiers in the system.
52 */
53@Component(immediate = true, service = OpenFlowService.class)
54public class OpenFlowClassifierManager extends ListenerRegistry<OpenFlowEvent, OpenFlowListener>
55 implements OpenFlowService {
56
57 private Logger log = getLogger(getClass());
58
59 private final InternalConfigListener listener = new InternalConfigListener();
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY)
62 protected NetworkConfigService cfgService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY)
65 protected NetworkConfigRegistry cfgRegistry;
66
67 private static final String FEATURE_NAME = "classifiers";
68 private final Set<ConfigFactory<?, ?>> factories = ImmutableSet.of(
69 new ConfigFactory<DeviceId, OpenFlowClassifierConfig>(DEVICE_SUBJECT_FACTORY,
70 OpenFlowClassifierConfig.class, FEATURE_NAME,
71 true) {
72 @Override
73 public OpenFlowClassifierConfig createConfig() {
74 return new OpenFlowClassifierConfig();
75 }
76 }
77 );
78
79 private final Map<DeviceId, Set<OpenFlowClassifier>> classifiersMap = Maps.newConcurrentMap();
80
81 @Activate
82 private void activate() {
83 factories.forEach(cfgRegistry::registerConfigFactory);
84 cfgService.addListener(listener);
85
86 for (DeviceId subject : cfgService.getSubjects(DeviceId.class, OpenFlowClassifierConfig.class)) {
87 OpenFlowClassifierConfig config = cfgService.getConfig(subject, OpenFlowClassifierConfig.class);
88
89 if (config != null) {
90 updateClassifiers(config);
91 }
92 }
93
94 log.info("Started Openflow Manager");
95 }
96
97 @Deactivate
98 private void deactivate() {
99 cfgService.removeListener(listener);
100
101 factories.forEach(cfgRegistry::unregisterConfigFactory);
102 log.info("Stopped Openflow manager");
103
104 }
105
106 @Override
107 public void add(OpenFlowClassifier classifier) {
108 checkNotNull(classifier, "Classifier cannot be null");
109
110 OpenFlowClassifierConfig config =
111 cfgService.addConfig(classifier.deviceId(), OpenFlowClassifierConfig.class);
112 config.addClassifier(classifier);
113 cfgService.applyConfig(classifier.deviceId(), OpenFlowClassifierConfig.class, config.node());
114 }
115
116 @Override
117 public void remove(OpenFlowClassifier classifier) {
118 checkNotNull(classifier, "Classifier cannot be null");
119
120 OpenFlowClassifierConfig config = cfgService.getConfig(classifier.deviceId(), OpenFlowClassifierConfig.class);
121
122 if (config == null) {
123 return;
124 }
125
126 config.removeClassifier(classifier);
127 cfgService.applyConfig(classifier.deviceId(), OpenFlowClassifierConfig.class, config.node());
128 }
129
130 @Override
131 public Set<OpenFlowClassifier> getClassifiers() {
132 Set<OpenFlowClassifier> classifiers = Sets.newHashSet();
133
134 classifiersMap.values().forEach(c -> classifiers.addAll(c));
135
136 return classifiers;
137 }
138
139 @Override
140 public Set<OpenFlowClassifier> getClassifiersByDeviceId(DeviceId deviceId) {
141 return classifiersMap.get(deviceId);
142 }
143
144 @Override
145 public Set<OpenFlowClassifier> getClassifiersByDeviceIdAndQueue(DeviceId deviceId, int idQueue) {
146 Set<OpenFlowClassifier> classifiers = classifiersMap.get(deviceId);
147 if (classifiers == null) {
148 return null;
149 } else {
150 return classifiers.stream()
151 .filter(p -> p.idQueue() == idQueue)
152 .collect(Collectors.toSet());
153 }
154 }
155
156 private void updateClassifiers(OpenFlowClassifierConfig classfConfig) {
157 Set<OpenFlowClassifier> old = classifiersMap.put(classfConfig.subject(),
158 Sets.newHashSet(classfConfig.getClassifiers()));
159
160 if (old == null) {
161 old = Collections.emptySet();
162 }
163
164 for (OpenFlowClassifier classf : classfConfig.getClassifiers()) {
165 if (old.contains(classf)) {
166 old.remove(classf);
167 } else {
168 process(new OpenFlowEvent(OpenFlowEvent.Type.INSERT, classf));
169 }
170 }
171
172 for (OpenFlowClassifier classf : old) {
173 process(new OpenFlowEvent(OpenFlowEvent.Type.REMOVE, classf));
174 }
175 }
176
177 private void removeClassifiers(DeviceId deviceId) {
178 Set<OpenFlowClassifier> old = classifiersMap.remove(deviceId);
179
180 for (OpenFlowClassifier classf : old) {
181 process(new OpenFlowEvent(OpenFlowEvent.Type.REMOVE, classf));
182 }
183 }
184
185 /**
186 * Listener for network config events.
187 */
188 private class InternalConfigListener implements NetworkConfigListener {
189
190 @Override
191 public void event(NetworkConfigEvent event) {
192 if (event.configClass() == OpenFlowClassifierConfig.class) {
193 switch (event.type()) {
194 case CONFIG_ADDED:
195 case CONFIG_UPDATED:
196 event.config().ifPresent(config -> updateClassifiers((OpenFlowClassifierConfig) config));
197 break;
198 case CONFIG_REMOVED:
199 removeClassifiers((DeviceId) event.subject());
200 break;
201 case CONFIG_REGISTERED:
202 case CONFIG_UNREGISTERED:
203 default:
204 break;
205 }
206 }
207 }
208 }
209}