blob: 5693db595cb1fb718c65b8f481cd5edc17fe6de4 [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
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
Jonathan Hart7dbe6292015-11-10 08:33:17 -080021import com.google.common.collect.Sets;
Jonathan Harteb8c9472015-08-05 07:43:13 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
27import org.apache.felix.scr.annotations.Service;
28import org.onlab.packet.IpAddress;
29import org.onlab.packet.VlanId;
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -070030import org.onosproject.event.ListenerRegistry;
Jonathan Hart4cb39882015-08-12 23:50:55 -040031import org.onosproject.incubator.net.config.basics.ConfigException;
Jonathan Harteb8c9472015-08-05 07:43:13 -070032import org.onosproject.incubator.net.config.basics.InterfaceConfig;
Ray Milkeyfacf2862017-08-03 11:58:29 -070033import org.onosproject.net.intf.Interface;
34import org.onosproject.net.intf.InterfaceAdminService;
35import org.onosproject.net.intf.InterfaceEvent;
36import org.onosproject.net.intf.InterfaceListener;
37import org.onosproject.net.intf.InterfaceService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070038import org.onosproject.net.ConnectPoint;
Jonathan Hart4cb39882015-08-12 23:50:55 -040039import org.onosproject.net.config.NetworkConfigEvent;
40import org.onosproject.net.config.NetworkConfigListener;
41import org.onosproject.net.config.NetworkConfigService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
Charles Chanb3b09cd2017-03-14 12:53:46 -070045import java.util.Collection;
Jonathan Hart4cb39882015-08-12 23:50:55 -040046import java.util.Collections;
Jonathan Harteb8c9472015-08-05 07:43:13 -070047import java.util.Map;
48import java.util.Optional;
49import java.util.Set;
Charles Chanb3b09cd2017-03-14 12:53:46 -070050import java.util.stream.Stream;
Jonathan Harteb8c9472015-08-05 07:43:13 -070051
52import static java.util.stream.Collectors.collectingAndThen;
53import static java.util.stream.Collectors.toSet;
54
55/**
56 * Manages the inventory of interfaces in the system.
57 */
58@Service
59@Component(immediate = true)
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -070060public class InterfaceManager extends ListenerRegistry<InterfaceEvent, InterfaceListener>
61 implements InterfaceService, InterfaceAdminService {
Jonathan Harteb8c9472015-08-05 07:43:13 -070062
63 private final Logger log = LoggerFactory.getLogger(getClass());
64
Jonathan Hart4cb39882015-08-12 23:50:55 -040065 private static final Class<ConnectPoint> SUBJECT_CLASS = ConnectPoint.class;
66 private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;
Jonathan Harteb8c9472015-08-05 07:43:13 -070067
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart4cb39882015-08-12 23:50:55 -040069 protected NetworkConfigService configService;
Jonathan Harteb8c9472015-08-05 07:43:13 -070070
71 private final InternalConfigListener listener = new InternalConfigListener();
72
73 private final Map<ConnectPoint, Set<Interface>> interfaces = Maps.newConcurrentMap();
74
75 @Activate
76 public void activate() {
77 configService.addListener(listener);
78
Jonathan Hart4cb39882015-08-12 23:50:55 -040079 // TODO address concurrency issues here
80 for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) {
81 InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS);
Jonathan Harteb8c9472015-08-05 07:43:13 -070082
Jonathan Hart4cb39882015-08-12 23:50:55 -040083 if (config != null) {
84 updateInterfaces(config);
Jonathan Harteb8c9472015-08-05 07:43:13 -070085 }
86 }
87
88 log.info("Started");
89 }
90
91 @Deactivate
92 public void deactivate() {
93 configService.removeListener(listener);
94
95 log.info("Stopped");
96 }
97
98 @Override
99 public Set<Interface> getInterfaces() {
100 return interfaces.values()
101 .stream()
102 .flatMap(set -> set.stream())
103 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
104 }
105
106 @Override
Jonathan Hart43d232e2016-02-03 15:34:10 -0800107 public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
108 Optional<Interface> intf =
109 interfaces.getOrDefault(connectPoint, Collections.emptySet())
110 .stream()
111 .filter(i -> i.name().equals(name))
112 .findAny();
113
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800114 return intf.orElse(null);
Jonathan Hart43d232e2016-02-03 15:34:10 -0800115 }
116
117 @Override
Jonathan Harteb8c9472015-08-05 07:43:13 -0700118 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400119 Set<Interface> intfs = interfaces.get(port);
120 if (intfs == null) {
121 return Collections.emptySet();
122 }
123 return ImmutableSet.copyOf(intfs);
Jonathan Harteb8c9472015-08-05 07:43:13 -0700124 }
125
126 @Override
127 public Set<Interface> getInterfacesByIp(IpAddress ip) {
128 return interfaces.values()
129 .stream()
Charles Chanb3b09cd2017-03-14 12:53:46 -0700130 .flatMap(Collection::stream)
131 .filter(intf -> intf.ipAddressesList()
Jonathan Hart4cb39882015-08-12 23:50:55 -0400132 .stream()
133 .anyMatch(ia -> ia.ipAddress().equals(ip)))
Jonathan Harteb8c9472015-08-05 07:43:13 -0700134 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
135 }
136
137 @Override
138 public Interface getMatchingInterface(IpAddress ip) {
Charles Chanb3b09cd2017-03-14 12:53:46 -0700139 return getMatchingInterfacesStream(ip).findFirst().orElse(null);
140 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700141
Charles Chanb3b09cd2017-03-14 12:53:46 -0700142 @Override
143 public Set<Interface> getMatchingInterfaces(IpAddress ip) {
144 return getMatchingInterfacesStream(ip).collect(toSet());
145 }
146
147 private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
148 return interfaces.values()
149 .stream()
150 .flatMap(Collection::stream)
151 .filter(intf -> intf.ipAddressesList()
152 .stream()
153 .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
Jonathan Harteb8c9472015-08-05 07:43:13 -0700154 }
155
156 @Override
157 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
158 return interfaces.values()
159 .stream()
Charles Chanb3b09cd2017-03-14 12:53:46 -0700160 .flatMap(Collection::stream)
Jonathan Harteb8c9472015-08-05 07:43:13 -0700161 .filter(intf -> intf.vlan().equals(vlan))
162 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
163 }
164
165 private void updateInterfaces(InterfaceConfig intfConfig) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400166 try {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700167 Set<Interface> old = interfaces.put(intfConfig.subject(),
168 Sets.newHashSet(intfConfig.getInterfaces()));
169
170 if (old == null) {
171 old = Collections.emptySet();
172 }
173
174 for (Interface intf : intfConfig.getInterfaces()) {
175 if (intf.name().equals(Interface.NO_INTERFACE_NAME)) {
176 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
177 } else {
178 Optional<Interface> oldIntf = findInterface(intf, old);
179 if (oldIntf.isPresent()) {
180 old.remove(oldIntf.get());
181 if (!oldIntf.get().equals(intf)) {
gaurav2c626cc2016-04-26 04:18:33 +0530182 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_UPDATED, intf, oldIntf.get()));
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700183 }
184 } else {
185 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
186 }
187 }
188 }
189
190 for (Interface intf : old) {
191 if (!intf.name().equals(Interface.NO_INTERFACE_NAME)) {
192 process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf));
193 }
194 }
Jonathan Hart4cb39882015-08-12 23:50:55 -0400195 } catch (ConfigException e) {
196 log.error("Error in interface config", e);
197 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700198 }
199
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700200 private Optional<Interface> findInterface(Interface intf, Set<Interface> set) {
201 return set.stream().filter(i -> i.name().equals(intf.name())).findAny();
202 }
203
Jonathan Harteb8c9472015-08-05 07:43:13 -0700204 private void removeInterfaces(ConnectPoint port) {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700205 Set<Interface> old = interfaces.remove(port);
206
207 old.stream()
208 .filter(i -> !i.name().equals(Interface.NO_INTERFACE_NAME))
209 .forEach(i -> process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, i)));
Jonathan Harteb8c9472015-08-05 07:43:13 -0700210 }
211
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700212 @Override
213 public void add(Interface intf) {
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700214 InterfaceConfig config =
215 configService.addConfig(intf.connectPoint(), CONFIG_CLASS);
216
217 config.addInterface(intf);
218
219 configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node());
220 }
221
222 @Override
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800223 public boolean remove(ConnectPoint connectPoint, String name) {
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800224 InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS);
225 config.removeInterface(name);
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700226
227 try {
228 if (config.getInterfaces().isEmpty()) {
229 configService.removeConfig(connectPoint, CONFIG_CLASS);
230 } else {
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800231 configService.applyConfig(connectPoint, CONFIG_CLASS, config.node());
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700232 }
233 } catch (ConfigException e) {
234 log.error("Error reading interfaces JSON", e);
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700235 return false;
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700236 }
Jonathan Hart7dbe6292015-11-10 08:33:17 -0800237
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700238 return true;
Jonathan Hart0bdf8372015-10-08 14:30:36 -0700239 }
240
Jonathan Harteb8c9472015-08-05 07:43:13 -0700241 /**
242 * Listener for network config events.
243 */
244 private class InternalConfigListener implements NetworkConfigListener {
245
246 @Override
247 public void event(NetworkConfigEvent event) {
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700248 if (event.configClass() == CONFIG_CLASS) {
249 switch (event.type()) {
250 case CONFIG_ADDED:
251 case CONFIG_UPDATED:
Jonathan Harteb8c9472015-08-05 07:43:13 -0700252 InterfaceConfig config =
253 configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
254 updateInterfaces(config);
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700255 break;
256 case CONFIG_REMOVED:
Jonathan Harteb8c9472015-08-05 07:43:13 -0700257 removeInterfaces((ConnectPoint) event.subject());
Jonathan Hart4b5c6dc2015-10-13 14:27:48 -0700258 break;
259 case CONFIG_REGISTERED:
260 case CONFIG_UNREGISTERED:
261 default:
262 break;
Jonathan Harteb8c9472015-08-05 07:43:13 -0700263 }
Jonathan Harteb8c9472015-08-05 07:43:13 -0700264 }
265 }
266 }
267}