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