Bug 5182 - Customized name support for VLAN trunk should be supported
[vpnservice.git] / arputil / arputil-impl / src / main / java / org / opendaylight / vpnservice / arputil / internal / ArpUtilImpl.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
9 package org.opendaylight.vpnservice.arputil.internal;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static com.google.common.base.Preconditions.checkNotNull;
13
14 import java.math.BigInteger;
15 import java.net.InetAddress;
16 import java.net.UnknownHostException;
17 import java.util.List;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ConcurrentMap;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.Future;
24 import org.opendaylight.controller.liblldp.NetUtils;
25 import org.opendaylight.controller.liblldp.Packet;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
28 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
29 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
32 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
33 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
34 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
35 import org.opendaylight.vpnservice.mdsalutil.NWUtil;
36 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
38 import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceived;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceivedBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceivedBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChangedBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.interfaces.InterfaceAddress;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceInput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceInputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
82 import org.opendaylight.yangtools.concepts.ListenerRegistration;
83 import org.opendaylight.yangtools.yang.binding.DataObject;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
86 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
87 import org.opendaylight.yangtools.yang.common.RpcResult;
88 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
89 import org.slf4j.Logger;
90 import org.slf4j.LoggerFactory;
91
92 import com.google.common.base.Optional;
93 import com.google.common.util.concurrent.FutureCallback;
94 import com.google.common.util.concurrent.Futures;
95 import com.google.common.util.concurrent.JdkFutureAdapters;
96 import com.google.common.util.concurrent.SettableFuture;
97
98 public class ArpUtilImpl implements OdlArputilService,
99         PacketProcessingListener, AutoCloseable {
100
101     private static final String FAILED_TO_GET_SRC_IP_FOR_INTERFACE = "Failed to get src ip for %s";
102
103     private static final String FAILED_TO_GET_SRC_MAC_FOR_INTERFACE = "Failed to get src mac for interface %s iid %s ";
104
105     private static final String FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE = "failed to send arp req for interface ";
106
107     private static final String UNKNOWN_IP_ADDRESS_SUPPLIED = "unknown ip address supplied";
108
109     private static final String NODE_CONNECTOR_NOT_FOUND_ERROR = "Node connector id not found for interface %s";
110
111     private static final String DPN_NOT_FOUND_ERROR = "dpn not found for interface %s ";
112
113     private static final short ARP_REQUEST_OP = (short) 1;
114
115     private static final short ARP_RESPONSE_OP = (short) 2;
116
117     private static final short ETH_TYPE_ARP = 0x0806;
118
119     private static final Logger LOGGER = LoggerFactory
120             .getLogger(ArpUtilImpl.class);
121
122     static OdlInterfaceRpcService intfRpc;
123     
124     ExecutorService threadPool = Executors.newFixedThreadPool(1);
125
126     DataBroker dataBroker;
127     PacketProcessingService packetProcessingService;
128     NotificationPublishService notificationPublishService;
129     NotificationService notificationService;
130     IMdsalApiManager mdsalMgr;
131
132     RpcProviderRegistry rpc;
133     ListenerRegistration<ArpUtilImpl> listenerRegistration;
134
135     ConcurrentMap<String, String> macsDB = new ConcurrentHashMap<>();
136     ConcurrentMap<String, SettableFuture<RpcResult<GetMacOutput>>> getMacFutures = new ConcurrentHashMap<>();
137
138     public ArpUtilImpl(DataBroker db,
139             PacketProcessingService packetProcessingService,
140             NotificationPublishService notificationPublishService,
141             NotificationService notificationService,
142             IMdsalApiManager mdsalApiManager,
143             RpcProviderRegistry rpc) {
144
145         this.dataBroker = db;
146         this.packetProcessingService = packetProcessingService;
147         this.notificationPublishService = notificationPublishService;
148         this.mdsalMgr = mdsalApiManager;
149         this.notificationService = notificationService;
150         this.rpc = rpc;
151         listenerRegistration = notificationService
152                 .registerNotificationListener(this);
153         LOGGER.info("ArpUtil Manager Initialized ");
154     }
155
156     OdlInterfaceRpcService getInterfaceRpcService() {
157         if (intfRpc == null ) {
158             intfRpc = rpc.getRpcService(OdlInterfaceRpcService.class);
159         }
160         return intfRpc;
161     }
162
163     @Override
164     public void close() throws Exception {
165         listenerRegistration.close();
166         LOGGER.trace("ArpUtil manager Closed");
167     }
168
169     String getIpAddressInString(IpAddress ipAddress)
170             throws UnknownHostException {
171         return InetAddress.getByName(ipAddress.getIpv4Address().getValue())
172                 .getHostAddress();
173     }
174
175     public Future<RpcResult<GetMacOutput>> getMac(GetMacInput input) {
176
177         try {
178             final String dstIpAddress = getIpAddressInString(input
179                     .getIpaddress());
180             if (LOGGER.isTraceEnabled()) {
181                 LOGGER.trace("getMac rpc invoked for ip " + dstIpAddress);
182             }
183             if (getMacFutures.get(dstIpAddress) != null) {
184                 if (LOGGER.isInfoEnabled()) {
185                     LOGGER.info("get mac already in progress for the ip "
186                             + dstIpAddress);
187                 }
188                 return getMacFutures.get(dstIpAddress);
189             }
190             SendArpRequestInputBuilder builder = new SendArpRequestInputBuilder()
191                     .setInterfaceAddress(input.getInterfaceAddress())
192                     .setIpaddress(input.getIpaddress());
193             Future<RpcResult<Void>> arpReqFt = sendArpRequest(builder.build());
194             final SettableFuture<RpcResult<GetMacOutput>> ft = SettableFuture
195                     .create();
196
197             Futures.addCallback(
198                     JdkFutureAdapters.listenInPoolThread(arpReqFt, threadPool),
199                     new FutureCallback<RpcResult<Void>>() {
200                         @Override
201                         public void onFailure(Throwable e) {
202                             RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder
203                                     .<GetMacOutput> failed().withError(
204                                             ErrorType.APPLICATION,
205                                             e.getMessage(), e);
206                             ft.set(resultBuilder.build());
207                         }
208
209                         @Override
210                         public void onSuccess(RpcResult<Void> result) {
211                             LOGGER.trace("Successfully sent the arp pkt out for ip "
212                                     + dstIpAddress);
213                         }
214                     });
215
216             getMacFutures.put(dstIpAddress, ft);
217             return ft;
218         } catch (Exception e) {
219             LOGGER.trace("failed to handle getMac request for {} {}",
220                     input.getIpaddress(), e);
221             RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder
222                     .<GetMacOutput> failed().withError(ErrorType.APPLICATION,
223                             e.getMessage(), e);
224             return Futures.immediateFuture(resultBuilder.build());
225         }
226     }
227
228     byte[] getIpAddressBytes(IpAddress ip) throws UnknownHostException {
229         return InetAddress.getByName(ip.getIpv4Address().getValue())
230                 .getAddress();
231     }
232
233     @Override
234     public Future<RpcResult<Void>> sendArpRequest(
235             SendArpRequestInput arpReqInput) {
236         if (LOGGER.isTraceEnabled()) {
237             LOGGER.trace("rpc sendArpRequest invoked for ip "
238                     + arpReqInput.getIpaddress());
239         }
240         BigInteger dpnId;
241         long groupId;
242         byte payload[];
243         String interfaceName = null;
244         byte srcIpBytes[];
245         byte[] dstIpBytes = null;
246
247         RpcResultBuilder<Void> failureBuilder = RpcResultBuilder
248                 .<Void> failed();
249         RpcResultBuilder<Void> successBuilder = RpcResultBuilder
250                 .<Void> success();
251
252         try {
253             dstIpBytes = getIpAddressBytes(arpReqInput.getIpaddress());
254         } catch (Exception e) {
255             failureBuilder.withError(ErrorType.APPLICATION,
256                     UNKNOWN_IP_ADDRESS_SUPPLIED);
257             return Futures.immediateFuture(failureBuilder.build());
258         }
259
260         int localErrorCount = 0;
261         for (InterfaceAddress interfaceAddress : arpReqInput
262                 .getInterfaceAddress()) {
263             try {
264                 interfaceName = interfaceAddress.getInterface();
265                 srcIpBytes = getIpAddressBytes(interfaceAddress.getIpAddress());
266
267                 NodeConnectorId id = getNodeConnectorFromInterfaceName(interfaceName);
268
269                 GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
270                 dpnId = portResult.getDpid();
271                 Long portid = portResult.getPortno();
272                 checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
273                         DPN_NOT_FOUND_ERROR, interfaceName);
274
275                 NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
276                         portid.toString());
277                 checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
278
279                 if (LOGGER.isTraceEnabled()) {
280                     LOGGER.trace(
281                             "sendArpRequest received dpnId {} out interface {}",
282                             dpnId, interfaceName);
283                 }
284                 byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(
285                         dataBroker,
286                         (InstanceIdentifier<NodeConnector>) ref.getValue());
287                 checkNotNull(srcMac, FAILED_TO_GET_SRC_MAC_FOR_INTERFACE,
288                         interfaceName, ref.getValue());
289                 checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
290                         interfaceName);
291
292                 payload = ArpPacketUtil.getPayload(ARP_REQUEST_OP, srcMac,
293                         srcIpBytes, ArpPacketUtil.EthernetDestination_Broadcast,
294                         dstIpBytes);
295
296                 sendPacketOut(dpnId, payload, ref);
297
298                 if (LOGGER.isTraceEnabled()) {
299                     LOGGER.trace("sent arp request for "
300                             + arpReqInput.getIpaddress());
301                 }
302             } catch (Throwable e) {
303                 LOGGER.trace("failed to send arp req for {} on interface {}",
304                         arpReqInput.getIpaddress(), interfaceName);
305
306                 failureBuilder
307                         .withError(ErrorType.APPLICATION,
308                                 FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
309                                         + interfaceName, e);
310                 successBuilder
311                         .withError(ErrorType.APPLICATION,
312                                 FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
313                                         + interfaceName, e);
314                 localErrorCount++;
315             }
316         }
317         if (localErrorCount == arpReqInput.getInterfaceAddress().size()) {
318             // All the requests failed
319             return Futures.immediateFuture(failureBuilder.build());
320         }
321         return Futures.immediateFuture(successBuilder.build());
322     }
323
324     public Future<RpcResult<Void>> sendPacketOut(BigInteger dpnId,
325             byte[] payload, NodeConnectorRef ref) {
326
327         NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId,
328                 "0xfffffffd");
329         return packetProcessingService
330                 .transmitPacket(new TransmitPacketInputBuilder()
331                         .setPayload(payload)
332                         .setNode(
333                                 new NodeRef(InstanceIdentifier
334                                         .builder(Nodes.class)
335                                         .child(Node.class,
336                                                 new NodeKey(new NodeId(
337                                                         "openflow:" + dpnId)))
338                                         .toInstance()))
339                         .setIngress(nodeConnectorRef).setEgress(ref).build());
340     }
341
342     @Override
343     public Future<RpcResult<Void>> sendArpResponse(SendArpResponseInput input) {
344         if (LOGGER.isTraceEnabled()) {
345             LOGGER.trace("sendArpResponse rpc invoked");
346         }
347         BigInteger dpnId;
348         long groupId;
349         byte payload[];
350
351         try {
352             String interfaceName = input.getInterface();
353             GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
354             dpnId = portResult.getDpid();
355             Long portid = portResult.getPortno();
356             NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
357                     portid.toString());
358             checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
359                     DPN_NOT_FOUND_ERROR, interfaceName);
360             checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
361
362             if (LOGGER.isTraceEnabled()) {
363                 LOGGER.trace(
364                         "sendArpRequest received dpnId {} out interface {}",
365                         dpnId, interfaceName);
366             }
367
368             byte[] srcIpBytes = getIpAddressBytes(input.getSrcIpAddress());
369             byte[] dstIpBytes = getIpAddressBytes(input.getIpaddress());
370             byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(dataBroker,
371                     (InstanceIdentifier<NodeConnector>) ref.getValue());
372             byte[] dstMac = NWUtil.parseMacAddress(input.getMacaddress()
373                     .getValue());
374             checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
375                     interfaceName);
376             payload = ArpPacketUtil.getPayload(ARP_RESPONSE_OP, srcMac, srcIpBytes,
377                     dstMac, dstIpBytes);
378
379             sendPacketOut(dpnId, payload, ref);
380             if (LOGGER.isTraceEnabled()) {
381                 LOGGER.trace("sent the arp response for "
382                         + input.getSrcIpAddress());
383             }
384         } catch (Throwable e) {
385             LOGGER.trace("failed to send arp response for {} {}",
386                     input.getSrcIpAddress(), e);
387             return RpcResultBuilder.<Void> failed()
388                     .withError(ErrorType.APPLICATION, e.getMessage(), e)
389                     .buildFuture();
390         }
391         RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
392         return Futures.immediateFuture(rpcResultBuilder.build());
393     }
394
395     @Override
396     public void onPacketReceived(PacketReceived packetReceived) {
397         Class<? extends PacketInReason> pktInReason = packetReceived
398                 .getPacketInReason();
399         if (LOGGER.isTraceEnabled()) {
400             LOGGER.trace("Packet Received {}", packetReceived);
401         }
402
403         if (pktInReason == SendToController.class) {
404
405             try {
406                 int tableId = packetReceived.getTableId().getValue();
407
408                 byte[] data = packetReceived.getPayload();
409                 Ethernet ethernet = new Ethernet();
410
411                 ethernet.deserialize(data, 0, data.length
412                         * NetUtils.NumBitsInAByte);
413                 if (ethernet.getEtherType() != ETH_TYPE_ARP) {
414                     return;
415                 }
416
417                 Packet pkt = ethernet.getPayload();
418                 ARP arp = (ARP) pkt;
419                 InetAddress srcInetAddr = InetAddress.getByAddress(arp
420                         .getSenderProtocolAddress());
421                 InetAddress dstInetAddr = InetAddress.getByAddress(arp
422                         .getTargetProtocolAddress());
423                 byte[] srcMac = ethernet.getSourceMACAddress();
424
425                 NodeConnectorRef ref = packetReceived.getIngress();
426
427                 Metadata metadata  = packetReceived.getMatch().getMetadata();
428                 String interfaceName = getInterfaceName(ref,metadata, dataBroker);
429                 
430                 checkAndFireMacChangedNotification(interfaceName, srcInetAddr,
431                         srcMac);
432
433                 macsDB.put(interfaceName + "-" + srcInetAddr.getHostAddress(),
434                         NWUtil.toStringMacAddress(srcMac));
435
436                 if (arp.getOpCode() == ARP_REQUEST_OP) {
437                     fireArpReqRecvdNotification(interfaceName, srcInetAddr,
438                             srcMac, dstInetAddr, tableId);
439                 } else {
440                     fireArpRespRecvdNotification(interfaceName, srcInetAddr,
441                             srcMac, tableId);
442                 }
443                 if (getMacFutures.get(srcInetAddr.getHostAddress()) != null) {
444                     threadPool.submit(new MacResponderTask(arp));
445                 }
446
447             } catch (Throwable e) {
448                 LOGGER.trace("Failed to decode packet: {}", e);
449             }
450         }
451     }
452
453     GetPortFromInterfaceOutput getPortFromInterface(String interfaceName) throws Throwable {
454         GetPortFromInterfaceInputBuilder getPortFromInterfaceInputBuilder = new GetPortFromInterfaceInputBuilder();
455         getPortFromInterfaceInputBuilder.setIntfName(interfaceName);;
456         Future<RpcResult<GetPortFromInterfaceOutput>> portFromInterface = intfRpc.getPortFromInterface(getPortFromInterfaceInputBuilder.build());
457         GetPortFromInterfaceOutput result = portFromInterface.get().getResult();
458         LOGGER.trace("getPortFromInterface rpc result is {} ", result);
459         if (result != null) {
460             LOGGER.trace("getPortFromInterface rpc result is {} {} ", result.getDpid(), result.getPortno());
461         }
462         return result;
463     }
464     
465     private String getInterfaceName(NodeConnectorRef ref, Metadata metadata, DataBroker dataBroker2) throws Throwable {
466         LOGGER.debug("metadata received is {} ", metadata);
467         
468         GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
469         BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata.getMetadata());
470         
471         ifIndexInputBuilder.setIfIndex(lportTag.intValue());
472         GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build();
473         OdlInterfaceRpcService intfRpc = getInterfaceRpcService();
474
475         Future<RpcResult<GetInterfaceFromIfIndexOutput>> interfaceFromIfIndex = intfRpc.getInterfaceFromIfIndex(input);
476         GetInterfaceFromIfIndexOutput interfaceFromIfIndexOutput = interfaceFromIfIndex.get().getResult();
477         return interfaceFromIfIndexOutput.getInterfaceName();
478     }
479
480         class MacResponderTask implements Runnable {
481         ARP arp;
482
483         MacResponderTask(ARP arp) {
484             this.arp = arp;
485         }
486
487         @Override
488         public void run() {
489             InetAddress srcAddr;
490             GetMacOutputBuilder outputBuilder;
491             String srcMac;
492             SettableFuture<RpcResult<GetMacOutput>> future = null;
493             RpcResultBuilder<GetMacOutput> resultBuilder;
494             try {
495                 srcAddr = InetAddress.getByAddress(arp
496                         .getSenderProtocolAddress());
497                 srcMac = NWUtil.toStringMacAddress(arp
498                         .getSenderHardwareAddress());
499                 future = getMacFutures.remove(srcAddr.getHostAddress());
500                 if (future == null) {
501                     LOGGER.trace("There are no pending mac requests.");
502                     return;
503                 }
504                 outputBuilder = new GetMacOutputBuilder()
505                         .setMacaddress(new PhysAddress(srcMac));
506                 resultBuilder = RpcResultBuilder.success(outputBuilder.build());
507                 if (LOGGER.isTraceEnabled()) {
508                     LOGGER.trace("sent the mac response for ip {}",
509                             srcAddr.getHostAddress());
510                 }
511             } catch (Exception e) {
512                 LOGGER.trace("failed to send mac response {} ", e);
513                 resultBuilder = RpcResultBuilder.<GetMacOutput> failed()
514                         .withError(ErrorType.APPLICATION, e.getMessage(), e);
515             }
516             future.set(resultBuilder.build());
517         }
518     }
519
520     private void fireArpRespRecvdNotification(String interfaceName,
521             InetAddress inetAddr, byte[] macAddressBytes, int tableId)
522             throws InterruptedException {
523
524         IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
525         String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
526         PhysAddress mac = new PhysAddress(macAddress);
527         ArpResponseReceivedBuilder builder = new ArpResponseReceivedBuilder();
528         builder.setInterface(interfaceName);
529         builder.setIpaddress(ip);
530         builder.setOfTableId((long) tableId);
531         builder.setMacaddress(mac);
532         notificationPublishService.putNotification(builder.build());
533     }
534
535     private void fireArpReqRecvdNotification(String interfaceName,
536             InetAddress srcInetAddr, byte[] srcMac, InetAddress dstInetAddr,
537             int tableId) throws InterruptedException {
538         String macAddress = NWUtil.toStringMacAddress(srcMac);
539         ArpRequestReceivedBuilder builder = new ArpRequestReceivedBuilder();
540         builder.setInterface(interfaceName);
541         builder.setOfTableId((long) tableId);
542         builder.setSrcIpaddress(new IpAddress(srcInetAddr.getHostAddress()
543                 .toCharArray()));
544         builder.setDstIpaddress(new IpAddress(dstInetAddr.getHostAddress()
545                 .toCharArray()));
546         builder.setSrcMac(new PhysAddress(macAddress));
547         notificationPublishService.putNotification(builder.build());
548     }
549
550     private void checkAndFireMacChangedNotification(String interfaceName,
551             InetAddress inetAddr, byte[] macAddressBytes)
552             throws InterruptedException {
553
554         IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
555         String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
556         PhysAddress mac = new PhysAddress(macAddress);
557
558         if (!macAddress.equals(macsDB.get(interfaceName + "-"
559                 + inetAddr.getHostAddress()))) {
560             if (LOGGER.isTraceEnabled()) {
561                 LOGGER.trace("mac address changed for " + inetAddr);
562             }
563             MacChangedBuilder builder = new MacChangedBuilder();
564             builder.setInterface(interfaceName);
565             builder.setIpaddress(ip);
566             builder.setMacaddress(mac);
567             notificationPublishService.putNotification(builder.build());
568         }
569     }
570
571     private InstanceIdentifier<Interface> buildInterfaceId(String interfaceName) {
572         InstanceIdentifierBuilder<Interface> idBuilder = InstanceIdentifier
573                 .builder(Interfaces.class).child(Interface.class,
574                         new InterfaceKey(interfaceName));
575         InstanceIdentifier<Interface> id = idBuilder.build();
576         return id;
577     }
578
579
580     private NodeConnectorId getNodeConnectorFromInterfaceName(String interfaceName) {
581         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
582                 InstanceIdentifier.builder(InterfacesState.class)
583                         .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
584                                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
585         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = idBuilder.build();
586
587         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil.read(dataBroker,
588                 LogicalDatastoreType.OPERATIONAL,
589                 ifStateId);
590
591         if (ifStateOptional.isPresent()) {
592             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifStateOptional.get();
593             List<String> lowerLayerIf = ifState.getLowerLayerIf();
594             if (!lowerLayerIf.isEmpty()) {
595                 return new NodeConnectorId(lowerLayerIf.get(0));
596             }
597         }
598         return null;
599     }
600 }