NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / arp / responder / ArpResponderHandler.java
1 /*
2  * Copyright (c) 2016 - 2017 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.arp.responder;
9
10 import java.util.Optional;
11 import javax.inject.Inject;
12 import javax.inject.Singleton;
13 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
14 import org.opendaylight.genius.mdsalutil.NWUtil;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderInput.ArpReponderInputBuilder;
17 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil;
18 import org.opendaylight.netvirt.elanmanager.api.IElanService;
19 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
20 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
24 import org.opendaylight.yangtools.yang.common.Uint64;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Class that is responsible for handling ARP Responder flows which involves to
30  * differentiate between router and connected mac cases, identify DPNs and
31  * installation and uninstallation of flows.
32  *
33  */
34 @Singleton
35 public class ArpResponderHandler {
36
37     private static final Logger LOG = LoggerFactory.getLogger(ArpResponderHandler.class);
38     /**
39      * MDSAL DataBroker reference.
40      */
41     private final DataBroker dataBroker;
42     /**
43      * Elan RPC service reference.
44      */
45     private final IElanService elanService;
46
47     /**
48      * RPC to access InterfaceManager APIs.
49      */
50     private final IInterfaceManager interfaceManager;
51
52     /**
53      * RPC to access ITM APIs.
54      */
55     private final ItmRpcService itmRpcService;
56
57     /**
58      * Vpn Utility.
59      */
60     private final VpnUtil vpnUtil;
61
62     /**
63      * Constructor.
64      *
65      * @param dataBroker
66      *            {@link #dataBroker}
67      * @param elanService
68      *            {@link #elanService}
69      * @param interfaceManager
70      *            {@link #interfaceManager}
71      * @param itmRpcService
72      *            {@link #itmRpcService}
73      * @param vpnUtil
74      *            {@link #vpnUtil}
75      */
76     @Inject
77     public ArpResponderHandler(DataBroker dataBroker, IElanService elanService, IInterfaceManager interfaceManager,
78                                ItmRpcService itmRpcService, VpnUtil vpnUtil) {
79         this.dataBroker = dataBroker;
80         this.elanService = elanService;
81         this.interfaceManager = interfaceManager;
82         this.itmRpcService = itmRpcService;
83         this.vpnUtil = vpnUtil;
84     }
85
86     /**
87      * Add ARP Responder flow, by invoking ELan RPC service.
88      *
89      * @param dpnId
90      *            dpn Id on which ARP responder flow to be added
91      * @param lportTag
92      *            lport tag of the interface
93      * @param interfaceName
94      *            interface to which ARP responder flow to be added
95      * @param gatewayIp
96      *            gateway ip of the interface
97      * @param mac
98      *            mac address
99      */
100
101     public void addArpResponderFlow(Uint64 dpnId, int lportTag, String interfaceName,
102                                     String gatewayIp, String mac) {
103
104         LOG.trace("Creating the ARP Responder flow for VPN Interface {}", interfaceName);
105         ArpReponderInputBuilder builder = new ArpReponderInputBuilder();
106         builder.setDpId(dpnId.toJava()).setInterfaceName(interfaceName)
107                 .setSpa(gatewayIp).setSha(mac).setLportTag(lportTag);
108         builder.setInstructions(ArpResponderUtil
109                 .getInterfaceInstructions(interfaceManager, interfaceName, gatewayIp, mac, itmRpcService));
110         elanService.addArpResponderFlow(builder.buildForInstallFlow());
111     }
112
113     /**
114      * Remove ARP Responder flow when VM interface is removed, by invoking ELan
115      * RPC service.
116      *
117      * @param dpId
118      *            dpn Id on which ARP responder flow to be removed
119      * @param lportTag
120      *            lport tag of the interface
121      * @param ifName
122      *            interface to which ARP responder flow to be removed
123      * @param gatewayIp
124      *            subnet gateway ip
125      * @param subnetUuid
126      *            subnet Id of the interface
127      */
128     public void removeArpResponderFlow(Uint64 dpId, int lportTag, String ifName, String gatewayIp,
129             Uuid subnetUuid) {
130         if (gatewayIp == null) {
131             Optional<String> gwIpOptional = vpnUtil.getVpnSubnetGatewayIp(subnetUuid);
132             if (gwIpOptional.isPresent()) {
133                 gatewayIp = gwIpOptional.get();
134             }
135         }
136         if (gatewayIp != null && NWUtil.isIpv4Address(gatewayIp)) {
137             ArpReponderInputBuilder builder = new ArpReponderInputBuilder();
138             builder.setDpId(dpId.toJava()).setInterfaceName(ifName).setSpa(gatewayIp).setLportTag(lportTag);
139             elanService.removeArpResponderFlow(builder.buildForRemoveFlow());
140         } else {
141             LOG.error("Subnet-Gateway-IP is null for interface {}, arpResponderFlow not removed", ifName);
142         }
143     }
144
145     /**
146      * Get Mac address from given gateway port and interface name.
147      *
148      * @param gwPort
149      *            gateway port
150      * @param ifName
151      *            interface for which gateway to be retrieved
152      * @return mac address if present else optional absent value
153      */
154     public Optional<String> getGatewayMacAddressForInterface(VpnPortipToPort gwPort, String ifName) {
155         // Check if a router gateway interface is available for the subnet gw is
156         // so then use Router interface
157         // else use connected interface
158         return Optional.of(gwPort != null && gwPort.isSubnetIp() ? gwPort.getMacAddress()
159                 : InterfaceUtils.getMacAddressForInterface(dataBroker, ifName).get());
160     }
161
162 }