Merge "ITM: Fix for tunnel ports not getting deleted."
[genius.git] / alivenessmonitor / alivenessmonitor-impl / src / main / java / org / opendaylight / genius / alivenessmonitor / internal / AlivenessProtocolHandlerARP.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.genius.alivenessmonitor.internal;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.base.Strings;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.JdkFutureAdapters;
15 import org.opendaylight.controller.liblldp.Packet;
16 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
17 import org.opendaylight.genius.mdsalutil.packet.ARP;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.EtherTypes;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.EndpointType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.Interface;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.configs.MonitoringInfo;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
33 import org.opendaylight.yangtools.yang.common.RpcError;
34 import org.opendaylight.yangtools.yang.common.RpcResult;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import java.math.BigInteger;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.concurrent.ExecutionException;
43 import java.util.concurrent.Future;
44
45 import static org.opendaylight.genius.alivenessmonitor.internal.AlivenessMonitorConstants.*;
46 import static org.opendaylight.genius.alivenessmonitor.internal.AlivenessMonitorConstants.SEPERATOR;
47 import static org.opendaylight.genius.alivenessmonitor.internal.AlivenessMonitorUtil.toStringIpAddress;
48
49 public class AlivenessProtocolHandlerARP extends AbstractAlivenessProtocolHandler {
50     private static final Logger LOG = LoggerFactory.getLogger(AlivenessProtocolHandlerARP.class);
51     private OdlArputilService arpService;
52
53     public AlivenessProtocolHandlerARP(ServiceProvider serviceProvider) {
54         super(serviceProvider);
55     }
56
57     void setArpManagerService(OdlArputilService arpService) {
58         this.arpService = arpService;
59     }
60
61     @Override
62     public Class<?> getPacketClass() {
63         return ARP.class;
64     }
65
66     @Override
67     public String handlePacketIn(Packet protocolPacket, PacketReceived packetReceived) {
68         ARP packet = (ARP) protocolPacket;
69         short tableId = packetReceived.getTableId().getValue();
70         int arpType = packet.getOpCode();
71
72         if (LOG.isTraceEnabled()) {
73             LOG.trace("packet: {}, tableId {}, arpType {}", packetReceived, tableId, arpType);
74         }
75
76         if (tableId == AlivenessMonitorConstants.L3_INTERFACE_TABLE) {
77             if (arpType == ARP.REPLY) {
78                 if (LOG.isTraceEnabled()) {
79                     LOG.trace("packet: {}, monitorKey {}", packetReceived);
80                 }
81
82                 BigInteger metadata = packetReceived.getMatch().getMetadata().getMetadata();
83                 int portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
84                 String interfaceName = null;
85
86                 try {
87                     GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(portTag).build();
88                     Future<RpcResult<GetInterfaceFromIfIndexOutput>> output = serviceProvider.getInterfaceManager().getInterfaceFromIfIndex(input);
89                     RpcResult<GetInterfaceFromIfIndexOutput> result = output.get();
90                     if(result.isSuccessful()) {
91                         GetInterfaceFromIfIndexOutput ifIndexOutput = result.getResult();
92                         interfaceName = ifIndexOutput.getInterfaceName();
93                     } else {
94                         LOG.warn("RPC call to get interface name for if index {} failed with errors {}", portTag, result.getErrors());
95                         return null;
96                     }
97                 } catch(InterruptedException | ExecutionException e) {
98                     LOG.warn("Error retrieving interface Name for tag {}", portTag, e);
99                 }
100                 if(!Strings.isNullOrEmpty(interfaceName)) {
101                     String sourceIp = toStringIpAddress(packet.getSenderProtocolAddress());
102                     String targetIp = toStringIpAddress(packet.getTargetProtocolAddress());
103                     return getMonitoringKey(interfaceName, targetIp, sourceIp);
104                 } else {
105                     LOG.debug("No interface associated with tag {} to interpret the received ARP Reply", portTag);
106                 }
107             }
108         }
109         return null;
110     }
111
112     @Override
113     public void startMonitoringTask(MonitoringInfo monitorInfo) {
114         if(arpService == null) {
115             LOG.debug("ARP Service not available to send the packet");
116             return;
117         }
118         EndpointType source = monitorInfo.getSource().getEndpointType();
119         final String sourceInterface = Preconditions.checkNotNull(getInterfaceName(source),
120                                        "Source interface is required to send ARP Packet for monitoring");
121
122         final String srcIp = Preconditions.checkNotNull(getIpAddress(source),
123                                     "Source Ip address is required to send ARP Packet for monitoring");
124
125         EndpointType target = monitorInfo.getDestination().getEndpointType();
126         final String targetIp = Preconditions.checkNotNull(getIpAddress(target),
127                                       "Target Ip address is required to send ARP Packet for monitoring");
128
129         if (LOG.isTraceEnabled()) {
130             LOG.trace("sendArpRequest interface {}, senderIPAddress {}, targetAddress {}", sourceInterface, srcIp, targetIp);
131         }
132
133         List<InterfaceAddress> addresses = Collections.singletonList(
134                            new InterfaceAddressBuilder().setInterface(sourceInterface)
135                                                         .setIpAddress(IpAddressBuilder.getDefaultInstance(srcIp)).build());
136         SendArpRequestInput input = new SendArpRequestInputBuilder().setInterfaceAddress(addresses)
137                                                                     .setIpaddress(IpAddressBuilder.getDefaultInstance(targetIp)).build();
138         Future<RpcResult<Void>> future = arpService.sendArpRequest(input);
139
140         final String msgFormat = String.format("Send ARP Request on interface %s to destination %s", sourceInterface, targetIp);
141         Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
142             @Override
143             public void onFailure(Throwable error) {
144                 LOG.error("Error - {}", msgFormat, error);
145             }
146
147             @Override
148             public void onSuccess(RpcResult<Void> result) {
149                 if(!result.isSuccessful()) {
150                     LOG.warn("Rpc call to {} failed {}", msgFormat, getErrorText(result.getErrors()));
151                 } else {
152                     LOG.debug("Successful RPC Result - {}", msgFormat);
153                 }
154             }
155         });
156     }
157
158     private String getErrorText(Collection<RpcError> errors) {
159         StringBuilder errorText = new StringBuilder();
160         for(RpcError error : errors) {
161             errorText.append(",").append(error.getErrorType()).append("-")
162                      .append(error.getMessage());
163         }
164         return errorText.toString();
165     }
166
167     @Override
168     public String getUniqueMonitoringKey(MonitoringInfo monitorInfo) {
169         String interfaceName = getInterfaceName(monitorInfo.getSource().getEndpointType());
170         String sourceIp = getIpAddress(monitorInfo.getSource().getEndpointType());
171         String targetIp = getIpAddress(monitorInfo.getDestination().getEndpointType());
172         return getMonitoringKey(interfaceName, sourceIp, targetIp);
173     }
174
175     private String getMonitoringKey(String interfaceName, String sourceIp, String targetIp) {
176         return new StringBuilder().append(interfaceName).append(SEPERATOR).append(sourceIp)
177                 .append(SEPERATOR).append(targetIp).append(SEPERATOR).append(EtherTypes.Arp).toString();
178     }
179
180     private String getIpAddress(EndpointType source) {
181         String ipAddress = null;
182         if( source instanceof IpAddress) {
183             ipAddress = ((IpAddress) source).getIpAddress().getIpv4Address().getValue();
184         } else if (source instanceof Interface) {
185             ipAddress = ((Interface)source).getInterfaceIp().getIpv4Address().getValue();
186         }
187         return ipAddress;
188     }
189
190     private String getInterfaceName(EndpointType endpoint) {
191         String interfaceName = null;
192         if(endpoint instanceof Interface) {
193             interfaceName = ((Interface)endpoint).getInterfaceName();
194         }
195         return interfaceName;
196     }
197
198 }