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 = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(id));
271                 //Long portid = MDSALUtil.getOfPortNumberFromPortName(id);
272                 dpnId = portResult.getDpid();
273                 Long portid = portResult.getPortno();
274                 checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
275                         DPN_NOT_FOUND_ERROR, interfaceName);
276
277                 NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
278                         portid.toString());
279                 checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
280
281                 if (LOGGER.isTraceEnabled()) {
282                     LOGGER.trace(
283                             "sendArpRequest received dpnId {} out interface {}",
284                             dpnId, interfaceName);
285                 }
286                 byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(
287                         dataBroker,
288                         (InstanceIdentifier<NodeConnector>) ref.getValue());
289                 checkNotNull(srcMac, FAILED_TO_GET_SRC_MAC_FOR_INTERFACE,
290                         interfaceName, ref.getValue());
291                 checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
292                         interfaceName);
293
294                 payload = ArpPacketUtil.getPayload(ARP_REQUEST_OP, srcMac,
295                         srcIpBytes, ArpPacketUtil.EthernetDestination_Broadcast,
296                         dstIpBytes);
297
298                 sendPacketOut(dpnId, payload, ref);
299
300                 if (LOGGER.isTraceEnabled()) {
301                     LOGGER.trace("sent arp request for "
302                             + arpReqInput.getIpaddress());
303                 }
304             } catch (Throwable e) {
305                 LOGGER.trace("failed to send arp req for {} on interface {}",
306                         arpReqInput.getIpaddress(), interfaceName);
307
308                 failureBuilder
309                         .withError(ErrorType.APPLICATION,
310                                 FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
311                                         + interfaceName, e);
312                 successBuilder
313                         .withError(ErrorType.APPLICATION,
314                                 FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
315                                         + interfaceName, e);
316                 localErrorCount++;
317             }
318         }
319         if (localErrorCount == arpReqInput.getInterfaceAddress().size()) {
320             // All the requests failed
321             return Futures.immediateFuture(failureBuilder.build());
322         }
323         return Futures.immediateFuture(successBuilder.build());
324     }
325
326     public Future<RpcResult<Void>> sendPacketOut(BigInteger dpnId,
327             byte[] payload, NodeConnectorRef ref) {
328
329         NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId,
330                 "0xfffffffd");
331         return packetProcessingService
332                 .transmitPacket(new TransmitPacketInputBuilder()
333                         .setPayload(payload)
334                         .setNode(
335                                 new NodeRef(InstanceIdentifier
336                                         .builder(Nodes.class)
337                                         .child(Node.class,
338                                                 new NodeKey(new NodeId(
339                                                         "openflow:" + dpnId)))
340                                         .toInstance()))
341                         .setIngress(nodeConnectorRef).setEgress(ref).build());
342     }
343
344     @Override
345     public Future<RpcResult<Void>> sendArpResponse(SendArpResponseInput input) {
346         if (LOGGER.isTraceEnabled()) {
347             LOGGER.trace("sendArpResponse rpc invoked");
348         }
349         BigInteger dpnId;
350         long groupId;
351         byte payload[];
352
353         try {
354             String interfaceName = input.getInterface();
355             //NodeConnectorId id = getNodeConnectorFromInterfaceName(interfaceName);
356
357             //dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(id));
358             //Long portid = MDSALUtil.getOfPortNumberFromPortName(id);
359
360             GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
361             //dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(id));
362             //Long portid = MDSALUtil.getOfPortNumberFromPortName(id);
363             dpnId = portResult.getDpid();
364             Long portid = portResult.getPortno();
365
366             
367             NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
368                     portid.toString());
369             checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
370                     DPN_NOT_FOUND_ERROR, interfaceName);
371             checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
372
373             if (LOGGER.isTraceEnabled()) {
374                 LOGGER.trace(
375                         "sendArpRequest received dpnId {} out interface {}",
376                         dpnId, interfaceName);
377             }
378
379             byte[] srcIpBytes = getIpAddressBytes(input.getSrcIpAddress());
380             byte[] dstIpBytes = getIpAddressBytes(input.getIpaddress());
381             byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(dataBroker,
382                     (InstanceIdentifier<NodeConnector>) ref.getValue());
383             byte[] dstMac = NWUtil.parseMacAddress(input.getMacaddress()
384                     .getValue());
385             checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
386                     interfaceName);
387             payload = ArpPacketUtil.getPayload(ARP_RESPONSE_OP, srcMac, srcIpBytes,
388                     dstMac, dstIpBytes);
389
390             sendPacketOut(dpnId, payload, ref);
391             if (LOGGER.isTraceEnabled()) {
392                 LOGGER.trace("sent the arp response for "
393                         + input.getSrcIpAddress());
394             }
395         } catch (Throwable e) {
396             LOGGER.trace("failed to send arp response for {} {}",
397                     input.getSrcIpAddress(), e);
398             return RpcResultBuilder.<Void> failed()
399                     .withError(ErrorType.APPLICATION, e.getMessage(), e)
400                     .buildFuture();
401         }
402         RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
403         return Futures.immediateFuture(rpcResultBuilder.build());
404     }
405
406     @Override
407     public void onPacketReceived(PacketReceived packetReceived) {
408         Class<? extends PacketInReason> pktInReason = packetReceived
409                 .getPacketInReason();
410         if (LOGGER.isTraceEnabled()) {
411             LOGGER.trace("Packet Received {}", packetReceived);
412         }
413
414         if (pktInReason == SendToController.class) {
415
416             try {
417                 int tableId = packetReceived.getTableId().getValue();
418
419                 byte[] data = packetReceived.getPayload();
420                 Ethernet ethernet = new Ethernet();
421
422                 ethernet.deserialize(data, 0, data.length
423                         * NetUtils.NumBitsInAByte);
424                 if (ethernet.getEtherType() != ETH_TYPE_ARP) {
425                     return;
426                 }
427
428                 Packet pkt = ethernet.getPayload();
429                 ARP arp = (ARP) pkt;
430                 InetAddress srcInetAddr = InetAddress.getByAddress(arp
431                         .getSenderProtocolAddress());
432                 InetAddress dstInetAddr = InetAddress.getByAddress(arp
433                         .getTargetProtocolAddress());
434                 byte[] srcMac = ethernet.getSourceMACAddress();
435
436                 NodeConnectorRef ref = packetReceived.getIngress();
437
438                 Metadata i  = packetReceived.getMatch().getMetadata();
439                 
440                 //String interfaceName = MDSALUtil.getInterfaceName(ref, dataBroker);
441                 String interfaceName = getInterfaceName(ref,i, dataBroker);
442                 
443                 checkAndFireMacChangedNotification(interfaceName, srcInetAddr,
444                         srcMac);
445
446                 macsDB.put(interfaceName + "-" + srcInetAddr.getHostAddress(),
447                         NWUtil.toStringMacAddress(srcMac));
448
449                 if (arp.getOpCode() == ARP_REQUEST_OP) {
450                     fireArpReqRecvdNotification(interfaceName, srcInetAddr,
451                             srcMac, dstInetAddr, tableId);
452                 } else {
453                     fireArpRespRecvdNotification(interfaceName, srcInetAddr,
454                             srcMac, tableId);
455                 }
456                 if (getMacFutures.get(srcInetAddr.getHostAddress()) != null) {
457                     threadPool.submit(new MacResponderTask(arp));
458                 }
459
460             } catch (Throwable e) {
461                 LOGGER.trace("Failed to decode packet: {}", e);
462             }
463         }
464     }
465
466     GetPortFromInterfaceOutput getPortFromInterface(String interfaceName) throws Throwable {
467         GetPortFromInterfaceInputBuilder x = new GetPortFromInterfaceInputBuilder();
468                 x.setIntfName(interfaceName);;
469                 Future<RpcResult<GetPortFromInterfaceOutput>> ft = intfRpc.getPortFromInterface(x.build());
470                 GetPortFromInterfaceOutput result = ft.get().getResult();
471                 LOGGER.trace("getPortFromInterface rpc result is {} ", result);
472                 if (result != null) {
473                         LOGGER.trace("getPortFromInterface rpc result is {} {} ", result.getDpid(), result.getPortno());
474                 }
475                 return result;
476     }
477     
478     private String getInterfaceName(NodeConnectorRef ref, Metadata metadata, DataBroker dataBroker2) throws Throwable {
479         LOGGER.debug("metadata received is {} ", metadata);
480         
481         GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
482         BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata.getMetadata());
483         
484         ifIndexInputBuilder.setIfIndex(lportTag.intValue());
485         GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build();
486         OdlInterfaceRpcService intfRpc = getInterfaceRpcService();
487
488                 Future<RpcResult<GetInterfaceFromIfIndexOutput>> interfaceFromIfIndex = intfRpc.getInterfaceFromIfIndex(input);
489                 GetInterfaceFromIfIndexOutput interfaceFromIfIndexOutput = interfaceFromIfIndex.get().getResult();
490         return interfaceFromIfIndexOutput.getInterfaceName();
491         }
492
493         class MacResponderTask implements Runnable {
494         ARP arp;
495
496         MacResponderTask(ARP arp) {
497             this.arp = arp;
498         }
499
500         @Override
501         public void run() {
502             InetAddress srcAddr;
503             GetMacOutputBuilder outputBuilder;
504             String srcMac;
505             SettableFuture<RpcResult<GetMacOutput>> future = null;
506             RpcResultBuilder<GetMacOutput> resultBuilder;
507             try {
508                 srcAddr = InetAddress.getByAddress(arp
509                         .getSenderProtocolAddress());
510                 srcMac = NWUtil.toStringMacAddress(arp
511                         .getSenderHardwareAddress());
512                 future = getMacFutures.remove(srcAddr.getHostAddress());
513                 if (future == null) {
514                     LOGGER.trace("There are no pending mac requests.");
515                     return;
516                 }
517                 outputBuilder = new GetMacOutputBuilder()
518                         .setMacaddress(new PhysAddress(srcMac));
519                 resultBuilder = RpcResultBuilder.success(outputBuilder.build());
520                 if (LOGGER.isTraceEnabled()) {
521                     LOGGER.trace("sent the mac response for ip {}",
522                             srcAddr.getHostAddress());
523                 }
524             } catch (Exception e) {
525                 LOGGER.trace("failed to send mac response {} ", e);
526                 resultBuilder = RpcResultBuilder.<GetMacOutput> failed()
527                         .withError(ErrorType.APPLICATION, e.getMessage(), e);
528             }
529             future.set(resultBuilder.build());
530         }
531     }
532
533     private void fireArpRespRecvdNotification(String interfaceName,
534             InetAddress inetAddr, byte[] macAddressBytes, int tableId)
535             throws InterruptedException {
536
537         IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
538         String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
539         PhysAddress mac = new PhysAddress(macAddress);
540         ArpResponseReceivedBuilder builder = new ArpResponseReceivedBuilder();
541         builder.setInterface(interfaceName);
542         builder.setIpaddress(ip);
543         builder.setOfTableId((long) tableId);
544         builder.setMacaddress(mac);
545         notificationPublishService.putNotification(builder.build());
546     }
547
548     private void fireArpReqRecvdNotification(String interfaceName,
549             InetAddress srcInetAddr, byte[] srcMac, InetAddress dstInetAddr,
550             int tableId) throws InterruptedException {
551         String macAddress = NWUtil.toStringMacAddress(srcMac);
552         ArpRequestReceivedBuilder builder = new ArpRequestReceivedBuilder();
553         builder.setInterface(interfaceName);
554         builder.setOfTableId((long) tableId);
555         builder.setSrcIpaddress(new IpAddress(srcInetAddr.getHostAddress()
556                 .toCharArray()));
557         builder.setDstIpaddress(new IpAddress(dstInetAddr.getHostAddress()
558                 .toCharArray()));
559         builder.setSrcMac(new PhysAddress(macAddress));
560         notificationPublishService.putNotification(builder.build());
561     }
562
563     private void checkAndFireMacChangedNotification(String interfaceName,
564             InetAddress inetAddr, byte[] macAddressBytes)
565             throws InterruptedException {
566
567         IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
568         String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
569         PhysAddress mac = new PhysAddress(macAddress);
570
571         if (!macAddress.equals(macsDB.get(interfaceName + "-"
572                 + inetAddr.getHostAddress()))) {
573             if (LOGGER.isTraceEnabled()) {
574                 LOGGER.trace("mac address changed for " + inetAddr);
575             }
576             MacChangedBuilder builder = new MacChangedBuilder();
577             builder.setInterface(interfaceName);
578             builder.setIpaddress(ip);
579             builder.setMacaddress(mac);
580             notificationPublishService.putNotification(builder.build());
581         }
582     }
583
584     private InstanceIdentifier<Interface> buildInterfaceId(String interfaceName) {
585         InstanceIdentifierBuilder<Interface> idBuilder = InstanceIdentifier
586                 .builder(Interfaces.class).child(Interface.class,
587                         new InterfaceKey(interfaceName));
588         InstanceIdentifier<Interface> id = idBuilder.build();
589         return id;
590     }
591
592
593     private NodeConnectorId getNodeConnectorFromInterfaceName(String interfaceName) {
594         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
595                 InstanceIdentifier.builder(InterfacesState.class)
596                         .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
597                                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
598         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = idBuilder.build();
599
600         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil.read(dataBroker,
601                 LogicalDatastoreType.OPERATIONAL,
602                 ifStateId);
603
604         if (ifStateOptional.isPresent()) {
605             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifStateOptional.get();
606             List<String> lowerLayerIf = ifState.getLowerLayerIf();
607             if (!lowerLayerIf.isEmpty()) {
608                 return new NodeConnectorId(lowerLayerIf.get(0));
609             }
610         }
611         return null;
612     }
613 }