2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.vpnservice.dhcpservice;
10 import java.math.BigInteger;
11 import java.util.List;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
18 import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
19 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.google.common.base.Optional;
34 import com.google.common.util.concurrent.FutureCallback;
36 public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
38 private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
39 private DhcpManager dhcpManager;
40 private ListenerRegistration<DataChangeListener> listenerRegistration;
41 private DataBroker dataBroker;
42 private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
43 public void onSuccess(Void result) {
44 logger.debug("Success in Datastore write operation");
47 public void onFailure(Throwable error) {
48 logger.error("Error in Datastore write operation", error);
52 public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker) {
53 super(Interface.class);
54 this.dhcpManager = dhcpManager;
55 this.dataBroker = dataBroker;
59 private void registerListener() {
61 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
62 getWildCardPath(), DhcpInterfaceEventListener.this, DataChangeScope.SUBTREE);
63 } catch (final Exception e) {
64 logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
65 throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
69 private InstanceIdentifier<Interface> getWildCardPath() {
70 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
74 public void close() throws Exception {
75 if (listenerRegistration != null) {
77 listenerRegistration.close();
78 } catch (final Exception e) {
79 logger.error("Error when cleaning up DataChangeListener.", e);
81 listenerRegistration = null;
83 logger.info("Interface Manager Closed");
88 protected void remove(InstanceIdentifier<Interface> identifier,
90 String interfaceName = del.getName();
91 List<String> ofportIds = del.getLowerLayerIf();
92 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
93 BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
94 logger.trace("Received remove DCN for interface {} dpId {}", interfaceName, dpId);
95 unInstallDhcpEntries(interfaceName, dpId);
99 protected void update(InstanceIdentifier<Interface> identifier,
100 Interface original, Interface update) {
104 protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
105 String interfaceName = add.getName();
106 List<String> ofportIds = add.getLowerLayerIf();
107 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
108 BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
109 logger.trace("Received add DCN for interface {}, dpid{}", interfaceName, dpId);
110 installDhcpEntries(interfaceName, dpId);
113 private String getNeutronMacAddress(String interfaceName) {
114 Port port = dhcpManager.getNeutronPort(interfaceName);
116 logger.trace("Port found in neutron. Interface Name {}, port {}", interfaceName, port);
117 return port.getMacAddress();
119 logger.trace("Port not found in neutron. Interface Name {}, vlanId {}", interfaceName);
123 private void unInstallDhcpEntries(String interfaceName, BigInteger dpId) {
124 String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
125 dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
128 private void installDhcpEntries(String interfaceName, BigInteger dpId) {
129 String vmMacAddress = getAndUpdateVmMacAddress(interfaceName);
130 dhcpManager.installDhcpEntries(dpId, vmMacAddress);
133 private String getAndUpdateVmMacAddress(String interfaceName) {
134 InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
135 Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
136 if (!existingEntry.isPresent()) {
137 logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
138 String vmMacAddress = getNeutronMacAddress(interfaceName);
139 if (vmMacAddress==null || vmMacAddress.isEmpty()) {
142 logger.trace("Updating InterfaceNameVmMacAddress map with {}, {}", interfaceName,vmMacAddress);
143 InterfaceNameMacAddress interfaceNameMacAddress = new InterfaceNameMacAddressBuilder().setKey(new InterfaceNameMacAddressKey(interfaceName)).setInterfaceName(interfaceName).setMacAddress(vmMacAddress).build();
144 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, interfaceNameMacAddress);
147 return existingEntry.get().getMacAddress();
150 private String getAndRemoveVmMacAddress(String interfaceName) {
151 InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
152 Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
153 if (existingEntry.isPresent()) {
154 String vmMacAddress = existingEntry.get().getMacAddress();
155 logger.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
156 MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, DEFAULT_CALLBACK);
159 logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);