From e70dce49fa1f1a7c3d38d38ee3a790807563ae05 Mon Sep 17 00:00:00 2001 From: suneel verma Date: Thu, 3 Dec 2015 15:35:07 +0530 Subject: [PATCH] added arputil module utility rpcs are added for sending arp request arp response and finding mac address of ip Change-Id: I08416fb2a4273bcb8c5e82f4ea6ffb6f4d6e47d8 Signed-off-by: suneel verma --- arputil/arputil-api/pom.xml | 56 ++ .../src/main/yang/odl-arputil.yang | 139 +++++ arputil/arputil-impl/pom.xml | 94 +++ .../src/main/config/default-config.xml | 47 ++ .../arputil/internal/ArpPacketUtil.java | 53 ++ .../arputil/internal/ArpUtilImpl.java | 538 ++++++++++++++++++ .../arputil/internal/ArpUtilProvider.java | 81 +++ .../impl/rev151126/ArputilImplModule.java | 30 + .../rev151126/ArputilImplModuleFactory.java | 13 + .../src/main/yang/arputil-impl.yang | 70 +++ arputil/pom.xml | 49 ++ commons/config-parent/pom.xml | 1 + features/pom.xml | 21 +- features/src/main/features/features.xml | 3 + mdsalutil/mdsalutil-api/pom.xml | 28 +- .../vpnservice/mdsalutil/MDSALUtil.java | 63 +- .../vpnservice/mdsalutil/NWUtil.java | 92 +++ .../vpnservice/mdsalutil/packet/ARP.java | 200 +++++++ .../vpnservice/mdsalutil/packet/Ethernet.java | 120 ++++ mdsalutil/mdsalutil-impl/pom.xml | 12 +- pom.xml | 1 + 21 files changed, 1691 insertions(+), 20 deletions(-) create mode 100644 arputil/arputil-api/pom.xml create mode 100644 arputil/arputil-api/src/main/yang/odl-arputil.yang create mode 100644 arputil/arputil-impl/pom.xml create mode 100644 arputil/arputil-impl/src/main/config/default-config.xml create mode 100644 arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpPacketUtil.java create mode 100644 arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilImpl.java create mode 100644 arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilProvider.java create mode 100644 arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModule.java create mode 100644 arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModuleFactory.java create mode 100644 arputil/arputil-impl/src/main/yang/arputil-impl.yang create mode 100644 arputil/pom.xml create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NWUtil.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/ARP.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java diff --git a/arputil/arputil-api/pom.xml b/arputil/arputil-api/pom.xml new file mode 100644 index 00000000..6c26ad34 --- /dev/null +++ b/arputil/arputil-api/pom.xml @@ -0,0 +1,56 @@ + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + 4.0.0 + org.opendaylight.vpnservice + arputil-api + ${vpnservices.version} + bundle + + + + org.opendaylight.openflowplugin.model + model-flow-base + ${openflowplugin.version} + + + org.opendaylight.openflowplugin.model + model-flow-service + ${openflowplugin.version} + + + org.opendaylight.mdsal + yang-binding + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.mdsal.model + yang-ext + + + org.opendaylight.mdsal.model + ietf-inet-types + + + org.opendaylight.mdsal.model + ietf-yang-types + + + org.opendaylight.mdsal.model + ietf-interfaces + + + org.opendaylight.mdsal.model + iana-if-type-2014-05-08 + + + diff --git a/arputil/arputil-api/src/main/yang/odl-arputil.yang b/arputil/arputil-api/src/main/yang/odl-arputil.yang new file mode 100644 index 00000000..3f176957 --- /dev/null +++ b/arputil/arputil-api/src/main/yang/odl-arputil.yang @@ -0,0 +1,139 @@ +module odl-arputil { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:arputil"; + prefix "odl-arputil"; + + import ietf-interfaces { + prefix if; + } + + import ietf-inet-types { + prefix inet; + } + + import ietf-yang-types { + prefix yang; + } + + import opendaylight-inventory { + prefix inv; revision-date 2013-08-19; + } + + import config { + prefix config; revision-date 2013-04-05; + } + + revision "2015-11-26" { + description "Arp Util module"; + } + + + grouping interfaces { + list interface-address { + key interface; + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + leaf ip-address { + type inet:ip-address; + } + } + } + + + rpc get-mac { + input { + leaf ipaddress { + type inet:ip-address; + } + uses interfaces; + } + output { + leaf macaddress { + type yang:phys-address; + } + } + } + + rpc send-arp-request { + input { + leaf ipaddress { + type inet:ip-address; + } + uses interfaces; + } + } + + rpc send-arp-response { + input { + leaf ipaddress { + type inet:ip-address; + } + leaf macaddress { + type yang:phys-address; + } + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + leaf src-ip-address { + type inet:ip-address; + } + } + } + + + notification mac-changed { + leaf ipaddress { + type inet:ip-address; + } + leaf macaddress { + type yang:phys-address; + } + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } + + notification arp-request-received { + leaf dst-ipaddress { + type inet:ip-address; + } + leaf src-ipaddress { + type inet:ip-address; + } + leaf src-mac { + type yang:phys-address; + } + leaf of-table-id { + type uint32; + } + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } + + notification arp-response-received { + leaf ipaddress { + type inet:ip-address; + } + leaf macaddress { + type yang:phys-address; + } + leaf of-table-id { + type uint32; + } + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } +} \ No newline at end of file diff --git a/arputil/arputil-impl/pom.xml b/arputil/arputil-impl/pom.xml new file mode 100644 index 00000000..b5de1cc6 --- /dev/null +++ b/arputil/arputil-impl/pom.xml @@ -0,0 +1,94 @@ + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + 4.0.0 + org.opendaylight.vpnservice + arputil-impl + ${vpnservices.version} + bundle + + + + + ${project.groupId} + interfacemgr-api + ${project.version} + + + org.opendaylight.controller + sal-binding-api + + + org.opendaylight.mdsal + yang-binding + + + org.opendaylight.yangtools + yang-common + + + ${project.groupId} + mdsalutil-api + ${vpnservices.version} + + + org.opendaylight.mdsal.model + yang-ext + + + org.opendaylight.controller + liblldp + ${liblldp.version} + + + org.opendaylight.mdsal.model + ietf-inet-types + + + ${project.groupId} + arputil-api + ${project.version} + + + org.opendaylight.mdsal.model + ietf-yang-types + + + org.opendaylight.mdsal.model + ietf-interfaces + + + org.opendaylight.mdsal.model + iana-if-type-2014-05-08 + + + org.opendaylight.openflowplugin.model + model-flow-base + ${openflowplugin.version} + + + org.opendaylight.openflowplugin.model + model-flow-service + ${openflowplugin.version} + + + org.opendaylight.controller + sal-binding-broker-impl + test + + + org.opendaylight.controller + sal-binding-broker-impl + ${mdsal.version} + test + test-jar + + + + diff --git a/arputil/arputil-impl/src/main/config/default-config.xml b/arputil/arputil-impl/src/main/config/default-config.xml new file mode 100644 index 00000000..dcd772c5 --- /dev/null +++ b/arputil/arputil-impl/src/main/config/default-config.xml @@ -0,0 +1,47 @@ + + + + + urn:opendaylight:params:xml:ns:yang:arputil:impl?module=arputil-impl&revision=2015-11-26 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10 + + + + + + + prefix:arputil-impl + arputil-default + + binding:binding-broker-osgi-registry + binding-osgi-broker + + + binding:binding-rpc-registry + binding-rpc-broker + + + mdsalutil:odl-mdsalutil + mdsalutil-service + + + bindingimpl:binding-new-notification-publish-service + binding-notification-publish-adapter + + + bindingimpl:binding-new-notification-service + binding-notification-adapter + + + + + + diff --git a/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpPacketUtil.java b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpPacketUtil.java new file mode 100644 index 00000000..46af8e80 --- /dev/null +++ b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpPacketUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.arputil.internal; + +import org.opendaylight.controller.liblldp.EtherTypes; +import org.opendaylight.controller.liblldp.PacketException; +import org.opendaylight.vpnservice.mdsalutil.packet.ARP; +import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet; + +public class ArpPacketUtil { + + public static byte[] EthernetDestination_Broadcast = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }; + public static byte[] MAC_Broadcast = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }; + + public static byte[] getPayload(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress, + byte[] targetIP) throws PacketException { + ARP arp = createARPPacket(opCode, senderMacAddress, senderIP, targetMacAddress, targetIP); + Ethernet ethernet = createEthernetPacket(senderMacAddress, targetMacAddress, arp); + return ethernet.serialize(); + } + + public static ARP createARPPacket(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress, + byte[] targetIP) { + ARP arp = new ARP(); + arp.setHardwareType(ARP.HW_TYPE_ETHERNET); + arp.setProtocolType(EtherTypes.IPv4.shortValue()); + arp.setHardwareAddressLength((byte) 6); + arp.setProtocolAddressLength((byte) 4); + arp.setOpCode(opCode); + arp.setSenderHardwareAddress(senderMacAddress); + arp.setSenderProtocolAddress(senderIP); + arp.setTargetHardwareAddress(targetMacAddress); + arp.setTargetProtocolAddress(targetIP); + return arp; + } + + public static Ethernet createEthernetPacket(byte[] sourceMAC, byte[] targetMAC, ARP arp) + throws PacketException { + Ethernet ethernet = new Ethernet(); + ethernet.setSourceMACAddress(sourceMAC); + ethernet.setDestinationMACAddress(targetMAC); + ethernet.setEtherType(EtherTypes.ARP.shortValue()); + ethernet.setPayload(arp); + return ethernet; + } +} \ No newline at end of file diff --git a/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilImpl.java b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilImpl.java new file mode 100644 index 00000000..45f6824e --- /dev/null +++ b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilImpl.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.arputil.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.opendaylight.controller.liblldp.NetUtils; +import org.opendaylight.controller.liblldp.Packet; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; +import org.opendaylight.controller.md.sal.binding.api.NotificationService; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.NWUtil; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.vpnservice.mdsalutil.packet.ARP; +import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceivedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceivedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChangedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.interfaces.InterfaceAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; +import com.google.common.util.concurrent.SettableFuture; + +public class ArpUtilImpl implements OdlArputilService, + PacketProcessingListener, AutoCloseable { + + private static final String FAILED_TO_GET_SRC_IP_FOR_INTERFACE = "Failed to get src ip for %s"; + + private static final String FAILED_TO_GET_SRC_MAC_FOR_INTERFACE = "Failed to get src mac for interface %s iid %s "; + + private static final String FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE = "failed to send arp req for interface "; + + private static final String UNKNOWN_IP_ADDRESS_SUPPLIED = "unknown ip address supplied"; + + private static final String NODE_CONNECTOR_NOT_FOUND_ERROR = "Node connector id not found for interface %s"; + + private static final String DPN_NOT_FOUND_ERROR = "dpn not found for interface %s "; + + private static final short ARP_REQUEST_OP = (short) 1; + + private static final short ARP_RESPONSE_OP = (short) 2; + + private static final Logger LOGGER = LoggerFactory + .getLogger(ArpUtilImpl.class); + + ExecutorService threadPool = Executors.newFixedThreadPool(1); + + DataBroker dataBroker; + PacketProcessingService packetProcessingService; + NotificationPublishService notificationPublishService; + NotificationService notificationService; + IMdsalApiManager mdsalMgr; + + ListenerRegistration listenerRegistration; + + ConcurrentMap macsDB = new ConcurrentHashMap<>(); + ConcurrentMap>> getMacFutures = new ConcurrentHashMap<>(); + + public ArpUtilImpl(DataBroker db, + PacketProcessingService packetProcessingService, + NotificationPublishService notificationPublishService, + NotificationService notificationService, + IMdsalApiManager mdsalApiManager) { + + this.dataBroker = db; + this.packetProcessingService = packetProcessingService; + this.notificationPublishService = notificationPublishService; + this.mdsalMgr = mdsalApiManager; + this.notificationService = notificationService; + + listenerRegistration = notificationService + .registerNotificationListener(this); + LOGGER.info("ArpUtil Manager Initialized "); + } + + @Override + public void close() throws Exception { + listenerRegistration.close(); + LOGGER.trace("ArpUtil manager Closed"); + } + + String getIpAddressInString(IpAddress ipAddress) + throws UnknownHostException { + return InetAddress.getByName(ipAddress.getIpv4Address().getValue()) + .getHostAddress(); + } + + public Future> getMac(GetMacInput input) { + + try { + final String dstIpAddress = getIpAddressInString(input + .getIpaddress()); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("getMac rpc invoked for ip " + dstIpAddress); + } + if (getMacFutures.get(dstIpAddress) != null) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("get mac already in progress for the ip " + + dstIpAddress); + } + return getMacFutures.get(dstIpAddress); + } + SendArpRequestInputBuilder builder = new SendArpRequestInputBuilder() + .setInterfaceAddress(input.getInterfaceAddress()) + .setIpaddress(input.getIpaddress()); + Future> arpReqFt = sendArpRequest(builder.build()); + final SettableFuture> ft = SettableFuture + .create(); + + Futures.addCallback( + JdkFutureAdapters.listenInPoolThread(arpReqFt, threadPool), + new FutureCallback>() { + @Override + public void onFailure(Throwable e) { + RpcResultBuilder resultBuilder = RpcResultBuilder + . failed().withError( + ErrorType.APPLICATION, + e.getMessage(), e); + ft.set(resultBuilder.build()); + } + + @Override + public void onSuccess(RpcResult result) { + LOGGER.trace("Successfully sent the arp pkt out for ip " + + dstIpAddress); + } + }); + + getMacFutures.put(dstIpAddress, ft); + return ft; + } catch (Exception e) { + LOGGER.trace("failed to handle getMac request for {} {}", + input.getIpaddress(), e); + RpcResultBuilder resultBuilder = RpcResultBuilder + . failed().withError(ErrorType.APPLICATION, + e.getMessage(), e); + return Futures.immediateFuture(resultBuilder.build()); + } + } + + byte[] getIpAddressBytes(IpAddress ip) throws UnknownHostException { + return InetAddress.getByName(ip.getIpv4Address().getValue()) + .getAddress(); + } + + @Override + public Future> sendArpRequest( + SendArpRequestInput arpReqInput) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("rpc sendArpRequest invoked for ip " + + arpReqInput.getIpaddress()); + } + BigInteger dpnId; + long groupId; + byte payload[]; + String interfaceName = null; + byte srcIpBytes[]; + byte[] dstIpBytes = null; + + RpcResultBuilder failureBuilder = RpcResultBuilder + . failed(); + RpcResultBuilder successBuilder = RpcResultBuilder + . success(); + + try { + dstIpBytes = getIpAddressBytes(arpReqInput.getIpaddress()); + } catch (Exception e) { + failureBuilder.withError(ErrorType.APPLICATION, + UNKNOWN_IP_ADDRESS_SUPPLIED); + return Futures.immediateFuture(failureBuilder.build()); + } + + int localErrorCount = 0; + for (InterfaceAddress interfaceAddress : arpReqInput + .getInterfaceAddress()) { + try { + interfaceName = interfaceAddress.getInterface(); + srcIpBytes = getIpAddressBytes(interfaceAddress.getIpAddress()); + + NodeConnectorId id = getNodeConnectorFromDataStore(interfaceName); + + dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(id)); + Long portid = MDSALUtil.getOfPortNumberFromPortName(id); + checkArgument(null != dpnId && BigInteger.ZERO != dpnId, + DPN_NOT_FOUND_ERROR, interfaceName); + + NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId, + portid.toString()); + checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace( + "sendArpRequest received dpnId {} out interface {}", + dpnId, interfaceName); + } + byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector( + dataBroker, + (InstanceIdentifier) ref.getValue()); + checkNotNull(srcMac, FAILED_TO_GET_SRC_MAC_FOR_INTERFACE, + interfaceName, ref.getValue()); + checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE, + interfaceName); + + payload = ArpPacketUtil.getPayload(ARP_REQUEST_OP, srcMac, + srcIpBytes, ArpPacketUtil.EthernetDestination_Broadcast, + dstIpBytes); + + sendPacketOut(dpnId, payload, ref); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("sent arp request for " + + arpReqInput.getIpaddress()); + } + } catch (Exception e) { + LOGGER.trace("failed to send arp req for {} on interface {}", + arpReqInput.getIpaddress(), interfaceName); + + failureBuilder + .withError(ErrorType.APPLICATION, + FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE + + interfaceName, e); + successBuilder + .withError(ErrorType.APPLICATION, + FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE + + interfaceName, e); + localErrorCount++; + } + } + if (localErrorCount == arpReqInput.getInterfaceAddress().size()) { + // All the requests failed + return Futures.immediateFuture(failureBuilder.build()); + } + return Futures.immediateFuture(successBuilder.build()); + } + + public Future> sendPacketOut(BigInteger dpnId, + byte[] payload, NodeConnectorRef ref) { + + NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId, + "0xfffffffd"); + return packetProcessingService + .transmitPacket(new TransmitPacketInputBuilder() + .setPayload(payload) + .setNode( + new NodeRef(InstanceIdentifier + .builder(Nodes.class) + .child(Node.class, + new NodeKey(new NodeId( + "openflow:" + dpnId))) + .toInstance())) + .setIngress(nodeConnectorRef).setEgress(ref).build()); + } + + @Override + public Future> sendArpResponse(SendArpResponseInput input) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("sendArpResponse rpc invoked"); + } + BigInteger dpnId; + long groupId; + byte payload[]; + + try { + String interfaceName = input.getInterface(); + NodeConnectorId id = getNodeConnectorFromDataStore(interfaceName); + + dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(id)); + Long portid = MDSALUtil.getOfPortNumberFromPortName(id); + + NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId, + portid.toString()); + checkArgument(null != dpnId && BigInteger.ZERO != dpnId, + DPN_NOT_FOUND_ERROR, interfaceName); + checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace( + "sendArpRequest received dpnId {} out interface {}", + dpnId, interfaceName); + } + + byte[] srcIpBytes = getIpAddressBytes(input.getSrcIpAddress()); + byte[] dstIpBytes = getIpAddressBytes(input.getIpaddress()); + byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(dataBroker, + (InstanceIdentifier) ref.getValue()); + byte[] dstMac = NWUtil.parseMacAddress(input.getMacaddress() + .getValue()); + checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE, + interfaceName); + payload = ArpPacketUtil.getPayload(ARP_RESPONSE_OP, srcMac, srcIpBytes, + dstMac, dstIpBytes); + + sendPacketOut(dpnId, payload, ref); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("sent the arp response for " + + input.getSrcIpAddress()); + } + } catch (Exception e) { + LOGGER.trace("failed to send arp response for {} {}", + input.getSrcIpAddress(), e); + return RpcResultBuilder. failed() + .withError(ErrorType.APPLICATION, e.getMessage(), e) + .buildFuture(); + } + RpcResultBuilder rpcResultBuilder = RpcResultBuilder.success(); + return Futures.immediateFuture(rpcResultBuilder.build()); + } + + @Override + public void onPacketReceived(PacketReceived packetReceived) { + Class pktInReason = packetReceived + .getPacketInReason(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Packet Received {}", packetReceived); + } + + if (pktInReason == SendToController.class) { + + try { + int tableId = packetReceived.getTableId().getValue(); + + byte[] data = packetReceived.getPayload(); + Ethernet ethernet = new Ethernet(); + + ethernet.deserialize(data, 0, data.length + * NetUtils.NumBitsInAByte); + if (ethernet.getEtherType() != ARP_REQUEST_OP + && ethernet.getEtherType() != ARP_REQUEST_OP) { + return; + } + + Packet pkt = ethernet.getPayload(); + ARP arp = (ARP) pkt; + InetAddress srcInetAddr = InetAddress.getByAddress(arp + .getSenderProtocolAddress()); + InetAddress dstInetAddr = InetAddress.getByAddress(arp + .getTargetProtocolAddress()); + byte[] srcMac = ethernet.getSourceMACAddress(); + + NodeConnectorRef ref = packetReceived.getIngress(); + + String interfaceName = MDSALUtil.getInterfaceName(ref, dataBroker); + + checkAndFireMacChangedNotification(interfaceName, srcInetAddr, + srcMac); + + macsDB.put(interfaceName + "-" + srcInetAddr.getHostAddress(), + NWUtil.toStringMacAddress(srcMac)); + + if (arp.getOpCode() == ARP_REQUEST_OP) { + fireArpReqRecvdNotification(interfaceName, srcInetAddr, + srcMac, dstInetAddr, tableId); + } else { + fireArpRespRecvdNotification(interfaceName, srcInetAddr, + srcMac, tableId); + } + if (getMacFutures.get(srcInetAddr.getHostAddress()) != null) { + threadPool.submit(new MacResponderTask(arp)); + } + + } catch (Exception e) { + LOGGER.trace("Failed to decode packet: {}", e); + } + } + } + + class MacResponderTask implements Runnable { + ARP arp; + + MacResponderTask(ARP arp) { + this.arp = arp; + } + + @Override + public void run() { + InetAddress srcAddr; + GetMacOutputBuilder outputBuilder; + String srcMac; + SettableFuture> future = null; + RpcResultBuilder resultBuilder; + try { + srcAddr = InetAddress.getByAddress(arp + .getSenderProtocolAddress()); + srcMac = NWUtil.toStringMacAddress(arp + .getSenderHardwareAddress()); + future = getMacFutures.remove(srcAddr.getHostAddress()); + if (future == null) { + LOGGER.trace("There are no pending mac requests."); + return; + } + outputBuilder = new GetMacOutputBuilder() + .setMacaddress(new PhysAddress(srcMac)); + resultBuilder = RpcResultBuilder.success(outputBuilder.build()); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("sent the mac response for ip {}", + srcAddr.getHostAddress()); + } + } catch (Exception e) { + LOGGER.trace("failed to send mac response {} ", e); + resultBuilder = RpcResultBuilder. failed() + .withError(ErrorType.APPLICATION, e.getMessage(), e); + } + future.set(resultBuilder.build()); + } + } + + private void fireArpRespRecvdNotification(String interfaceName, + InetAddress inetAddr, byte[] macAddressBytes, int tableId) + throws InterruptedException { + + IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray()); + String macAddress = NWUtil.toStringMacAddress(macAddressBytes); + PhysAddress mac = new PhysAddress(macAddress); + ArpResponseReceivedBuilder builder = new ArpResponseReceivedBuilder(); + builder.setInterface(interfaceName); + builder.setIpaddress(ip); + builder.setOfTableId((long) tableId); + builder.setMacaddress(mac); + notificationPublishService.putNotification(builder.build()); + } + + private void fireArpReqRecvdNotification(String interfaceName, + InetAddress srcInetAddr, byte[] srcMac, InetAddress dstInetAddr, + int tableId) throws InterruptedException { + String macAddress = NWUtil.toStringMacAddress(srcMac); + ArpRequestReceivedBuilder builder = new ArpRequestReceivedBuilder(); + builder.setInterface(interfaceName); + builder.setOfTableId((long) tableId); + builder.setSrcIpaddress(new IpAddress(srcInetAddr.getHostAddress() + .toCharArray())); + builder.setDstIpaddress(new IpAddress(dstInetAddr.getHostAddress() + .toCharArray())); + builder.setSrcMac(new PhysAddress(macAddress)); + notificationPublishService.putNotification(builder.build()); + } + + private void checkAndFireMacChangedNotification(String interfaceName, + InetAddress inetAddr, byte[] macAddressBytes) + throws InterruptedException { + + IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray()); + String macAddress = NWUtil.toStringMacAddress(macAddressBytes); + PhysAddress mac = new PhysAddress(macAddress); + + if (!macAddress.equals(macsDB.get(interfaceName + "-" + + inetAddr.getHostAddress()))) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("mac address changed for " + inetAddr); + } + MacChangedBuilder builder = new MacChangedBuilder(); + builder.setInterface(interfaceName); + builder.setIpaddress(ip); + builder.setMacaddress(mac); + notificationPublishService.putNotification(builder.build()); + } + } + + private InstanceIdentifier buildInterfaceId(String interfaceName) { + InstanceIdentifierBuilder idBuilder = InstanceIdentifier + .builder(Interfaces.class).child(Interface.class, + new InterfaceKey(interfaceName)); + InstanceIdentifier id = idBuilder.build(); + return id; + } + + + private NodeConnectorId getNodeConnectorFromDataStore(String interfaceName) { + InstanceIdentifier id = buildInterfaceId(interfaceName); + Optional interf = MDSALUtil.read(dataBroker, + LogicalDatastoreType.CONFIGURATION, + id); + if (interf.isPresent()) { + return interf.get().getAugmentation(BaseIds.class).getOfPortId(); + } + return null; + } + +} diff --git a/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilProvider.java b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilProvider.java new file mode 100644 index 00000000..d22f6996 --- /dev/null +++ b/arputil/arputil-impl/src/main/java/org/opendaylight/vpnservice/arputil/internal/ArpUtilProvider.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.arputil.internal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; +import org.opendaylight.controller.md.sal.binding.api.NotificationService; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ArpUtilProvider implements BindingAwareProvider, AutoCloseable { + + private static final Logger s_logger = LoggerFactory.getLogger(ArpUtilProvider.class); + + RpcProviderRegistry rpcProviderRegistry; + + NotificationService notificationService; + + NotificationPublishService notificationPublishService; + + ArpUtilImpl arpManager; + + IMdsalApiManager mdsalApiManager; + + BindingAwareBroker.RpcRegistration rpcRegistration; + + public ArpUtilProvider(RpcProviderRegistry rpcRegistry, + NotificationPublishService publishService, + NotificationService notificationService, + IMdsalApiManager iMdsalApiManager) { + + this.rpcProviderRegistry = rpcRegistry; + this.mdsalApiManager = iMdsalApiManager; + this.notificationPublishService = publishService; + this.notificationService = notificationService; + } + + public ArpUtilProvider() { + } + + @Override + public void onSessionInitiated(final ProviderContext session){ + + s_logger.info( " Session Initiated for Arp Provider") ; + + try { + DataBroker dataBroker = session.getSALService(DataBroker.class); + PacketProcessingService packetProcessingService = + session.getRpcService(PacketProcessingService.class); + + arpManager = new ArpUtilImpl( dataBroker, packetProcessingService, + notificationPublishService, notificationService, + mdsalApiManager) ; + + rpcRegistration = rpcProviderRegistry. + addRpcImplementation(OdlArputilService.class, arpManager); + s_logger.info( " Session Initialized for Arp Provider") ; + }catch( Exception e) { + s_logger.error( "Error initializing Arp " , e ); + } + } + + @Override + public void close() throws Exception { + rpcRegistration.close(); + arpManager.close(); + s_logger.info("ArpManager Manager Closed"); + } +} diff --git a/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModule.java b/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModule.java new file mode 100644 index 00000000..83f95792 --- /dev/null +++ b/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModule.java @@ -0,0 +1,30 @@ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126; + +import org.opendaylight.vpnservice.arputil.internal.ArpUtilProvider; + +public class ArputilImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126.AbstractArputilImplModule { + public ArputilImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public ArputilImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126.ArputilImplModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + ArpUtilProvider provider = new ArpUtilProvider(getRpcRegistryDependency(), + getNotificationPublishServiceDependency(), + getNotificationServiceDependency(), + getMdsalutilDependency() + ); + getBrokerDependency().registerProvider(provider); + return provider; + } + +} diff --git a/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModuleFactory.java b/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModuleFactory.java new file mode 100644 index 00000000..af7a5753 --- /dev/null +++ b/arputil/arputil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/arputil/impl/rev151126/ArputilImplModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: arputil-impl yang module local name: arputil-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Mon Dec 07 21:19:46 IST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126; +public class ArputilImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126.AbstractArputilImplModuleFactory { + +} diff --git a/arputil/arputil-impl/src/main/yang/arputil-impl.yang b/arputil/arputil-impl/src/main/yang/arputil-impl.yang new file mode 100644 index 00000000..2107ff3a --- /dev/null +++ b/arputil/arputil-impl/src/main/yang/arputil-impl.yang @@ -0,0 +1,70 @@ +module arputil-impl { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:arputil:impl"; + prefix "arputil-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;} + import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;} + import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;} + import ietf-inet-types { prefix inet; } + import ietf-yang-types { prefix yang;} + + description + "Service definition for mdsal project"; + + revision "2015-11-26" { + description + "Initial revision"; + } + + identity arputil-impl { + base config:module-type; + } + + augment "/config:modules/config:module/config:configuration" { + case arputil-impl { + when "/config:modules/config:module/config:type = 'arputil-impl'"; + container broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-broker-osgi-registry; + } + } + } + container rpc-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-rpc-registry; + } + } + } + container mdsalutil { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity odl-mdsal:odl-mdsalutil; + } + } + } + container notification-publish-service { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding-impl:binding-new-notification-publish-service; + } + } + } + container notification-service { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding-impl:binding-new-notification-service; + } + } + } + } + } +} diff --git a/arputil/pom.xml b/arputil/pom.xml new file mode 100644 index 00000000..a65eb708 --- /dev/null +++ b/arputil/pom.xml @@ -0,0 +1,49 @@ + + + + + + org.opendaylight.odlparent + odlparent + 1.6.0-SNAPSHOT + + + + org.opendaylight.vpnservice + arputil-aggregator + 0.2.0-SNAPSHOT + arputil + pom + 4.0.0 + + 3.1.1 + + + arputil-api + arputil-impl + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-install-plugin + + true + + + + + diff --git a/commons/config-parent/pom.xml b/commons/config-parent/pom.xml index 0a47ecfa..60c9534b 100644 --- a/commons/config-parent/pom.xml +++ b/commons/config-parent/pom.xml @@ -30,6 +30,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 2013.07.15.8-SNAPSHOT 0.2.0-SNAPSHOT 1.2.1-SNAPSHOT + 0.10.0-SNAPSHOT diff --git a/features/pom.xml b/features/pom.xml index 72b6f763..4fae2518 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -28,6 +28,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL 0.8.0-SNAPSHOT 0.2.0-SNAPSHOT 1.2.1-SNAPSHOT + ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} @@ -116,11 +117,29 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL ${vpnmanager.version} config xml - + + ${project.groupId} mdsalutil-impl ${mdsalutil.version} + + ${project.groupId} + arputil-api + ${arputil.version} + + + ${project.groupId} + arputil-impl + ${arputil.version} + config + xml + + + ${project.groupId} + arputil-impl + ${arputil.version} + ${project.groupId} mdsalutil-impl diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index 270db04d..c7167833 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -23,6 +23,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}} mvn:org.opendaylight.vpnservice/lockmanager-api/${lockmanager.version} mvn:org.opendaylight.vpnservice/idmanager-api/${idmanager.version} + mvn:org.opendaylight.vpnservice/arputil-api/${arputil.version} mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version} mvn:org.opendaylight.vpnservice/nexthopmgr-api/${nexthopmgr.version} mvn:org.opendaylight.vpnservice/fibmanager-api/${fibmanager.version} @@ -39,6 +40,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/bgpmanager-api/${vpnservices.version} mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version} mvn:org.opendaylight.vpnservice/mdsalutil-api/${interfacemgr.version} + mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version} mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version} mvn:org.opendaylight.vpnservice/interfacemgr-api/${interfacemgr.version} mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version} @@ -55,6 +57,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}/xml/config mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version}/xml/config mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version}/xml/config + mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version}/xml/config mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}/xml/config mvn:org.opendaylight.vpnservice/nexthopmgr-impl/${nexthopmgr.version}/xml/config mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}/xml/config diff --git a/mdsalutil/mdsalutil-api/pom.xml b/mdsalutil/mdsalutil-api/pom.xml index 61410f8c..424319fa 100644 --- a/mdsalutil/mdsalutil-api/pom.xml +++ b/mdsalutil/mdsalutil-api/pom.xml @@ -1,14 +1,14 @@ - + org.opendaylight.vpnservice config-parent 0.2.0-SNAPSHOT ../../commons/config-parent - + 4.0.0 org.opendaylight.vpnservice mdsalutil-api @@ -16,16 +16,20 @@ bundle - - org.opendaylight.openflowplugin.model - model-flow-base - ${openflowplugin.version} - - - org.opendaylight.openflowplugin.model - model-flow-service - ${openflowplugin.version} + + org.opendaylight.openflowplugin.model + model-flow-base + ${openflowplugin.version} + + + org.opendaylight.openflowplugin.model + model-flow-service + ${openflowplugin.version} + + + org.opendaylight.controller + liblldp + ${liblldp.version} - diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java index 5ccaa576..1d10a69a 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java @@ -17,6 +17,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; @@ -62,6 +66,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder; +import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -72,7 +77,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.controller.liblldp.HexEncode; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.primitives.Bytes; @@ -314,6 +320,12 @@ public class MDSALUtil { return getOfPortNumberFromPortName(nodeConnectorId.getValue()); } + public static long getDpnIdFromPortName(NodeConnectorId nodeConnectorId) { + String ofPortName = nodeConnectorId.getValue(); + return Long.parseLong(ofPortName.substring(ofPortName.indexOf(":")+1, + ofPortName.lastIndexOf(":"))); + } + public static long getOfPortNumberFromPortName(String sMdsalPortName) { String sPortNumber = sMdsalPortName.substring(sMdsalPortName.lastIndexOf(":") + 1); return Long.parseLong(sPortNumber); @@ -374,7 +386,6 @@ public class MDSALUtil { } catch (Exception e) { throw new RuntimeException(e); } - return result; } @@ -418,4 +429,52 @@ public class MDSALUtil { throw new RuntimeException(e.getMessage()); } } + + public static byte[] getMacAddressForNodeConnector(DataBroker broker, + InstanceIdentifier nodeConnectorId) { + Optional optNc = MDSALDataStoreUtils.read(broker, + LogicalDatastoreType.OPERATIONAL, nodeConnectorId); + if(optNc.isPresent()) { + NodeConnector nc = optNc.get(); + FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class); + MacAddress macAddress = fcnc.getHardwareAddress(); + return HexEncode.bytesFromHexString(macAddress.getValue()); + } + return null; + } + + public static NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) { + return new NodeId(ncId.getValue().substring(0, + ncId.getValue().lastIndexOf(":"))); + } + + public static String getInterfaceName(NodeConnectorRef ref, DataBroker dataBroker) { + NodeConnectorId nodeConnectorId = getNodeConnectorId(dataBroker, ref); + NodeId nodeId = getNodeIdFromNodeConnectorId(nodeConnectorId); + InstanceIdentifier ncIdentifier = InstanceIdentifier + .builder(Nodes.class) + .child(Node.class, new NodeKey(nodeId)) + .child(NodeConnector.class, + new NodeConnectorKey(nodeConnectorId)).build(); + + Optional nodeConnectorOptional = read( + dataBroker, + LogicalDatastoreType.OPERATIONAL, ncIdentifier); + if (!nodeConnectorOptional.isPresent()) { + return null; + } + NodeConnector nc = nodeConnectorOptional.get(); + FlowCapableNodeConnector fc = nc + .getAugmentation(FlowCapableNodeConnector.class); + return fc.getName(); + } + + public static NodeConnectorId getNodeConnectorId(DataBroker dataBroker, + NodeConnectorRef ref) { + Optional nc = (Optional) read( + dataBroker, + LogicalDatastoreType.CONFIGURATION, ref.getValue()); + return nc.get().getId(); + } + } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NWUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NWUtil.java new file mode 100644 index 00000000..e2f3d635 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NWUtil.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.mdsalutil; + +import java.net.InetAddress; + +import com.google.common.primitives.UnsignedBytes; + +public class NWUtil { + + public static long convertInetAddressToLong(InetAddress address) { + byte[] ipAddressRaw = address.getAddress(); + return (((ipAddressRaw[0] & 0xFF) << (3 * 8)) + + ((ipAddressRaw[1] & 0xFF) << (2 * 8)) + + ((ipAddressRaw[2] & 0xFF) << (1 * 8)) + + (ipAddressRaw[3] & 0xFF)) + & 0xffffffffL; + } + + public static byte[] parseIpAddress(String ipAddress) { + byte cur; + + String[] addressPart = ipAddress.split("."); + int size = addressPart.length; + + byte[] part = new byte[size]; + for (int i = 0; i < size; i++) { + cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16); + part[i] = cur; + } + + return part; + } + + public static byte[] parseMacAddress(String macAddress) { + byte cur; + + String[] addressPart = macAddress.split(":"); + int size = addressPart.length; + + byte[] part = new byte[size]; + for (int i = 0; i < size; i++) { + cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16); + part[i] = cur; + } + + return part; + } + + public static String toStringIpAddress(byte[] ipAddress) + { + if (ipAddress == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(18); + + for (int i = 0; i < ipAddress.length; i++) { + sb.append(UnsignedBytes.toString(ipAddress[i], 10)); + sb.append("."); + } + + sb.setLength(17); + return sb.toString(); + } + + public static String toStringMacAddress(byte[] macAddress) + { + if (macAddress == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(18); + + for (int i = 0; i < macAddress.length; i++) { + String tmp = UnsignedBytes.toString(macAddress[i], 16).toUpperCase(); + if(tmp.length() == 1 || macAddress[i] == (byte)0) { + sb.append("0"); + } + sb.append(tmp); + sb.append(":"); + } + + sb.setLength(17); + return sb.toString(); + } +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/ARP.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/ARP.java new file mode 100644 index 00000000..5f502d07 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/ARP.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.mdsalutil.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.liblldp.BitBufferHelper; +import org.opendaylight.controller.liblldp.Packet; + +/** + * Class that represents the ARP packet objects + * taken from opendaylight(helium) adsal bundle + * + */ + +public class ARP extends Packet { + private static final String HWTYPE = "HardwareType"; + private static final String PTYPE = "ProtocolType"; + private static final String HWADDRLENGTH = "HardwareAddressLength"; + private static final String PADDRLENGTH = "ProtocolAddressLength"; + private static final String OPCODE = "OpCode"; + private static final String SENDERHWADDR = "SenderHardwareAddress"; + private static final String SENDERPADDR = "SenderProtocolAddress"; + private static final String TARGETHWADDR = "TargetHardwareAddress"; + private static final String TARGETPADDR = "TargetProtocolAddress"; + + public static short HW_TYPE_ETHERNET = (short) 0x1; + public static short REQUEST = (short) 0x1; + public static short REPLY = (short) 0x2; + + public static short PROTO_TYPE_IP = 0x800; + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(HWTYPE, new ImmutablePair(0, 16)); + put(PTYPE, new ImmutablePair(16, 16)); + put(HWADDRLENGTH, new ImmutablePair(32, 8)); + put(PADDRLENGTH, new ImmutablePair(40, 8)); + put(OPCODE, new ImmutablePair(48, 16)); + put(SENDERHWADDR, new ImmutablePair(64, 48)); + put(SENDERPADDR, new ImmutablePair(112, 32)); + put(TARGETHWADDR, new ImmutablePair(144, 48)); + put(TARGETPADDR, new ImmutablePair(192, 32)); + + } + }; + private Map fieldValues; + + /** + * Default constructor that creates and sets the HashMap + */ + public ARP() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that sets the access level for the packet and + * creates and sets the HashMap + */ + public ARP(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + public short getHardwareType() { + return (BitBufferHelper.getShort(fieldValues.get(HWTYPE))); + + } + + public short getProtocolType() { + return (BitBufferHelper.getShort(fieldValues.get(PTYPE))); + } + + public byte getHardwareAddressLength() { + return (BitBufferHelper.getByte(fieldValues.get(HWADDRLENGTH))); + } + + public byte getProtocolAddressLength() { + return (BitBufferHelper.getByte(fieldValues.get(PADDRLENGTH))); + } + + public short getOpCode() { + return (BitBufferHelper.getShort(fieldValues.get(OPCODE))); + } + + public byte[] getSenderHardwareAddress() { + return (fieldValues.get(SENDERHWADDR)); + } + + public byte[] getSenderProtocolAddress() { + return (fieldValues.get(SENDERPADDR)); + } + + public byte[] getTargetHardwareAddress() { + return (fieldValues.get(TARGETHWADDR)); + } + + public ARP setHardwareType(short hardwareType) { + byte[] hwType = BitBufferHelper.toByteArray(hardwareType); + fieldValues.put(HWTYPE, hwType); + return this; + } + + public ARP setProtocolType(short protocolType) { + byte[] protType = BitBufferHelper.toByteArray(protocolType); + fieldValues.put(PTYPE, protType); + return this; + } + + public ARP setHardwareAddressLength(byte hardwareAddressLength) { + byte[] hwAddressLength = BitBufferHelper + .toByteArray(hardwareAddressLength); + fieldValues.put(HWADDRLENGTH, hwAddressLength); + return this; + } + + public ARP setProtocolAddressLength(byte protocolAddressLength) { + byte[] protocolAddrLength = BitBufferHelper + .toByteArray(protocolAddressLength); + fieldValues.put(PADDRLENGTH, protocolAddrLength); + return this; + } + + public ARP setOpCode(short opCode) { + byte[] operationCode = BitBufferHelper.toByteArray(opCode); + fieldValues.put(OPCODE, operationCode); + return this; + } + + public ARP setSenderHardwareAddress(byte[] senderHardwareAddress) { + fieldValues.put(SENDERHWADDR, senderHardwareAddress); + return this; + } + + public ARP setTargetHardwareAddress(byte[] targetHardwareAddress) { + fieldValues.put(TARGETHWADDR, targetHardwareAddress); + return this; + } + + public ARP setTargetProtocolAddress(byte[] targetProtocolAddress) { + fieldValues.put(TARGETPADDR, targetProtocolAddress); + return this; + } + + public ARP setSenderProtocolAddress(byte[] senderIP) { + fieldValues.put(SENDERPADDR, senderIP); + return this; + } + + public byte[] getTargetProtocolAddress() { + return fieldValues.get(TARGETPADDR); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((fieldValues == null) ? 0 : fieldValues.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ARP other = (ARP) obj; + if (fieldValues == null) { + if (other.fieldValues != null) { + return false; + } + } else if (!fieldValues.equals(other.fieldValues)) { + return false; + } + return true; + } +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java new file mode 100644 index 00000000..5fce3de1 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.mdsalutil.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.liblldp.BitBufferHelper; +import org.opendaylight.controller.liblldp.EtherTypes; +import org.opendaylight.controller.liblldp.LLDP; +import org.opendaylight.controller.liblldp.NetUtils; +import org.opendaylight.controller.liblldp.Packet; + +/** + * Class that represents the Ethernet frame objects + * taken from opendaylight(helium) adsal bundle + */ +public class Ethernet extends Packet { + private static final String DMAC = "DestinationMACAddress"; + private static final String SMAC = "SourceMACAddress"; + private static final String ETHT = "EtherType"; + + // TODO: This has to be outside and it should be possible for osgi + // to add new coming packet classes + public static final Map> etherTypeClassMap; + static { + etherTypeClassMap = new HashMap>(); + etherTypeClassMap.put(EtherTypes.ARP.shortValue(), ARP.class); + // TODO: Add support for more classes here + // etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class); + // etherTypeClassMap.put(EtherTypes.OLDQINQ.shortValue(), IEEE8021Q.class); + // etherTypeClassMap.put(EtherTypes.QINQ.shortValue(), IEEE8021Q.class); + // etherTypeClassMap.put(EtherTypes.CISCOQINQ.shortValue(), IEEE8021Q.class); + } + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(DMAC, new ImmutablePair(0, 48)); + put(SMAC, new ImmutablePair(48, 48)); + put(ETHT, new ImmutablePair(96, 16)); + } + }; + private final Map fieldValues; + + /** + * Default constructor that creates and sets the HashMap + */ + public Ethernet() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that sets the access level for the packet and + * creates and sets the HashMap + */ + public Ethernet(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + @Override + public void setHeaderField(String headerField, byte[] readValue) { + if (headerField.equals(ETHT)) { + payloadClass = etherTypeClassMap.get(BitBufferHelper + .getShort(readValue)); + } + hdrFieldsMap.put(headerField, readValue); + } + + public byte[] getDestinationMACAddress() { + return fieldValues.get(DMAC); + } + + public byte[] getSourceMACAddress() { + return fieldValues.get(SMAC); + } + + public short getEtherType() { + return BitBufferHelper.getShort(fieldValues.get(ETHT)); + } + + public boolean isBroadcast(){ + return NetUtils.isBroadcastMACAddr(getDestinationMACAddress()); + } + + public boolean isMulticast(){ + return NetUtils.isMulticastMACAddr(getDestinationMACAddress()); + } + + public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) { + fieldValues.put(DMAC, destinationMACAddress); + return this; + } + + public Ethernet setSourceMACAddress(byte[] sourceMACAddress) { + fieldValues.put(SMAC, sourceMACAddress); + return this; + } + + public Ethernet setEtherType(short etherType) { + byte[] ethType = BitBufferHelper.toByteArray(etherType); + fieldValues.put(ETHT, ethType); + return this; + } + +} diff --git a/mdsalutil/mdsalutil-impl/pom.xml b/mdsalutil/mdsalutil-impl/pom.xml index dcc08370..0e9aeaf7 100644 --- a/mdsalutil/mdsalutil-impl/pom.xml +++ b/mdsalutil/mdsalutil-impl/pom.xml @@ -1,7 +1,7 @@ - + org.opendaylight.vpnservice config-parent @@ -13,10 +13,7 @@ mdsalutil-impl 0.2.0-SNAPSHOT bundle - - - 2.4.3 - + org.opendaylight.controller @@ -27,6 +24,11 @@ model-flow-base ${openflowplugin.version} + + org.opendaylight.controller + liblldp + ${liblldp.version} + org.opendaylight.openflowplugin.model model-flow-service diff --git a/pom.xml b/pom.xml index d1924206..4e9b4dd3 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL mdsalutil lockmanager idmanager + arputil vpnmanager interfacemgr nexthopmgr -- 2.36.6