blob: 7a28bc48a3442576e529bc09591bee37b513a06e [file] [log] [blame]
Jonathan Harteb8c9472015-08-05 07:43:13 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Jonathan Harteb8c9472015-08-05 07:43:13 -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 */
16
Ray Milkeyfacf2862017-08-03 11:58:29 -070017package org.onosproject.net.intf.impl;
Jonathan Harteb8c9472015-08-05 07:43:13 -070018
Deepa Vaddireddy2740a112017-10-26 06:23:26 +000019
Jonathan Harteb8c9472015-08-05 07:43:13 -070020import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Maps;
Jonathan Hart7dbe6292015-11-10 08:33:17 -080022import com.google.common.collect.Sets;
Jonathan Harteb8c9472015-08-05 07:43:13 -070023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
28import org.apache.felix.scr.annotations.Service;
29import org.onlab.packet.IpAddress;
30import org.onlab.packet.VlanId;
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -070031import org.onosproject.event.ListenerRegistry;
Ray Milkey6c013742017-08-15 10:16:43 -070032import org.onosproject.net.config.ConfigException;
33import org.onosproject.net.config.basics.InterfaceConfig;
Ray Milkeyfacf2862017-08-03 11:58:29 -070034import org.onosproject.net.intf.Interface;
35import org.onosproject.net.intf.InterfaceAdminService;
36import org.onosproject.net.intf.InterfaceEvent;
37import org.onosproject.net.intf.InterfaceListener;
38import org.onosproject.net.intf.InterfaceService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070039import org.onosproject.net.ConnectPoint;
Deepa Vaddireddy2740a112017-10-26 06:23:26 +000040import org.onosproject.net.config.BasicNetworkConfigService;
Jonathan Hart4cb39882015-08-12 23:50:55 -040041import org.onosproject.net.config.NetworkConfigEvent;
42import org.onosproject.net.config.NetworkConfigListener;
43import org.onosproject.net.config.NetworkConfigService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
Charles Chanb3b09cd2017-03-14 12:53:46 -070047import java.util.Collection;
Jonathan Hart4cb39882015-08-12 23:50:55 -040048import java.util.Collections;
Jonathan Harteb8c9472015-08-05 07:43:13 -070049import java.util.Map;
50import java.util.Optional;
51import java.util.Set;
Charles Chanb3b09cd2017-03-14 12:53:46 -070052import java.util.stream.Stream;
Jonathan Harteb8c9472015-08-05 07:43:13 -070053
54import static java.util.stream.Collectors.collectingAndThen;
55import static java.util.stream.Collectors.toSet;
56
57/**
58 * Manages the inventory of interfaces in the system.
59 */
60@Service
61@Component(immediate = true)
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -070062public class InterfaceManager extends ListenerRegistry<InterfaceEvent, InterfaceListener>
63 implements InterfaceService, InterfaceAdminService {
Jonathan Harteb8c9472015-08-05 07:43:13 -070064
65 private final Logger log = LoggerFactory.getLogger(getClass());
66
Jonathan Hart4cb39882015-08-12 23:50:55 -040067 private static final Class<ConnectPoint> SUBJECT_CLASS = ConnectPoint.class;
68 private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;
Jonathan Harteb8c9472015-08-05 07:43:13 -070069
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart4cb39882015-08-12 23:50:55 -040071 protected NetworkConfigService configService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070072
Deepa Vaddireddy2740a112017-10-26 06:23:26 +000073 //Dependency to ensure subject factories are properly initialized
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected BasicNetworkConfigService basicNetworkConfigService;
76
Jonathan Harteb8c9472015-08-05 07:43:13 -070077 private final InternalConfigListener listener = new InternalConfigListener();
78
79 private final Map<ConnectPoint, Set<Interface>> interfaces = Maps.newConcurrentMap();
80
81 @Activate
82 public void activate() {
83 configService.addListener(listener);
84
Jonathan Hart4cb39882015-08-12 23:50:55 -040085 // TODO address concurrency issues here
86 for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) {
87 InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS);
Jonathan Harteb8c9472015-08-05 07:43:13 -070088
Jonathan Hart4cb39882015-08-12 23:50:55 -040089 if (config != null) {
90 updateInterfaces(config);
Jonathan Harteb8c9472015-08-05 07:43:13 -070091 }
92 }
93
94 log.info("Started");
95 }
96
97 @Deactivate
98 public void deactivate() {
99 configService.removeListener(listener);
100
101 log.info("Stopped");
102 }
103
104 @Override
105 public Set<Interface> getInterfaces() {
106 return interfaces.values()
107 .stream()
108 .flatMap(set -> set.stream())
109 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
110 }
111
112 @Override
Jonathan Hart43d232e2016-02-03 15:34:10 -0800113 public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
114 Optional<Interface> intf =
115 interfaces.getOrDefault(connectPoint, Collections.emptySet())
116 .stream()
117 .filter(i -> i.name().equals(name))
118 .findAny();
119
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800120 return intf.orElse(null);
Jonathan Hart43d232e2016-02-03 15:34:10 -0800121 }
122
123 @Override
Jonathan Harteb8c9472015-08-05 07:43:13 -0700124 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400125 Set<Interface> intfs = interfaces.get(port);
126 if (intfs == null) {
127 return Collections.emptySet();
128 }
129 return ImmutableSet.copyOf(intfs);
Jonathan Harteb8c9472015-08-05 07:43:13 -0700130 }
131
132 @Override
133 public Set<Interface> getInterfacesByIp(IpAddress ip) {
134 return interfaces.values()
135 .stream()
Charles Chanb3b09cd2017-03-14 12:53:46 -0700136 .flatMap(Collection::stream)
137 .filter(intf -> intf.ipAddressesList()
Jonathan Hart4cb39882015-08-12 23:50:55 -0400138 .stream()
139 .anyMatch(ia -> ia.ipAddress().equals(ip)))
Jonathan Harteb8c9472015-08-05 07:43:13 -0700140 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
141 }
142
143 @Override
144 public Interface getMatchingInterface(IpAddress ip) {
Charles Chanb3b09cd2017-03-14 12:53:46 -0700145 return getMatchingInterfacesStream(ip).findFirst().orElse(null);
146 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700147
Charles Chanb3b09cd2017-03-14 12:53:46 -0700148 @Override
149 public Set<Interface> getMatchingInterfaces(IpAddress ip) {
150 return getMatchingInterfacesStream(ip).collect(toSet());
151 }
152
153 private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
154 return interfaces.values()
155 .stream()
156 .flatMap(Collection::stream)
157 .filter(intf -> intf.ipAddressesList()
158 .stream()
159 .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
Jonathan Harteb8c9472015-08-05 07:43:13 -0700160 }
161
162 @Override
163 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
164 return interfaces.values()
165 .stream()
Charles Chanb3b09cd2017-03-14 12:53:46 -0700166 .flatMap(Collection::stream)
Jonathan Harteb8c9472015-08-05 07:43:13 -0700167 .filter(intf -> intf.vlan().equals(vlan))
168 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
169 }
170
171 private void updateInterfaces(InterfaceConfig intfConfig) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400172 try {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700173 Set<Interface> old = interfaces.put(intfConfig.subject(),
174 Sets.newHashSet(intfConfig.getInterfaces()));
175
176 if (old == null) {
177 old = Collections.emptySet();
178 }
179
180 for (Interface intf : intfConfig.getInterfaces()) {
181 if (intf.name().equals(Interface.NO_INTERFACE_NAME)) {
182 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
183 } else {
184 Optional<Interface> oldIntf = findInterface(intf, old);
185 if (oldIntf.isPresent()) {
186 old.remove(oldIntf.get());
187 if (!oldIntf.get().equals(intf)) {
gaurav2c626cc2016-04-26 04:18:33 +0530188 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_UPDATED, intf, oldIntf.get()));
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700189 }
190 } else {
191 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
192 }
193 }
194 }
195
196 for (Interface intf : old) {
197 if (!intf.name().equals(Interface.NO_INTERFACE_NAME)) {
198 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf));
199 }
200 }
Jonathan Hart4cb39882015-08-12 23:50:55 -0400201 } catch (ConfigException e) {
202 log.error("Error in interface config", e);
203 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700204 }
205
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700206 private Optional<Interface> findInterface(Interface intf, Set<Interface> set) {
207 return set.stream().filter(i -> i.name().equals(intf.name())).findAny();
208 }
209
Jonathan Harteb8c9472015-08-05 07:43:13 -0700210 private void removeInterfaces(ConnectPoint port) {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700211 Set<Interface> old = interfaces.remove(port);
212
213 old.stream()
214 .filter(i -> !i.name().equals(Interface.NO_INTERFACE_NAME))
215 .forEach(i -> process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, i)));
Jonathan Harteb8c9472015-08-05 07:43:13 -0700216 }
217
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700218 @Override
219 public void add(Interface intf) {
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700220 InterfaceConfig config =
221 configService.addConfig(intf.connectPoint(), CONFIG_CLASS);
222
223 config.addInterface(intf);
224
225 configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node());
226 }
227
228 @Override
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800229 public boolean remove(ConnectPoint connectPoint, String name) {
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800230 InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS);
231 config.removeInterface(name);
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700232
233 try {
234 if (config.getInterfaces().isEmpty()) {
235 configService.removeConfig(connectPoint, CONFIG_CLASS);
236 } else {
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800237 configService.applyConfig(connectPoint, CONFIG_CLASS, config.node());
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700238 }
239 } catch (ConfigException e) {
240 log.error("Error reading interfaces JSON", e);
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700241 return false;
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700242 }
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800243
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700244 return true;
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700245 }
246
Jonathan Harteb8c9472015-08-05 07:43:13 -0700247 /**
248 * Listener for network config events.
249 */
250 private class InternalConfigListener implements NetworkConfigListener {
251
252 @Override
253 public void event(NetworkConfigEvent event) {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700254 if (event.configClass() == CONFIG_CLASS) {
255 switch (event.type()) {
256 case CONFIG_ADDED:
257 case CONFIG_UPDATED:
Charles Chanee993b12017-08-14 13:32:49 -0700258 event.config().ifPresent(config -> updateInterfaces((InterfaceConfig) config));
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700259 break;
260 case CONFIG_REMOVED:
Jonathan Harteb8c9472015-08-05 07:43:13 -0700261 removeInterfaces((ConnectPoint) event.subject());
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700262 break;
263 case CONFIG_REGISTERED:
264 case CONFIG_UNREGISTERED:
265 default:
266 break;
Jonathan Harteb8c9472015-08-05 07:43:13 -0700267 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700268 }
269 }
270 }
271}