71f4872b88ffdc738e192d1e5f107a7ece7234ac
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / FloatingIpGarpHandler.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.net.InetAddresses;
11 import java.math.BigInteger;
12 import java.util.Collection;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
18 import org.opendaylight.genius.mdsalutil.MDSALUtil;
19 import org.opendaylight.netvirt.elanmanager.api.IElanService;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.opendaylight.yangtools.yang.common.RpcResult;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class FloatingIpGarpHandler extends AsyncDataTreeChangeListenerBase<RouterPorts, FloatingIpGarpHandler>
41         implements AutoCloseable {
42     private static final Logger LOG = LoggerFactory.getLogger(FloatingIpGarpHandler.class);
43     private final DataBroker dataBroker;
44     private final PacketProcessingService packetService;
45     private final IElanService elanService;
46     private final OdlInterfaceRpcService intfRpc;
47
48     public FloatingIpGarpHandler(final DataBroker dataBroker, final PacketProcessingService packetService,
49                                  final IElanService elanService, final OdlInterfaceRpcService interfaceManager) {
50         super(RouterPorts.class, FloatingIpGarpHandler.class);
51         this.dataBroker = dataBroker;
52         this.packetService = packetService;
53         this.elanService = elanService;
54         this.intfRpc = interfaceManager;
55     }
56
57     public void start() {
58         LOG.info("{} start", getClass().getSimpleName());
59         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
60     }
61
62     @Override
63     protected InstanceIdentifier<RouterPorts> getWildCardPath() {
64         return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class);
65     }
66
67     @Override
68     protected void remove(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModification) {
69     }
70
71     @Override
72     protected void update(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModificationBefore,
73             RouterPorts dataObjectModificationAfter) {
74         sendGarpForFloatingIps(dataObjectModificationAfter);
75     }
76
77     private void sendGarpForFloatingIps(RouterPorts dataObjectModificationAfter) {
78         for (Ports port : dataObjectModificationAfter.getPorts()) {
79             for (IpMapping ipMapping : port.getIpMapping()) {
80                 IpAddress ip = IpAddressBuilder.getDefaultInstance(ipMapping.getExternalIp());
81                 sendGarpForIp(dataObjectModificationAfter, ip);
82             }
83         }
84     }
85
86     private void sendGarpForIp(RouterPorts dataObjectModificationAfter, IpAddress ip) {
87         if (ip.getIpv4Address() == null) {
88             LOG.warn("Faild to send GARP for IP. recieved IPv6.");
89             return;
90         }
91         Port floatingIpPort = VpnUtil.getNeutronPortForFloatingIp(dataBroker, ip);
92         MacAddress floatingIpMac = floatingIpPort.getMacAddress();
93         String extNet = VpnUtil.getAssociatedExternalNetwork(dataBroker, dataObjectModificationAfter.getRouterId());
94         Collection<String> interfaces = elanService.getExternalElanInterfaces(extNet);
95         for (String externalInterface:interfaces) {
96             sendGarpOnInterface(ip, floatingIpMac, externalInterface);
97             
98         }
99     }
100
101     private void sendGarpOnInterface(IpAddress ip, MacAddress floatingIpMac, String externalInterface) {
102         GetPortFromInterfaceInput getPortFromInterfaceInput = new GetPortFromInterfaceInputBuilder().setIntfName(externalInterface).build();
103         Future<RpcResult<GetPortFromInterfaceOutput>> interfacePort = intfRpc.getPortFromInterface(getPortFromInterfaceInput);
104         try {
105             BigInteger dpId = interfacePort.get().getResult().getDpid();
106             String portName = interfacePort.get().getResult().getPortname();
107             NodeConnectorRef ingress = MDSALUtil.getNodeConnRef(dpId, portName);
108             byte[] ipBytes = InetAddresses.forString(ip.getIpv4Address().getValue()).getAddress();
109             TransmitPacketInput arpRequestInput = ArpUtils.createArpRequestInput(dpId, ArpUtils.getMacInBytes(floatingIpMac.getValue()), ipBytes, ipBytes, ingress);
110             packetService.transmitPacket(arpRequestInput);
111         } catch (InterruptedException e) {
112             LOG.warn("Faild to send GARP. rpc call getPortFromInterface did not return with a value.");
113         } catch (ExecutionException e) {
114             LOG.warn("Faild to send GARP. rpc call getPortFromInterface did not return with a value.");
115         }
116     }
117
118
119     @Override
120     protected void add(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModification) {
121         sendGarpForFloatingIps(dataObjectModification);
122     }
123
124     @Override
125     protected FloatingIpGarpHandler getDataTreeChangeListener() {
126         return this;
127     }
128 }