summaryrefslogtreecommitdiffstats
path: root/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java
diff options
context:
space:
mode:
Diffstat (limited to 'v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java461
1 files changed, 461 insertions, 0 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java
new file mode 100644
index 000000000..f466adb53
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2015 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.v3po.impl;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.SoftwareLoopback;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.Statistics;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.StatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.IpAddressOrigin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64;
+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.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStatisticsAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStatisticsAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet.Duplex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.EthernetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.interconnection.XconnectBasedBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.vppjapi.vppBridgeDomainDetails;
+import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails;
+import org.openvpp.vppjapi.vppIPv4Address;
+import org.openvpp.vppjapi.vppIPv6Address;
+import org.openvpp.vppjapi.vppInterfaceCounters;
+import org.openvpp.vppjapi.vppInterfaceDetails;
+import org.openvpp.vppjapi.vppVxlanTunnelDetails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+/*
+ * VPP API Class overriding interface details callback
+ */
+public class V3poApiRequest extends V3poRequest {
+ private static final Logger LOG = LoggerFactory.getLogger(V3poApiRequest.class);
+ public String ifNames = "";
+ private VppPollOperDataImpl caller;
+
+ public V3poApiRequest(VppPollOperDataImpl vppPollOperData) {
+ caller = vppPollOperData;
+ }
+
+ private InstanceIdentifier<Interface> getStateInterfaceIid(String interfaceName) {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class,
+ new InterfaceKey(interfaceName));
+ }
+
+ private InstanceIdentifier<Interface2> getStateInterfaceIpId(InstanceIdentifier<Interface> iid) {
+ return iid.augmentation(Interface2.class);
+ }
+
+ private InstanceIdentifier<Statistics> getStateInterfaceStatsId(InstanceIdentifier<Interface> iid) {
+ return iid.child(Statistics.class);
+ }
+
+ private static Counter64 getCounter64(long num) {
+ return new Counter64(BigInteger.valueOf(num));
+ }
+
+ private static Counter32 getCounter32(long num) {
+ return new Counter32(num);
+ }
+
+ private Statistics buildInterfaceStatistics(vppInterfaceCounters ifCounters) {
+ if (ifCounters == null) {
+ return null;
+ }
+ StatisticsBuilder statsBuilder = new StatisticsBuilder();
+
+ statsBuilder.setInBroadcastPkts(getCounter64(ifCounters.rxBroadcast));
+ statsBuilder.setInDiscards(getCounter32(ifCounters.rxDiscard));
+ statsBuilder.setInErrors(getCounter32(ifCounters.rxError));
+ statsBuilder.setInMulticastPkts(getCounter64(ifCounters.rxMulticast));
+ statsBuilder.setInOctets(getCounter64(ifCounters.rxOctets));
+ statsBuilder.setInUnicastPkts(getCounter64(ifCounters.rxUnicast));
+ statsBuilder.setInUnknownProtos(getCounter32(ifCounters.rxUnknownProto));
+
+ statsBuilder.setOutBroadcastPkts(getCounter64(ifCounters.txBroadcast));
+ statsBuilder.setOutDiscards(getCounter32(ifCounters.txDiscard));
+ statsBuilder.setOutErrors(getCounter32(ifCounters.txError));
+ statsBuilder.setOutMulticastPkts(getCounter64(ifCounters.txMulticast));
+ statsBuilder.setOutOctets(getCounter64(ifCounters.txOctets));
+ statsBuilder.setOutUnicastPkts(getCounter64(ifCounters.txUnicast));
+
+ VppInterfaceStatisticsAugmentationBuilder statsAugBuilder =
+ new VppInterfaceStatisticsAugmentationBuilder();
+ statsAugBuilder.setInErrorsMiss(getCounter64(ifCounters.rxMiss));
+ statsAugBuilder.setInErrorsNoBuf(getCounter64(ifCounters.rxFifoFull)); // FIXME? Is this right?
+ statsAugBuilder.setOutDiscardsFifoFull(getCounter64(ifCounters.txFifoFull));
+
+ statsBuilder.addAugmentation(VppInterfaceStatisticsAugmentation.class,
+ statsAugBuilder.build());
+
+ return statsBuilder.build();
+ }
+
+ private static String getMacAddress(byte[] mac) {
+ StringBuilder sb = new StringBuilder(18);
+ for (byte b : mac) {
+ if (sb.length() > 0) {
+ sb.append(':');
+ }
+ sb.append(String.format("%02x", b));
+ }
+ return sb.toString();
+ }
+
+ private static final Gauge64 vppSpeed0 = new Gauge64(BigInteger.ZERO);
+ private static final Gauge64 vppSpeed1 = new Gauge64(BigInteger.valueOf(10 * 1000000));
+ private static final Gauge64 vppSpeed2 = new Gauge64(BigInteger.valueOf(100 * 1000000));
+ private static final Gauge64 vppSpeed4 = new Gauge64(BigInteger.valueOf(1000 * 1000000));
+ private static final Gauge64 vppSpeed8 = new Gauge64(BigInteger.valueOf(10000L * 1000000));
+ private static final Gauge64 vppSpeed16 = new Gauge64(BigInteger.valueOf(40000L * 1000000));
+ private static final Gauge64 vppSpeed32 = new Gauge64(BigInteger.valueOf(100000L * 1000000));
+
+ private static Gauge64 getSpeed(byte vppSpeed) {
+ switch (vppSpeed) {
+ case 1: return vppSpeed1;
+ case 2: return vppSpeed2;
+ case 4: return vppSpeed4;
+ case 8: return vppSpeed8;
+ case 16: return vppSpeed16;
+ case 32: return vppSpeed32;
+ default: return vppSpeed0;
+ }
+ }
+
+ private static String ipv4IntToString(int ip) {
+ InetAddress addr = null;
+ byte[] bytes = Ints.toByteArray(ip);
+ try {
+ addr = InetAddress.getByAddress(bytes);
+ } catch (java.net.UnknownHostException e) {
+ e.printStackTrace();
+ return null;
+ }
+ return addr.getHostAddress();
+ }
+
+ private Interface buildStateInterface(int ifIndex,
+ String interfaceName,
+ int supIfIndex,
+ byte[] physAddr,
+ byte adminUp, byte linkUp,
+ byte linkDuplex, byte linkSpeed,
+ int subId, byte subDot1ad,
+ byte subNumberOfTags,
+ int subOuterVlanId,
+ int subInnerVlanId,
+ byte subExactMatch,
+ byte subDefault,
+ byte subOuterVlanIdAny,
+ byte subInnerVlanIdAny,
+ int vtrOp, int vtrPushDot1q,
+ int vtrTag1, int vtrTag2,
+ Statistics stats) {
+ InterfaceBuilder ifBuilder = new InterfaceBuilder();
+ java.lang.Class<? extends InterfaceType> ifType;
+
+ // FIXME: missing types for virtualethernet, subinterface, tap interface etc
+ if (interfaceName.startsWith("loop")) {
+ ifType = SoftwareLoopback.class;
+ } else if (interfaceName.startsWith("vxlan_tunnel")) {
+ ifType = VxlanTunnel.class;
+ } else {
+ ifType = EthernetCsmacd.class;
+ }
+ ifBuilder.setName(interfaceName)
+ .setType(ifType)
+ .setAdminStatus((adminUp == 0 ? AdminStatus.Down : AdminStatus.Up))
+ .setOperStatus((linkUp == 0 ? OperStatus.Down : OperStatus.Up));
+/*
+ DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = ImmutableNodes.mapEntryBuilder()
+ .withNodeIdentifier(new NodeIdentifierWithPredicates(Interface.QNAME, NAME_QNAME, interfaceName));
+ builder.withChild(ImmutableNodes.leafNode(IF_TYPE, SoftwareLoopback.QNAME))*/
+
+ // subinterface?
+ if (ifIndex != supIfIndex) {
+ // TODO: get name and set
+ }
+
+ if (physAddr != null) {
+ ifBuilder.setPhysAddress(new PhysAddress(getMacAddress(physAddr)));
+ }
+ ifBuilder.setSpeed(getSpeed(linkSpeed));
+
+ if (stats != null) {
+ ifBuilder.setStatistics(stats);
+ }
+ int bdId = this.bridgeDomainIdFromInterfaceName(interfaceName);
+ vppBridgeDomainDetails bd = (bdId != -1 ? this.getBridgeDomainDetails(bdId) : null);
+
+ String bdName = null;
+ short splitHorizonGroup = 0;
+ boolean bvi = false;
+
+ if (bd != null) {
+ bdName = bd.name;
+ for (int ifIdx = 0; ifIdx < bd.interfaces.length; ifIdx++) {
+ vppBridgeDomainInterfaceDetails bdIf = bd.interfaces[ifIdx];
+
+ if (bdIf.interfaceName != interfaceName) {
+ continue;
+ }
+ if (bd.bviInterfaceName == interfaceName) {
+ bvi = true;
+ }
+ splitHorizonGroup = (short)bdIf.splitHorizonGroup;
+ }
+ }
+
+ VppInterfaceStateAugmentationBuilder vppIfStateAugBuilder =
+ new VppInterfaceStateAugmentationBuilder();
+
+ vppIfStateAugBuilder.setDescription(this.getInterfaceDescription(interfaceName));
+
+ setStateInterfaceL2(vppIfStateAugBuilder, bdId != -1, false, null,
+ bdName, splitHorizonGroup, bvi);
+
+ if (EthernetCsmacd.class == ifType) {
+ setStateInterfaceEthernet(vppIfStateAugBuilder, linkDuplex == 2,
+ "ACME Inc.", 1234);
+ }
+
+ vppVxlanTunnelDetails[] vxlanDet = this.vxlanTunnelDump(ifIndex);
+ if (null != vxlanDet && vxlanDet.length >= 1) {
+ setStateInterfaceVxlan(vppIfStateAugBuilder, vxlanDet[0].srcAddress,
+ vxlanDet[0].dstAddress, vxlanDet[0].vni,
+ vxlanDet[0].encapVrfId);
+ }
+
+ ifBuilder.addAugmentation(VppInterfaceStateAugmentation.class,
+ vppIfStateAugBuilder.build());
+
+ InterfaceStateIpv4Builder ipv4Builder = new InterfaceStateIpv4Builder();
+// TODO ipv4Builder.setMtu(1234);
+
+ InetAddress addr = null;
+
+ vppIPv4Address[] ipv4Addrs = ipv4AddressDump(interfaceName);
+ if (ipv4Addrs != null) {
+ for (vppIPv4Address vppAddr : ipv4Addrs) {
+ if (null == vppAddr) {
+ LOG.error("ipv4 address structure in null");
+ continue;
+ }
+
+ // FIXME: vppIPv4Address and vppIPv6 address can be the same if both will use
+ // byte array for ip
+ byte[] bytes = Ints.toByteArray(vppAddr.ip);
+ try {
+ addr = InetAddress.getByAddress(bytes);
+ } catch (java.net.UnknownHostException e) {
+ e.printStackTrace();
+ continue;
+ }
+
+ ipv4Builder.addAddress(addr.getHostAddress(), vppAddr.prefixLength, IpAddressOrigin.Static);
+ }
+ }
+
+ InterfaceStateIpv6Builder ipv6Builder = new InterfaceStateIpv6Builder();
+// TODO ipv6Builder.setMtu(1234);
+
+ vppIPv6Address[] ipv6Addrs = ipv6AddressDump(interfaceName);
+ if (ipv6Addrs != null) {
+ for (vppIPv6Address vppAddr : ipv6Addrs) {
+ if (null == vppAddr) {
+ LOG.error("ipv6 address structure in null");
+ continue;
+ }
+
+ byte[] bytes = vppAddr.ip;
+ try {
+ addr = InetAddress.getByAddress(bytes);
+ } catch (java.net.UnknownHostException e) {
+ e.printStackTrace();
+ continue;
+ }
+
+ ipv6Builder.addAddress(addr.getHostAddress(), vppAddr.prefixLength, IpAddressOrigin.Static);
+ }
+ }
+ Interface2Builder ipBuilder = new Interface2Builder();
+
+ ipBuilder.setIpv4(ipv4Builder.build());
+ ipBuilder.setIpv6(ipv6Builder.build());
+
+ ifBuilder.addAugmentation(Interface2.class, ipBuilder.build());
+
+ return ifBuilder.build();
+ }
+
+ private void setStateInterfaceL2(
+ VppInterfaceStateAugmentationBuilder augBuilder,
+ boolean isL2BridgeBased, boolean isXconnect,
+ String xconnectOutgoingInterface,
+ String bdName, short splitHorizonGroup, boolean bvi) {
+
+ L2Builder l2Builder = new L2Builder();
+
+ if (isXconnect) {
+ l2Builder.setInterconnection(
+ new XconnectBasedBuilder()
+ .setXconnectOutgoingInterface(xconnectOutgoingInterface)
+ .build());
+ } else if (isL2BridgeBased) {
+ l2Builder.setInterconnection(
+ new BridgeBasedBuilder()
+ .setBridgeDomain(bdName)
+ .setSplitHorizonGroup(splitHorizonGroup)
+ .setBridgedVirtualInterface(bvi)
+ .build());
+ }
+
+ augBuilder.setL2(l2Builder.build());
+ }
+
+ private void setStateInterfaceEthernet(
+ VppInterfaceStateAugmentationBuilder augBuilder,
+ boolean isFullDuplex, String manufacturerDesc, Integer mtu) {
+
+ EthernetBuilder ethBuilder = new EthernetBuilder();
+ ethBuilder.setDuplex((isFullDuplex ? Duplex.Full : Duplex.Half))
+ .setManufacturerDescription(manufacturerDesc)
+ .setMtu(mtu);
+
+ augBuilder.setEthernet(ethBuilder.build());
+ }
+
+ private void setStateInterfaceVxlan(
+ VppInterfaceStateAugmentationBuilder augBuilder, int srcAddress,
+ int dstAddress, int vni, int encapVrfId) {
+
+ String srcAddressStr = ipv4IntToString(srcAddress);
+ String dstAddressStr = ipv4IntToString(dstAddress);
+
+ VxlanBuilder vxlanBuilder = new VxlanBuilder();
+ Vxlan vxlan = vxlanBuilder
+ .setSrc(new Ipv4AddressNoZone(srcAddressStr))
+ .setDst(new Ipv4AddressNoZone(dstAddressStr))
+ .setVni((long)vni)
+ .setEncapVrfId((long)encapVrfId)
+ .build();
+
+ augBuilder.setVxlan(vxlan);
+ }
+
+ private void writeToIfState(InstanceIdentifier<Interface> iid,
+ Interface intf) {
+ DataBroker db = caller.getDataBroker();
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+ // TODO: how to delete existing interfaces that disappeared? (reset it before each dumpInterfaces call?)
+
+ /*LOG.info("VPPOPER-INFO: Adding interface " + intf.getName()
+ + " to oper DataStore.");*/
+ transaction.put(LogicalDatastoreType.OPERATIONAL, iid, intf);
+
+ CheckedFuture<Void, TransactionCommitFailedException> future =
+ transaction.submit();
+ Futures.addCallback(future, new LoggingFuturesCallBack<Void>(
+ "VPPOPER-WARNING: Failed to write "
+ + "interface to ietf-interfaces state", LOG));
+ }
+
+ private void processInterfaces(vppInterfaceDetails[] ifaces) {
+ for (vppInterfaceDetails swIf : ifaces) {
+ interfaceDetails(swIf);
+ }
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void swInterfaceDumpAll() {
+ vppInterfaceDetails[] ifaces;
+
+ ifaces = swInterfaceDump((byte) 1, "Ether".getBytes());
+ processInterfaces(ifaces);
+
+ ifaces = swInterfaceDump((byte) 1, "lo".getBytes());
+ processInterfaces(ifaces);
+
+ ifaces = swInterfaceDump((byte) 1, "vxlan".getBytes());
+ processInterfaces(ifaces);
+
+ ifaces = swInterfaceDump((byte) 1, "l2tpv3_tunnel".getBytes());
+ processInterfaces(ifaces);
+
+ ifaces = swInterfaceDump((byte) 1, "tap".getBytes());
+ processInterfaces(ifaces);
+ }
+
+ private void interfaceDetails(vppInterfaceDetails swIf) {
+ /*LOG.info("Got interface {} (idx: {}) adminUp: {} linkUp: {} duplex: {} speed: {} subId: {}",
+ swIf.interfaceName, swIf.ifIndex, swIf.adminUp, swIf.linkUp, swIf.linkDuplex, swIf.linkSpeed, swIf.subId);*/
+
+ vppInterfaceCounters ifCounters = getInterfaceCounters(swIf.ifIndex);
+
+ InstanceIdentifier<Interface> iid = getStateInterfaceIid(swIf.interfaceName);
+
+ Statistics stats = buildInterfaceStatistics(ifCounters);
+
+ Interface intf = buildStateInterface(swIf.ifIndex, swIf.interfaceName,
+ swIf.supIfIndex, swIf.physAddr,
+ swIf.adminUp, swIf.linkUp,
+ swIf.linkDuplex, swIf.linkSpeed,
+ swIf.subId, swIf.subDot1ad,
+ swIf.subNumberOfTags,
+ swIf.subOuterVlanId,
+ swIf.subInnerVlanId,
+ swIf.subExactMatch, swIf.subDefault,
+ swIf.subOuterVlanIdAny,
+ swIf.subInnerVlanIdAny,
+ swIf.vtrOp, swIf.vtrPushDot1q,
+ swIf.vtrTag1, swIf.vtrTag2, stats);
+ writeToIfState(iid, intf);
+
+ ifNames += " " + swIf.interfaceName;
+ }
+}