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