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