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