blob: a577ae8439068ee2cc8330cbda2f276b3c5cd618 [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
Saurav Das15626a02018-09-27 18:36:45 -070018import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType;
19import static org.onlab.packet.MacAddress.valueOf;
20import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
21
22import java.nio.ByteBuffer;
23import java.util.ArrayList;
24import java.util.Arrays;
25import java.util.Dictionary;
26import java.util.List;
27import java.util.Map;
28import java.util.Optional;
29import java.util.Set;
30import java.util.concurrent.atomic.AtomicReference;
31import java.util.stream.Collectors;
32
Amit Ghosh47243cb2017-07-26 05:08:53 +010033import org.apache.felix.scr.annotations.Activate;
34import org.apache.felix.scr.annotations.Component;
35import org.apache.felix.scr.annotations.Deactivate;
36import org.apache.felix.scr.annotations.Modified;
37import org.apache.felix.scr.annotations.Property;
38import org.apache.felix.scr.annotations.Reference;
39import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hartc36c9552018-07-31 15:07:53 -040040import org.apache.felix.scr.annotations.Service;
Amit Ghosh47243cb2017-07-26 05:08:53 +010041import org.onlab.packet.DHCP;
Amit Ghosh47243cb2017-07-26 05:08:53 +010042import org.onlab.packet.DHCPPacketType;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000043import org.onlab.packet.Ethernet;
Amit Ghosh47243cb2017-07-26 05:08:53 +010044import org.onlab.packet.IPv4;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053045import org.onlab.packet.IpAddress;
Deepa vaddireddy0060f532017-08-04 06:46:05 +000046import org.onlab.packet.MacAddress;
Amit Ghosh47243cb2017-07-26 05:08:53 +010047import org.onlab.packet.TpPort;
48import org.onlab.packet.UDP;
49import org.onlab.packet.VlanId;
Jonathan Hartedbf6422018-05-02 17:30:05 -070050import org.onlab.packet.dhcp.DhcpOption;
Amit Ghosh47243cb2017-07-26 05:08:53 +010051import org.onlab.util.Tools;
52import org.onosproject.cfg.ComponentConfigService;
53import org.onosproject.core.ApplicationId;
54import org.onosproject.core.CoreService;
Jonathan Hartc36c9552018-07-31 15:07:53 -040055import org.onosproject.event.AbstractListenerManager;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053056import org.onosproject.mastership.MastershipEvent;
57import org.onosproject.mastership.MastershipListener;
58import org.onosproject.mastership.MastershipService;
Amit Ghosh47243cb2017-07-26 05:08:53 +010059import org.onosproject.net.AnnotationKeys;
60import org.onosproject.net.ConnectPoint;
Amit Ghosh83c8c892017-11-09 11:08:27 +000061import org.onosproject.net.Device;
62import org.onosproject.net.DeviceId;
Amit Ghosh47243cb2017-07-26 05:08:53 +010063import org.onosproject.net.Host;
64import org.onosproject.net.Port;
Amit Ghosh83c8c892017-11-09 11:08:27 +000065import org.onosproject.net.PortNumber;
Amit Ghosh47243cb2017-07-26 05:08:53 +010066import org.onosproject.net.config.ConfigFactory;
67import org.onosproject.net.config.NetworkConfigEvent;
68import org.onosproject.net.config.NetworkConfigListener;
69import org.onosproject.net.config.NetworkConfigRegistry;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053070import org.onosproject.net.device.DeviceEvent;
71import org.onosproject.net.device.DeviceListener;
Amit Ghosh47243cb2017-07-26 05:08:53 +010072import org.onosproject.net.device.DeviceService;
73import org.onosproject.net.flow.DefaultTrafficSelector;
74import org.onosproject.net.flow.DefaultTrafficTreatment;
75import org.onosproject.net.flow.TrafficSelector;
76import org.onosproject.net.flow.TrafficTreatment;
77import org.onosproject.net.host.HostService;
78import org.onosproject.net.packet.DefaultOutboundPacket;
79import org.onosproject.net.packet.OutboundPacket;
80import org.onosproject.net.packet.PacketContext;
81import org.onosproject.net.packet.PacketPriority;
82import org.onosproject.net.packet.PacketProcessor;
83import org.onosproject.net.packet.PacketService;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053084import org.opencord.dhcpl2relay.packet.DhcpOption82;
Amit Ghosh47243cb2017-07-26 05:08:53 +010085import org.opencord.sadis.SubscriberAndDeviceInformation;
86import org.opencord.sadis.SubscriberAndDeviceInformationService;
Amit Ghosh47243cb2017-07-26 05:08:53 +010087import org.osgi.service.component.ComponentContext;
88import org.slf4j.Logger;
89import org.slf4j.LoggerFactory;
90
Saurav Das15626a02018-09-27 18:36:45 -070091import com.google.common.collect.ImmutableSet;
92import com.google.common.collect.Lists;
93import com.google.common.collect.Maps;
94import com.google.common.collect.Sets;
Amit Ghosh47243cb2017-07-26 05:08:53 +010095
96/**
97 * DHCP Relay Agent Application Component.
98 */
Jonathan Hartc36c9552018-07-31 15:07:53 -040099@Service
Amit Ghosh47243cb2017-07-26 05:08:53 +0100100@Component(immediate = true)
Jonathan Hartc36c9552018-07-31 15:07:53 -0400101public class DhcpL2Relay
102 extends AbstractListenerManager<DhcpL2RelayEvent, DhcpL2RelayListener>
103 implements DhcpL2RelayService {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100104
105 public static final String DHCP_L2RELAY_APP = "org.opencord.dhcpl2relay";
106 private final Logger log = LoggerFactory.getLogger(getClass());
107 private final InternalConfigListener cfgListener =
108 new InternalConfigListener();
109
110 private final Set<ConfigFactory> factories = ImmutableSet.of(
111 new ConfigFactory<ApplicationId, DhcpL2RelayConfig>(APP_SUBJECT_FACTORY,
112 DhcpL2RelayConfig.class,
113 "dhcpl2relay") {
114 @Override
115 public DhcpL2RelayConfig createConfig() {
116 return new DhcpL2RelayConfig();
117 }
118 }
119 );
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected NetworkConfigRegistry cfgService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 protected CoreService coreService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected PacketService packetService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected HostService hostService;
132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected ComponentConfigService componentConfigService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected SubscriberAndDeviceInformationService subsService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 protected DeviceService deviceService;
141
Amit Ghosh8951f042017-08-10 13:48:10 +0100142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 protected MastershipService mastershipService;
144
Amit Ghosh47243cb2017-07-26 05:08:53 +0100145 @Property(name = "option82", boolValue = true,
146 label = "Add option 82 to relayed packets")
147 protected boolean option82 = true;
148
Amit Ghosha17354e2017-08-23 12:56:04 +0100149 @Property(name = "enableDhcpBroadcastReplies", boolValue = false,
Amit Ghosh2095dc62017-09-25 20:56:55 +0100150 label = "Ask the DHCP Server to send back replies as L2 broadcast")
Amit Ghosha17354e2017-08-23 12:56:04 +0100151 protected boolean enableDhcpBroadcastReplies = false;
152
Amit Ghosh47243cb2017-07-26 05:08:53 +0100153 private DhcpRelayPacketProcessor dhcpRelayPacketProcessor =
154 new DhcpRelayPacketProcessor();
155
Amit Ghosh8951f042017-08-10 13:48:10 +0100156 private InnerMastershipListener changeListener = new InnerMastershipListener();
157 private InnerDeviceListener deviceListener = new InnerDeviceListener();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100158
Amit Ghosh8951f042017-08-10 13:48:10 +0100159 // connect points to the DHCP server
160 Set<ConnectPoint> dhcpConnectPoints;
161 private AtomicReference<ConnectPoint> dhcpServerConnectPoint = new AtomicReference<>();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100162 private MacAddress dhcpConnectMac = MacAddress.BROADCAST;
163 private ApplicationId appId;
164
Amit Ghosha17354e2017-08-23 12:56:04 +0100165 static Map<String, DhcpAllocationInfo> allocationMap = Maps.newConcurrentMap();
Amit Ghosh83c8c892017-11-09 11:08:27 +0000166 private boolean modifyClientPktsSrcDstMac = false;
167 //Whether to use the uplink port of the OLTs to send/receive messages to the DHCP server
168 private boolean useOltUplink = false;
Amit Ghosha17354e2017-08-23 12:56:04 +0100169
Amit Ghosh47243cb2017-07-26 05:08:53 +0100170 @Activate
171 protected void activate(ComponentContext context) {
172 //start the dhcp relay agent
173 appId = coreService.registerApplication(DHCP_L2RELAY_APP);
174 componentConfigService.registerProperties(getClass());
Jonathan Hartc36c9552018-07-31 15:07:53 -0400175 eventDispatcher.addSink(DhcpL2RelayEvent.class, listenerRegistry);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100176
177 cfgService.addListener(cfgListener);
Amit Ghosh8951f042017-08-10 13:48:10 +0100178 mastershipService.addListener(changeListener);
179 deviceService.addListener(deviceListener);
180
Amit Ghosh47243cb2017-07-26 05:08:53 +0100181 factories.forEach(cfgService::registerConfigFactory);
182 //update the dhcp server configuration.
183 updateConfig();
184 //add the packet services.
185 packetService.addProcessor(dhcpRelayPacketProcessor,
186 PacketProcessor.director(0));
187 requestDhcpPackets();
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000188 if (context != null) {
189 modified(context);
190 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100191
192 log.info("DHCP-L2-RELAY Started");
193 }
194
195 @Deactivate
196 protected void deactivate() {
197 cfgService.removeListener(cfgListener);
198 factories.forEach(cfgService::unregisterConfigFactory);
199 packetService.removeProcessor(dhcpRelayPacketProcessor);
200 cancelDhcpPackets();
201
202 componentConfigService.unregisterProperties(getClass(), false);
Deepa Vaddireddy77a6ac72017-09-20 20:36:52 +0530203 deviceService.removeListener(deviceListener);
204 mastershipService.removeListener(changeListener);
Jonathan Hartc36c9552018-07-31 15:07:53 -0400205 eventDispatcher.removeSink(DhcpL2RelayEvent.class);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100206 log.info("DHCP-L2-RELAY Stopped");
207 }
208
209 @Modified
210 protected void modified(ComponentContext context) {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000211
Amit Ghosh47243cb2017-07-26 05:08:53 +0100212 Dictionary<?, ?> properties = context.getProperties();
213
214 Boolean o = Tools.isPropertyEnabled(properties, "option82");
215 if (o != null) {
216 option82 = o;
217 }
Amit Ghosh2095dc62017-09-25 20:56:55 +0100218
219 o = Tools.isPropertyEnabled(properties, "enableDhcpBroadcastReplies");
220 if (o != null) {
221 enableDhcpBroadcastReplies = o;
222 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100223 }
224
225 /**
226 * Checks if this app has been configured.
227 *
228 * @return true if all information we need have been initialized
229 */
230 private boolean configured() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000231 if (!useOltUplink) {
232 return dhcpServerConnectPoint.get() != null;
233 }
234 return true;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100235 }
236
Amit Ghosh8951f042017-08-10 13:48:10 +0100237 /**
238 * Selects a connect point through an available device for which it is the master.
239 */
240 private void selectServerConnectPoint() {
241 synchronized (this) {
242 dhcpServerConnectPoint.set(null);
243 if (dhcpConnectPoints != null) {
244 // find a connect point through a device for which we are master
245 for (ConnectPoint cp: dhcpConnectPoints) {
246 if (mastershipService.isLocalMaster(cp.deviceId())) {
247 if (deviceService.isAvailable(cp.deviceId())) {
248 dhcpServerConnectPoint.set(cp);
249 }
250 log.info("DHCP connectPoint selected is {}", cp);
251 break;
252 }
253 }
254 }
255
256 log.info("DHCP Server connectPoint is {}", dhcpServerConnectPoint.get());
257
258 if (dhcpServerConnectPoint.get() == null) {
259 log.error("Master of none, can't relay DHCP Message to server");
260 }
261 }
262 }
263
264 /**
265 * Updates the network configuration.
266 */
Amit Ghosh47243cb2017-07-26 05:08:53 +0100267 private void updateConfig() {
268 DhcpL2RelayConfig cfg = cfgService.getConfig(appId, DhcpL2RelayConfig.class);
269 if (cfg == null) {
270 log.warn("Dhcp Server info not available");
271 return;
272 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100273
274 dhcpConnectPoints = Sets.newConcurrentHashSet(cfg.getDhcpServerConnectPoint());
Amit Ghosh83c8c892017-11-09 11:08:27 +0000275 modifyClientPktsSrcDstMac = cfg.getModifySrcDstMacAddresses();
276 useOltUplink = cfg.getUseOltUplinkForServerPktInOut();
Amit Ghosh8951f042017-08-10 13:48:10 +0100277
Amit Ghosh83c8c892017-11-09 11:08:27 +0000278 if (!useOltUplink) {
279 selectServerConnectPoint();
280 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100281
Amit Ghosh47243cb2017-07-26 05:08:53 +0100282 log.info("dhcp server connect point: " + dhcpServerConnectPoint);
283 }
284
285 /**
Amit Ghosh83c8c892017-11-09 11:08:27 +0000286 * Returns all the uplink ports of OLTs configured in SADIS.
287 * Only ports visible in ONOS and for which this instance is master
288 * are returned
289 */
290 private List<ConnectPoint> getUplinkPortsOfOlts() {
291 List<ConnectPoint> cps = new ArrayList<>();
292
293 // find all the olt devices and if their uplink ports are visible
294 Iterable<Device> devices = deviceService.getDevices();
295 for (Device d : devices) {
296 // check if this device is provisioned in Sadis
297
298 log.debug("getUplinkPortsOfOlts: Checking mastership of {}", d);
299 // do only for devices for which we are the master
300 if (!mastershipService.isLocalMaster(d.id())) {
301 continue;
302 }
303
304 String devSerialNo = d.serialNumber();
305 SubscriberAndDeviceInformation deviceInfo = subsService.get(devSerialNo);
306 log.debug("getUplinkPortsOfOlts: Found device: {}", deviceInfo);
307 if (deviceInfo != null) {
308 // check if the uplink port with that number is available on the device
309 PortNumber pNum = PortNumber.portNumber(deviceInfo.uplinkPort());
310 Port port = deviceService.getPort(d.id(), pNum);
311 log.debug("getUplinkPortsOfOlts: Found port: {}", port);
312 if (port != null) {
313 cps.add(new ConnectPoint(d.id(), pNum));
314 }
315 }
316 }
317 return cps;
318 }
319
320 /**
321 * Returns whether the passed port is the uplink port of the olt device.
322 */
323 private boolean isUplinkPortOfOlt(DeviceId dId, Port p) {
324 log.debug("isUplinkPortOfOlt: DeviceId: {} Port: {}", dId, p);
325 // do only for devices for which we are the master
326 if (!mastershipService.isLocalMaster(dId)) {
327 return false;
328 }
329
330 Device d = deviceService.getDevice(dId);
331 SubscriberAndDeviceInformation deviceInfo = subsService.get(d.serialNumber());
332
333 if (deviceInfo != null) {
334 return (deviceInfo.uplinkPort() == p.number().toLong());
335 }
336
337 return false;
338 }
339
340 /**
341 * Returns the connectPoint which is the uplink port of the OLT.
342 */
343 private ConnectPoint getUplinkConnectPointOfOlt(DeviceId dId) {
344
345 Device d = deviceService.getDevice(dId);
346 SubscriberAndDeviceInformation deviceInfo = subsService.get(d.serialNumber());
347 log.debug("getUplinkConnectPointOfOlt DeviceId: {} devInfo: {}", dId, deviceInfo);
348 if (deviceInfo != null) {
349 PortNumber pNum = PortNumber.portNumber(deviceInfo.uplinkPort());
350 Port port = deviceService.getPort(d.id(), pNum);
351 if (port != null) {
352 return new ConnectPoint(d.id(), pNum);
353 }
354 }
355
356 return null;
357 }
358
359 /**
360 * Request DHCP packet from particular connect point via PacketService.
361 */
362 private void requestDhcpPacketsFromConnectPoint(ConnectPoint cp) {
363 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
364 .matchEthType(Ethernet.TYPE_IPV4)
365 .matchInPort(cp.port())
366 .matchIPProtocol(IPv4.PROTOCOL_UDP)
367 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
368 packetService.requestPackets(selectorServer.build(),
369 PacketPriority.CONTROL, appId, Optional.of(cp.deviceId()));
370 }
371
372 /**
373 * Cancel DHCP packet from particular connect point via PacketService.
374 */
375 private void cancelDhcpPacketsFromConnectPoint(ConnectPoint cp) {
376 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
377 .matchEthType(Ethernet.TYPE_IPV4)
378 .matchInPort(cp.port())
379 .matchIPProtocol(IPv4.PROTOCOL_UDP)
380 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
381 packetService.cancelPackets(selectorServer.build(),
382 PacketPriority.CONTROL, appId, Optional.of(cp.deviceId()));
383 }
384
385 /**
Amit Ghosh47243cb2017-07-26 05:08:53 +0100386 * Request DHCP packet in via PacketService.
387 */
388 private void requestDhcpPackets() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000389 if (!useOltUplink) {
390 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
391 .matchEthType(Ethernet.TYPE_IPV4)
392 .matchIPProtocol(IPv4.PROTOCOL_UDP)
393 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
394 packetService.requestPackets(selectorServer.build(),
395 PacketPriority.CONTROL, appId);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100396
Amit Ghosh83c8c892017-11-09 11:08:27 +0000397 TrafficSelector.Builder selectorClient = DefaultTrafficSelector.builder()
398 .matchEthType(Ethernet.TYPE_IPV4)
399 .matchIPProtocol(IPv4.PROTOCOL_UDP)
400 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
401 packetService.requestPackets(selectorClient.build(),
402 PacketPriority.CONTROL, appId);
403 } else {
404 for (ConnectPoint cp: getUplinkPortsOfOlts()) {
405 log.debug("requestDhcpPackets: ConnectPoint: {}", cp);
406 requestDhcpPacketsFromConnectPoint(cp);
407 }
408 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100409
Amit Ghosh47243cb2017-07-26 05:08:53 +0100410 }
411
412 /**
413 * Cancel requested DHCP packets in via packet service.
414 */
415 private void cancelDhcpPackets() {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000416 if (!useOltUplink) {
417 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
418 .matchEthType(Ethernet.TYPE_IPV4)
419 .matchIPProtocol(IPv4.PROTOCOL_UDP)
420 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
421 packetService.cancelPackets(selectorServer.build(),
422 PacketPriority.CONTROL, appId);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100423
Amit Ghosh83c8c892017-11-09 11:08:27 +0000424 TrafficSelector.Builder selectorClient = DefaultTrafficSelector.builder()
425 .matchEthType(Ethernet.TYPE_IPV4)
426 .matchIPProtocol(IPv4.PROTOCOL_UDP)
427 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
428 packetService.cancelPackets(selectorClient.build(),
429 PacketPriority.CONTROL, appId);
430 } else {
431 for (ConnectPoint cp: getUplinkPortsOfOlts()) {
432 cancelDhcpPacketsFromConnectPoint(cp);
433 }
434 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100435 }
436
Amit Ghosha17354e2017-08-23 12:56:04 +0100437 public static Map<String, DhcpAllocationInfo> allocationMap() {
438 return allocationMap;
439 }
440
Amit Ghosh47243cb2017-07-26 05:08:53 +0100441 private SubscriberAndDeviceInformation getDevice(PacketContext context) {
442 String serialNo = deviceService.getDevice(context.inPacket().
443 receivedFrom().deviceId()).serialNumber();
444
445 return subsService.get(serialNo);
446 }
447
448 private SubscriberAndDeviceInformation getDevice(ConnectPoint cp) {
449 String serialNo = deviceService.getDevice(cp.deviceId()).
450 serialNumber();
451
452 return subsService.get(serialNo);
453 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100454
455 private MacAddress relayAgentMacAddress(PacketContext context) {
456
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000457 SubscriberAndDeviceInformation device = this.getDevice(context);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100458 if (device == null) {
459 log.warn("Device not found for {}", context.inPacket().
460 receivedFrom());
461 return null;
462 }
463
464 return device.hardwareIdentifier();
465 }
466
467 private String nasPortId(PacketContext context) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100468 return nasPortId(context.inPacket().receivedFrom());
469 }
470
471 private String nasPortId(ConnectPoint cp) {
472 Port p = deviceService.getPort(cp);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100473 return p.annotations().value(AnnotationKeys.PORT_NAME);
474 }
475
476 private SubscriberAndDeviceInformation getSubscriber(PacketContext context) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100477 return subsService.get(nasPortId(context));
478 }
479
480 private VlanId cTag(PacketContext context) {
481 SubscriberAndDeviceInformation sub = getSubscriber(context);
482 if (sub == null) {
483 log.warn("Subscriber info not found for {}", context.inPacket().
484 receivedFrom());
485 return VlanId.NONE;
486 }
487 return sub.cTag();
488 }
489
Amit Ghosh8951f042017-08-10 13:48:10 +0100490 private VlanId cTag(ConnectPoint cp) {
491 String portId = nasPortId(cp);
492 SubscriberAndDeviceInformation sub = subsService.get(portId);
493 if (sub == null) {
494 log.warn("Subscriber info not found for {} looking for C-TAG", cp);
495 return VlanId.NONE;
496 }
497 return sub.cTag();
498 }
499
500 private VlanId sTag(ConnectPoint cp) {
501 String portId = nasPortId(cp);
502 SubscriberAndDeviceInformation sub = subsService.get(portId);
503 if (sub == null) {
504 log.warn("Subscriber info not found for {} looking for S-TAG", cp);
505 return VlanId.NONE;
506 }
507 return sub.sTag();
508 }
509
Amit Ghosh47243cb2017-07-26 05:08:53 +0100510 private VlanId sTag(PacketContext context) {
511 SubscriberAndDeviceInformation sub = getSubscriber(context);
512 if (sub == null) {
513 log.warn("Subscriber info not found for {}", context.inPacket().
514 receivedFrom());
515 return VlanId.NONE;
516 }
517 return sub.sTag();
518 }
519
520 private class DhcpRelayPacketProcessor implements PacketProcessor {
521
522 @Override
523 public void process(PacketContext context) {
524 if (!configured()) {
525 log.warn("Missing DHCP relay config. Abort packet processing");
526 return;
527 }
528
529 // process the packet and get the payload
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530530 Ethernet packet = context.inPacket().parsed();
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000531
Amit Ghosh47243cb2017-07-26 05:08:53 +0100532 if (packet == null) {
533 log.warn("Packet is null");
534 return;
535 }
536
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530537 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100538 IPv4 ipv4Packet = (IPv4) packet.getPayload();
539
540 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
541 UDP udpPacket = (UDP) ipv4Packet.getPayload();
542 if (udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT ||
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000543 udpPacket.getSourcePort() == UDP.DHCP_SERVER_PORT) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100544 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
545 //This packet is dhcp.
546 processDhcpPacket(context, packet, dhcpPayload);
547 }
548 }
549 }
550 }
551
552 //forward the packet to ConnectPoint where the DHCP server is attached.
Amit Ghosh83c8c892017-11-09 11:08:27 +0000553 private void forwardPacket(Ethernet packet, PacketContext context) {
554 ConnectPoint toSendTo = null;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100555
Amit Ghosh83c8c892017-11-09 11:08:27 +0000556 if (!useOltUplink) {
557 toSendTo = dhcpServerConnectPoint.get();
558 } else {
559 toSendTo = getUplinkConnectPointOfOlt(context.inPacket().
560 receivedFrom().deviceId());
561 }
562
563 if (toSendTo != null) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100564 TrafficTreatment t = DefaultTrafficTreatment.builder()
Amit Ghosh83c8c892017-11-09 11:08:27 +0000565 .setOutput(toSendTo.port()).build();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100566 OutboundPacket o = new DefaultOutboundPacket(
Amit Ghosh83c8c892017-11-09 11:08:27 +0000567 toSendTo.deviceId(), t,
Amit Ghosh47243cb2017-07-26 05:08:53 +0100568 ByteBuffer.wrap(packet.serialize()));
569 if (log.isTraceEnabled()) {
Saurav Das15626a02018-09-27 18:36:45 -0700570 log.trace("Relaying packet to dhcp server at {} {}",
571 toSendTo, packet);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100572 }
573 packetService.emit(o);
574 } else {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000575 log.error("No connect point to send msg to DHCP Server");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100576 }
577 }
578
Amit Ghosha17354e2017-08-23 12:56:04 +0100579 // get the type of the DHCP packet
580 private DHCPPacketType getDhcpPacketType(DHCP dhcpPayload) {
581
Jonathan Hartedbf6422018-05-02 17:30:05 -0700582 for (DhcpOption option : dhcpPayload.getOptions()) {
Amit Ghosha17354e2017-08-23 12:56:04 +0100583 if (option.getCode() == OptionCode_MessageType.getValue()) {
584 byte[] data = option.getData();
585 return DHCPPacketType.getType(data[0]);
586 }
587 }
588 return null;
589 }
590
Amit Ghosh47243cb2017-07-26 05:08:53 +0100591 //process the dhcp packet before sending to server
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530592 private void processDhcpPacket(PacketContext context, Ethernet packet,
Amit Ghosh47243cb2017-07-26 05:08:53 +0100593 DHCP dhcpPayload) {
594 if (dhcpPayload == null) {
595 log.warn("DHCP payload is null");
596 return;
597 }
598
Amit Ghosha17354e2017-08-23 12:56:04 +0100599 DHCPPacketType incomingPacketType = getDhcpPacketType(dhcpPayload);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000600
Saurav Das15626a02018-09-27 18:36:45 -0700601 log.info("Received DHCP Packet of type {} from {}",
602 incomingPacketType, context.inPacket().receivedFrom());
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.
Saurav Das15626a02018-09-27 18:36:45 -0700614 Ethernet ethernetPacketOffer =
615 processDhcpPacketFromServer(context, packet);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000616 if (ethernetPacketOffer != null) {
617 sendReply(ethernetPacketOffer, dhcpPayload);
618 }
619 break;
620 case DHCPREQUEST:
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530621 Ethernet ethernetPacketRequest =
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000622 processDhcpPacketFromClient(context, packet);
623 if (ethernetPacketRequest != null) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000624 forwardPacket(ethernetPacketRequest, context);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000625 }
626 break;
627 case DHCPACK:
628 //reply to dhcp client.
Saurav Das15626a02018-09-27 18:36:45 -0700629 Ethernet ethernetPacketAck =
630 processDhcpPacketFromServer(context, packet);
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000631 if (ethernetPacketAck != null) {
632 sendReply(ethernetPacketAck, dhcpPayload);
633 }
634 break;
635 default:
636 break;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100637 }
638 }
639
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530640 private Ethernet processDhcpPacketFromClient(PacketContext context,
641 Ethernet ethernetPacket) {
Saurav Das15626a02018-09-27 18:36:45 -0700642 if (log.isTraceEnabled()) {
643 log.trace("DHCP packet received from client at {} {}",
644 context.inPacket().receivedFrom(), ethernetPacket);
645 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100646
647 MacAddress relayAgentMac = relayAgentMacAddress(context);
648 if (relayAgentMac == null) {
649 log.warn("RelayAgent MAC not found ");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100650 return null;
651 }
652
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530653 Ethernet etherReply = ethernetPacket;
Amit Ghosh47243cb2017-07-26 05:08:53 +0100654
655 IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
656 UDP udpPacket = (UDP) ipv4Packet.getPayload();
657 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
658
Amit Ghosha17354e2017-08-23 12:56:04 +0100659 if (enableDhcpBroadcastReplies) {
660 // We want the reply to come back as a L2 broadcast
661 dhcpPacket.setFlags((short) 0x8000);
662 }
663
Jonathan Hartc36c9552018-07-31 15:07:53 -0400664 MacAddress clientMac = MacAddress.valueOf(dhcpPacket.getClientHardwareAddress());
665 IpAddress clientIp = IpAddress.valueOf(dhcpPacket.getClientIPAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100666
Jonathan Hartc36c9552018-07-31 15:07:53 -0400667 SubscriberAndDeviceInformation entry = getSubscriber(context);
668 if (entry == null) {
Saurav Das15626a02018-09-27 18:36:45 -0700669 log.warn("Dropping packet as subscriber entry is not available");
Jonathan Hartc36c9552018-07-31 15:07:53 -0400670 return null;
671 }
672
673 DhcpAllocationInfo info = new DhcpAllocationInfo(
674 context.inPacket().receivedFrom(), dhcpPacket.getPacketType(),
675 entry.nasPortId(), clientMac, clientIp);
676
677 allocationMap.put(entry.nasPortId(), info);
678
Saurav Das15626a02018-09-27 18:36:45 -0700679 post(new DhcpL2RelayEvent(DhcpL2RelayEvent.Type.UPDATED, info,
680 context.inPacket().receivedFrom()));
Amit Ghosha17354e2017-08-23 12:56:04 +0100681
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000682 if (option82) {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000683 DHCP dhcpPacketWithOption82 = addOption82(dhcpPacket, entry);
684 udpPacket.setPayload(dhcpPacketWithOption82);
685 }
686
687 ipv4Packet.setPayload(udpPacket);
688 etherReply.setPayload(ipv4Packet);
Amit Ghosh83c8c892017-11-09 11:08:27 +0000689 if (modifyClientPktsSrcDstMac) {
690 etherReply.setSourceMACAddress(relayAgentMac);
691 etherReply.setDestinationMACAddress(dhcpConnectMac);
692 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100693
Amit Ghosh8951f042017-08-10 13:48:10 +0100694 etherReply.setPriorityCode(ethernetPacket.getPriorityCode());
Amit Ghosh47243cb2017-07-26 05:08:53 +0100695 etherReply.setVlanID(cTag(context).toShort());
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530696 etherReply.setQinQTPID(Ethernet.TYPE_VLAN);
697 etherReply.setQinQVID(sTag(context).toShort());
Saurav Das15626a02018-09-27 18:36:45 -0700698 log.info("Finished processing packet.. relaying to dhcpServer");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100699 return etherReply;
700 }
701
702 //build the DHCP offer/ack with proper client port.
Saurav Das15626a02018-09-27 18:36:45 -0700703 private Ethernet processDhcpPacketFromServer(PacketContext context,
704 Ethernet ethernetPacket) {
705 if (log.isTraceEnabled()) {
706 log.trace("DHCP packet received from server at {} {}",
707 context.inPacket().receivedFrom(), ethernetPacket);
708 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100709 // get dhcp header.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530710 Ethernet etherReply = (Ethernet) ethernetPacket.clone();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100711 IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
712 UDP udpPacket = (UDP) ipv4Packet.getPayload();
713 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
714
Amit Ghosh47243cb2017-07-26 05:08:53 +0100715 MacAddress dstMac = valueOf(dhcpPayload.getClientHardwareAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100716 ConnectPoint subsCp = getConnectPointOfClient(dstMac);
Amit Ghosh2095dc62017-09-25 20:56:55 +0100717 // If we can't find the subscriber, can't process further
718 if (subsCp == null) {
719 return null;
720 }
Amit Ghosha17354e2017-08-23 12:56:04 +0100721 // if it's an ACK packet store the information for display purpose
722 if (getDhcpPacketType(dhcpPayload) == DHCPPacketType.DHCPACK) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100723
Amit Ghosha17354e2017-08-23 12:56:04 +0100724 String portId = nasPortId(subsCp);
725 SubscriberAndDeviceInformation sub = subsService.get(portId);
726 if (sub != null) {
Jonathan Hartedbf6422018-05-02 17:30:05 -0700727 List<DhcpOption> options = dhcpPayload.getOptions();
728 List<DhcpOption> circuitIds = options.stream()
Amit Ghosha17354e2017-08-23 12:56:04 +0100729 .filter(option -> option.getCode() == DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
730 .collect(Collectors.toList());
731
732 String circuitId = "None";
733 if (circuitIds.size() == 1) {
Amit Ghosh2095dc62017-09-25 20:56:55 +0100734 byte[] array = circuitIds.get(0).getData();
735
736 try {
737 // we leave the first two bytes as they are the id and length
738 circuitId = new String(Arrays.copyOfRange(array, 2, array.length), "UTF-8");
739 } catch (Exception e) { }
Amit Ghosha17354e2017-08-23 12:56:04 +0100740 }
741
742 IpAddress ip = IpAddress.valueOf(dhcpPayload.getYourIPAddress());
743
744 //storeDHCPAllocationInfo
Jonathan Hartc36c9552018-07-31 15:07:53 -0400745 DhcpAllocationInfo info = new DhcpAllocationInfo(subsCp,
746 dhcpPayload.getPacketType(), circuitId, dstMac, ip);
Amit Ghosha17354e2017-08-23 12:56:04 +0100747
748 allocationMap.put(sub.nasPortId(), info);
Jonathan Hartc36c9552018-07-31 15:07:53 -0400749
750 post(new DhcpL2RelayEvent(DhcpL2RelayEvent.Type.UPDATED, info, subsCp));
Amit Ghosha17354e2017-08-23 12:56:04 +0100751 }
752 } // end storing of info
Amit Ghosh47243cb2017-07-26 05:08:53 +0100753
754 // we leave the srcMac from the original packet
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530755 etherReply.setDestinationMACAddress(dstMac);
756 etherReply.setQinQVID(sTag(subsCp).toShort());
Amit Ghosh8951f042017-08-10 13:48:10 +0100757 etherReply.setPriorityCode(ethernetPacket.getPriorityCode());
758 etherReply.setVlanID((cTag(subsCp).toShort()));
Amit Ghosh47243cb2017-07-26 05:08:53 +0100759
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000760 if (option82) {
761 udpPacket.setPayload(removeOption82(dhcpPayload));
762 } else {
763 udpPacket.setPayload(dhcpPayload);
764 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100765 ipv4Packet.setPayload(udpPacket);
766 etherReply.setPayload(ipv4Packet);
767
Saurav Das15626a02018-09-27 18:36:45 -0700768 log.info("Finished processing packet.. relaying to client");
Amit Ghosh47243cb2017-07-26 05:08:53 +0100769 return etherReply;
770 }
771
Amit Ghosha17354e2017-08-23 12:56:04 +0100772 /*
773 * Get ConnectPoint of the Client based on it's MAC address
774 */
775 private ConnectPoint getConnectPointOfClient(MacAddress dstMac) {
776 Set<Host> hosts = hostService.getHostsByMac(dstMac);
777 if (hosts == null || hosts.isEmpty()) {
778 log.warn("Cannot determine host for DHCP client: {}. Aborting "
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530779 + "relay for dhcp packet from server",
Amit Ghosha17354e2017-08-23 12:56:04 +0100780 dstMac);
781 return null;
782 }
783 for (Host h : hosts) {
784 // if more than one,
785 // find the connect point which has an valid entry in SADIS
786 ConnectPoint cp = new ConnectPoint(h.location().deviceId(),
787 h.location().port());
788
789 if (sTag(cp) != VlanId.NONE) {
790 return cp;
791 }
792 }
793
794 return null;
795 }
796
Amit Ghosh47243cb2017-07-26 05:08:53 +0100797 //send the response to the requester host.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530798 private void sendReply(Ethernet ethPacket, DHCP dhcpPayload) {
Amit Ghosh47243cb2017-07-26 05:08:53 +0100799 MacAddress descMac = valueOf(dhcpPayload.getClientHardwareAddress());
Amit Ghosha17354e2017-08-23 12:56:04 +0100800 ConnectPoint subCp = getConnectPointOfClient(descMac);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100801
802 // Send packet out to requester if the host information is available
Amit Ghosha17354e2017-08-23 12:56:04 +0100803 if (subCp != null) {
Saurav Das15626a02018-09-27 18:36:45 -0700804 log.info("Sending DHCP packet to client at {}", subCp);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100805 TrafficTreatment t = DefaultTrafficTreatment.builder()
Amit Ghosha17354e2017-08-23 12:56:04 +0100806 .setOutput(subCp.port()).build();
Amit Ghosh47243cb2017-07-26 05:08:53 +0100807 OutboundPacket o = new DefaultOutboundPacket(
Amit Ghosha17354e2017-08-23 12:56:04 +0100808 subCp.deviceId(), t, ByteBuffer.wrap(ethPacket.serialize()));
Amit Ghosh47243cb2017-07-26 05:08:53 +0100809 if (log.isTraceEnabled()) {
Saurav Das15626a02018-09-27 18:36:45 -0700810 log.trace("Relaying packet to dhcp client at {} {}", subCp,
811 ethPacket);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100812 }
813 packetService.emit(o);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100814 } else {
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000815 log.error("Dropping DHCP packet because can't find host for {}", descMac);
Amit Ghosh47243cb2017-07-26 05:08:53 +0100816 }
817 }
818 }
819
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000820 private DHCP addOption82(DHCP dhcpPacket, SubscriberAndDeviceInformation entry) {
821 log.debug("option82data {} ", entry);
822
Jonathan Hartedbf6422018-05-02 17:30:05 -0700823 List<DhcpOption> options = Lists.newArrayList(dhcpPacket.getOptions());
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000824 DhcpOption82 option82 = new DhcpOption82();
825 option82.setAgentCircuitId(entry.circuitId());
826 option82.setAgentRemoteId(entry.remoteId());
Jonathan Hartedbf6422018-05-02 17:30:05 -0700827 DhcpOption option = new DhcpOption()
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530828 .setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
829 .setData(option82.toByteArray())
830 .setLength(option82.length());
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000831
832 options.add(options.size() - 1, option);
833 dhcpPacket.setOptions(options);
Amit Ghosh8951f042017-08-10 13:48:10 +0100834
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000835 return dhcpPacket;
836
837 }
838
839 private DHCP removeOption82(DHCP dhcpPacket) {
Jonathan Hartedbf6422018-05-02 17:30:05 -0700840 List<DhcpOption> options = dhcpPacket.getOptions();
841 List<DhcpOption> newoptions = options.stream()
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000842 .filter(option -> option.getCode() != DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
843 .collect(Collectors.toList());
844
845 return dhcpPacket.setOptions(newoptions);
846 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100847 /**
848 * Listener for network config events.
849 */
850 private class InternalConfigListener implements NetworkConfigListener {
851
852 @Override
853 public void event(NetworkConfigEvent event) {
854
855 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
856 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
857 event.configClass().equals(DhcpL2RelayConfig.class)) {
858 updateConfig();
859 log.info("Reconfigured");
860 }
861 }
862 }
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000863
Amit Ghosh8951f042017-08-10 13:48:10 +0100864 /**
865 * Handles Mastership changes for the devices which connect
866 * to the DHCP server.
867 */
868 private class InnerMastershipListener implements MastershipListener {
869 @Override
870 public void event(MastershipEvent event) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000871 if (!useOltUplink) {
872 if (dhcpServerConnectPoint.get() != null &&
873 dhcpServerConnectPoint.get().deviceId().
874 equals(event.subject())) {
875 log.trace("Mastership Event recevived for {}", event.subject());
876 // mastership of the device for our connect point has changed
877 // reselect
878 selectServerConnectPoint();
879 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100880 }
881 }
882 }
Deepa vaddireddy0060f532017-08-04 06:46:05 +0000883
Amit Ghosh8951f042017-08-10 13:48:10 +0100884 /**
885 * Handles Device status change for the devices which connect
886 * to the DHCP server.
887 */
888 private class InnerDeviceListener implements DeviceListener {
889 @Override
890 public void event(DeviceEvent event) {
Saurav Das15626a02018-09-27 18:36:45 -0700891 if (log.isTraceEnabled() &&
892 !event.type().equals(DeviceEvent.Type.PORT_STATS_UPDATED)) {
893 log.trace("Device Event received for {} event {}",
894 event.subject(), event.type());
895 }
Amit Ghosh83c8c892017-11-09 11:08:27 +0000896 if (!useOltUplink) {
897 if (dhcpServerConnectPoint.get() == null) {
898 switch (event.type()) {
899 case DEVICE_ADDED:
900 case DEVICE_AVAILABILITY_CHANGED:
901 // some device is available check if we can get one
902 selectServerConnectPoint();
903 break;
904 default:
905 break;
906 }
907 return;
Amit Ghosh8951f042017-08-10 13:48:10 +0100908 }
Amit Ghosh83c8c892017-11-09 11:08:27 +0000909 if (dhcpServerConnectPoint.get().deviceId().
910 equals(event.subject().id())) {
911 switch (event.type()) {
912 case DEVICE_AVAILABILITY_CHANGED:
913 case DEVICE_REMOVED:
914 case DEVICE_SUSPENDED:
915 // state of our device has changed, check if we need
916 // to re-select
917 selectServerConnectPoint();
918 break;
919 default:
920 break;
921 }
922 }
923 } else {
Amit Ghosh8951f042017-08-10 13:48:10 +0100924 switch (event.type()) {
Amit Ghosh83c8c892017-11-09 11:08:27 +0000925 case PORT_ADDED:
926 if (isUplinkPortOfOlt(event.subject().id(), event.port())) {
927 requestDhcpPacketsFromConnectPoint(new ConnectPoint(event.subject().id(),
928 event.port().number()));
929 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100930 break;
931 default:
932 break;
933 }
934 }
935 }
936 }
Amit Ghosh47243cb2017-07-26 05:08:53 +0100937}