blob: b67cf0bb9d49911acb186b1570774ba1cc611f1b [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabib7911a052014-10-16 17:49:37 -070019package org.onlab.onos.provider.lldp.impl;
20
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabib875d6262014-10-17 16:19:40 -070026import org.onlab.onos.mastership.MastershipService;
alshabib7911a052014-10-16 17:49:37 -070027import org.onlab.onos.net.ConnectPoint;
28import org.onlab.onos.net.Device;
29import org.onlab.onos.net.DeviceId;
alshabibacd91832014-10-17 14:38:41 -070030import org.onlab.onos.net.Port;
alshabib7911a052014-10-16 17:49:37 -070031import org.onlab.onos.net.device.DeviceEvent;
32import org.onlab.onos.net.device.DeviceListener;
33import org.onlab.onos.net.device.DeviceService;
34import org.onlab.onos.net.link.LinkProvider;
35import org.onlab.onos.net.link.LinkProviderRegistry;
36import org.onlab.onos.net.link.LinkProviderService;
37import org.onlab.onos.net.packet.PacketContext;
38import org.onlab.onos.net.packet.PacketProcessor;
39import org.onlab.onos.net.packet.PacketService;
40import org.onlab.onos.net.provider.AbstractProvider;
41import org.onlab.onos.net.provider.ProviderId;
42import org.slf4j.Logger;
43
44import java.util.Map;
45import java.util.concurrent.ConcurrentHashMap;
46
47import static org.slf4j.LoggerFactory.getLogger;
48
49
50/**
51 * Provider which uses an OpenFlow controller to detect network
52 * infrastructure links.
53 */
54@Component(immediate = true)
55public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
56
57 private final Logger log = getLogger(getClass());
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected LinkProviderRegistry providerRegistry;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected DeviceService deviceService;
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected PacketService packetSevice;
67
alshabib875d6262014-10-17 16:19:40 -070068 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected MastershipService masterService;
70
alshabib7911a052014-10-16 17:49:37 -070071 private LinkProviderService providerService;
72
73 private final boolean useBDDP = true;
74
75
76 private final InternalLinkProvider listener = new InternalLinkProvider();
77
78 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
79
80 /**
81 * Creates an OpenFlow link provider.
82 */
83 public LLDPLinkProvider() {
84 super(new ProviderId("lldp", "org.onlab.onos.provider.lldp"));
85 }
86
87 @Activate
88 public void activate() {
89 providerService = providerRegistry.register(this);
90 deviceService.addListener(listener);
91 packetSevice.addProcessor(listener, 0);
alshabibdfc7afb2014-10-21 20:13:27 -070092 LinkDiscovery ld;
93 for (Device device : deviceService.getDevices()) {
94 ld = new LinkDiscovery(device, packetSevice, masterService,
95 providerService, useBDDP);
96 discoverers.put(device.id(), ld);
97 for (Port p : deviceService.getPorts(device.id())) {
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -070098 if (!p.number().isLogical()) {
99 ld.addPort(p);
100 }
alshabibdfc7afb2014-10-21 20:13:27 -0700101 }
102 }
alshabib7911a052014-10-16 17:49:37 -0700103
104 log.info("Started");
105 }
106
107 @Deactivate
108 public void deactivate() {
109 for (LinkDiscovery ld : discoverers.values()) {
110 ld.stop();
111 }
112 providerRegistry.unregister(this);
113 deviceService.removeListener(listener);
114 packetSevice.removeProcessor(listener);
115 providerService = null;
116
117 log.info("Stopped");
118 }
119
120
121 private class InternalLinkProvider implements PacketProcessor, DeviceListener {
122
123 @Override
124 public void event(DeviceEvent event) {
125 LinkDiscovery ld = null;
126 Device device = event.subject();
alshabibacd91832014-10-17 14:38:41 -0700127 Port port = event.port();
alshabibdfc7afb2014-10-21 20:13:27 -0700128 if (device == null) {
129 log.error("Device is null.");
130 return;
131 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700132 log.trace("{} {} {}", event.type(), event.subject(), event);
alshabib7911a052014-10-16 17:49:37 -0700133 switch (event.type()) {
134 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700135 case DEVICE_UPDATED:
136 ld = discoverers.get(device.id());
137 if (ld == null) {
138 log.debug("Device added ({}) {}", event.type(), device.id());
139 discoverers.put(device.id(),
140 new LinkDiscovery(device, packetSevice, masterService,
141 providerService, useBDDP));
142 } else {
143 if (ld.isStopped()) {
144 log.debug("Device restarted ({}) {}", event.type(), device.id());
145 ld.start();
146 }
147 }
alshabib7911a052014-10-16 17:49:37 -0700148 break;
149 case PORT_ADDED:
150 case PORT_UPDATED:
151 if (event.port().isEnabled()) {
alshabibacd91832014-10-17 14:38:41 -0700152 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700153 if (ld == null) {
154 return;
155 }
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700156 if (!port.number().isLogical()) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700157 log.debug("Port added {}", port);
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700158 ld.addPort(port);
159 }
alshabib7911a052014-10-16 17:49:37 -0700160 } else {
alshabibacd91832014-10-17 14:38:41 -0700161 ConnectPoint point = new ConnectPoint(device.id(),
162 port.number());
alshabib7911a052014-10-16 17:49:37 -0700163 providerService.linksVanished(point);
164 }
165 break;
166 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700167 log.debug("Port removed {}", port);
alshabibacd91832014-10-17 14:38:41 -0700168 ConnectPoint point = new ConnectPoint(device.id(),
169 port.number());
alshabib7911a052014-10-16 17:49:37 -0700170 providerService.linksVanished(point);
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700171 // TODO: Don't we need to removePort from ld?
alshabib7911a052014-10-16 17:49:37 -0700172 break;
173 case DEVICE_REMOVED:
174 case DEVICE_SUSPENDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700175 log.debug("Device removed {}", device.id());
alshabibacd91832014-10-17 14:38:41 -0700176 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700177 if (ld == null) {
178 return;
179 }
180 ld.stop();
alshabibacd91832014-10-17 14:38:41 -0700181 providerService.linksVanished(device.id());
alshabib7911a052014-10-16 17:49:37 -0700182 break;
183 case DEVICE_AVAILABILITY_CHANGED:
alshabibacd91832014-10-17 14:38:41 -0700184 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700185 if (ld == null) {
186 return;
187 }
alshabibacd91832014-10-17 14:38:41 -0700188 if (deviceService.isAvailable(device.id())) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700189 log.debug("Device up {}", device.id());
alshabib7911a052014-10-16 17:49:37 -0700190 ld.start();
191 } else {
alshabibacd91832014-10-17 14:38:41 -0700192 providerService.linksVanished(device.id());
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700193 log.debug("Device down {}", device.id());
alshabib7911a052014-10-16 17:49:37 -0700194 ld.stop();
195 }
196 break;
alshabib7911a052014-10-16 17:49:37 -0700197 case DEVICE_MASTERSHIP_CHANGED:
alshabibdfc7afb2014-10-21 20:13:27 -0700198 if (!discoverers.containsKey(device.id())) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700199 // TODO: ideally, should never reach here
200 log.debug("Device mastership changed ({}) {}", event.type(), device.id());
alshabibdfc7afb2014-10-21 20:13:27 -0700201 discoverers.put(device.id(),
202 new LinkDiscovery(device, packetSevice, masterService,
203 providerService, useBDDP));
204 }
alshabib7911a052014-10-16 17:49:37 -0700205 break;
206 default:
207 log.debug("Unknown event {}", event);
208 }
209 }
210
211 @Override
212 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700213 if (context == null) {
214 return;
215 }
alshabib7911a052014-10-16 17:49:37 -0700216 LinkDiscovery ld = discoverers.get(
217 context.inPacket().receivedFrom().deviceId());
218 if (ld == null) {
219 return;
220 }
221
222 if (ld.handleLLDP(context)) {
223 context.block();
224 }
225 }
226 }
227
228}