summaryrefslogtreecommitdiffstats
path: root/v3po/impl/src/main/java/io
diff options
context:
space:
mode:
authorEd Warnicke <eaw@cisco.com>2016-01-10 06:15:18 -0800
committerRobert Varga <nite@hq.sk>2016-01-30 00:01:07 +0100
commit36424f46ff5543c2ae475c60bb3e08f299c55799 (patch)
tree604e5edce7433e8fb4c0fbd16f1bf1ffdfd997bb /v3po/impl/src/main/java/io
parentbca403e3d9abfd87a8eeffa88f4a1eb823e6780f (diff)
Initial honeycomb code commit.
This commit drops the basic structure with disabled integration tests. The tests will be enabled in a follow-up patch, which sorts out the current .so loading problems. Change-Id: If70f2f13b2cf49af82996f884218ac05d335c2ed Signed-off-by: Ed Warnicke <eaw@cisco.com> Signed-off-by: Robert Varga <nite@hq.sk>
Diffstat (limited to 'v3po/impl/src/main/java/io')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataRegistry.java24
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolver.java26
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolverInterfaceState.java36
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv4Builder.java94
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv6Builder.java87
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/LoggingFuturesCallBack.java48
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poApiRequest.java461
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java326
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poRequest.java28
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppBridgeDomainListener.java217
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppIetfInterfaceListener.java566
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppPollOperDataImpl.java147
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateBridgeDomainBuilder.java102
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateCustomBuilder.java73
14 files changed, 2235 insertions, 0 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataRegistry.java
new file mode 100644
index 000000000..5888dc998
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataRegistry.java
@@ -0,0 +1,24 @@
+/*
+ * 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 org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface DataRegistry {
+ <T extends DataObject> void registerModule(InstanceIdentifier<T> path, DataResolver<T> resolver);
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolver.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolver.java
new file mode 100644
index 000000000..5ada80f86
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolver.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface DataResolver<T extends DataObject> {
+ public void resolve(InstanceIdentifier<T> path, WriteTransaction tx);
+}
+
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolverInterfaceState.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolverInterfaceState.java
new file mode 100644
index 000000000..fd2d48c01
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/DataResolverInterfaceState.java
@@ -0,0 +1,36 @@
+/*
+ * 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 org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+// Return Interface data from interfaces.state based on InstanceIdentifier
+public class DataResolverInterfaceState implements DataResolver<Interface> {
+
+ @Override
+ public void resolve(InstanceIdentifier<Interface> path,
+ WriteTransaction tx) {
+ InterfaceKey key = path.firstKeyOf(Interface.class);
+ String interfaceName = key.getName();
+
+ return;
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv4Builder.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv4Builder.java
new file mode 100644
index 000000000..5e2141d6f
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv4Builder.java
@@ -0,0 +1,94 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+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.ip.rev140616.IpAddressOrigin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.NeighborOrigin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+
+public class InterfaceStateIpv4Builder {
+ private List<Address> addrs = new ArrayList<Address>();
+ private List<Neighbor> neighbors = new ArrayList<Neighbor>();
+ private Ipv4Builder ipv4Builder = new Ipv4Builder();
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addAddress(String ipv4Addr, short prefixLength, IpAddressOrigin origin) {
+ // address
+ AddressBuilder addrBuilder = new AddressBuilder();
+
+ // IpAddressOrigin.Static
+ addrBuilder.setOrigin(origin); // FIXME: how to find origin?
+
+ PrefixLength prefixLen = new PrefixLengthBuilder().setPrefixLength(prefixLength).build();
+ addrBuilder.setSubnet(prefixLen);
+
+ addrBuilder.setIp(new Ipv4AddressNoZone(ipv4Addr));
+
+ addrs.add(addrBuilder.build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addNeighbor(String ipv4Addr, String physAddr, NeighborOrigin origin) {
+ // address neighbor
+ NeighborBuilder nbrBuilder = new NeighborBuilder();
+ nbrBuilder.setIp(new Ipv4AddressNoZone(ipv4Addr));
+ nbrBuilder.setLinkLayerAddress(new PhysAddress(physAddr)); // TODO ("00:00:00:00:00:00")
+ nbrBuilder.setOrigin(origin);
+
+ neighbors.add(nbrBuilder.build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setForwarding(boolean fwd) {
+ ipv4Builder.setForwarding(fwd);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setMtu(int mtu) {
+ ipv4Builder.setMtu(mtu);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public Ipv4 build() {
+ ipv4Builder.setAddress(addrs);
+ ipv4Builder.setNeighbor(neighbors);
+ return ipv4Builder.build();
+ }
+}
+
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv6Builder.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv6Builder.java
new file mode 100644
index 000000000..42862a944
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/InterfaceStateIpv6Builder.java
@@ -0,0 +1,87 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+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.ip.rev140616.NeighborOrigin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv6.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv6.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv6.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv6.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+
+public class InterfaceStateIpv6Builder {
+ private List<Address> addrs = new ArrayList<Address>();
+ private List<Neighbor> neighbors = new ArrayList<Neighbor>();
+ private Ipv6Builder ipv6Builder = new Ipv6Builder();
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addAddress(String ipv6Addr, short prefixLength, IpAddressOrigin origin) {
+ // address
+ AddressBuilder addrBuilder = new AddressBuilder();
+
+ // IpAddressOrigin.Static
+ addrBuilder.setOrigin(origin); // FIXME: how to find origin?
+ addrBuilder.setPrefixLength(prefixLength);
+ addrBuilder.setIp(new Ipv6AddressNoZone(ipv6Addr));
+
+ addrs.add(addrBuilder.build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addNeighbor(String ipv6Addr, String physAddr, NeighborOrigin origin) {
+ // address neighbor
+ NeighborBuilder nbrBuilder = new NeighborBuilder();
+ nbrBuilder.setIp(new Ipv6AddressNoZone(ipv6Addr));
+ nbrBuilder.setLinkLayerAddress(new PhysAddress(physAddr)); // TODO ("00:00:00:00:00:00")
+ nbrBuilder.setOrigin(origin);
+
+ neighbors.add(nbrBuilder.build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setForwarding(boolean fwd) {
+ ipv6Builder.setForwarding(fwd);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setMtu(long mtu) {
+ ipv6Builder.setMtu(mtu);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public Ipv6 build() {
+ ipv6Builder.setAddress(addrs);
+ ipv6Builder.setNeighbor(neighbors);
+ return ipv6Builder.build();
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/LoggingFuturesCallBack.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/LoggingFuturesCallBack.java
new file mode 100644
index 000000000..35795cb7b
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/LoggingFuturesCallBack.java
@@ -0,0 +1,48 @@
+/*
+ * 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 com.google.common.util.concurrent.FutureCallback;
+import org.slf4j.Logger;
+
+public class LoggingFuturesCallBack<V> implements FutureCallback<V> {
+
+ private static Logger LOG;
+ private String message;
+
+ public LoggingFuturesCallBack(String message, Logger log) {
+ this.message = message;
+ this.LOG = log;
+ }
+
+ @Override
+ public void onFailure(Throwable err) {
+ LOG.warn(message,err);
+
+ }
+
+ @Override
+ public void onSuccess(V arg0) {
+ /* suppress success messages
+ if (arg0 == null) {
+ LOG.info("Success!");
+ } else {
+ LOG.info("Success! {}", arg0);
+ }
+ */
+ }
+}
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;
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java
new file mode 100644
index 000000000..3b546f16f
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poProvider.java
@@ -0,0 +1,326 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+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.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+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.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+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.InterfacesBuilder;
+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.InterfacesStateBuilder;
+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.InterfaceBuilder;
+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.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.V3poService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.EthernetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.vppjapi.vppApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+
+public class V3poProvider implements BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(V3poProvider.class);
+ private RpcRegistration<V3poService> v3poService;
+ private VppIetfInterfaceListener vppInterfaceListener;
+ private VppBridgeDomainListener vppBridgeDomainListener;
+ private static final vppApi api = new vppApi();
+ private static DataBroker db;
+ VppPollOperDataImpl vppPollOperData;
+
+ private void writeToBridgeDomain(String bdName, Boolean flood,
+ Boolean forward, Boolean learn,
+ Boolean unknownUnicastFlood,
+ Boolean arpTermination) {
+
+ BridgeDomainBuilder bdBuilder = new BridgeDomainBuilder();
+ bdBuilder.setName(bdName);
+ bdBuilder.setFlood(flood);
+ bdBuilder.setForward(forward);
+ bdBuilder.setLearn(learn);
+ bdBuilder.setUnknownUnicastFlood(unknownUnicastFlood);
+ bdBuilder.setArpTermination(arpTermination);
+
+ LOG.info("VPPCFG-INFO: Adding Bridge Domain " + bdName + " to DataStore.");
+ InstanceIdentifier<BridgeDomain> iid =
+ InstanceIdentifier.create(Vpp.class)
+ .child(BridgeDomains.class)
+ .child(BridgeDomain.class, new BridgeDomainKey(bdName));
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, bdBuilder.build());
+ CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+ Futures.addCallback(future, new LoggingFuturesCallBack<Void>(
+ "VPPCFG-WARNING: Failed to write bridge domain " + bdName + " to Bridge Domains", LOG));
+ }
+
+ private void writeIpv4AddressToInterface(String name, Ipv4AddressNoZone ipv4Addr, short plen) {
+ AddressKey addrKey = new AddressKey(ipv4Addr);
+ AddressBuilder addrBuilder = new AddressBuilder();
+ PrefixLength prefixLen = new PrefixLengthBuilder().setPrefixLength(plen).build();
+ addrBuilder.setSubnet(prefixLen);
+ addrBuilder.setIp(new Ipv4AddressNoZone(ipv4Addr));
+ addrBuilder.setKey(addrKey);
+
+ List<Address> addrs = new ArrayList<Address>();
+ addrs.add(addrBuilder.build());
+
+ Ipv4 ip4 = new Ipv4Builder().setAddress(addrs).build();
+ Interface1Builder if1Builder = new Interface1Builder();
+ if1Builder.setIpv4(ip4);
+
+ InterfaceBuilder ifBuilder = new InterfaceBuilder();
+ ifBuilder.setName(name);
+ ifBuilder.addAugmentation(Interface1.class, if1Builder.build());
+
+ LOG.info("VPPCFG-INFO: Adding ipv4 address {} to interface {} to DataStore.", ipv4Addr, name);
+ InstanceIdentifier<Interface> iid =
+ InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(name));
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, ifBuilder.build());
+ CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+ Futures.addCallback(future, new LoggingFuturesCallBack<Void>(
+ "VPPCFG-WARNING: Failed to write " + name + "interface to ietf-interfaces", LOG));
+ }
+
+ private void writeToInterface(String name, String description,
+ Boolean enabled, String bdName, int vrfId) {
+ VppInterfaceAugmentationBuilder ifAugBuilder = new VppInterfaceAugmentationBuilder();
+
+ EthernetBuilder ethBuilder = new EthernetBuilder();
+ ethBuilder.setMtu(1234);
+ ifAugBuilder.setEthernet(ethBuilder.build());
+
+ if (bdName != null) {
+ BridgeBasedBuilder bridgeBuilder = new BridgeBasedBuilder();
+ bridgeBuilder.setBridgeDomain(bdName);
+ bridgeBuilder.setSplitHorizonGroup((short)0);
+ bridgeBuilder.setBridgedVirtualInterface(false);
+
+ L2Builder l2Builder = new L2Builder();
+ l2Builder.setInterconnection(bridgeBuilder.build());
+ ifAugBuilder.setL2(l2Builder.build());
+ }
+
+ if (vrfId > 0) {
+ RoutingBuilder rtBuilder = new RoutingBuilder();
+ rtBuilder.setVrfId(new Long(vrfId));
+ ifAugBuilder.setRouting(rtBuilder.build());
+ }
+
+ InterfaceBuilder ifBuilder = new InterfaceBuilder();
+ ifBuilder.setName(name);
+ ifBuilder.setDescription(description);
+ ifBuilder.setType(EthernetCsmacd.class);
+ ifBuilder.setEnabled(enabled);
+ ifBuilder.setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Disabled);
+
+ ifBuilder.addAugmentation(VppInterfaceAugmentation.class, ifAugBuilder.build());
+
+ LOG.info("VPPCFG-INFO: Adding interface " + name + " to DataStore.");
+ InstanceIdentifier<Interface> iid = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(name));
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, ifBuilder.build());
+ CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+ Futures.addCallback(future, new LoggingFuturesCallBack<Void>(
+ "VPPCFG-WARNING: Failed to write " + name + "interface to ietf-interfaces", LOG));
+ }
+
+ private void initializeVppConfig() {
+
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+ InstanceIdentifier<Vpp> viid = InstanceIdentifier.create(Vpp.class);
+ Vpp vpp = new VppBuilder().build();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, viid, vpp);
+ CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+ Futures.addCallback(future, new
+ LoggingFuturesCallBack<>("VPPCFG-WARNING: Failed to create Vpp "
+ + "configuration db.",
+ LOG));
+ vppBridgeDomainListener = new VppBridgeDomainListener(db, api);
+
+ LOG.info("VPPCFG-INFO: Preparing to initialize the IETF Interface " + "list configuration db.");
+ transaction = db.newWriteOnlyTransaction();
+ InstanceIdentifier<Interfaces> iid = InstanceIdentifier.create(Interfaces.class);
+ Interfaces intf = new InterfacesBuilder().build();
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, intf);
+ future = transaction.submit();
+ Futures.addCallback(future, new
+ LoggingFuturesCallBack<>("VPPCFG-WARNING: Failed to create IETF "
+ + "Interface list configuration db.",
+ LOG));
+ vppInterfaceListener = new VppIetfInterfaceListener(db, api);
+
+ /* DAW-DEBUG:
+ try {
+ int wait = 3;
+ LOG.info("VPPCFG-INFO: Sleeping for {} seconds...", wait);
+ TimeUnit.SECONDS.sleep(wait);
+ } catch (InterruptedException e) {
+ LOG.info("VPPCFG-INFO: Sleep Interrupted!");
+ }
+ LOG.info("VPPCFG-INFO: Nap complete. I feel much better now.");
+ */
+
+ /* Test DataChangeListener by writing to db */
+ writeToBridgeDomain("CocaCola", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+ writeToBridgeDomain("PepsiCola", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+
+
+ writeToInterface("TenGigabitEthernet86/0/1",
+ "Physical 10GbE Interface (Transport)",
+ true, null, 7);
+ writeToInterface("TenGigabitEthernet86/0/0", "Physical 10GbE Interface",
+ true, "CocaCola", 0);
+ writeToInterface("GigabitEthernet8/0/1", "Physical 1GbE Interface",
+ true, "PepsiCola", 0);
+
+ /*
+ writeIpv4AddressToInterface("GigabitEthernet86/0/1",
+ new Ipv4AddressNoZone("10.10.10.10"),
+ (short)24);
+ writeIpv4AddressToInterface("GigabitEthernet86/0/1",
+ new Ipv4AddressNoZone("11.11.11.10"),
+ (short)24);
+ writeIpv4AddressToInterface("GigabitEthernet86/0/1",
+ new Ipv4AddressNoZone("11.11.11.10"),
+ (short)24);
+ */
+ /* Interfaces on virtual testbed VMs (e.g. js-cluster-1) */
+ writeToBridgeDomain("Balvenie", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+ writeToBridgeDomain("Laphroaig", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+ writeToBridgeDomain("Glenfiddich", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+ writeToBridgeDomain("Macallan", true /*flood*/, true /*forward*/,
+ true /*learn*/, true /*uuFlood*/,
+ false /*arpTermination*/);
+
+ writeToInterface("GigabitEthernet2/2/0", "Physical 1GbE Interface",
+ true, "Balvenie", 0);
+ writeToInterface("GigabitEthernet2/3/0", "Physical 1GbE Interface",
+ true, "Laphroaig", 0);
+ writeToInterface("GigabitEthernet2/4/0", "Physical 1GbE Interface",
+ true, "Glenfiddich", 0);
+ writeToInterface("GigabitEthernet2/5/0", "Physical 1GbE Interface",
+ true, "Macallan", 0);
+ writeToInterface("GigabitEthernet2/6/0",
+ "Physical 1GbE Interface (Transport)",
+ true, null, 7);
+ }
+
+ /* operational data */
+
+ private void initVppOperational() {
+ /*
+ * List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.
+ * interfaces.rev140508.interfaces.state.Interface> ifaces = new
+ * ArrayList<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.
+ * ietf.interfaces.rev140508.interfaces.state.Interface>();
+ */
+ LOG.info("VPPOPER-INFO: Preparing to initialize the IETF Interface " + "state list operational db.");
+ InterfacesState ifsState = new InterfacesStateBuilder().build();
+ WriteTransaction tx = db.newWriteOnlyTransaction();
+ InstanceIdentifier<InterfacesState> isid = InstanceIdentifier.builder(InterfacesState.class).build();
+ tx.put(LogicalDatastoreType.OPERATIONAL, isid, ifsState);
+ Futures.addCallback(tx.submit(), new LoggingFuturesCallBack<>(
+ "VPPOPER-WARNING: Failed to create IETF " + "Interface state list operational db.", LOG));
+ }
+
+ private void startOperationalUpdateTimer() {
+ Timer timer = new Timer();
+
+ // fire task after 1 second and then repeat each 10 seconds
+ timer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ vppPollOperData.updateOperational();
+ }
+ }, 1000, 10000);
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("VPP-INFO: V3poProvider Session Initiated");
+ int rv = api.clientConnect("v3poODL");
+ LOG.info("VPP-INFO: VPP api client connection return value = {}", rv);
+ if (rv != 0) {
+ LOG.error("VPP-ERROR: VPP api client connection failed: return value = {}", rv);
+ return;
+ }
+ db = session.getSALService(DataBroker.class);
+ initializeVppConfig();
+ initVppOperational();
+
+ vppPollOperData = new VppPollOperDataImpl(db);
+ v3poService = session.addRpcImplementation(V3poService.class,
+ vppPollOperData);
+ startOperationalUpdateTimer();
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("VPP-INFO: V3poProvider Closed");
+ if (v3poService != null) {
+ v3poService.close();
+ }
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poRequest.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poRequest.java
new file mode 100644
index 000000000..900161577
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/V3poRequest.java
@@ -0,0 +1,28 @@
+/*
+ * 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 org.openvpp.vppjapi.vppApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Abstract class overriding all callbacks with default error message
+ */
+public abstract class V3poRequest extends vppApi {
+ private static final Logger LOG = LoggerFactory.getLogger(V3poRequest.class);
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppBridgeDomainListener.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppBridgeDomainListener.java
new file mode 100644
index 000000000..94d8df7c7
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppBridgeDomainListener.java
@@ -0,0 +1,217 @@
+/*
+ * 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.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.vppjapi.vppApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VppBridgeDomainListener implements DataTreeChangeListener<BridgeDomain>,
+ AutoCloseable {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(VppBridgeDomainListener.class);
+ private ListenerRegistration<VppBridgeDomainListener> registration;
+ private DataBroker db;
+ private vppApi api;
+
+ private enum DataChangeType {
+ CREATE, UPDATE, DELETE
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public VppBridgeDomainListener(DataBroker db, vppApi api) {
+ this.db = db;
+ this.api = api;
+ InstanceIdentifier<BridgeDomain> iid = InstanceIdentifier
+ .create(Vpp.class)
+ .child(BridgeDomains.class)
+ .child(BridgeDomain.class);
+ LOG.info("VPPCFG-INFO: Register listener for VPP Bridge Domain data changes");
+
+ DataTreeIdentifier<BridgeDomain> path =
+ new DataTreeIdentifier<BridgeDomain>(LogicalDatastoreType.CONFIGURATION, iid);
+ registration = this.db.registerDataTreeChangeListener(path, this);
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<BridgeDomain>> changes) {
+
+ for (DataTreeModification<BridgeDomain> change: changes) {
+ InstanceIdentifier<BridgeDomain> iid = change.getRootPath().getRootIdentifier();
+ DataObjectModification<BridgeDomain> changeDiff = change.getRootNode();
+
+ switch (changeDiff.getModificationType()) {
+ case SUBTREE_MODIFIED:
+ case WRITE:
+ // create, modify or replace
+ createOrUpdateBridgeDomain(changeDiff);
+ break;
+ case DELETE:
+ deleteBridgeDomain(changeDiff);
+ break;
+ default:
+ LOG.info("Unsupported change type {} for {}",
+ changeDiff.getModificationType(), iid);
+ }
+ }
+ }
+
+ // handles only CREATE and UPDATE calls
+ private void vppSetBridgeDomain(BridgeDomain bridgeDomain, DataChangeType type,
+ BridgeDomain originalBridgeDomain) {
+ int rv = -77;
+ int cnt = 0;
+ String bdName = bridgeDomain.getName();
+ int bdId = api.findOrAddBridgeDomainId(bdName);
+
+ LOG.info("VPPCFG-INFO: {} <bridgeDomain>", type);
+ LOG.info("VPPCFG-INFO: Name: " + bdName);
+ LOG.info("VPPCFG-INFO: Flood: {} ", bridgeDomain.isFlood());
+ LOG.info("VPPCFG-INFO: Forward: {} ", bridgeDomain.isForward());
+ LOG.info("VPPCFG-INFO: Learn: {} ", bridgeDomain.isLearn());
+ LOG.info("VPPCFG-INFO: UnknownUnicastFlood: {} ",
+ bridgeDomain.isUnknownUnicastFlood());
+ LOG.info("VPPCFG-INFO: ArpTermination: {} ",
+ bridgeDomain.isArpTermination());
+ LOG.info("VPPCFG-INFO: {} </bridgeDomain>", type);
+
+ switch (type) {
+ case CREATE:
+ case UPDATE:
+ byte flood = bridgeDomain.isFlood() ? (byte) 1 : (byte) 0;
+ byte forward = bridgeDomain.isForward() ? (byte) 1 : (byte) 0;
+ byte learn = bridgeDomain.isLearn() ? (byte) 1 : (byte) 0;
+ byte uuf = bridgeDomain.isUnknownUnicastFlood() ? (byte) 1 : (byte) 0;
+ byte arpTerm = bridgeDomain.isArpTermination() ? (byte) 1 : (byte) 0;
+ if ((bdId == -1) || (bdId == 0)) {
+ LOG.warn("VPPCFG-WARNING: Bridge Domain create/lookup failed"
+ + " (bdId = {})! Ignoring vppSetBridgeDomain request {}",
+ bdId, type);
+ return;
+ } else {
+ int ctxId = api.bridgeDomainAddDel(bdId, flood, forward,
+ learn, uuf, arpTerm,
+ (byte) 1 /* isAdd */);
+ LOG.info("VPPCFG-INFO: {} api.bridgeDomainAddDel({} ({})) "
+ + "ctxId = {}", type, bdName, bdId, ctxId);
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ LOG.info("VPPCFG-INFO: {} api.bridgeDomainAddDel({} ({})) "
+ + "retval {} after {} tries.",
+ type, bdName, bdId, rv, cnt);
+
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {} api.bridgeDomainAddDel({}"
+ + " ({})) failed: retval {}!",
+ type, bdName, bdId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ }
+ }
+ break;
+ default:
+ LOG.warn("VPPCFG-WARNING: Unknown DataChangeType {}! "
+ + "Ignoring vppSetBridgeDomain request", type);
+ return;
+ }
+ bdId = api.bridgeDomainIdFromName(bdName);
+ LOG.info("VPPCFG-INFO: {} api.bridgeDomainIdFromName({}) = {}",
+ type, bdName, bdId);
+ }
+
+ private void createOrUpdateBridgeDomain(DataObjectModification<BridgeDomain> changeDiff) {
+ if (changeDiff.getDataBefore() == null) {
+ vppSetBridgeDomain(changeDiff.getDataAfter(),
+ DataChangeType.CREATE, null);
+ } else {
+ vppSetBridgeDomain(changeDiff.getDataAfter(),
+ DataChangeType.UPDATE,
+ changeDiff.getDataBefore());
+ }
+ }
+
+ // handles DELETE calls
+ private void deleteBridgeDomain(DataObjectModification<BridgeDomain> changeDiff) {
+ DataChangeType type = DataChangeType.DELETE;
+ BridgeDomain bridgeDomain = changeDiff.getDataBefore();
+ String bdName = bridgeDomain.getName();
+ int rv = -77;
+ int cnt = 0;
+
+ LOG.info("VPPCFG-INFO: {} <bridgeDomain>", type);
+ LOG.info("VPPCFG-INFO: Name: " + bdName);
+ LOG.info("VPPCFG-INFO: Flood: {} ", bridgeDomain.isFlood());
+ LOG.info("VPPCFG-INFO: Forward: {} ", bridgeDomain.isForward());
+ LOG.info("VPPCFG-INFO: Learn: {} ", bridgeDomain.isLearn());
+ LOG.info("VPPCFG-INFO: UnknownUnicastFlood: {} ",
+ bridgeDomain.isUnknownUnicastFlood());
+ LOG.info("VPPCFG-INFO: ArpTermination: {} ",
+ bridgeDomain.isArpTermination());
+ LOG.info("VPPCFG-INFO: {} </bridgeDomain>", type);
+
+ int bdId = api.findOrAddBridgeDomainId(bdName);
+ if ((bdId == -1) || (bdId == 0)) {
+ LOG.warn("VPPCFG-WARNING: Unknown Bridge Domain {} "
+ + " (bdId = {})! Ignoring vppSetBridgeDomain request {}",
+ bdName, bdId, type);
+ return;
+ } else {
+ int ctxId = api.bridgeDomainAddDel(bdId, (byte) 0 /* flood */,
+ (byte) 0 /* forward */,
+ (byte) 0 /* learn */,
+ (byte) 0 /* uuf */,
+ (byte) 0 /* arpTerm */,
+ (byte) 0 /* isAdd */);
+ LOG.info("VPPCFG-INFO: {} api.bridgeDomainAddDel({} ({})) "
+ + "ctxId = {}", type, bdName, bdId, ctxId);
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ LOG.info("VPPCFG-INFO: {} api.bridgeDomainAddDel({} ({})) "
+ + "retval {} after {} tries.",
+ type, bdName, bdId, rv, cnt);
+
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {} api.bridgeDomainAddDel({} ({}))"
+ + " failed: retval {}!", type, bdName, bdId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ registration.close();
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppIetfInterfaceListener.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppIetfInterfaceListener.java
new file mode 100644
index 000000000..7e6aa50f1
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppIetfInterfaceListener.java
@@ -0,0 +1,566 @@
+/*
+ * 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.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.ietf.inet.types.rev130715.Ipv4Address;
+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.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.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.Subnet;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
+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._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.Interconnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.XconnectBased;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.vppjapi.vppApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VppIetfInterfaceListener implements DataTreeChangeListener<Interface>, AutoCloseable {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(VppIetfInterfaceListener.class);
+
+ private ListenerRegistration<VppIetfInterfaceListener> registration;
+ private DataBroker db;
+ private vppApi api;
+
+ private enum DataChangeType {
+ CREATE, UPDATE, DELETE
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public VppIetfInterfaceListener(DataBroker db, vppApi api) {
+ this.db = db;
+ this.api = api;
+ InstanceIdentifier<Interface> iid = InstanceIdentifier
+ .create(Interfaces.class)
+ .child(Interface.class);
+ LOG.info("VPPCFG-INFO: Register listener for VPP Ietf Interface data changes");
+
+ DataTreeIdentifier<Interface> path =
+ new DataTreeIdentifier<Interface>(LogicalDatastoreType.CONFIGURATION, iid);
+
+ registration = this.db.registerDataTreeChangeListener(path, this);
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<Interface>> changes) {
+ LOG.info("VPPCFG-INFO: swIf onDataTreeChanged()");
+ for (DataTreeModification<Interface> change: changes) {
+ InstanceIdentifier<Interface> iid = change.getRootPath().getRootIdentifier();
+ DataObjectModification<Interface> changeDiff = change.getRootNode();
+
+ switch (changeDiff.getModificationType()) {
+ case SUBTREE_MODIFIED:
+ case WRITE:
+ // create, modify or replace
+ createOrUpdateInterface(changeDiff);
+ break;
+ case DELETE:
+ deleteInterface(changeDiff);
+ break;
+ default:
+ LOG.info("Unsupported change type {} for {}",
+ changeDiff.getModificationType(), iid);
+ }
+ }
+ }
+
+ private void vppSetVppInterfaceEthernetAndL2(int swIfIndex,
+ String swIfName,
+ VppInterfaceAugmentation
+ vppInterface) {
+ int ctxId = 0;
+ int rv = -77;
+ int cnt = 0;
+ String apiName = "";
+
+ LOG.info("VPPCFG-INFO: <vppSetVppInterfaceEthernetAndL2>");
+ LOG.info("VPPCFG-INFO: swIfIndex = {}", swIfIndex);
+ LOG.info("VPPCFG-INFO: swIfName = {}", swIfName);
+ LOG.info("VPPCFG-INFO: vppInterface = {}", vppInterface);
+ LOG.info("VPPCFG-INFO: </vppSetVppInterfaceEthernetAndL2>");
+ if (vppInterface != null) {
+ Ethernet vppEth = vppInterface.getEthernet();
+ if (vppEth != null) {
+ LOG.info("VPPCFG-INFO: {} Ethernet MTU = {}",
+ swIfName, vppEth.getMtu());
+ /* DAW-FIXME: Need vpe-api msg to configure the Ethernet MTU */
+ }
+
+ L2 vppL2 = vppInterface.getL2();
+ if (vppL2 != null) {
+ Interconnection ic = vppL2.getInterconnection();
+ if (ic instanceof XconnectBased) {
+ XconnectBased xc = (XconnectBased) ic;
+ String outSwIfName = xc.getXconnectOutgoingInterface();
+ LOG.info("VPPCFG-INFO: XconnectBased");
+ LOG.info("VPPCFG-INFO: XconnectOutgoingInterface = {}",
+ outSwIfName);
+
+ int outSwIfIndex = api.swIfIndexFromName(outSwIfName);
+ if (swIfIndex != -1) {
+ apiName = "api.swInterfaceSetL2Xconnect";
+ ctxId =
+ api.swInterfaceSetL2Xconnect(swIfIndex,
+ outSwIfIndex,
+ (byte)1 /* enable */);
+ LOG.info("VPPCFG-INFO: {}() : outSwIfName = {}, "
+ + "outSwIfIndex = {}, ctxId = {}", apiName,
+ outSwIfName, outSwIfIndex, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {}() ctxId = {} failed:"
+ + " retval = {}!", apiName, ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {}"
+ + " after {} tries.", apiName, ctxId,
+ rv, cnt);
+ }
+
+ } else {
+ LOG.warn("VPPCFG-WARNING: Unknown Outgoing Interface ({})"
+ + " specified", outSwIfName);
+ }
+
+ } else if (ic instanceof BridgeBased) {
+ BridgeBased bb = (BridgeBased) ic;
+ String bdName = bb.getBridgeDomain();
+ int bdId = api.bridgeDomainIdFromName(bdName);
+ if (bdId > 0) {
+ byte bvi =
+ bb.isBridgedVirtualInterface() ? (byte) 1 : (byte) 0;
+ byte shg = bb.getSplitHorizonGroup().byteValue();
+
+ LOG.info("VPPCFG-INFO: BridgeBased");
+ LOG.info("VPPCFG-INFO: BridgeDomain = {}, bdId = {}",
+ bdName, bdId);
+ LOG.info("VPPCFG-INFO: SplitHorizonGroup = {}",
+ shg);
+ LOG.info("VPPCFG-INFO: isBridgedVirtualInterface = {}",
+ bvi);
+
+ apiName = "api.swInterfaceSetL2Bridge";
+ ctxId =
+ api.swInterfaceSetL2Bridge(swIfIndex,
+ bdId, shg, bvi,
+ (byte)1 /* enable */);
+ LOG.info("VPPCFG-INFO: {}() : bdId = {}, shg = {}, "
+ + "bvi = {}, ctxId = {}", apiName, bdId,
+ shg, bvi, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING:{}() ctxId = {} failed: "
+ + "retval = {}!", apiName, ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {}"
+ + " after {} tries.", apiName, ctxId,
+ rv, cnt);
+ }
+
+ } else {
+ LOG.error("VPPCFG-ERROR: Bridge Domain {} does not exist!",
+ bdName);
+ }
+
+ } else {
+ LOG.error("VPPCFG-ERROR: unknonwn interconnection type!");
+ }
+ }
+ }
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public static int parseIp(String address) {
+ int result = 0;
+
+ // iterate over each octet
+ for (String part : address.split("\\.")) {
+ // shift the previously parsed bits over by 1 byte
+ result = result << 8;
+ // set the low order bits to the current octet
+ result |= Integer.parseInt(part);
+ }
+ return result;
+ }
+
+ private void createVxlanTunnel(String swIfName, Vxlan vxlan) {
+ Ipv4Address srcAddress = vxlan.getSrc();
+ Ipv4Address dstAddress = vxlan.getDst();
+
+ int srcAddr = parseIp(srcAddress.getValue());
+ int dstAddr = parseIp(dstAddress.getValue());
+ int encapVrfId = vxlan.getEncapVrfId().intValue();
+ int vni = vxlan.getVni().intValue();
+
+ int ctxId = api.vxlanAddDelTunnel((byte)1 /* is add */, srcAddr, dstAddr, encapVrfId, -1, vni);
+ String apiName = "api.vxlanAddDelTunnel";
+ LOG.info("VPPCFG-INFO: {}({}, src: {}, dst: {} enabled ([]), ...) : "
+ + "ctxId = {}", apiName, swIfName, srcAddress.getValue(),
+ dstAddress.getValue(), ctxId);
+
+ /* need to wait for creation of interface */
+ int rv = -77;
+ int cnt = 0;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {}() ctxId = {} failed: retval = {}!", apiName, ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {} after {} tries.", apiName, ctxId, rv, cnt);
+ }
+ }
+
+ private byte [] ipv4AddressNoZoneToArray(Ipv4AddressNoZone ipv4Addr) {
+ byte [] retval = new byte [4];
+ String addr = ipv4Addr.getValue().toString();
+ String [] dots = addr.split("\\.");
+
+ for (int d = 3; d >= 0; d--) {
+ retval[d] = (byte)(Short.parseShort(dots[3 - d]) & 0xff);
+ }
+ return retval;
+ }
+
+ private void vppSetInterface(Interface swIf, DataChangeType type,
+ Interface originalIf) {
+ VppInterfaceAugmentation vppInterface =
+ swIf.getAugmentation(VppInterfaceAugmentation.class);
+ int ctxId = 0;
+ int cnt = 0;
+ int rv = -77;
+ String apiName = "";
+
+ /* DAW-FIXME: If type == UPDATE, use originalDataObject to get
+ * state of api parameters which have not been changed.
+ * For now, all parameters must be set at the same time.
+ */
+ LOG.info("VPPCFG-INFO: {} <swIf>", type);
+ LOG.info("VPPCFG-INFO: Name: " + swIf.getName());
+ LOG.info("VPPCFG-INFO: Desc: " + swIf.getDescription());
+ java.lang.Class<? extends
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType>
+ ifType = swIf.getType();
+ if (ifType != null) {
+ LOG.info("VPPCFG-INFO: Type: " + swIf.getType().getSimpleName());
+ }
+ LOG.info("VPPCFG-INFO: {} </swIf>", type);
+
+ String swIfName = swIf.getName();
+ int swIfIndex = api.swIfIndexFromName(swIfName);
+
+ if ((ifType != null) && ifType.isAssignableFrom(EthernetCsmacd.class)) {
+ if (swIfIndex != -1) {
+ LOG.info("VPPCFG-INFO: {} : swIfIndex = {}",
+ swIfName, swIfIndex);
+
+ /* set vpp ethernet and l2 containers */
+ vppSetVppInterfaceEthernetAndL2(swIfIndex, swIfName,
+ vppInterface);
+
+ byte enabled = swIf.isEnabled() ? (byte) 1 : (byte) 0;
+ apiName = "api.swInterfaceSetFlags";
+ ctxId = api.swInterfaceSetFlags((int)swIfIndex,
+ (byte)enabled,
+ (byte)enabled,
+ (byte)0 /* deleted */);
+ LOG.info("VPPCFG-INFO: {}({} ([]), enabled ([]), ...) : "
+ + "ctxId = {}", apiName, swIfName, swIfIndex,
+ enabled, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: api.swInterfaceSetFlags() "
+ + "ctxId = {} failed: retval = {}!", ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {} after"
+ + " {} tries.", apiName, ctxId, rv, cnt);
+ }
+ } else {
+ LOG.error("VPPCFG-ERROR: {} not found!",
+ swIf.getType().getSimpleName());
+ LOG.error("VPPCFG-ERROR: cannot create {} type interfaces : "
+ + "ignoring create request for {} !",
+ swIf.getType().getSimpleName(), swIf.getName());
+ }
+
+ } else if ((ifType != null)
+ && ifType.isAssignableFrom(VxlanTunnel.class)) {
+ LOG.info("VPPCFG-INFO: VxLAN tunnel configuration");
+
+ // TODO: check name of interface, make use of renumber to change vpp
+ // interface name to desired one
+
+ if (swIfIndex != -1) {
+ // interface exists in vpp
+ if (type == DataChangeType.DELETE) {
+ // TODO
+ } else {
+ // TODO
+ Vxlan vxlan = vppInterface.getVxlan();
+
+ LOG.info("Vxlan update: {}", vxlan);
+ }
+ } else {
+ // interface does not exist in vpp
+ if (type == DataChangeType.DELETE) {
+ // cannot delete non existent interface
+ LOG.error("VPPCFG-ERROR: Cannot delete non existing interface ({})", swIf.getName());
+ } else {
+ Vxlan vxlan = vppInterface.getVxlan();
+
+ createVxlanTunnel(swIfName, vxlan);
+
+ // refresh interfaces to be able to get ifIndex
+ api.swInterfaceDump((byte)1, "vxlan".getBytes());
+
+ int newSwIfIndex = api.swIfIndexFromName(swIfName);
+
+ /* set vpp ethernet and l2 containers */
+ vppSetVppInterfaceEthernetAndL2(newSwIfIndex,
+ swIfName,
+ vppInterface);
+
+ byte enabled = swIf.isEnabled() ? (byte) 1 : (byte) 0;
+ ctxId = api.swInterfaceSetFlags((int)newSwIfIndex,
+ (byte)enabled,
+ (byte)enabled,
+ (byte)0 /* deleted */);
+
+ swIfIndex = newSwIfIndex;
+
+ apiName = "api.swInterfaceSetFlags";
+ LOG.info("VPPCFG-INFO: {}({} ({}), enabled ({}), ...) :"
+ + " ctxId = {}", apiName, swIfName,
+ newSwIfIndex, enabled, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {}() ctxId = {} failed: retval = {}!", apiName, ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {} after {} tries.", apiName, ctxId, rv, cnt);
+ }
+ }
+ }
+
+ /* DAW-FIXME: Add additional interface types here.
+ *
+ * } else if ((ifType != null) && ifType.isAssignableFrom(*.class)) {
+ */
+ } else if (ifType != null) {
+ LOG.error("VPPCFG-ERROR: Unsupported interface type ({}) : {}"
+ + " cannot be created!", ifType.getSimpleName(),
+ swIf.getName());
+ }
+
+ if (swIfIndex == -1) {
+ LOG.warn("VPPCFG-INFO: Unknown Interface {}", swIfName);
+ return;
+ }
+
+ if (swIf.getDescription() != null) {
+ api.setInterfaceDescription(swIfName, swIf.getDescription());
+ } else {
+ api.setInterfaceDescription(swIfName, "");
+ }
+ Routing rt = vppInterface.getRouting();
+ int vrfId = (rt != null) ? rt.getVrfId().intValue() : 0;
+ LOG.info("VPPCFG-INFO: vrfId = {}", vrfId);
+ if (vrfId > 0) {
+ apiName = "api.swInterfaceSetTable";
+ ctxId = api.swInterfaceSetTable((int)swIfIndex,
+ (byte)0, /* isIpv6 */
+ vrfId);
+ LOG.info("VPPCFG-INFO: {}({} ([]), 0 /* isIpv6 */, {} /* vrfId */)"
+ + " : ctxId = {}", apiName, swIfName, swIfIndex,
+ vrfId, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: api.swInterfaceSetTable() ctxId = {} failed: retval = {}!", ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval = {} after {} tries.", apiName, ctxId, rv, cnt);
+ }
+ }
+
+ Interface1 ipIf = swIf.getAugmentation(Interface1.class);
+ LOG.info("VPPCFG-INFO: ipIf = {}", ipIf);
+ if (ipIf != null) {
+ Ipv4 v4 = ipIf.getIpv4();
+ if (v4 != null) {
+ LOG.info("VPPCFG-INFO: v4 = {}", v4);
+
+ for (Address v4Addr : v4.getAddress()) {
+ Subnet subnet = v4Addr.getSubnet();
+
+ if (subnet instanceof PrefixLength) {
+ Short plen = ((PrefixLength)subnet).getPrefixLength();
+ byte [] addr = ipv4AddressNoZoneToArray(v4Addr.getIp());
+
+ if ((plen > 0) && (addr != null)) {
+ apiName = "api.swInterfaceAddDelAddress";
+ ctxId =
+ api.swInterfaceAddDelAddress((int)swIfIndex,
+ (byte)1 /* isAdd */,
+ (byte)0 /* isIpv6 */,
+ (byte)0 /* delAll */,
+ plen.byteValue(), addr);
+ LOG.info("VPPCFG-INFO: {}({}/{}) to {} ({}): {}()"
+ + " returned ctxId = {}", apiName, addr,
+ plen, swIfName, swIfIndex, ctxId);
+ cnt = 0;
+ rv = -77;
+ while (rv == -77) {
+ rv = api.getRetval(ctxId, 1 /* release */);
+ cnt++;
+ }
+ if (rv < 0) {
+ LOG.warn("VPPCFG-WARNING: {}() ctxId = {} "
+ + "failed: retval = {}!", apiName,
+ ctxId, rv);
+ /* DAW-FIXME: throw exception on failure? */
+ } else {
+ LOG.info("VPPCFG-INFO: {}() ctxId = {} retval"
+ + " = {} after {} tries.", apiName,
+ ctxId, rv, cnt);
+ }
+ } else {
+ LOG.warn("VPPCFG-WARNING: Malformed ipv4 address ({}/{}) "
+ + "specified for {} ({}): ignoring config!",
+ addr, plen, swIfName, swIfIndex);
+ }
+ } else if (subnet instanceof Netmask) {
+ LOG.warn("VPPCFG-WARNING: Unsupported ipv4 address subnet type 'Netmask' "
+ + "specified for {} ({}): ignoring config!",
+ swIfName, swIfIndex);
+ } else {
+ LOG.error("VPPCFG-ERROR: Unknown ipv4 address subnet type "
+ + "specified for {} ({}): ignoring config!",
+ swIfName, swIfIndex);
+ }
+ }
+ }
+
+ Ipv6 v6 = ipIf.getIpv6();
+ if (v6 != null) {
+ LOG.info("VPPCFG-INFO: v6 = {}", v6);
+
+ // DAW-FIXME: Add Ipv6 address support.
+ LOG.warn("VPPCFG-WARNING: Ipv6 address support TBD: ignoring config!");
+ }
+ }
+ }
+
+ private void createOrUpdateInterface(DataObjectModification<Interface> changeDiff) {
+ if (changeDiff.getDataBefore() == null) {
+ // create
+ vppSetInterface(changeDiff.getDataAfter(),
+ DataChangeType.CREATE, null);
+ } else {
+ // update
+ vppSetInterface(changeDiff.getDataAfter(),
+ DataChangeType.UPDATE,
+ changeDiff.getDataBefore());
+ }
+ }
+
+ private void deleteInterface(DataObjectModification<Interface> changeDiff) {
+ Interface swIf = changeDiff.getDataBefore();
+ LOG.info("VPPCFG-INFO: <swIf>");
+ LOG.info("VPPCFG-INFO: Name: " + swIf.getName());
+ LOG.info("VPPCFG-INFO: Desc: " + swIf.getDescription());
+ LOG.info("VPPCFG-INFO: Type: " + swIf.getType().getSimpleName());
+ LOG.info("VPPCFG-INFO: </swIf>");
+
+ if (swIf.getType().isAssignableFrom(EthernetCsmacd.class)) {
+ LOG.error("VPPCFG-ERROR: {} Interface {} cannot be deleted!",
+ swIf.getType().getSimpleName(),
+ swIf.getName());
+
+ /* DAW-FIXME: Add additional interface types here.
+ *
+ * } else if (swIf.getType().isAssignableFrom(*.class)) {
+ */
+
+ } else {
+ LOG.error("VPPCFG-ERROR: Unsupported interface type ({}) : "
+ + "{} cannot be deleted!",
+ swIf.getType().getSimpleName(),
+ swIf.getName());
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ registration.close();
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppPollOperDataImpl.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppPollOperDataImpl.java
new file mode 100644
index 000000000..71d4bea4b
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppPollOperDataImpl.java
@@ -0,0 +1,147 @@
+/*
+ * 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.util.HashMap;
+import java.util.concurrent.Future;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+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.opendaylight.params.xml.ns.yang.v3po.rev150105.V3poService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppPollOperDataOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppPollOperDataOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.openvpp.vppjapi.vppBridgeDomainDetails;
+import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails;
+import org.openvpp.vppjapi.vppL2Fib;
+import org.openvpp.vppjapi.vppVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VppPollOperDataImpl implements V3poService {
+ private static final Logger LOG = LoggerFactory.getLogger(VppPollOperDataImpl.class);
+ private vppVersion version;
+ private DataBroker db;
+ private int[] bdIds;
+ private HashMap<Integer, vppL2Fib[]> l2fibByBdId = new HashMap<Integer, vppL2Fib[]>();
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public VppPollOperDataImpl(DataBroker dataBroker) {
+ db = dataBroker;
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public DataBroker getDataBroker() {
+ return db;
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ * Update operational data and return string of space separated
+ * interfaces names
+ */
+ public String updateOperational() {
+ V3poApiRequest api = new V3poApiRequest(this);
+ version = api.getVppVersion();
+
+ bdIds = api.bridgeDomainDump(-1);
+
+ // TODO: we don't need to cache BDs now that we got rid of callbacks
+ l2fibByBdId.clear();
+ if (bdIds != null) {
+ for (int idx = 0; idx < bdIds.length; idx++) {
+ l2fibByBdId.put(bdIds[idx], api.l2FibTableDump(bdIds[idx]));
+ }
+ }
+ api.swInterfaceDumpAll();
+
+ // build vpp-state
+ VppStateCustomBuilder stateBuilder = new VppStateCustomBuilder();
+
+ // bridge domains
+ for (int i = 0; i < bdIds.length; i++) {
+ vppBridgeDomainDetails bd = api.getBridgeDomainDetails(bdIds[i]);
+ VppStateBridgeDomainBuilder bdBuilder =
+ new VppStateBridgeDomainBuilder(
+ bd.name, bd.flood, bd.uuFlood,
+ bd.arpTerm, bd.forward, bd.learn);
+
+ for (int ifIdx = 0; ifIdx < bd.interfaces.length; ifIdx++) {
+ vppBridgeDomainInterfaceDetails bdIf = bd.interfaces[ifIdx];
+ bdBuilder.addInterface(bdIf.interfaceName,
+ bd.bviInterfaceName == bdIf.interfaceName,
+ bdIf.splitHorizonGroup);
+ }
+
+ vppL2Fib[] bdFibs = l2fibByBdId.get(bdIds[i]);
+
+ for (int fibIdx = 0; fibIdx < bdFibs.length; fibIdx++) {
+ vppL2Fib fib = bdFibs[fibIdx];
+ bdBuilder.addL2Fib(fib.filter, fib.bridgedVirtualInterface,
+ fib.outgoingInterface, fib.physAddress,
+ fib.staticConfig);
+ }
+
+ stateBuilder.addBridgeDomain(bdBuilder.build());
+ }
+
+ stateBuilder.setVersion(version);
+
+ // write to oper
+ writeVppState(getVppStateIid(), stateBuilder.build());
+
+ return api.ifNames;
+ }
+
+ @Override
+ public Future<RpcResult<VppPollOperDataOutput>> vppPollOperData() {
+ String ifNames = updateOperational();
+
+
+ VppPollOperDataOutput output = new VppPollOperDataOutputBuilder()
+ .setStatus(new Long(1)).build();
+
+ return RpcResultBuilder.success(output).buildFuture();
+ }
+
+ private InstanceIdentifier<VppState> getVppStateIid() {
+ return (InstanceIdentifier.create(VppState.class));
+ }
+
+ private void writeVppState(InstanceIdentifier<VppState> iid, VppState vppState) {
+ WriteTransaction transaction = db.newWriteOnlyTransaction();
+
+ //LOG.info("VPPOPER-INFO: Writing vpp-state to oper DataStore.");
+ transaction.put(LogicalDatastoreType.OPERATIONAL, iid, vppState);
+
+ CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+ Futures.addCallback(future, new LoggingFuturesCallBack<Void>(
+ "VPPOPER-WARNING: Failed to write vpp-state to oper datastore", LOG));
+ }
+}
+
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateBridgeDomainBuilder.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateBridgeDomainBuilder.java
new file mode 100644
index 000000000..d547342bd
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateBridgeDomainBuilder.java
@@ -0,0 +1,102 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+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.vpp.state.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2Fib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2Fib.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibBuilder;
+
+public class VppStateBridgeDomainBuilder {
+ private BridgeDomainBuilder bdStateBuilder = new BridgeDomainBuilder();
+ private List<Interface> bdIfaces = new ArrayList<Interface>();
+ private List<L2Fib> bdL2Fibs = new ArrayList<L2Fib>();
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public VppStateBridgeDomainBuilder(String bdName, boolean flood,
+ boolean unknownUnicastFlood,
+ boolean arpTermination,
+ boolean forward, boolean learn) {
+ bdStateBuilder
+ .setName(bdName)
+ .setFlood(flood)
+ .setUnknownUnicastFlood(unknownUnicastFlood)
+ .setArpTermination(arpTermination)
+ .setForward(forward)
+ .setLearn(learn);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addInterface(String interfaceName, boolean bvi,
+ short splitHorizonGroup) {
+ InterfaceBuilder ifBuilder = new InterfaceBuilder();
+ ifBuilder
+ .setName(interfaceName)
+ .setBridgedVirtualInterface(bvi)
+ .setSplitHorizonGroup(splitHorizonGroup);
+
+ bdIfaces.add(ifBuilder.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();
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addL2Fib(boolean filter, boolean bvi,
+ String outgoingIfaceName, byte[] physAddress,
+ boolean isStatic) {
+ L2FibBuilder l2fibBuilder = new L2FibBuilder();
+ l2fibBuilder
+ .setAction((filter ? Action.Filter : Action.Forward))
+ .setBridgedVirtualInterface(bvi)
+ .setOutgoingInterface(outgoingIfaceName)
+ .setPhysAddress(new PhysAddress(getMacAddress(physAddress)))
+ .setStaticConfig(isStatic);
+
+ bdL2Fibs.add(l2fibBuilder.build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public BridgeDomain build() {
+ bdStateBuilder.setInterface(bdIfaces);
+ bdStateBuilder.setL2Fib(bdL2Fibs);
+ return bdStateBuilder.build();
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateCustomBuilder.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateCustomBuilder.java
new file mode 100644
index 000000000..86e44ec0b
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/VppStateCustomBuilder.java
@@ -0,0 +1,73 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.VersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain;
+import org.openvpp.vppjapi.vppVersion;
+
+public class VppStateCustomBuilder {
+ VppStateBuilder stateBuilder = new VppStateBuilder();
+
+ List<BridgeDomain> bridgeDomains = new ArrayList<BridgeDomain>();
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setVersion(String name, String branch, String buildDate,
+ String buildDir) {
+ stateBuilder.setVersion(
+ new VersionBuilder()
+ .setBranch(branch)
+ .setBuildDate(buildDate)
+ .setBuildDirectory(buildDir)
+ .setName(name)
+ .build());
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void setVersion(vppVersion vppVer) {
+ setVersion(vppVer.programName, vppVer.gitBranch,
+ vppVer.buildDate, vppVer.buildDirectory);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public void addBridgeDomain(BridgeDomain bd) {
+ bridgeDomains.add(bd);
+ }
+
+ /**
+ * TODO-ADD-JAVADOC.
+ */
+ public VppState build() {
+ stateBuilder.setBridgeDomains(
+ new BridgeDomainsBuilder()
+ .setBridgeDomain(bridgeDomains)
+ .build());
+ return stateBuilder.build();
+ }
+}