Vpnmanager module sync up
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / ArpNotificationHandler.java
1 /*
2  * Copyright (c) 2016 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 com.google.common.base.Optional;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
13 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpRequestReceived;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpResponseReceived;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.MacChanged;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilListener;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import java.math.BigInteger;
35
36 public class ArpNotificationHandler implements OdlArputilListener {
37
38     VpnInterfaceManager vpnIfManager;
39     DataBroker broker;
40
41     private static final Logger LOG = LoggerFactory.getLogger(ArpNotificationHandler.class);
42
43     public ArpNotificationHandler(VpnInterfaceManager vpnIfMgr, DataBroker dataBroker) {
44         vpnIfManager = vpnIfMgr;
45         broker = dataBroker;
46     }
47     
48     public void onMacChanged(MacChanged notification){
49
50     }
51
52     public void onArpRequestReceived(ArpRequestReceived notification){
53         LOG.trace("ArpNotification Request Received from interface {} and IP {} having MAC {} target destination {}",
54                 notification.getInterface(), notification.getSrcIpaddress().getIpv4Address().getValue(),
55                 notification.getSrcMac().getValue(),notification.getDstIpaddress().getIpv4Address().getValue());
56         String srcInterface = notification.getInterface();
57         IpAddress srcIP = notification.getSrcIpaddress();
58         PhysAddress srcMac = notification.getSrcMac();
59         IpAddress targetIP = notification.getDstIpaddress();
60         BigInteger metadata = notification.getMetadata();
61         if (metadata != null && metadata != BigInteger.ZERO) {
62             long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
63             // Respond to ARP request only if vpnservice is configured on the interface
64             if (VpnUtil.isVpnInterfaceConfigured(broker, srcInterface)) {
65                 LOG.info("Received ARP Request for interface {} ", srcInterface);
66                 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
67                         vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
68                 Optional<VpnIds> vpnIdsOptional
69                         = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
70                 if (!vpnIdsOptional.isPresent()) {
71                     // Donot respond to ARP requests on unknown VPNs
72                     LOG.trace("ARP NO_RESOLVE: VPN {} not configured. Ignoring responding to ARP requests on this VPN", vpnId);
73                     return;
74                 }
75                 String vpnName = vpnIdsOptional.get().getVpnInstanceName();
76                 String ipToQuery = notification.getSrcIpaddress().getIpv4Address().getValue();
77                 LOG.trace("ArpRequest being processed for Source IP {}", ipToQuery);
78                 VpnIds vpnIds = vpnIdsOptional.get();
79                 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker, vpnIds.getVpnInstanceName(), ipToQuery);
80                 if (vpnPortipToPort != null) {
81                     String oldPortName = vpnPortipToPort.getPortName();
82                     String oldMac = vpnPortipToPort.getMacAddress();
83                     if (!oldMac.equalsIgnoreCase(srcMac.getValue())) {
84                         //MAC has changed for requested IP
85                         LOG.trace("ARP request Source IP/MAC data etmodified for IP {} with MAC {} and Port {}", ipToQuery,
86                                 srcMac, srcInterface);
87                         if (!vpnPortipToPort.isConfig()) {
88                             VpnUtil.updateVpnPortFixedIpToPort(broker, vpnName, ipToQuery, srcInterface,
89                                     srcMac.getValue(), false, false, true);
90                             vpnIfManager.removeMIPAdjacency(vpnName, oldPortName, srcIP);
91                             try {
92                                 Thread.sleep(2000);
93                             } catch (Exception e) {
94                             }
95                             vpnIfManager.addMIPAdjacency(vpnName, srcInterface, srcIP);
96                         } else {
97                             //MAC mismatch for a Neutron learned IP
98                             LOG.warn("MAC Address mismatach for Interface {} having a Mac  {},  IP {} and Arp learnt Mac {}",
99                                     oldPortName, oldMac, ipToQuery, srcMac.getValue());
100                             return;
101                         }
102                     }
103                 } else {
104                     VpnUtil.createVpnPortFixedIpToPort(broker, vpnName, ipToQuery, srcInterface, srcMac.getValue(), false, false, true);
105                     vpnIfManager.addMIPAdjacency(vpnName, srcInterface, srcIP);
106                 }
107                 String targetIpToQuery = notification.getDstIpaddress().getIpv4Address().getValue();
108                 VpnPortipToPort vpnTargetIpToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker,
109                         vpnIds.getVpnInstanceName(), targetIpToQuery);
110                 //Process and respond from Controller only for GatewayIp ARP request
111                 if (vpnTargetIpToPort != null) {
112                     if (vpnTargetIpToPort.isSubnetIp()) {
113                         String macAddress = vpnTargetIpToPort.getMacAddress();
114                         PhysAddress targetMac = new PhysAddress(macAddress);
115                         vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, targetMac, srcInterface);
116                     }
117                 } else {
118                     //Respond for gateway Ips ARP requests if L3vpn configured without a router
119                     if( vpnIds.isExternalVpn()) {
120                         Port prt;
121                         String gw = null;
122                         Uuid portUuid = new Uuid(srcInterface);
123                         InstanceIdentifier<Port> inst = InstanceIdentifier.create(Neutron.class)
124                                 .child(Ports.class)
125                                 .child(Port.class, new PortKey(portUuid));
126                         Optional<Port> port = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
127                         if (port.isPresent()) {
128                             prt = port.get();
129                             Uuid subnetUUID = prt.getFixedIps().get(0).getSubnetId();
130                             LOG.trace("Subnet UUID for this VPN Interface is {}", subnetUUID);
131                             SubnetKey subnetkey = new SubnetKey(subnetUUID);
132                             InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
133                                     .child(Subnets.class)
134                                     .child(Subnet.class, subnetkey);
135                             Optional<Subnet> subnet = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
136                             if (subnet.isPresent()) {
137                                 gw = subnet.get().getGatewayIp().getIpv4Address().getValue();
138                                 if (targetIpToQuery.equalsIgnoreCase(gw)) {
139                                     LOG.trace("Target Destination matches the Gateway IP {} so respond for ARP", gw);
140                                     vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, null, srcInterface);
141                                 }
142                             }
143                         }
144                     } else {
145                         LOG.trace("ARP request is not on an External VPN, so ignoring the request.");
146                     }
147
148                 }
149
150             }
151         }
152     }
153     public void onArpResponseReceived(ArpResponseReceived notification){
154         LOG.trace("ArpNotification Response Received from interface {} and IP {} having MAC {}",notification.getInterface(),
155                 notification.getIpaddress().getIpv4Address().getValue(), notification.getMacaddress().getValue());
156         String srcInterface = notification.getInterface();
157         IpAddress srcIP = notification.getIpaddress();
158         PhysAddress srcMac = notification.getMacaddress();
159         BigInteger metadata = notification.getMetadata();
160         if (metadata != null && metadata != BigInteger.ZERO) {
161             long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
162             InstanceIdentifier<VpnIds>
163                     vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
164             Optional<VpnIds> vpnIdsOptional
165                     = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
166             if (!vpnIdsOptional.isPresent()) {
167                 // Donot respond to ARP requests on unknown VPNs
168                 LOG.trace("ARP NO_RESOLVE: VPN {} not configured. Ignoring responding to ARP requests on this VPN", vpnId);
169                 return;
170             }
171             if (VpnUtil.isVpnInterfaceConfigured(broker, srcInterface)) {
172                 String vpnName = vpnIdsOptional.get().getVpnInstanceName();
173                 String ipToQuery = notification.getIpaddress().getIpv4Address().getValue();
174                 VpnIds vpnIds = vpnIdsOptional.get();
175                 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker, vpnIds.getVpnInstanceName(), ipToQuery);
176                 if (vpnPortipToPort != null) {
177                     String oldMac = vpnPortipToPort.getMacAddress();
178                     String oldPortName = vpnPortipToPort.getPortName();
179                     if (!oldMac.equalsIgnoreCase(srcMac.getValue())) {
180                         //MAC has changed for requested IP
181                         LOG.trace("ARP response Source IP/MAC data modified for IP {} with MAC {} and Port {}", ipToQuery,
182                                 srcMac, srcInterface);
183                         if (!vpnPortipToPort.isConfig()) {
184                             VpnUtil.updateVpnPortFixedIpToPort(broker, vpnName, ipToQuery, srcInterface,
185                                     srcMac.getValue(), false, false, true);
186                             vpnIfManager.removeMIPAdjacency(vpnName, oldPortName, srcIP);
187                             try {
188                                 Thread.sleep(2000);
189                             } catch (Exception e) {
190                             }
191                             vpnIfManager.addMIPAdjacency(vpnName, srcInterface, srcIP);
192                         } else {
193                             //MAC mismatch for a Neutron learned IP set learnt back to false
194                             LOG.warn("MAC Address mismatch for Interface {} having a Mac  {} , IP {} and Arp learnt Mac {}",
195                                     srcInterface, oldMac, ipToQuery, srcMac.getValue());
196                         }
197                     }
198                 } else {
199                     VpnUtil.createVpnPortFixedIpToPort(broker, vpnName, ipToQuery, srcInterface, srcMac.getValue(), false, false, true);
200                     vpnIfManager.addMIPAdjacency(vpnName, srcInterface, srcIP);
201                 }
202             }
203         }
204     }
205
206 }