blob: 6dc464e4b4e5a1ec21039648f04b1334379e6a6f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
alshabib7911a052014-10-16 17:49:37 -070016package org.onlab.onos.provider.lldp.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabib875d6262014-10-17 16:19:40 -070023import org.onlab.onos.mastership.MastershipService;
alshabib7911a052014-10-16 17:49:37 -070024import org.onlab.onos.net.ConnectPoint;
25import org.onlab.onos.net.Device;
26import org.onlab.onos.net.DeviceId;
alshabibacd91832014-10-17 14:38:41 -070027import org.onlab.onos.net.Port;
alshabib7911a052014-10-16 17:49:37 -070028import org.onlab.onos.net.device.DeviceEvent;
29import org.onlab.onos.net.device.DeviceListener;
30import org.onlab.onos.net.device.DeviceService;
31import org.onlab.onos.net.link.LinkProvider;
32import org.onlab.onos.net.link.LinkProviderRegistry;
33import org.onlab.onos.net.link.LinkProviderService;
34import org.onlab.onos.net.packet.PacketContext;
35import org.onlab.onos.net.packet.PacketProcessor;
36import org.onlab.onos.net.packet.PacketService;
37import org.onlab.onos.net.provider.AbstractProvider;
38import org.onlab.onos.net.provider.ProviderId;
39import org.slf4j.Logger;
40
41import java.util.Map;
42import java.util.concurrent.ConcurrentHashMap;
43
44import static org.slf4j.LoggerFactory.getLogger;
45
46
47/**
48 * Provider which uses an OpenFlow controller to detect network
49 * infrastructure links.
50 */
51@Component(immediate = true)
52public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
53
54 private final Logger log = getLogger(getClass());
55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected LinkProviderRegistry providerRegistry;
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected DeviceService deviceService;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected PacketService packetSevice;
64
alshabib875d6262014-10-17 16:19:40 -070065 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected MastershipService masterService;
67
alshabib7911a052014-10-16 17:49:37 -070068 private LinkProviderService providerService;
69
70 private final boolean useBDDP = true;
71
72
73 private final InternalLinkProvider listener = new InternalLinkProvider();
74
75 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
76
77 /**
78 * Creates an OpenFlow link provider.
79 */
80 public LLDPLinkProvider() {
81 super(new ProviderId("lldp", "org.onlab.onos.provider.lldp"));
82 }
83
84 @Activate
85 public void activate() {
86 providerService = providerRegistry.register(this);
87 deviceService.addListener(listener);
88 packetSevice.addProcessor(listener, 0);
alshabibdfc7afb2014-10-21 20:13:27 -070089 LinkDiscovery ld;
90 for (Device device : deviceService.getDevices()) {
91 ld = new LinkDiscovery(device, packetSevice, masterService,
92 providerService, useBDDP);
93 discoverers.put(device.id(), ld);
94 for (Port p : deviceService.getPorts(device.id())) {
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -070095 if (!p.number().isLogical()) {
96 ld.addPort(p);
97 }
alshabibdfc7afb2014-10-21 20:13:27 -070098 }
99 }
alshabib7911a052014-10-16 17:49:37 -0700100
101 log.info("Started");
102 }
103
104 @Deactivate
105 public void deactivate() {
106 for (LinkDiscovery ld : discoverers.values()) {
107 ld.stop();
108 }
109 providerRegistry.unregister(this);
110 deviceService.removeListener(listener);
111 packetSevice.removeProcessor(listener);
112 providerService = null;
113
114 log.info("Stopped");
115 }
116
117
118 private class InternalLinkProvider implements PacketProcessor, DeviceListener {
119
120 @Override
121 public void event(DeviceEvent event) {
122 LinkDiscovery ld = null;
123 Device device = event.subject();
alshabibacd91832014-10-17 14:38:41 -0700124 Port port = event.port();
alshabibdfc7afb2014-10-21 20:13:27 -0700125 if (device == null) {
126 log.error("Device is null.");
127 return;
128 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700129 log.trace("{} {} {}", event.type(), event.subject(), event);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700130 final DeviceId deviceId = device.id();
alshabib7911a052014-10-16 17:49:37 -0700131 switch (event.type()) {
132 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700133 case DEVICE_UPDATED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700134 ld = discoverers.get(deviceId);
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700135 if (ld == null) {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700136 log.debug("Device added ({}) {}", event.type(), deviceId);
137 discoverers.put(deviceId,
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700138 new LinkDiscovery(device, packetSevice, masterService,
139 providerService, useBDDP));
140 } else {
141 if (ld.isStopped()) {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700142 log.debug("Device restarted ({}) {}", event.type(), deviceId);
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700143 ld.start();
144 }
145 }
alshabib7911a052014-10-16 17:49:37 -0700146 break;
147 case PORT_ADDED:
148 case PORT_UPDATED:
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700149 if (port.isEnabled()) {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700150 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700151 if (ld == null) {
152 return;
153 }
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700154 if (!port.number().isLogical()) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700155 log.debug("Port added {}", port);
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700156 ld.addPort(port);
157 }
alshabib7911a052014-10-16 17:49:37 -0700158 } else {
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700159 log.debug("Port down {}", port);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700160 ConnectPoint point = new ConnectPoint(deviceId,
alshabibacd91832014-10-17 14:38:41 -0700161 port.number());
alshabib7911a052014-10-16 17:49:37 -0700162 providerService.linksVanished(point);
163 }
164 break;
165 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700166 log.debug("Port removed {}", port);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700167 ConnectPoint point = new ConnectPoint(deviceId,
alshabibacd91832014-10-17 14:38:41 -0700168 port.number());
alshabib7911a052014-10-16 17:49:37 -0700169 providerService.linksVanished(point);
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700170 // TODO: Don't we need to removePort from ld?
alshabib7911a052014-10-16 17:49:37 -0700171 break;
172 case DEVICE_REMOVED:
173 case DEVICE_SUSPENDED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700174 log.debug("Device removed {}", deviceId);
175 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700176 if (ld == null) {
177 return;
178 }
179 ld.stop();
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700180 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700181 break;
182 case DEVICE_AVAILABILITY_CHANGED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700183 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700184 if (ld == null) {
185 return;
186 }
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700187 if (deviceService.isAvailable(deviceId)) {
188 log.debug("Device up {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700189 ld.start();
190 } else {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700191 providerService.linksVanished(deviceId);
192 log.debug("Device down {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700193 ld.stop();
194 }
195 break;
alshabib7911a052014-10-16 17:49:37 -0700196 case DEVICE_MASTERSHIP_CHANGED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700197 if (!discoverers.containsKey(deviceId)) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700198 // TODO: ideally, should never reach here
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700199 log.debug("Device mastership changed ({}) {}", event.type(), deviceId);
200 discoverers.put(deviceId,
alshabibdfc7afb2014-10-21 20:13:27 -0700201 new LinkDiscovery(device, packetSevice, masterService,
202 providerService, useBDDP));
203 }
alshabib7911a052014-10-16 17:49:37 -0700204 break;
205 default:
206 log.debug("Unknown event {}", event);
207 }
208 }
209
210 @Override
211 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700212 if (context == null) {
213 return;
214 }
alshabib7911a052014-10-16 17:49:37 -0700215 LinkDiscovery ld = discoverers.get(
216 context.inPacket().receivedFrom().deviceId());
217 if (ld == null) {
218 return;
219 }
220
221 if (ld.handleLLDP(context)) {
222 context.block();
223 }
224 }
225 }
226
227}