blob: 720c6cd2c372e84cc1260b166b2e8907a47f0194 [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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.host.impl;
alshabibe1cf87d2014-10-17 09:23:50 -070017
Jonathan Harte8600eb2015-01-12 10:30:45 -080018import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.Dictionary;
21import java.util.Set;
22
alshabibe1cf87d2014-10-17 09:23:50 -070023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuska33601602014-11-19 03:32:15 -080026import org.apache.felix.scr.annotations.Modified;
27import org.apache.felix.scr.annotations.Property;
alshabibe1cf87d2014-10-17 09:23:50 -070028import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Harte8600eb2015-01-12 10:30:45 -080030import org.onlab.packet.ARP;
31import org.onlab.packet.Ethernet;
32import org.onlab.packet.IPacket;
33import org.onlab.packet.IPv6;
34import org.onlab.packet.IpAddress;
35import org.onlab.packet.VlanId;
36import org.onlab.packet.ndp.NeighborAdvertisement;
37import org.onlab.packet.ndp.NeighborSolicitation;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080038import org.onosproject.core.ApplicationId;
39import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.ConnectPoint;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080041import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.Host;
43import org.onosproject.net.HostId;
44import org.onosproject.net.HostLocation;
45import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080048import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080049import org.onosproject.net.flow.TrafficSelector;
Brian O'Connorabafb502014-12-02 22:26:20 -080050import org.onosproject.net.host.DefaultHostDescription;
51import org.onosproject.net.host.HostDescription;
52import org.onosproject.net.host.HostProvider;
53import org.onosproject.net.host.HostProviderRegistry;
54import org.onosproject.net.host.HostProviderService;
55import org.onosproject.net.host.HostService;
56import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080057import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080058import org.onosproject.net.packet.PacketProcessor;
59import org.onosproject.net.packet.PacketService;
60import org.onosproject.net.provider.AbstractProvider;
61import org.onosproject.net.provider.ProviderId;
62import org.onosproject.net.topology.Topology;
63import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33601602014-11-19 03:32:15 -080064import org.osgi.service.component.ComponentContext;
alshabibe1cf87d2014-10-17 09:23:50 -070065import org.slf4j.Logger;
66
alshabibe1cf87d2014-10-17 09:23:50 -070067/**
68 * Provider which uses an OpenFlow controller to detect network
69 * end-station hosts.
70 */
71@Component(immediate = true)
72public class HostLocationProvider extends AbstractProvider implements HostProvider {
73
74 private final Logger log = getLogger(getClass());
75
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080076 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected CoreService coreService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibe1cf87d2014-10-17 09:23:50 -070080 protected HostProviderRegistry providerRegistry;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected PacketService pktService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected TopologyService topologyService;
87
Thomas Vachuska33601602014-11-19 03:32:15 -080088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected HostService hostService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected DeviceService deviceService;
93
alshabibe1cf87d2014-10-17 09:23:50 -070094 private HostProviderService providerService;
95
96 private final InternalHostProvider processor = new InternalHostProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -080097 private final DeviceListener deviceListener = new InternalDeviceListener();
98
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080099 private ApplicationId appId;
100
Thomas Vachuska33601602014-11-19 03:32:15 -0800101 @Property(name = "hostRemovalEnabled", boolValue = true,
102 label = "Enable host removal on port/device down events")
103 private boolean hostRemovalEnabled = true;
alshabibe1cf87d2014-10-17 09:23:50 -0700104
105
106 /**
107 * Creates an OpenFlow host provider.
108 */
109 public HostLocationProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -0800110 super(new ProviderId("of", "org.onosproject.provider.host"));
alshabibe1cf87d2014-10-17 09:23:50 -0700111 }
112
113 @Activate
Thomas Vachuska33601602014-11-19 03:32:15 -0800114 public void activate(ComponentContext context) {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800115 appId =
116 coreService.registerApplication("org.onosproject.provider.host");
117
Thomas Vachuska33601602014-11-19 03:32:15 -0800118 modified(context);
alshabibe1cf87d2014-10-17 09:23:50 -0700119 providerService = providerRegistry.register(this);
120 pktService.addProcessor(processor, 1);
Thomas Vachuska33601602014-11-19 03:32:15 -0800121 deviceService.addListener(deviceListener);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800122
123 TrafficSelector.Builder selectorBuilder =
124 DefaultTrafficSelector.builder();
125 selectorBuilder.matchEthType(Ethernet.TYPE_ARP);
126 pktService.requestPackets(selectorBuilder.build(),
127 PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800128
alshabibe1cf87d2014-10-17 09:23:50 -0700129 log.info("Started");
130 }
131
132 @Deactivate
133 public void deactivate() {
134 providerRegistry.unregister(this);
135 pktService.removeProcessor(processor);
alshabibbfc6b722014-11-29 12:53:48 -0800136 deviceService.removeListener(deviceListener);
alshabibe1cf87d2014-10-17 09:23:50 -0700137 providerService = null;
138 log.info("Stopped");
139 }
140
Thomas Vachuska33601602014-11-19 03:32:15 -0800141 @Modified
142 public void modified(ComponentContext context) {
143 Dictionary properties = context.getProperties();
144 try {
145 String flag = (String) properties.get("hostRemovalEnabled");
146 if (flag != null) {
147 hostRemovalEnabled = flag.equals("true");
148 }
149 } catch (Exception e) {
150 hostRemovalEnabled = true;
151 }
152 log.info("Host removal is {}", hostRemovalEnabled ? "enabled" : "disabled");
153 }
154
alshabibe1cf87d2014-10-17 09:23:50 -0700155 @Override
156 public void triggerProbe(Host host) {
157 log.info("Triggering probe on device {}", host);
158 }
159
160 private class InternalHostProvider implements PacketProcessor {
161
162 @Override
163 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700164 if (context == null) {
165 return;
166 }
alshabibe1cf87d2014-10-17 09:23:50 -0700167 Ethernet eth = context.inPacket().parsed();
168
Jonathan Harte8600eb2015-01-12 10:30:45 -0800169 if (eth == null) {
170 return;
171 }
172
alshabibe1cf87d2014-10-17 09:23:50 -0700173 VlanId vlan = VlanId.vlanId(eth.getVlanID());
174 ConnectPoint heardOn = context.inPacket().receivedFrom();
175
176 // If this is not an edge port, bail out.
177 Topology topology = topologyService.currentTopology();
178 if (topologyService.isInfrastructure(topology, heardOn)) {
179 return;
180 }
181
182 HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());
183
184 HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
185
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800186 // ARP: possible new hosts, update both location and IP
alshabibe1cf87d2014-10-17 09:23:50 -0700187 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
188 ARP arp = (ARP) eth.getPayload();
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800189 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, arp.getSenderProtocolAddress());
alshabibe1cf87d2014-10-17 09:23:50 -0700190 HostDescription hdescr =
191 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
192 providerService.hostDetected(hid, hdescr);
193
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800194 // IPv4: update location only
alshabibe1cf87d2014-10-17 09:23:50 -0700195 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
alshabibe1cf87d2014-10-17 09:23:50 -0700196 HostDescription hdescr =
197 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
198 providerService.hostDetected(hid, hdescr);
199
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800200 // NeighborAdvertisement and NeighborSolicitation: possible new hosts, update both location and IP
201 // IPv6: update location only
202 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
203 IpAddress ip = null;
204 IPv6 ipv6 = (IPv6) eth.getPayload();
205
206 IPacket iPkt = ipv6;
207 while (iPkt != null) {
208 if (iPkt instanceof NeighborAdvertisement || iPkt instanceof NeighborSolicitation) {
209 IpAddress sourceAddress =
210 IpAddress.valueOf(IpAddress.Version.INET6, ipv6.getSourceAddress());
211 // Ignore DAD packets, in which source address is all zeros.
212 if (!sourceAddress.isZero()) {
213 ip = sourceAddress;
214 break;
215 }
216 }
217 iPkt = iPkt.getPayload();
218 }
219 HostDescription hdescr = (ip == null) ?
220 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc) :
221 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
222 providerService.hostDetected(hid, hdescr);
alshabibe1cf87d2014-10-17 09:23:50 -0700223 }
224 }
225 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800226
227 // Auxiliary listener to device events.
228 private class InternalDeviceListener implements DeviceListener {
229 @Override
230 public void event(DeviceEvent event) {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800231 Device device = event.subject();
232 switch (event.type()) {
233 case DEVICE_ADDED:
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800234 break;
235 case DEVICE_AVAILABILITY_CHANGED:
236 if (hostRemovalEnabled &&
237 !deviceService.isAvailable(device.id())) {
238 removeHosts(hostService.getConnectedHosts(device.id()));
Thomas Vachuska33601602014-11-19 03:32:15 -0800239 }
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800240 break;
241 case DEVICE_SUSPENDED:
242 case DEVICE_UPDATED:
243 // Nothing to do?
244 break;
245 case DEVICE_REMOVED:
246 if (hostRemovalEnabled) {
247 removeHosts(hostService.getConnectedHosts(device.id()));
248 }
249 break;
250 case PORT_ADDED:
251 break;
252 case PORT_UPDATED:
253 if (hostRemovalEnabled) {
254 ConnectPoint point =
255 new ConnectPoint(device.id(), event.port().number());
256 removeHosts(hostService.getConnectedHosts(point));
257 }
258 break;
259 case PORT_REMOVED:
260 // Nothing to do?
261 break;
262 default:
263 break;
Thomas Vachuska33601602014-11-19 03:32:15 -0800264 }
265 }
266 }
267
268 // Signals host vanish for all specified hosts.
269 private void removeHosts(Set<Host> hosts) {
270 for (Host host : hosts) {
271 providerService.hostVanished(host.id());
272 }
273 }
274
alshabibe1cf87d2014-10-17 09:23:50 -0700275}