2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.genius.arputil.internal;
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static com.google.common.base.Preconditions.checkNotNull;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import com.google.common.util.concurrent.SettableFuture;
20 import java.io.UnsupportedEncodingException;
21 import java.math.BigInteger;
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.ExecutorService;
30 import java.util.concurrent.Executors;
31 import java.util.concurrent.Future;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
34 import org.opendaylight.controller.liblldp.HexEncode;
35 import org.opendaylight.controller.liblldp.NetUtils;
36 import org.opendaylight.controller.liblldp.Packet;
37 import org.opendaylight.controller.liblldp.PacketException;
38 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
39 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
40 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
41 import org.opendaylight.genius.arputil.api.ArpConstants;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
44 import org.opendaylight.genius.mdsalutil.NWUtil;
45 import org.opendaylight.genius.mdsalutil.packet.ARP;
46 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
47 import org.opendaylight.infrautils.inject.AbstractLifecycle;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpRequestReceivedBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpResponseReceivedBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.GetMacInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.GetMacOutput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.GetMacOutputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.MacChangedBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
85 import org.opendaylight.yangtools.concepts.ListenerRegistration;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
87 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
88 import org.opendaylight.yangtools.yang.common.RpcResult;
89 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
94 public class ArpUtilImpl extends AbstractLifecycle implements OdlArputilService, PacketProcessingListener {
95 private static final Logger LOG = LoggerFactory.getLogger(ArpUtilImpl.class);
96 private final DataBroker dataBroker;
97 private final PacketProcessingService packetProcessingService;
98 private final NotificationPublishService notificationPublishService;
99 private final NotificationService notificationService;
100 private final OdlInterfaceRpcService odlInterfaceRpcService;
101 private ListenerRegistration<ArpUtilImpl> listenerRegistration;
102 private final ExecutorService threadPool = Executors.newFixedThreadPool(1);
103 private final ConcurrentMap<String, String> macsDB = new ConcurrentHashMap<>();
104 private final ConcurrentMap<String, SettableFuture<RpcResult<GetMacOutput>>> macAddrs = new ConcurrentHashMap<>();
107 public ArpUtilImpl(final DataBroker dataBroker, final PacketProcessingService packetProcessingService,
108 final NotificationPublishService notificationPublishService, final NotificationService notificationService,
109 final OdlInterfaceRpcService odlInterfaceRpcService) {
110 this.dataBroker = dataBroker;
111 this.packetProcessingService = packetProcessingService;
112 this.notificationPublishService = notificationPublishService;
113 this.notificationService = notificationService;
114 this.odlInterfaceRpcService = odlInterfaceRpcService;
118 public void start() {
119 LOG.info("{} start", getClass().getSimpleName());
120 listenerRegistration = notificationService.registerNotificationListener(this);
125 LOG.info("{} stop", getClass().getSimpleName());
127 if (listenerRegistration != null) {
128 listenerRegistration.close();
129 listenerRegistration = null;
133 private String getIpAddressInString(IpAddress ipAddress) throws UnknownHostException {
134 return InetAddress.getByName(ipAddress.getIpv4Address().getValue()).getHostAddress();
138 public Future<RpcResult<GetMacOutput>> getMac(GetMacInput input) {
140 final String dstIpAddress = getIpAddressInString(input.getIpaddress());
141 LOG.trace("getMac rpc invoked for ip {}", dstIpAddress);
142 if (macAddrs.get(dstIpAddress) != null) {
143 if (LOG.isInfoEnabled()) {
144 LOG.info("get mac already in progress for the ip {}", dstIpAddress);
146 return macAddrs.get(dstIpAddress);
148 SendArpRequestInputBuilder builder = new SendArpRequestInputBuilder()
149 .setInterfaceAddress(input.getInterfaceAddress()).setIpaddress(input.getIpaddress());
150 Future<RpcResult<Void>> arpReqFt = sendArpRequest(builder.build());
151 final SettableFuture<RpcResult<GetMacOutput>> ft = SettableFuture.create();
153 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(arpReqFt, threadPool),
154 new FutureCallback<RpcResult<Void>>() {
156 public void onFailure(Throwable ex) {
157 RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder.<GetMacOutput>failed()
158 .withError(ErrorType.APPLICATION, ex.getMessage(), ex);
159 ft.set(resultBuilder.build());
163 public void onSuccess(RpcResult<Void> result) {
164 LOG.trace("Successfully sent the arp pkt out for ip {}", dstIpAddress);
166 }, MoreExecutors.directExecutor());
168 macAddrs.put(dstIpAddress, ft);
170 } catch (UnknownHostException e) {
171 LOG.error("Failed to handle getMac request for {}", input.getIpaddress(), e);
172 RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder.<GetMacOutput>failed()
173 .withError(ErrorType.APPLICATION, e.getMessage(), e);
174 return Futures.immediateFuture(resultBuilder.build());
178 private byte[] getIpAddressBytes(IpAddress ip) throws UnknownHostException {
179 return InetAddress.getByName(ip.getIpv4Address().getValue()).getAddress();
183 public Future<RpcResult<Void>> sendArpRequest(SendArpRequestInput arpReqInput) {
184 LOG.trace("rpc sendArpRequest invoked for ip {}", arpReqInput.getIpaddress());
187 String interfaceName = null;
192 RpcResultBuilder<Void> failureBuilder = RpcResultBuilder.failed();
193 RpcResultBuilder<Void> successBuilder = RpcResultBuilder.success();
196 dstIpBytes = getIpAddressBytes(arpReqInput.getIpaddress());
197 } catch (UnknownHostException e) {
198 LOG.error("Cannot get IP address", e);
199 failureBuilder.withError(ErrorType.APPLICATION, ArpConstants.UNKNOWN_IP_ADDRESS_SUPPLIED);
200 return Futures.immediateFuture(failureBuilder.build());
203 int localErrorCount = 0;
204 for (InterfaceAddress interfaceAddress : arpReqInput.getInterfaceAddress()) {
206 interfaceName = interfaceAddress.getInterface();
207 srcIpBytes = getIpAddressBytes(interfaceAddress.getIpAddress());
209 GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
210 checkNotNull(portResult);
211 dpnId = portResult.getDpid();
212 Long portid = portResult.getPortno();
213 checkArgument(null != dpnId && !BigInteger.ZERO.equals(dpnId),
214 ArpConstants.DPN_NOT_FOUND_ERROR, interfaceName);
216 NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId, portid.toString());
217 checkNotNull(ref, ArpConstants.NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
219 LOG.trace("sendArpRequest received dpnId {} out interface {}", dpnId, interfaceName);
220 if (interfaceAddress.getMacaddress() == null) {
221 srcMac = MDSALUtil.getMacAddressForNodeConnector(dataBroker,
222 (InstanceIdentifier<NodeConnector>) ref.getValue());
224 String macAddr = interfaceAddress.getMacaddress().getValue();
225 srcMac = HexEncode.bytesFromHexString(macAddr);
227 checkNotNull(srcMac, ArpConstants.FAILED_TO_GET_SRC_MAC_FOR_INTERFACE, interfaceName, ref.getValue());
228 checkNotNull(srcIpBytes, ArpConstants.FAILED_TO_GET_SRC_IP_FOR_INTERFACE, interfaceName);
230 payload = ArpPacketUtil.getPayload(ArpConstants.ARP_REQUEST_OP, srcMac, srcIpBytes,
231 ArpPacketUtil.ETHERNET_BROADCAST_DESTINATION, dstIpBytes);
233 List<Action> actions = getEgressAction(interfaceName);
234 sendPacketOutWithActions(dpnId, payload, ref, actions);
236 LOG.trace("sent arp request for {}", arpReqInput.getIpaddress());
237 } catch (UnknownHostException | PacketException | InterruptedException | ExecutionException e) {
238 LOG.trace("failed to send arp req for {} on interface {}", arpReqInput.getIpaddress(), interfaceName);
240 failureBuilder.withError(ErrorType.APPLICATION,
241 ArpConstants.FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE + interfaceName, e);
242 successBuilder.withError(ErrorType.APPLICATION,
243 ArpConstants.FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE + interfaceName, e);
247 if (localErrorCount == arpReqInput.getInterfaceAddress().size()) {
248 // All the requests failed
249 return Futures.immediateFuture(failureBuilder.build());
251 return Futures.immediateFuture(successBuilder.build());
254 public Future<RpcResult<Void>> sendPacketOut(BigInteger dpnId, byte[] payload, NodeConnectorRef ref) {
255 NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId, "0xfffffffd");
256 return packetProcessingService.transmitPacket(new TransmitPacketInputBuilder().setPayload(payload)
257 .setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class)
258 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
259 .setIngress(nodeConnectorRef).setEgress(ref).build());
262 private Future<RpcResult<Void>> sendPacketOutWithActions(BigInteger dpnId, byte[] payload, NodeConnectorRef ref,
263 List<Action> actions) {
264 NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId, "0xfffffffd");
265 TransmitPacketInput transmitPacketInput = new TransmitPacketInputBuilder().setPayload(payload)
266 .setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class)
267 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
268 .setIngress(nodeConnectorRef).setEgress(ref).setAction(actions).build();
269 LOG.trace("PacketOut message framed for transmitting {}", transmitPacketInput);
270 return packetProcessingService.transmitPacket(transmitPacketInput);
273 private List<Action> getEgressAction(String interfaceName) {
274 List<Action> actions = new ArrayList<>();
276 GetEgressActionsForInterfaceInputBuilder egressAction = new GetEgressActionsForInterfaceInputBuilder()
277 .setIntfName(interfaceName);
278 OdlInterfaceRpcService intfRpc = odlInterfaceRpcService;
279 if (intfRpc == null) {
280 LOG.error("Unable to obtain interfaceMgrRpc service, ignoring egress actions for interfaceName {}",
284 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result = intfRpc
285 .getEgressActionsForInterface(egressAction.build());
286 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
287 if (!rpcResult.isSuccessful()) {
288 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", interfaceName,
289 rpcResult.getErrors());
291 actions = rpcResult.getResult().getAction();
293 } catch (InterruptedException | ExecutionException e) {
294 LOG.error("Exception when egress actions for interface {}", interfaceName, e);
300 public Future<RpcResult<Void>> sendArpResponse(SendArpResponseInput input) {
301 LOG.trace("sendArpResponse rpc invoked");
307 String interfaceName = input.getInterface();
308 GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
309 checkNotNull(portResult);
310 dpnId = portResult.getDpid();
311 Long portid = portResult.getPortno();
312 NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId, portid.toString());
313 checkArgument(null != dpnId && !BigInteger.ZERO.equals(dpnId),
314 ArpConstants.DPN_NOT_FOUND_ERROR, interfaceName);
315 checkNotNull(ref, ArpConstants.NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
317 LOG.trace("sendArpRequest received dpnId {} out interface {}", dpnId, interfaceName);
319 byte[] srcIpBytes = getIpAddressBytes(input.getSrcIpaddress());
320 byte[] dstIpBytes = getIpAddressBytes(input.getDstIpaddress());
321 if (input.getSrcMacaddress() == null) {
322 srcMac = portResult.getPhyAddress().getBytes("UTF-8");
324 String macAddr = input.getSrcMacaddress().getValue();
325 srcMac = HexEncode.bytesFromHexString(macAddr);
327 byte[] dstMac = NWUtil.parseMacAddress(input.getDstMacaddress().getValue());
328 checkNotNull(srcIpBytes, ArpConstants.FAILED_TO_GET_SRC_IP_FOR_INTERFACE, interfaceName);
329 payload = ArpPacketUtil.getPayload(ArpConstants.ARP_RESPONSE_OP, srcMac, srcIpBytes, dstMac, dstIpBytes);
331 List<Action> actions = getEgressAction(interfaceName);
332 sendPacketOutWithActions(dpnId, payload, ref, actions);
333 LOG.debug("Sent ARP response for IP {}, from source MAC {} to target MAC {} and target IP {} via dpnId {}",
334 input.getSrcIpaddress().getIpv4Address().getValue(), HexEncode.bytesToHexStringFormat(srcMac),
335 HexEncode.bytesToHexStringFormat(dstMac), input.getDstIpaddress().getIpv4Address().getValue(),
337 } catch (UnknownHostException | PacketException | InterruptedException | UnsupportedEncodingException
338 | ExecutionException e) {
339 LOG.error("failed to send arp response for {}: ", input.getSrcIpaddress(), e);
340 return RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, e.getMessage(), e).buildFuture();
342 RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
343 return Futures.immediateFuture(rpcResultBuilder.build());
347 public void onPacketReceived(PacketReceived packetReceived) {
348 Class<? extends PacketInReason> pktInReason = packetReceived.getPacketInReason();
349 LOG.trace("Packet Received {}", packetReceived);
351 if (pktInReason == SendToController.class) {
353 int tableId = packetReceived.getTableId().getValue();
355 byte[] data = packetReceived.getPayload();
356 Ethernet ethernet = new Ethernet();
358 ethernet.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
359 if (ethernet.getEtherType() != ArpConstants.ETH_TYPE_ARP) {
363 Packet pkt = ethernet.getPayload();
365 InetAddress srcInetAddr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
366 InetAddress dstInetAddr = InetAddress.getByAddress(arp.getTargetProtocolAddress());
367 byte[] srcMac = ethernet.getSourceMACAddress();
368 byte[] dstMac = ethernet.getDestinationMACAddress();
370 Metadata metadata = packetReceived.getMatch().getMetadata();
372 String interfaceName = getInterfaceName(metadata);
374 checkAndFireMacChangedNotification(interfaceName, srcInetAddr, srcMac);
375 macsDB.put(interfaceName + "-" + srcInetAddr.getHostAddress(), NWUtil.toStringMacAddress(srcMac));
376 if (arp.getOpCode() == ArpConstants.ARP_REQUEST_OP) {
377 fireArpReqRecvdNotification(interfaceName, srcInetAddr, srcMac, dstInetAddr, tableId,
378 metadata.getMetadata());
380 fireArpRespRecvdNotification(interfaceName, srcInetAddr, srcMac, tableId, metadata.getMetadata(),
381 dstInetAddr, dstMac);
383 if (macAddrs.get(srcInetAddr.getHostAddress()) != null) {
384 threadPool.execute(new MacResponderTask(arp));
386 } catch (PacketException | UnknownHostException | InterruptedException | ExecutionException e) {
387 LOG.trace("Failed to decode packet", e);
392 private GetPortFromInterfaceOutput getPortFromInterface(String interfaceName)
393 throws InterruptedException, ExecutionException {
394 GetPortFromInterfaceInputBuilder getPortFromInterfaceInputBuilder = new GetPortFromInterfaceInputBuilder();
395 getPortFromInterfaceInputBuilder.setIntfName(interfaceName);
397 Future<RpcResult<GetPortFromInterfaceOutput>> portFromInterface = odlInterfaceRpcService
398 .getPortFromInterface(getPortFromInterfaceInputBuilder.build());
399 GetPortFromInterfaceOutput result = portFromInterface.get().getResult();
400 LOG.trace("getPortFromInterface rpc result is {} ", result);
401 if (result != null) {
402 LOG.trace("getPortFromInterface rpc result is {} {} ", result.getDpid(), result.getPortno());
407 private String getInterfaceName(Metadata metadata)
408 throws InterruptedException, ExecutionException {
409 LOG.debug("metadata received is {} ", metadata);
411 GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
412 BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata.getMetadata());
414 ifIndexInputBuilder.setIfIndex(lportTag.intValue());
415 GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build();
417 Future<RpcResult<GetInterfaceFromIfIndexOutput>> interfaceFromIfIndex = odlInterfaceRpcService
418 .getInterfaceFromIfIndex(input);
419 GetInterfaceFromIfIndexOutput interfaceFromIfIndexOutput = interfaceFromIfIndex.get().getResult();
420 return interfaceFromIfIndexOutput.getInterfaceName();
423 private class MacResponderTask implements Runnable {
426 MacResponderTask(ARP arp) {
433 GetMacOutputBuilder outputBuilder;
436 srcAddr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
437 srcMac = NWUtil.toStringMacAddress(arp.getSenderHardwareAddress());
438 SettableFuture<RpcResult<GetMacOutput>> future = macAddrs.remove(srcAddr.getHostAddress());
439 if (future == null) {
440 LOG.trace("There are no pending mac requests.");
443 outputBuilder = new GetMacOutputBuilder().setMacaddress(new PhysAddress(srcMac));
444 future.set(RpcResultBuilder.success(outputBuilder.build()).build());
445 if (LOG.isTraceEnabled()) {
446 LOG.trace("sent the mac response for ip {}", srcAddr.getHostAddress());
448 } catch (UnknownHostException e) {
449 LOG.error("failed to send mac response", e);
454 private void fireArpRespRecvdNotification(String interfaceName, InetAddress srcInetAddr, byte[] srcMacAddressBytes,
455 int tableId, BigInteger metadata, InetAddress dstInetAddr, byte[] dstMacAddressBytes)
456 throws InterruptedException {
457 ArpUtilCounters.arp_res_rcv.inc();
459 IpAddress srcIp = new IpAddress(srcInetAddr.getHostAddress().toCharArray());
460 IpAddress dstIp = new IpAddress(dstInetAddr.getHostAddress().toCharArray());
461 String srcMacAddress = NWUtil.toStringMacAddress(srcMacAddressBytes);
462 PhysAddress srcMac = new PhysAddress(srcMacAddress);
463 String dstMacAddress = NWUtil.toStringMacAddress(dstMacAddressBytes);
464 PhysAddress dstMac = new PhysAddress(dstMacAddress);
465 ArpResponseReceivedBuilder builder = new ArpResponseReceivedBuilder();
466 builder.setInterface(interfaceName);
467 builder.setSrcIpaddress(srcIp);
468 builder.setOfTableId((long) tableId);
469 builder.setSrcMac(srcMac);
470 builder.setMetadata(metadata);
471 builder.setDstIpaddress(dstIp);
472 builder.setDstMac(dstMac);
473 ListenableFuture<?> offerNotification = notificationPublishService.offerNotification(builder.build());
474 if (offerNotification != null && offerNotification.equals(NotificationPublishService.REJECTED)) {
475 ArpUtilCounters.arp_res_rcv_notification_rejected.inc();
477 ArpUtilCounters.arp_res_rcv_notification.inc();
481 private void fireArpReqRecvdNotification(String interfaceName, InetAddress srcInetAddr, byte[] srcMac,
482 InetAddress dstInetAddr, int tableId, BigInteger metadata) throws InterruptedException {
483 ArpUtilCounters.arp_req_rcv.inc();
484 String macAddress = NWUtil.toStringMacAddress(srcMac);
485 ArpRequestReceivedBuilder builder = new ArpRequestReceivedBuilder();
486 builder.setInterface(interfaceName);
487 builder.setOfTableId((long) tableId);
488 builder.setSrcIpaddress(new IpAddress(srcInetAddr.getHostAddress().toCharArray()));
489 builder.setDstIpaddress(new IpAddress(dstInetAddr.getHostAddress().toCharArray()));
490 builder.setSrcMac(new PhysAddress(macAddress));
491 builder.setMetadata(metadata);
492 ListenableFuture<?> offerNotification = notificationPublishService.offerNotification(builder.build());
493 if (offerNotification != null && offerNotification.equals(NotificationPublishService.REJECTED)) {
494 ArpUtilCounters.arp_req_rcv_notification_rejected.inc();
496 ArpUtilCounters.arp_req_rcv_notification.inc();
500 private void checkAndFireMacChangedNotification(String interfaceName, InetAddress inetAddr, byte[] macAddressBytes)
501 throws InterruptedException {
503 IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
504 String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
505 PhysAddress mac = new PhysAddress(macAddress);
507 if (!macAddress.equals(macsDB.get(interfaceName + "-" + inetAddr.getHostAddress()))) {
508 if (LOG.isTraceEnabled()) {
509 LOG.trace("mac address changed for {}", inetAddr);
511 MacChangedBuilder builder = new MacChangedBuilder();
512 builder.setInterface(interfaceName);
513 builder.setIpaddress(ip);
514 builder.setMacaddress(mac);
515 notificationPublishService.putNotification(builder.build());