blob: 296d300c12d8e0395a1924e58cc95d0c96e7bf62 [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 */
alshabibe1cf87d2014-10-17 09:23:50 -070016package org.onlab.onos.provider.host.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuska33601602014-11-19 03:32:15 -080021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
alshabibe1cf87d2014-10-17 09:23:50 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onlab.onos.net.ConnectPoint;
Thomas Vachuska33601602014-11-19 03:32:15 -080026import org.onlab.onos.net.DeviceId;
alshabibe1cf87d2014-10-17 09:23:50 -070027import org.onlab.onos.net.Host;
28import org.onlab.onos.net.HostId;
29import org.onlab.onos.net.HostLocation;
Thomas Vachuska33601602014-11-19 03:32:15 -080030import org.onlab.onos.net.device.DeviceEvent;
31import org.onlab.onos.net.device.DeviceListener;
32import org.onlab.onos.net.device.DeviceService;
alshabibe1cf87d2014-10-17 09:23:50 -070033import org.onlab.onos.net.host.DefaultHostDescription;
34import org.onlab.onos.net.host.HostDescription;
35import org.onlab.onos.net.host.HostProvider;
36import org.onlab.onos.net.host.HostProviderRegistry;
37import org.onlab.onos.net.host.HostProviderService;
Thomas Vachuska33601602014-11-19 03:32:15 -080038import org.onlab.onos.net.host.HostService;
alshabibe1cf87d2014-10-17 09:23:50 -070039import org.onlab.onos.net.packet.PacketContext;
40import org.onlab.onos.net.packet.PacketProcessor;
41import org.onlab.onos.net.packet.PacketService;
42import org.onlab.onos.net.provider.AbstractProvider;
43import org.onlab.onos.net.provider.ProviderId;
44import org.onlab.onos.net.topology.Topology;
45import org.onlab.onos.net.topology.TopologyService;
alshabibe1cf87d2014-10-17 09:23:50 -070046import org.onlab.packet.ARP;
47import org.onlab.packet.Ethernet;
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -070048import org.onlab.packet.IpAddress;
alshabibe1cf87d2014-10-17 09:23:50 -070049import org.onlab.packet.VlanId;
Thomas Vachuska33601602014-11-19 03:32:15 -080050import org.osgi.service.component.ComponentContext;
alshabibe1cf87d2014-10-17 09:23:50 -070051import org.slf4j.Logger;
52
Thomas Vachuska33601602014-11-19 03:32:15 -080053import java.util.Dictionary;
54import java.util.Set;
55
56import static org.slf4j.LoggerFactory.getLogger;
57
alshabibe1cf87d2014-10-17 09:23:50 -070058/**
59 * Provider which uses an OpenFlow controller to detect network
60 * end-station hosts.
61 */
62@Component(immediate = true)
63public class HostLocationProvider extends AbstractProvider implements HostProvider {
64
65 private final Logger log = getLogger(getClass());
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected HostProviderRegistry providerRegistry;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected PacketService pktService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected TopologyService topologyService;
75
Thomas Vachuska33601602014-11-19 03:32:15 -080076 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected HostService hostService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected DeviceService deviceService;
81
alshabibe1cf87d2014-10-17 09:23:50 -070082 private HostProviderService providerService;
83
84 private final InternalHostProvider processor = new InternalHostProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -080085 private final DeviceListener deviceListener = new InternalDeviceListener();
86
87 @Property(name = "hostRemovalEnabled", boolValue = true,
88 label = "Enable host removal on port/device down events")
89 private boolean hostRemovalEnabled = true;
alshabibe1cf87d2014-10-17 09:23:50 -070090
91
92 /**
93 * Creates an OpenFlow host provider.
94 */
95 public HostLocationProvider() {
96 super(new ProviderId("of", "org.onlab.onos.provider.host"));
97 }
98
99 @Activate
Thomas Vachuska33601602014-11-19 03:32:15 -0800100 public void activate(ComponentContext context) {
101 modified(context);
alshabibe1cf87d2014-10-17 09:23:50 -0700102 providerService = providerRegistry.register(this);
103 pktService.addProcessor(processor, 1);
Thomas Vachuska33601602014-11-19 03:32:15 -0800104 deviceService.addListener(deviceListener);
alshabibe1cf87d2014-10-17 09:23:50 -0700105 log.info("Started");
106 }
107
108 @Deactivate
109 public void deactivate() {
110 providerRegistry.unregister(this);
111 pktService.removeProcessor(processor);
alshabibbfc6b722014-11-29 12:53:48 -0800112 deviceService.removeListener(deviceListener);
alshabibe1cf87d2014-10-17 09:23:50 -0700113 providerService = null;
114 log.info("Stopped");
115 }
116
Thomas Vachuska33601602014-11-19 03:32:15 -0800117 @Modified
118 public void modified(ComponentContext context) {
119 Dictionary properties = context.getProperties();
120 try {
121 String flag = (String) properties.get("hostRemovalEnabled");
122 if (flag != null) {
123 hostRemovalEnabled = flag.equals("true");
124 }
125 } catch (Exception e) {
126 hostRemovalEnabled = true;
127 }
128 log.info("Host removal is {}", hostRemovalEnabled ? "enabled" : "disabled");
129 }
130
alshabibe1cf87d2014-10-17 09:23:50 -0700131 @Override
132 public void triggerProbe(Host host) {
133 log.info("Triggering probe on device {}", host);
134 }
135
136 private class InternalHostProvider implements PacketProcessor {
137
138 @Override
139 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700140 if (context == null) {
141 return;
142 }
alshabibe1cf87d2014-10-17 09:23:50 -0700143 Ethernet eth = context.inPacket().parsed();
144
145 VlanId vlan = VlanId.vlanId(eth.getVlanID());
146 ConnectPoint heardOn = context.inPacket().receivedFrom();
147
148 // If this is not an edge port, bail out.
149 Topology topology = topologyService.currentTopology();
150 if (topologyService.isInfrastructure(topology, heardOn)) {
151 return;
152 }
153
154 HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());
155
156 HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
157
158 // Potentially a new or moved host
159 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
160 ARP arp = (ARP) eth.getPayload();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700161 IpAddress ip =
Thomas Vachuska33601602014-11-19 03:32:15 -0800162 IpAddress.valueOf(IpAddress.Version.INET,
163 arp.getSenderProtocolAddress());
alshabibe1cf87d2014-10-17 09:23:50 -0700164 HostDescription hdescr =
165 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
166 providerService.hostDetected(hid, hdescr);
167
168 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
169 //Do not learn new ip from ip packet.
170 HostDescription hdescr =
171 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
172 providerService.hostDetected(hid, hdescr);
173
174 }
175 }
176 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800177
178 // Auxiliary listener to device events.
179 private class InternalDeviceListener implements DeviceListener {
180 @Override
181 public void event(DeviceEvent event) {
182 if (!hostRemovalEnabled) {
183 return;
184 }
185
186 DeviceEvent.Type type = event.type();
187 DeviceId deviceId = event.subject().id();
188 if (type == DeviceEvent.Type.PORT_UPDATED) {
189 ConnectPoint point = new ConnectPoint(deviceId, event.port().number());
190 removeHosts(hostService.getConnectedHosts(point));
191
192 } else if (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED) {
193 if (!deviceService.isAvailable(deviceId)) {
194 removeHosts(hostService.getConnectedHosts(deviceId));
195 }
196
197 } else if (type == DeviceEvent.Type.DEVICE_REMOVED) {
198 removeHosts(hostService.getConnectedHosts(deviceId));
199 }
200 }
201 }
202
203 // Signals host vanish for all specified hosts.
204 private void removeHosts(Set<Host> hosts) {
205 for (Host host : hosts) {
206 providerService.hostVanished(host.id());
207 }
208 }
209
alshabibe1cf87d2014-10-17 09:23:50 -0700210}