Arp cache feature changes
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / ArpMonitoringHandler.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.vpnmanager;
9
10 import java.math.BigInteger;
11 import java.net.InetAddress;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
17 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.EtherTypes;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.common.base.Optional;
33
34 public class ArpMonitoringHandler extends AsyncDataTreeChangeListenerBase<VpnPortipToPort, ArpMonitoringHandler> {
35     private static final Logger LOG = LoggerFactory.getLogger(ArpMonitoringHandler.class);
36     private final DataBroker dataBroker;
37     private final OdlInterfaceRpcService interfaceRpc;
38     private final IMdsalApiManager mdsalManager;
39     private final AlivenessMonitorService alivenessManager;
40     private final INeutronVpnManager neutronVpnService;
41     private Long arpMonitorProfileId = 0L;
42
43     public ArpMonitoringHandler(final DataBroker dataBroker, final OdlInterfaceRpcService interfaceRpc,
44             IMdsalApiManager mdsalManager, AlivenessMonitorService alivenessManager, INeutronVpnManager neutronVpnService) {
45         super(VpnPortipToPort.class, ArpMonitoringHandler.class);
46         this.dataBroker = dataBroker;
47         this.interfaceRpc = interfaceRpc;
48         this.mdsalManager = mdsalManager;
49         this.alivenessManager = alivenessManager;
50         this.neutronVpnService = neutronVpnService;
51     }
52
53     public void start() {
54         Optional <Long> profileIdOptional = AlivenessMonitorUtils.allocateProfile(alivenessManager,
55                 ArpConstants.FAILURE_THRESHOLD, ArpConstants.ARP_CACHE_TIMEOUT_MILLIS, ArpConstants.MONITORING_WINDOW,
56                 EtherTypes.Arp);
57         if(profileIdOptional.isPresent()) {
58             arpMonitorProfileId = profileIdOptional.get();
59         } else {
60             LOG.error("Error while allocating Profile Id", profileIdOptional);
61         }
62         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
63     }
64
65     @Override
66     protected InstanceIdentifier<VpnPortipToPort> getWildCardPath() {
67         return InstanceIdentifier.create(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class);
68     }
69
70     public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortInstanceOpDataIdentifier(String ip, String vpnName) {
71         return InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
72                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(ip, vpnName)).build();
73     }
74
75     @Override
76     protected ArpMonitoringHandler getDataTreeChangeListener() {
77         return this;
78     }
79
80     @Override
81     protected void update(InstanceIdentifier<VpnPortipToPort> id, VpnPortipToPort value,
82             VpnPortipToPort dataObjectModificationAfter) {
83         try {
84             Boolean islearnt = value.isLearnt();
85             if(value.getMacAddress() == null || dataObjectModificationAfter.getMacAddress() == null) {
86                 LOG.warn("The Macaddress received is null for VpnPortipToPort {}, ignoring the DTCN", dataObjectModificationAfter);
87                 return;
88             }
89             if(islearnt) {
90                 remove(id, value);
91                 add(id, dataObjectModificationAfter);
92             }
93         } catch (Exception e) {
94             LOG.error("Error in handling update to vpnPortIpToPort for vpnName {} and IP Address {}", value.getVpnName() , value.getPortFixedip());
95             e.printStackTrace();
96         }
97     }
98
99     @Override
100     protected void add(InstanceIdentifier<VpnPortipToPort> identifier, VpnPortipToPort value) {
101         try {
102             InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
103             String macAddress = value.getMacAddress();
104             if(value.getMacAddress() == null) {
105                 LOG.warn("The Macaddress received is null for VpnPortipToPort {}, ignoring the DTCN", value);
106                 return;
107             }
108             MacAddress srcMacAddress = MacAddress.getDefaultInstance(value.getMacAddress());
109             String vpnName =  value.getVpnName();
110             String interfaceName =  value.getPortName();
111             Boolean islearnt = value.isLearnt();
112             if (islearnt) {
113                 MacEntry macEntry = new MacEntry(vpnName, srcMacAddress, srcInetAddr, interfaceName);
114                 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
115                 coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
116                         new ArpMonitorStartTask(macEntry, arpMonitorProfileId, dataBroker, alivenessManager,
117                                 interfaceRpc, neutronVpnService));
118             }
119             if (value.isSubnetIp()) {
120                 WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
121                 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName,
122                         macAddress, BigInteger.ZERO /* On all DPNs */, writeTx, NwConstants.ADD_FLOW);
123                 writeTx.submit();
124             }
125         } catch (Exception e) {
126             LOG.error("Error in deserializing packet {} with exception {}", value, e);
127         }
128     }
129
130     @Override
131     protected void remove(InstanceIdentifier<VpnPortipToPort> key, VpnPortipToPort value) {
132         try {
133             InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
134             String macAddress = value.getMacAddress();
135             if(value.getMacAddress() == null) {
136                 LOG.warn("The Macaddress received is null for VpnPortipToPort {}, ignoring the DTCN", value);
137                 return;
138             }
139             MacAddress srcMacAddress = MacAddress.getDefaultInstance(value.getMacAddress());
140             String vpnName =  value.getVpnName();
141             String interfaceName =  value.getPortName();
142             Boolean islearnt = value.isLearnt();
143             if (islearnt) {
144                 MacEntry macEntry = new MacEntry(vpnName, srcMacAddress, srcInetAddr, interfaceName);
145                 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
146                 coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
147                         new ArpMonitorStopTask(macEntry, dataBroker, alivenessManager));
148             }
149             if (value.isSubnetIp()) {
150                 WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
151                 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName,
152                         macAddress, BigInteger.ZERO /* On all DPNs */, writeTx, NwConstants.DEL_FLOW);
153                 writeTx.submit();
154             }
155         } catch (Exception e) {
156             LOG.error("Error in deserializing packet {} with exception {}", value, e);
157         }
158     }
159
160     static String buildJobKey(String ip, String vpnName) {
161         return new StringBuilder(ArpConstants.ARPJOB).append(ip).append(vpnName).toString();
162     }
163 }