blob: 8821d76aa5644f8b9225aa813fb477fa4935f382 [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);
112 providerService = null;
113 log.info("Stopped");
114 }
115
Thomas Vachuska33601602014-11-19 03:32:15 -0800116 @Modified
117 public void modified(ComponentContext context) {
118 Dictionary properties = context.getProperties();
119 try {
120 String flag = (String) properties.get("hostRemovalEnabled");
121 if (flag != null) {
122 hostRemovalEnabled = flag.equals("true");
123 }
124 } catch (Exception e) {
125 hostRemovalEnabled = true;
126 }
127 log.info("Host removal is {}", hostRemovalEnabled ? "enabled" : "disabled");
128 }
129
alshabibe1cf87d2014-10-17 09:23:50 -0700130 @Override
131 public void triggerProbe(Host host) {
132 log.info("Triggering probe on device {}", host);
133 }
134
135 private class InternalHostProvider implements PacketProcessor {
136
137 @Override
138 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700139 if (context == null) {
140 return;
141 }
alshabibe1cf87d2014-10-17 09:23:50 -0700142 Ethernet eth = context.inPacket().parsed();
143
144 VlanId vlan = VlanId.vlanId(eth.getVlanID());
145 ConnectPoint heardOn = context.inPacket().receivedFrom();
146
147 // If this is not an edge port, bail out.
148 Topology topology = topologyService.currentTopology();
149 if (topologyService.isInfrastructure(topology, heardOn)) {
150 return;
151 }
152
153 HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());
154
155 HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
156
157 // Potentially a new or moved host
158 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
159 ARP arp = (ARP) eth.getPayload();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700160 IpAddress ip =
Thomas Vachuska33601602014-11-19 03:32:15 -0800161 IpAddress.valueOf(IpAddress.Version.INET,
162 arp.getSenderProtocolAddress());
alshabibe1cf87d2014-10-17 09:23:50 -0700163 HostDescription hdescr =
164 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
165 providerService.hostDetected(hid, hdescr);
166
167 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
168 //Do not learn new ip from ip packet.
169 HostDescription hdescr =
170 new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
171 providerService.hostDetected(hid, hdescr);
172
173 }
174 }
175 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800176
177 // Auxiliary listener to device events.
178 private class InternalDeviceListener implements DeviceListener {
179 @Override
180 public void event(DeviceEvent event) {
181 if (!hostRemovalEnabled) {
182 return;
183 }
184
185 DeviceEvent.Type type = event.type();
186 DeviceId deviceId = event.subject().id();
187 if (type == DeviceEvent.Type.PORT_UPDATED) {
188 ConnectPoint point = new ConnectPoint(deviceId, event.port().number());
189 removeHosts(hostService.getConnectedHosts(point));
190
191 } else if (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED) {
192 if (!deviceService.isAvailable(deviceId)) {
193 removeHosts(hostService.getConnectedHosts(deviceId));
194 }
195
196 } else if (type == DeviceEvent.Type.DEVICE_REMOVED) {
197 removeHosts(hostService.getConnectedHosts(deviceId));
198 }
199 }
200 }
201
202 // Signals host vanish for all specified hosts.
203 private void removeHosts(Set<Host> hosts) {
204 for (Host host : hosts) {
205 providerService.hostVanished(host.id());
206 }
207 }
208
alshabibe1cf87d2014-10-17 09:23:50 -0700209}