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