blob: e1872a945043e4c84afa0ae530fe9f5c405922d1 [file] [log] [blame]
Amit Ghosh47243cb2017-07-26 05:08:53 +01001/*
Deepa vaddireddy0060f532017-08-04 06:46:05 +00002 * Copyright 2017-present Open Networking Foundation
Amit Ghosh47243cb2017-07-26 05:08:53 +01003 *
4 * 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
7 *
8 * 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.
15 */
16package org.opencord.dhcpl2relay;
17
18import com.google.common.collect.ImmutableSet;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000019import com.google.common.collect.Lists;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053020import com.google.common.collect.Maps;
Amit Ghosh8951f042017-08-10 13:48:10 +010021import com.google.common.collect.Sets;
Amit Ghosh47243cb2017-07-26 05:08:53 +010022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Modified;
26import org.apache.felix.scr.annotations.Property;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hartc36c9552018-07-31 15:07:53 -040029import org.apache.felix.scr.annotations.Service;
Amit Ghosh47243cb2017-07-26 05:08:53 +010030import org.onlab.packet.DHCP;
Amit Ghosh47243cb2017-07-26 05:08:53 +010031import org.onlab.packet.DHCPPacketType;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000032import org.onlab.packet.Ethernet;
Amit Ghosh47243cb2017-07-26 05:08:53 +010033import org.onlab.packet.IPv4;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053034import org.onlab.packet.IpAddress;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000035import org.onlab.packet.MacAddress;
Amit Ghosh47243cb2017-07-26 05:08:53 +010036import org.onlab.packet.TpPort;
37import org.onlab.packet.UDP;
38import org.onlab.packet.VlanId;
Jonathan Hartedbf6422018-05-02 17:30:05 -070039import org.onlab.packet.dhcp.DhcpOption;
Amit Ghosh47243cb2017-07-26 05:08:53 +010040import org.onlab.util.Tools;
41import org.onosproject.cfg.ComponentConfigService;
42import org.onosproject.core.ApplicationId;
43import org.onosproject.core.CoreService;
Jonathan Hartc36c9552018-07-31 15:07:53 -040044import org.onosproject.event.AbstractListenerManager;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053045import org.onosproject.mastership.MastershipEvent;
46import org.onosproject.mastership.MastershipListener;
47import org.onosproject.mastership.MastershipService;
Amit Ghosh47243cb2017-07-26 05:08:53 +010048import org.onosproject.net.AnnotationKeys;
49import org.onosproject.net.ConnectPoint;
Amit Ghosh83c8c892017-11-09 11:08:27 +000050import org.onosproject.net.Device;
51import org.onosproject.net.DeviceId;
Amit Ghosh47243cb2017-07-26 05:08:53 +010052import org.onosproject.net.Host;
53import org.onosproject.net.Port;
Amit Ghosh83c8c892017-11-09 11:08:27 +000054import org.onosproject.net.PortNumber;
Amit Ghosh47243cb2017-07-26 05:08:53 +010055import org.onosproject.net.config.ConfigFactory;
56import org.onosproject.net.config.NetworkConfigEvent;
57import org.onosproject.net.config.NetworkConfigListener;
58import org.onosproject.net.config.NetworkConfigRegistry;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053059import org.onosproject.net.device.DeviceEvent;
60import org.onosproject.net.device.DeviceListener;
Amit Ghosh47243cb2017-07-26 05:08:53 +010061import org.onosproject.net.device.DeviceService;
62import org.onosproject.net.flow.DefaultTrafficSelector;
63import org.onosproject.net.flow.DefaultTrafficTreatment;
64import org.onosproject.net.flow.TrafficSelector;
65import org.onosproject.net.flow.TrafficTreatment;
66import org.onosproject.net.host.HostService;
67import org.onosproject.net.packet.DefaultOutboundPacket;
68import org.onosproject.net.packet.OutboundPacket;
69import org.onosproject.net.packet.PacketContext;
70import org.onosproject.net.packet.PacketPriority;
71import org.onosproject.net.packet.PacketProcessor;
72import org.onosproject.net.packet.PacketService;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053073import org.opencord.dhcpl2relay.packet.DhcpOption82;
Amit Ghosh47243cb2017-07-26 05:08:53 +010074import org.opencord.sadis.SubscriberAndDeviceInformation;
75import org.opencord.sadis.SubscriberAndDeviceInformationService;
Amit Ghosh47243cb2017-07-26 05:08:53 +010076import org.osgi.service.component.ComponentContext;
77import org.slf4j.Logger;
78import org.slf4j.LoggerFactory;
79
80import java.nio.ByteBuffer;
Amit Ghosh83c8c892017-11-09 11:08:27 +000081import java.util.ArrayList;
Jonathan Hartedbf6422018-05-02 17:30:05 -070082import java.util.Arrays;
Amit Ghosh47243cb2017-07-26 05:08:53 +010083import java.util.Dictionary;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000084import java.util.List;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053085import java.util.Map;
Amit Ghosh83c8c892017-11-09 11:08:27 +000086import java.util.Optional;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000087import java.util.Set;
Amit Ghosh8951f042017-08-10 13:48:10 +010088import java.util.concurrent.atomic.AtomicReference;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000089import java.util.stream.Collectors;
Amit Ghosh47243cb2017-07-26 05:08:53 +010090
91import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType;
92import static org.onlab.packet.MacAddress.valueOf;
93import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
94
95/**
96 * DHCP Relay Agent Application Component.
97 */
Jonathan Hartc36c9552018-07-31 15:07:53 -040098@Service
Amit Ghosh47243cb2017-07-26 05:08:53 +010099@Component(immediate = true)
Jonathan Hartc36c9552018-07-31 15:07:53 -0400100public class DhcpL2Relay
101 extends AbstractListenerManager<DhcpL2RelayEvent, DhcpL2RelayListener>
102 implements DhcpL2RelayService {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100103
104 public static final String DHCP_L2RELAY_APP = "org.opencord.dhcpl2relay";
105 private final Logger log = LoggerFactory.getLogger(getClass());
106 private final InternalConfigListener cfgListener =
107 new InternalConfigListener();
108
109 private final Set<ConfigFactory> factories = ImmutableSet.of(
110 new ConfigFactory<ApplicationId, DhcpL2RelayConfig>(APP_SUBJECT_FACTORY,
111 DhcpL2RelayConfig.class,
112 "dhcpl2relay") {
113 @Override
114 public DhcpL2RelayConfig createConfig() {
115 return new DhcpL2RelayConfig();
116 }
117 }
118 );
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected NetworkConfigRegistry cfgService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected CoreService coreService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected PacketService packetService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected HostService hostService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected ComponentConfigService componentConfigService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected SubscriberAndDeviceInformationService subsService;
137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
139 protected DeviceService deviceService;
140
Amit Ghosh8951f042017-08-10 13:48:10 +0100141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected MastershipService mastershipService;
143
Amit Ghosh47243cb2017-07-26 05:08:53 +0100144 @Property(name = "option82", boolValue = true,
145 label = "Add option 82 to relayed packets")
146 protected boolean option82 = true;
147
Amit Ghosha17354e2017-08-23 12:56:04 +0100148 @Property(name = "enableDhcpBroadcastReplies", boolValue = false,
Amit Ghosh2095dc62017-09-25 20:56:55 +0100149 label = "Ask the DHCP Server to send back replies as L2 broadcast")
Amit Ghosha17354e2017-08-23 12:56:04 +0100150 protected boolean enableDhcpBroadcastReplies = false;
151
Amit Ghosh47243cb2017-07-26 05:08:53 +0100152 private DhcpRelayPacketProcessor dhcpRelayPacketProcessor =
153 new DhcpRelayPacketProcessor();
154
Amit Ghosh8951f042017-08-10 13:48:10 +0100155 private InnerMastershipListener changeListener = new InnerMastershipListener();
156 private InnerDeviceListener deviceListener = new InnerDeviceListener();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100157
Amit Ghosh8951f042017-08-10 13:48:10 +0100158 // connect points to the DHCP server
159 Set<ConnectPoint> dhcpConnectPoints;
160 private AtomicReference<ConnectPoint> dhcpServerConnectPoint = new AtomicReference<>();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100161 private MacAddress dhcpConnectMac = MacAddress.BROADCAST;
162 private ApplicationId appId;
163
Amit Ghosha17354e2017-08-23 12:56:04 +0100164 static Map<String, DhcpAllocationInfo> allocationMap = Maps.newConcurrentMap();
Amit Ghosh83c8c892017-11-09 11:08:27 +0000165 private boolean modifyClientPktsSrcDstMac = false;
166 //Whether to use the uplink port of the OLTs to send/receive messages to the DHCP server
167 private boolean useOltUplink = false;
Amit Ghosha17354e2017-08-23 12:56:04 +0100168
Amit Ghosh47243cb2017-07-26 05:08:53 +0100169 @Activate
170 protected void activate(ComponentContext context) {
171 //start the dhcp relay agent
172 appId = coreService.registerApplication(DHCP_L2RELAY_APP);
173 componentConfigService.registerProperties(getClass());
Jonathan Hartc36c9552018-07-31 15:07:53 -0400174 eventDispatcher.addSink(DhcpL2RelayEvent.class, listenerRegistry);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100175
176 cfgService.addListener(cfgListener);
Amit Ghosh8951f042017-08-10 13:48:10 +0100177 mastershipService.addListener(changeListener);
178 deviceService.addListener(deviceListener);
179
Amit Ghosh47243cb2017-07-26 05:08:53 +0100180 factories.forEach(cfgService::registerConfigFactory);
181 //update the dhcp server configuration.
182 updateConfig();
183 //add the packet services.
184 packetService.addProcessor(dhcpRelayPacketProcessor,
185 PacketProcessor.director(0));
186 requestDhcpPackets();
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000187 if (context != null) {
188 modified(context);
189 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100190
191 log.info("DHCP-L2-RELAY Started");
192 }
193
194 @Deactivate
195 protected void deactivate() {
196 cfgService.removeListener(cfgListener);
197 factories.forEach(cfgService::unregisterConfigFactory);
198 packetService.removeProcessor(dhcpRelayPacketProcessor);
199 cancelDhcpPackets();
200
201 componentConfigService.unregisterProperties(getClass(), false);
Deepa Vaddireddy77a6ac72017-09-20 20:36:52 +0530202 deviceService.removeListener(deviceListener);
203 mastershipService.removeListener(changeListener);
Jonathan Hartc36c9552018-07-31 15:07:53 -0400204 eventDispatcher.removeSink(DhcpL2RelayEvent.class);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100205 log.info("DHCP-L2-RELAY Stopped");
206 }
207
208 @Modified
209 protected void modified(ComponentContext context) {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000210
Amit Ghosh47243cb2017-07-26 05:08:53 +0100211 Dictionary<?, ?> properties = context.getProperties();
212
213 Boolean o = Tools.isPropertyEnabled(properties, "option82");
214 if (o != null) {
215 option82 = o;
216 }
Amit Ghosh2095dc62017-09-25 20:56:55 +0100217
218 o = Tools.isPropertyEnabled(properties, "enableDhcpBroadcastReplies");
219 if (o != null) {
220 enableDhcpBroadcastReplies = o;
221 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100222 }
223
224 /**
225 * Checks if this app has been configured.
226 *
227 * @return true if all information we need have been initialized
228 */
229 private boolean configured() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000230 if (!useOltUplink) {
231 return dhcpServerConnectPoint.get() != null;
232 }
233 return true;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100234 }
235
Amit Ghosh8951f042017-08-10 13:48:10 +0100236 /**
237 * Selects a connect point through an available device for which it is the master.
238 */
239 private void selectServerConnectPoint() {
240 synchronized (this) {
241 dhcpServerConnectPoint.set(null);
242 if (dhcpConnectPoints != null) {
243 // find a connect point through a device for which we are master
244 for (ConnectPoint cp: dhcpConnectPoints) {
245 if (mastershipService.isLocalMaster(cp.deviceId())) {
246 if (deviceService.isAvailable(cp.deviceId())) {
247 dhcpServerConnectPoint.set(cp);
248 }
249 log.info("DHCP connectPoint selected is {}", cp);
250 break;
251 }
252 }
253 }
254
255 log.info("DHCP Server connectPoint is {}", dhcpServerConnectPoint.get());
256
257 if (dhcpServerConnectPoint.get() == null) {
258 log.error("Master of none, can't relay DHCP Message to server");
259 }
260 }
261 }
262
263 /**
264 * Updates the network configuration.
265 */
Amit Ghosh47243cb2017-07-26 05:08:53 +0100266 private void updateConfig() {
267 DhcpL2RelayConfig cfg = cfgService.getConfig(appId, DhcpL2RelayConfig.class);
268 if (cfg == null) {
269 log.warn("Dhcp Server info not available");
270 return;
271 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100272
273 dhcpConnectPoints = Sets.newConcurrentHashSet(cfg.getDhcpServerConnectPoint());
Amit Ghosh83c8c892017-11-09 11:08:27 +0000274 modifyClientPktsSrcDstMac = cfg.getModifySrcDstMacAddresses();
275 useOltUplink = cfg.getUseOltUplinkForServerPktInOut();
Amit Ghosh8951f042017-08-10 13:48:10 +0100276
Amit Ghosh83c8c892017-11-09 11:08:27 +0000277 if (!useOltUplink) {
278 selectServerConnectPoint();
279 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100280
Amit Ghosh47243cb2017-07-26 05:08:53 +0100281 log.info("dhcp server connect point: " + dhcpServerConnectPoint);
282 }
283
284 /**
Amit Ghosh83c8c892017-11-09 11:08:27 +0000285 * Returns all the uplink ports of OLTs configured in SADIS.
286 * Only ports visible in ONOS and for which this instance is master
287 * are returned
288 */
289 private List<ConnectPoint> getUplinkPortsOfOlts() {
290 List<ConnectPoint> cps = new ArrayList<>();
291
292 // find all the olt devices and if their uplink ports are visible
293 Iterable<Device> devices = deviceService.getDevices();
294 for (Device d : devices) {
295 // check if this device is provisioned in Sadis
296
297 log.debug("getUplinkPortsOfOlts: Checking mastership of {}", d);
298 // do only for devices for which we are the master
299 if (!mastershipService.isLocalMaster(d.id())) {
300 continue;
301 }
302
303 String devSerialNo = d.serialNumber();
304 SubscriberAndDeviceInformation deviceInfo = subsService.get(devSerialNo);
305 log.debug("getUplinkPortsOfOlts: Found device: {}", deviceInfo);
306 if (deviceInfo != null) {
307 // check if the uplink port with that number is available on the device
308 PortNumber pNum = PortNumber.portNumber(deviceInfo.uplinkPort());
309 Port port = deviceService.getPort(d.id(), pNum);
310 log.debug("getUplinkPortsOfOlts: Found port: {}", port);
311 if (port != null) {
312 cps.add(new ConnectPoint(d.id(), pNum));
313 }
314 }
315 }
316 return cps;
317 }
318
319 /**
320 * Returns whether the passed port is the uplink port of the olt device.
321 */
322 private boolean isUplinkPortOfOlt(DeviceId dId, Port p) {
323 log.debug("isUplinkPortOfOlt: DeviceId: {} Port: {}", dId, p);
324 // do only for devices for which we are the master
325 if (!mastershipService.isLocalMaster(dId)) {
326 return false;
327 }
328
329 Device d = deviceService.getDevice(dId);
330 SubscriberAndDeviceInformation deviceInfo = subsService.get(d.serialNumber());
331
332 if (deviceInfo != null) {
333 return (deviceInfo.uplinkPort() == p.number().toLong());
334 }
335
336 return false;
337 }
338
339 /**
340 * Returns the connectPoint which is the uplink port of the OLT.
341 */
342 private ConnectPoint getUplinkConnectPointOfOlt(DeviceId dId) {
343
344 Device d = deviceService.getDevice(dId);
345 SubscriberAndDeviceInformation deviceInfo = subsService.get(d.serialNumber());
346 log.debug("getUplinkConnectPointOfOlt DeviceId: {} devInfo: {}", dId, deviceInfo);
347 if (deviceInfo != null) {
348 PortNumber pNum = PortNumber.portNumber(deviceInfo.uplinkPort());
349 Port port = deviceService.getPort(d.id(), pNum);
350 if (port != null) {
351 return new ConnectPoint(d.id(), pNum);
352 }
353 }
354
355 return null;
356 }
357
358 /**
359 * Request DHCP packet from particular connect point via PacketService.
360 */
361 private void requestDhcpPacketsFromConnectPoint(ConnectPoint cp) {
362 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
363 .matchEthType(Ethernet.TYPE_IPV4)
364 .matchInPort(cp.port())
365 .matchIPProtocol(IPv4.PROTOCOL_UDP)
366 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
367 packetService.requestPackets(selectorServer.build(),
368 PacketPriority.CONTROL, appId, Optional.of(cp.deviceId()));
369 }
370
371 /**
372 * Cancel DHCP packet from particular connect point via PacketService.
373 */
374 private void cancelDhcpPacketsFromConnectPoint(ConnectPoint cp) {
375 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
376 .matchEthType(Ethernet.TYPE_IPV4)
377 .matchInPort(cp.port())
378 .matchIPProtocol(IPv4.PROTOCOL_UDP)
379 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
380 packetService.cancelPackets(selectorServer.build(),
381 PacketPriority.CONTROL, appId, Optional.of(cp.deviceId()));
382 }
383
384 /**
Amit Ghosh47243cb2017-07-26 05:08:53 +0100385 * Request DHCP packet in via PacketService.
386 */
387 private void requestDhcpPackets() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000388 if (!useOltUplink) {
389 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
390 .matchEthType(Ethernet.TYPE_IPV4)
391 .matchIPProtocol(IPv4.PROTOCOL_UDP)
392 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
393 packetService.requestPackets(selectorServer.build(),
394 PacketPriority.CONTROL, appId);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100395
Amit Ghosh83c8c892017-11-09 11:08:27 +0000396 TrafficSelector.Builder selectorClient = DefaultTrafficSelector.builder()
397 .matchEthType(Ethernet.TYPE_IPV4)
398 .matchIPProtocol(IPv4.PROTOCOL_UDP)
399 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
400 packetService.requestPackets(selectorClient.build(),
401 PacketPriority.CONTROL, appId);
402 } else {
403 for (ConnectPoint cp: getUplinkPortsOfOlts()) {
404 log.debug("requestDhcpPackets: ConnectPoint: {}", cp);
405 requestDhcpPacketsFromConnectPoint(cp);
406 }
407 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100408
Amit Ghosh47243cb2017-07-26 05:08:53 +0100409 }
410
411 /**
412 * Cancel requested DHCP packets in via packet service.
413 */
414 private void cancelDhcpPackets() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000415 if (!useOltUplink) {
416 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
417 .matchEthType(Ethernet.TYPE_IPV4)
418 .matchIPProtocol(IPv4.PROTOCOL_UDP)
419 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
420 packetService.cancelPackets(selectorServer.build(),
421 PacketPriority.CONTROL, appId);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100422
Amit Ghosh83c8c892017-11-09 11:08:27 +0000423 TrafficSelector.Builder selectorClient = DefaultTrafficSelector.builder()
424 .matchEthType(Ethernet.TYPE_IPV4)
425 .matchIPProtocol(IPv4.PROTOCOL_UDP)
426 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
427 packetService.cancelPackets(selectorClient.build(),
428 PacketPriority.CONTROL, appId);
429 } else {
430 for (ConnectPoint cp: getUplinkPortsOfOlts()) {
431 cancelDhcpPacketsFromConnectPoint(cp);
432 }
433 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100434 }
435
Amit Ghosha17354e2017-08-23 12:56:04 +0100436 public static Map<String, DhcpAllocationInfo> allocationMap() {
437 return allocationMap;
438 }
439
Amit Ghosh47243cb2017-07-26 05:08:53 +0100440 private SubscriberAndDeviceInformation getDevice(PacketContext context) {
441 String serialNo = deviceService.getDevice(context.inPacket().
442 receivedFrom().deviceId()).serialNumber();
443
444 return subsService.get(serialNo);
445 }
446
447 private SubscriberAndDeviceInformation getDevice(ConnectPoint cp) {
448 String serialNo = deviceService.getDevice(cp.deviceId()).
449 serialNumber();
450
451 return subsService.get(serialNo);
452 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100453
454 private MacAddress relayAgentMacAddress(PacketContext context) {
455
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000456 SubscriberAndDeviceInformation device = this.getDevice(context);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100457 if (device == null) {
458 log.warn("Device not found for {}", context.inPacket().
459 receivedFrom());
460 return null;
461 }
462
463 return device.hardwareIdentifier();
464 }
465
466 private String nasPortId(PacketContext context) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100467 return nasPortId(context.inPacket().receivedFrom());
468 }
469
470 private String nasPortId(ConnectPoint cp) {
471 Port p = deviceService.getPort(cp);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100472 return p.annotations().value(AnnotationKeys.PORT_NAME);
473 }
474
475 private SubscriberAndDeviceInformation getSubscriber(PacketContext context) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100476 return subsService.get(nasPortId(context));
477 }
478
479 private VlanId cTag(PacketContext context) {
480 SubscriberAndDeviceInformation sub = getSubscriber(context);
481 if (sub == null) {
482 log.warn("Subscriber info not found for {}", context.inPacket().
483 receivedFrom());
484 return VlanId.NONE;
485 }
486 return sub.cTag();
487 }
488
Amit Ghosh8951f042017-08-10 13:48:10 +0100489 private VlanId cTag(ConnectPoint cp) {
490 String portId = nasPortId(cp);
491 SubscriberAndDeviceInformation sub = subsService.get(portId);
492 if (sub == null) {
493 log.warn("Subscriber info not found for {} looking for C-TAG", cp);
494 return VlanId.NONE;
495 }
496 return sub.cTag();
497 }
498
499 private VlanId sTag(ConnectPoint cp) {
500 String portId = nasPortId(cp);
501 SubscriberAndDeviceInformation sub = subsService.get(portId);
502 if (sub == null) {
503 log.warn("Subscriber info not found for {} looking for S-TAG", cp);
504 return VlanId.NONE;
505 }
506 return sub.sTag();
507 }
508
Amit Ghosh47243cb2017-07-26 05:08:53 +0100509 private VlanId sTag(PacketContext context) {
510 SubscriberAndDeviceInformation sub = getSubscriber(context);
511 if (sub == null) {
512 log.warn("Subscriber info not found for {}", context.inPacket().
513 receivedFrom());
514 return VlanId.NONE;
515 }
516 return sub.sTag();
517 }
518
519 private class DhcpRelayPacketProcessor implements PacketProcessor {
520
521 @Override
522 public void process(PacketContext context) {
523 if (!configured()) {
524 log.warn("Missing DHCP relay config. Abort packet processing");
525 return;
526 }
527
528 // process the packet and get the payload
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530529 Ethernet packet = context.inPacket().parsed();
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000530
Amit Ghosh47243cb2017-07-26 05:08:53 +0100531 if (packet == null) {
532 log.warn("Packet is null");
533 return;
534 }
535
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000536 log.debug("Got a packet ", packet);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100537
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530538 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100539 IPv4 ipv4Packet = (IPv4) packet.getPayload();
540
541 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
542 UDP udpPacket = (UDP) ipv4Packet.getPayload();
543 if (udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT ||
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000544 udpPacket.getSourcePort() == UDP.DHCP_SERVER_PORT) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100545 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
546 //This packet is dhcp.
547 processDhcpPacket(context, packet, dhcpPayload);
548 }
549 }
550 }
551 }
552
553 //forward the packet to ConnectPoint where the DHCP server is attached.
Amit Ghosh83c8c892017-11-09 11:08:27 +0000554 private void forwardPacket(Ethernet packet, PacketContext context) {
555 ConnectPoint toSendTo = null;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100556
Amit Ghosh83c8c892017-11-09 11:08:27 +0000557 if (!useOltUplink) {
558 toSendTo = dhcpServerConnectPoint.get();
559 } else {
560 toSendTo = getUplinkConnectPointOfOlt(context.inPacket().
561 receivedFrom().deviceId());
562 }
563
564 if (toSendTo != null) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100565 TrafficTreatment t = DefaultTrafficTreatment.builder()
Amit Ghosh83c8c892017-11-09 11:08:27 +0000566 .setOutput(toSendTo.port()).build();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100567 OutboundPacket o = new DefaultOutboundPacket(
Amit Ghosh83c8c892017-11-09 11:08:27 +0000568 toSendTo.deviceId(), t,
Amit Ghosh47243cb2017-07-26 05:08:53 +0100569 ByteBuffer.wrap(packet.serialize()));
570 if (log.isTraceEnabled()) {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530571 log.trace("Relaying packet to dhcp server {} at {}",
Amit Ghosh83c8c892017-11-09 11:08:27 +0000572 packet, toSendTo);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100573 }
574 packetService.emit(o);
575 } else {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000576 log.error("No connect point to send msg to DHCP Server");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100577 }
578 }
579
Amit Ghosha17354e2017-08-23 12:56:04 +0100580 // get the type of the DHCP packet
581 private DHCPPacketType getDhcpPacketType(DHCP dhcpPayload) {
582
Jonathan Hartedbf6422018-05-02 17:30:05 -0700583 for (DhcpOption option : dhcpPayload.getOptions()) {
Amit Ghosha17354e2017-08-23 12:56:04 +0100584 if (option.getCode() == OptionCode_MessageType.getValue()) {
585 byte[] data = option.getData();
586 return DHCPPacketType.getType(data[0]);
587 }
588 }
589 return null;
590 }
591
Amit Ghosh47243cb2017-07-26 05:08:53 +0100592 //process the dhcp packet before sending to server
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530593 private void processDhcpPacket(PacketContext context, Ethernet packet,
Amit Ghosh47243cb2017-07-26 05:08:53 +0100594 DHCP dhcpPayload) {
595 if (dhcpPayload == null) {
596 log.warn("DHCP payload is null");
597 return;
598 }
599
Amit Ghosha17354e2017-08-23 12:56:04 +0100600 DHCPPacketType incomingPacketType = getDhcpPacketType(dhcpPayload);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000601
Amit Ghosh47243cb2017-07-26 05:08:53 +0100602 log.info("Received DHCP Packet of type {}", incomingPacketType);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100603
604 switch (incomingPacketType) {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000605 case DHCPDISCOVER:
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530606 Ethernet ethernetPacketDiscover =
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000607 processDhcpPacketFromClient(context, packet);
608 if (ethernetPacketDiscover != null) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000609 forwardPacket(ethernetPacketDiscover, context);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000610 }
611 break;
612 case DHCPOFFER:
613 //reply to dhcp client.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530614 Ethernet ethernetPacketOffer = processDhcpPacketFromServer(packet);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000615 if (ethernetPacketOffer != null) {
616 sendReply(ethernetPacketOffer, dhcpPayload);
617 }
618 break;
619 case DHCPREQUEST:
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530620 Ethernet ethernetPacketRequest =
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000621 processDhcpPacketFromClient(context, packet);
622 if (ethernetPacketRequest != null) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000623 forwardPacket(ethernetPacketRequest, context);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000624 }
625 break;
626 case DHCPACK:
627 //reply to dhcp client.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530628 Ethernet ethernetPacketAck = processDhcpPacketFromServer(packet);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000629 if (ethernetPacketAck != null) {
630 sendReply(ethernetPacketAck, dhcpPayload);
631 }
632 break;
633 default:
634 break;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100635 }
636 }
637
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530638 private Ethernet processDhcpPacketFromClient(PacketContext context,
639 Ethernet ethernetPacket) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100640
641 MacAddress relayAgentMac = relayAgentMacAddress(context);
642 if (relayAgentMac == null) {
643 log.warn("RelayAgent MAC not found ");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100644 return null;
645 }
646
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530647 Ethernet etherReply = ethernetPacket;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100648
649 IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
650 UDP udpPacket = (UDP) ipv4Packet.getPayload();
651 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
652
Amit Ghosha17354e2017-08-23 12:56:04 +0100653 if (enableDhcpBroadcastReplies) {
654 // We want the reply to come back as a L2 broadcast
655 dhcpPacket.setFlags((short) 0x8000);
656 }
657
Jonathan Hartc36c9552018-07-31 15:07:53 -0400658 MacAddress clientMac = MacAddress.valueOf(dhcpPacket.getClientHardwareAddress());
659 IpAddress clientIp = IpAddress.valueOf(dhcpPacket.getClientIPAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100660
Jonathan Hartc36c9552018-07-31 15:07:53 -0400661 SubscriberAndDeviceInformation entry = getSubscriber(context);
662 if (entry == null) {
663 log.info("Dropping packet as subscriber entry is not available");
664 return null;
665 }
666
667 DhcpAllocationInfo info = new DhcpAllocationInfo(
668 context.inPacket().receivedFrom(), dhcpPacket.getPacketType(),
669 entry.nasPortId(), clientMac, clientIp);
670
671 allocationMap.put(entry.nasPortId(), info);
672
673 post(new DhcpL2RelayEvent(DhcpL2RelayEvent.Type.UPDATED, info, context.inPacket().receivedFrom()));
Amit Ghosha17354e2017-08-23 12:56:04 +0100674
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000675 if (option82) {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000676 DHCP dhcpPacketWithOption82 = addOption82(dhcpPacket, entry);
677 udpPacket.setPayload(dhcpPacketWithOption82);
678 }
679
680 ipv4Packet.setPayload(udpPacket);
681 etherReply.setPayload(ipv4Packet);
Amit Ghosh83c8c892017-11-09 11:08:27 +0000682 if (modifyClientPktsSrcDstMac) {
683 etherReply.setSourceMACAddress(relayAgentMac);
684 etherReply.setDestinationMACAddress(dhcpConnectMac);
685 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100686
Amit Ghosh8951f042017-08-10 13:48:10 +0100687 etherReply.setPriorityCode(ethernetPacket.getPriorityCode());
Amit Ghosh47243cb2017-07-26 05:08:53 +0100688 etherReply.setVlanID(cTag(context).toShort());
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530689 etherReply.setQinQTPID(Ethernet.TYPE_VLAN);
690 etherReply.setQinQVID(sTag(context).toShort());
Amit Ghosh47243cb2017-07-26 05:08:53 +0100691
Amit Ghosh8951f042017-08-10 13:48:10 +0100692 log.info("Finished processing packet -- sending packet {}", etherReply);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100693 return etherReply;
694 }
695
696 //build the DHCP offer/ack with proper client port.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530697 private Ethernet processDhcpPacketFromServer(Ethernet ethernetPacket) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100698 // get dhcp header.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530699 Ethernet etherReply = (Ethernet) ethernetPacket.clone();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100700 IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
701 UDP udpPacket = (UDP) ipv4Packet.getPayload();
702 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
703
Amit Ghosh47243cb2017-07-26 05:08:53 +0100704 MacAddress dstMac = valueOf(dhcpPayload.getClientHardwareAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100705 ConnectPoint subsCp = getConnectPointOfClient(dstMac);
Amit Ghosh2095dc62017-09-25 20:56:55 +0100706 // If we can't find the subscriber, can't process further
707 if (subsCp == null) {
708 return null;
709 }
Amit Ghosha17354e2017-08-23 12:56:04 +0100710 // if it's an ACK packet store the information for display purpose
711 if (getDhcpPacketType(dhcpPayload) == DHCPPacketType.DHCPACK) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100712
Amit Ghosha17354e2017-08-23 12:56:04 +0100713 String portId = nasPortId(subsCp);
714 SubscriberAndDeviceInformation sub = subsService.get(portId);
715 if (sub != null) {
Jonathan Hartedbf6422018-05-02 17:30:05 -0700716 List<DhcpOption> options = dhcpPayload.getOptions();
717 List<DhcpOption> circuitIds = options.stream()
Amit Ghosha17354e2017-08-23 12:56:04 +0100718 .filter(option -> option.getCode() == DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
719 .collect(Collectors.toList());
720
721 String circuitId = "None";
722 if (circuitIds.size() == 1) {
Amit Ghosh2095dc62017-09-25 20:56:55 +0100723 byte[] array = circuitIds.get(0).getData();
724
725 try {
726 // we leave the first two bytes as they are the id and length
727 circuitId = new String(Arrays.copyOfRange(array, 2, array.length), "UTF-8");
728 } catch (Exception e) { }
Amit Ghosha17354e2017-08-23 12:56:04 +0100729 }
730
731 IpAddress ip = IpAddress.valueOf(dhcpPayload.getYourIPAddress());
732
733 //storeDHCPAllocationInfo
Jonathan Hartc36c9552018-07-31 15:07:53 -0400734 DhcpAllocationInfo info = new DhcpAllocationInfo(subsCp,
735 dhcpPayload.getPacketType(), circuitId, dstMac, ip);
Amit Ghosha17354e2017-08-23 12:56:04 +0100736
737 allocationMap.put(sub.nasPortId(), info);
Jonathan Hartc36c9552018-07-31 15:07:53 -0400738
739 post(new DhcpL2RelayEvent(DhcpL2RelayEvent.Type.UPDATED, info, subsCp));
Amit Ghosha17354e2017-08-23 12:56:04 +0100740 }
741 } // end storing of info
Amit Ghosh47243cb2017-07-26 05:08:53 +0100742
743 // we leave the srcMac from the original packet
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530744 etherReply.setDestinationMACAddress(dstMac);
745 etherReply.setQinQVID(sTag(subsCp).toShort());
Amit Ghosh8951f042017-08-10 13:48:10 +0100746 etherReply.setPriorityCode(ethernetPacket.getPriorityCode());
747 etherReply.setVlanID((cTag(subsCp).toShort()));
Amit Ghosh47243cb2017-07-26 05:08:53 +0100748
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000749 if (option82) {
750 udpPacket.setPayload(removeOption82(dhcpPayload));
751 } else {
752 udpPacket.setPayload(dhcpPayload);
753 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100754 ipv4Packet.setPayload(udpPacket);
755 etherReply.setPayload(ipv4Packet);
756
757 log.info("Finished processing packet");
758 return etherReply;
759 }
760
Amit Ghosha17354e2017-08-23 12:56:04 +0100761 /*
762 * Get ConnectPoint of the Client based on it's MAC address
763 */
764 private ConnectPoint getConnectPointOfClient(MacAddress dstMac) {
765 Set<Host> hosts = hostService.getHostsByMac(dstMac);
766 if (hosts == null || hosts.isEmpty()) {
767 log.warn("Cannot determine host for DHCP client: {}. Aborting "
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530768 + "relay for dhcp packet from server",
Amit Ghosha17354e2017-08-23 12:56:04 +0100769 dstMac);
770 return null;
771 }
772 for (Host h : hosts) {
773 // if more than one,
774 // find the connect point which has an valid entry in SADIS
775 ConnectPoint cp = new ConnectPoint(h.location().deviceId(),
776 h.location().port());
777
778 if (sTag(cp) != VlanId.NONE) {
779 return cp;
780 }
781 }
782
783 return null;
784 }
785
Amit Ghosh47243cb2017-07-26 05:08:53 +0100786 //send the response to the requester host.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530787 private void sendReply(Ethernet ethPacket, DHCP dhcpPayload) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100788 MacAddress descMac = valueOf(dhcpPayload.getClientHardwareAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100789 ConnectPoint subCp = getConnectPointOfClient(descMac);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100790
791 // Send packet out to requester if the host information is available
Amit Ghosha17354e2017-08-23 12:56:04 +0100792 if (subCp != null) {
793 log.info("Sending DHCP packet to cp: {}", subCp);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100794 TrafficTreatment t = DefaultTrafficTreatment.builder()
Amit Ghosha17354e2017-08-23 12:56:04 +0100795 .setOutput(subCp.port()).build();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100796 OutboundPacket o = new DefaultOutboundPacket(
Amit Ghosha17354e2017-08-23 12:56:04 +0100797 subCp.deviceId(), t, ByteBuffer.wrap(ethPacket.serialize()));
Amit Ghosh47243cb2017-07-26 05:08:53 +0100798 if (log.isTraceEnabled()) {
799 log.trace("Relaying packet to dhcp client {}", ethPacket);
800 }
801 packetService.emit(o);
Amit Ghosha17354e2017-08-23 12:56:04 +0100802 log.info("DHCP Packet sent to {}", subCp);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100803 } else {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000804 log.error("Dropping DHCP packet because can't find host for {}", descMac);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100805 }
806 }
807 }
808
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000809 private DHCP addOption82(DHCP dhcpPacket, SubscriberAndDeviceInformation entry) {
810 log.debug("option82data {} ", entry);
811
Jonathan Hartedbf6422018-05-02 17:30:05 -0700812 List<DhcpOption> options = Lists.newArrayList(dhcpPacket.getOptions());
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000813 DhcpOption82 option82 = new DhcpOption82();
814 option82.setAgentCircuitId(entry.circuitId());
815 option82.setAgentRemoteId(entry.remoteId());
Jonathan Hartedbf6422018-05-02 17:30:05 -0700816 DhcpOption option = new DhcpOption()
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530817 .setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
818 .setData(option82.toByteArray())
819 .setLength(option82.length());
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000820
821 options.add(options.size() - 1, option);
822 dhcpPacket.setOptions(options);
Amit Ghosh8951f042017-08-10 13:48:10 +0100823
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000824 return dhcpPacket;
825
826 }
827
828 private DHCP removeOption82(DHCP dhcpPacket) {
Jonathan Hartedbf6422018-05-02 17:30:05 -0700829 List<DhcpOption> options = dhcpPacket.getOptions();
830 List<DhcpOption> newoptions = options.stream()
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000831 .filter(option -> option.getCode() != DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
832 .collect(Collectors.toList());
833
834 return dhcpPacket.setOptions(newoptions);
835 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100836 /**
837 * Listener for network config events.
838 */
839 private class InternalConfigListener implements NetworkConfigListener {
840
841 @Override
842 public void event(NetworkConfigEvent event) {
843
844 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
845 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
846 event.configClass().equals(DhcpL2RelayConfig.class)) {
847 updateConfig();
848 log.info("Reconfigured");
849 }
850 }
851 }
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000852
Amit Ghosh8951f042017-08-10 13:48:10 +0100853 /**
854 * Handles Mastership changes for the devices which connect
855 * to the DHCP server.
856 */
857 private class InnerMastershipListener implements MastershipListener {
858 @Override
859 public void event(MastershipEvent event) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000860 if (!useOltUplink) {
861 if (dhcpServerConnectPoint.get() != null &&
862 dhcpServerConnectPoint.get().deviceId().
863 equals(event.subject())) {
864 log.trace("Mastership Event recevived for {}", event.subject());
865 // mastership of the device for our connect point has changed
866 // reselect
867 selectServerConnectPoint();
868 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100869 }
870 }
871 }
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000872
Amit Ghosh8951f042017-08-10 13:48:10 +0100873 /**
874 * Handles Device status change for the devices which connect
875 * to the DHCP server.
876 */
877 private class InnerDeviceListener implements DeviceListener {
878 @Override
879 public void event(DeviceEvent event) {
880 log.trace("Device Event recevived for {} event {}", event.subject(), event.type());
Amit Ghosh83c8c892017-11-09 11:08:27 +0000881 if (!useOltUplink) {
882 if (dhcpServerConnectPoint.get() == null) {
883 switch (event.type()) {
884 case DEVICE_ADDED:
885 case DEVICE_AVAILABILITY_CHANGED:
886 // some device is available check if we can get one
887 selectServerConnectPoint();
888 break;
889 default:
890 break;
891 }
892 return;
Amit Ghosh8951f042017-08-10 13:48:10 +0100893 }
Amit Ghosh83c8c892017-11-09 11:08:27 +0000894 if (dhcpServerConnectPoint.get().deviceId().
895 equals(event.subject().id())) {
896 switch (event.type()) {
897 case DEVICE_AVAILABILITY_CHANGED:
898 case DEVICE_REMOVED:
899 case DEVICE_SUSPENDED:
900 // state of our device has changed, check if we need
901 // to re-select
902 selectServerConnectPoint();
903 break;
904 default:
905 break;
906 }
907 }
908 } else {
Amit Ghosh8951f042017-08-10 13:48:10 +0100909 switch (event.type()) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000910 case PORT_ADDED:
911 if (isUplinkPortOfOlt(event.subject().id(), event.port())) {
912 requestDhcpPacketsFromConnectPoint(new ConnectPoint(event.subject().id(),
913 event.port().number()));
914 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100915 break;
916 default:
917 break;
918 }
919 }
920 }
921 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100922}