blob: 50dceb3ea357df53f40c2b485d96f75bc269889e [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);
alshabib7911a052014-10-16 17:49:37 -0700130 switch (event.type()) {
131 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700132 case DEVICE_UPDATED:
133 ld = discoverers.get(device.id());
134 if (ld == null) {
135 log.debug("Device added ({}) {}", event.type(), device.id());
136 discoverers.put(device.id(),
137 new LinkDiscovery(device, packetSevice, masterService,
138 providerService, useBDDP));
139 } else {
140 if (ld.isStopped()) {
141 log.debug("Device restarted ({}) {}", event.type(), device.id());
142 ld.start();
143 }
144 }
alshabib7911a052014-10-16 17:49:37 -0700145 break;
146 case PORT_ADDED:
147 case PORT_UPDATED:
148 if (event.port().isEnabled()) {
alshabibacd91832014-10-17 14:38:41 -0700149 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700150 if (ld == null) {
151 return;
152 }
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700153 if (!port.number().isLogical()) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700154 log.debug("Port added {}", port);
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700155 ld.addPort(port);
156 }
alshabib7911a052014-10-16 17:49:37 -0700157 } else {
alshabibacd91832014-10-17 14:38:41 -0700158 ConnectPoint point = new ConnectPoint(device.id(),
159 port.number());
alshabib7911a052014-10-16 17:49:37 -0700160 providerService.linksVanished(point);
161 }
162 break;
163 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700164 log.debug("Port removed {}", port);
alshabibacd91832014-10-17 14:38:41 -0700165 ConnectPoint point = new ConnectPoint(device.id(),
166 port.number());
alshabib7911a052014-10-16 17:49:37 -0700167 providerService.linksVanished(point);
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700168 // TODO: Don't we need to removePort from ld?
alshabib7911a052014-10-16 17:49:37 -0700169 break;
170 case DEVICE_REMOVED:
171 case DEVICE_SUSPENDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700172 log.debug("Device removed {}", device.id());
alshabibacd91832014-10-17 14:38:41 -0700173 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700174 if (ld == null) {
175 return;
176 }
177 ld.stop();
alshabibacd91832014-10-17 14:38:41 -0700178 providerService.linksVanished(device.id());
alshabib7911a052014-10-16 17:49:37 -0700179 break;
180 case DEVICE_AVAILABILITY_CHANGED:
alshabibacd91832014-10-17 14:38:41 -0700181 ld = discoverers.get(device.id());
alshabib7911a052014-10-16 17:49:37 -0700182 if (ld == null) {
183 return;
184 }
alshabibacd91832014-10-17 14:38:41 -0700185 if (deviceService.isAvailable(device.id())) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700186 log.debug("Device up {}", device.id());
alshabib7911a052014-10-16 17:49:37 -0700187 ld.start();
188 } else {
alshabibacd91832014-10-17 14:38:41 -0700189 providerService.linksVanished(device.id());
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700190 log.debug("Device down {}", device.id());
alshabib7911a052014-10-16 17:49:37 -0700191 ld.stop();
192 }
193 break;
alshabib7911a052014-10-16 17:49:37 -0700194 case DEVICE_MASTERSHIP_CHANGED:
alshabibdfc7afb2014-10-21 20:13:27 -0700195 if (!discoverers.containsKey(device.id())) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700196 // TODO: ideally, should never reach here
197 log.debug("Device mastership changed ({}) {}", event.type(), device.id());
alshabibdfc7afb2014-10-21 20:13:27 -0700198 discoverers.put(device.id(),
199 new LinkDiscovery(device, packetSevice, masterService,
200 providerService, useBDDP));
201 }
alshabib7911a052014-10-16 17:49:37 -0700202 break;
203 default:
204 log.debug("Unknown event {}", event);
205 }
206 }
207
208 @Override
209 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700210 if (context == null) {
211 return;
212 }
alshabib7911a052014-10-16 17:49:37 -0700213 LinkDiscovery ld = discoverers.get(
214 context.inPacket().receivedFrom().deviceId());
215 if (ld == null) {
216 return;
217 }
218
219 if (ld.handleLLDP(context)) {
220 context.block();
221 }
222 }
223 }
224
225}