summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-09-09 11:41:03 +0200
committerMaros Marsalek <mmarsale@cisco.com>2016-09-09 13:26:03 +0200
commit4605c552b8073fb203a204e594e48f137a5b5ee2 (patch)
tree05484da93d8a5374c8a836b07b209c32390cc290
parent413d05ccfc941b56737aac87e9ffea7e1ff46f68 (diff)
HONEYCOMB-204 exclude deleted interfaces from operational data
Change-Id: I187ac52095e15c8c9302871a0d7e7be792e6a0e2 Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
-rw-r--r--v3po/api/src/main/yang/v3po-context.yang29
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManager.java106
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java50
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java51
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java4
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizer.java41
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizer.java68
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizer.java81
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManagerTest.java106
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizerTest.java24
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizerTest.java5
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizerTest.java30
-rw-r--r--vpp-common/naming-context-api/src/main/yang/naming-context.yang2
13 files changed, 488 insertions, 109 deletions
diff --git a/v3po/api/src/main/yang/v3po-context.yang b/v3po/api/src/main/yang/v3po-context.yang
new file mode 100644
index 000000000..ae35be5dd
--- /dev/null
+++ b/v3po/api/src/main/yang/v3po-context.yang
@@ -0,0 +1,29 @@
+module v3po-context {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:v3po:context";
+ prefix "v3po-ctx";
+
+ revision "2016-09-09" {
+ description
+ "Initial revision of v3po specific context";
+ }
+
+ container disabled-interfaces {
+ config false;
+ // context data
+
+ description "Index list of disabled interfaces. VPP does not always delete an interface after deletion. It just
+ disables it and keeps it there. Honeycomb can hide such interfaces from operational data, and this
+ is the place to heep track of which interfaces were deleted, but are expected to show up in VPP";
+
+ list disabled-interface-index {
+
+ key "index";
+
+ leaf index {
+ type int32;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManager.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManager.java
new file mode 100644
index 000000000..9772923c3
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManager.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016 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.translate.v3po;
+
+import com.google.common.base.Optional;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Facade on top of {@link MappingContext} making access to {@link DisabledInterfaces} easier.
+ */
+public class DisabledInterfacesManager {
+
+ private static final InstanceIdentifier<DisabledInterfaces>
+ DISABLED_IFCS_ROOT = InstanceIdentifier.create(DisabledInterfaces.class);
+
+ /**
+ * Read the list of currently disabled interfaces.
+ */
+ public List<Integer> getDisabledInterfaces(@Nonnull final MappingContext ctx) {
+ final Optional<DisabledInterfaces> read = ctx.read(DISABLED_IFCS_ROOT);
+ if (read.isPresent()) {
+ return read.get().getDisabledInterfaceIndex().stream()
+ .map(DisabledInterfaceIndex::getIndex)
+ .collect(Collectors.toList());
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Check whether a specific interface is disabled.
+ */
+ public boolean isInterfaceDisabled(final int index, @Nonnull final MappingContext ctx) {
+ return ctx.read(getKeyedId(index))
+ .isPresent();
+ }
+
+ /**
+ * Make a specific interface disabled.
+ */
+ public void disableInterface(final int index, @Nonnull final MappingContext ctx) {
+ ctx.put(getKeyedId(index), getDisabledInterfaceIndex(index));
+ }
+
+ /**
+ * Remove interface disability.
+ */
+ public void removeDisabledInterface(final int index, @Nonnull final MappingContext ctx) {
+ ctx.delete(getKeyedId(index));
+ }
+
+ private static DisabledInterfaceIndex getDisabledInterfaceIndex(final int index) {
+ return new DisabledInterfaceIndexBuilder().setIndex(index).build();
+ }
+
+ private static KeyedInstanceIdentifier<DisabledInterfaceIndex, DisabledInterfaceIndexKey> getKeyedId(final int id) {
+ return DISABLED_IFCS_ROOT.child(DisabledInterfaceIndex.class, new DisabledInterfaceIndexKey(id));
+ }
+
+ public static final class ContextsReaderFactory implements ReaderFactory {
+
+ @Inject
+ @Named("honeycomb-context")
+ private DataBroker contextBindingBrokerDependency;
+
+ @Override
+ public void init(final ModifiableReaderRegistryBuilder registry) {
+ registry.add(new BindingBrokerReader<>(DISABLED_IFCS_ROOT,
+ contextBindingBrokerDependency,
+ LogicalDatastoreType.OPERATIONAL, DisabledInterfacesBuilder.class));
+ }
+ }
+
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java
index 69ac8f9b8..ef020e971 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java
@@ -66,10 +66,11 @@ import org.openvpp.jvpp.core.future.FutureJVppCore;
public final class InterfacesStateReaderFactory implements ReaderFactory {
- private NamingContext ifcCtx;
- private NamingContext bdCtx;
- private NamingContext classifyCtx;
- private FutureJVppCore jvpp;
+ private final NamingContext ifcNamingCtx;
+ private final NamingContext bdNamingCtx;
+ private final NamingContext classifyNamingCtx;
+ private final DisabledInterfacesManager ifcDisableContext;
+ private final FutureJVppCore jvpp;
static final InstanceIdentifier<InterfacesState> IFC_STATE_ID =
InstanceIdentifier.create(InterfacesState.class);
@@ -77,13 +78,15 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
@Inject
public InterfacesStateReaderFactory(final FutureJVppCore jvpp,
- @Named("interface-context") final NamingContext ifcCtx,
- @Named("bridge-domain-context") final NamingContext bdCtx,
- @Named("classify-table-context") final NamingContext classifyCtx) {
+ @Named("interface-context") final NamingContext ifcNamingCtx,
+ @Named("bridge-domain-context") final NamingContext bdNamingCtx,
+ @Named("classify-table-context") final NamingContext classifyNamingCtx,
+ final DisabledInterfacesManager ifcDisableContext) {
this.jvpp = jvpp;
- this.ifcCtx = ifcCtx;
- this.bdCtx = bdCtx;
- this.classifyCtx = classifyCtx;
+ this.ifcNamingCtx = ifcNamingCtx;
+ this.bdNamingCtx = bdNamingCtx;
+ this.classifyNamingCtx = classifyNamingCtx;
+ this.ifcDisableContext = ifcDisableContext;
}
@Override
@@ -91,14 +94,14 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
// InterfacesState(Structural)
registry.addStructuralReader(IFC_STATE_ID, InterfacesStateBuilder.class);
// Interface
- registry.add(new GenericListReader<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericListReader<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingCtx, ifcDisableContext)));
// v3po.yang
initVppIfcAugmentationReaders(registry, IFC_ID);
// ietf-ip.yang
initInterface2AugmentationReaders(registry, IFC_ID);
// vpp-vlan.yang
- new SubinterfaceStateAugmentationReaderFactory(jvpp, ifcCtx, bdCtx, classifyCtx).init(registry);
+ new SubinterfaceStateAugmentationReaderFactory(jvpp, ifcNamingCtx, bdNamingCtx, classifyNamingCtx).init(registry);
}
private void initInterface2AugmentationReaders(final ModifiableReaderRegistryBuilder registry,
@@ -111,13 +114,13 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
registry.add(new GenericReader<>(ipv4Id, new Ipv4Customizer(jvpp)));
// Address
final InstanceIdentifier<Address> ipv4AddrId = ipv4Id.child(Address.class);
- registry.add(new GenericListReader<>(ipv4AddrId, new Ipv4AddressCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericListReader<>(ipv4AddrId, new Ipv4AddressCustomizer(jvpp, ifcNamingCtx)));
// Neighbor
final InstanceIdentifier<Neighbor> neighborId = ipv4Id.child(Neighbor.class);
registry.add(new GenericListReader<>(neighborId, new Ipv4NeighbourCustomizer(jvpp)));
// Ipv6
final InstanceIdentifier<Ipv6> ipv6Id = ifc2AugId.child(Ipv6.class);
- registry.add(new GenericReader<>(ipv6Id, new Ipv6Customizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(ipv6Id, new Ipv6Customizer(jvpp, ifcNamingCtx)));
}
private void initVppIfcAugmentationReaders(final ModifiableReaderRegistryBuilder registry,
@@ -126,26 +129,27 @@ public final class InterfacesStateReaderFactory implements ReaderFactory {
final InstanceIdentifier<VppInterfaceStateAugmentation> vppIfcAugId = ifcId.augmentation(VppInterfaceStateAugmentation.class);
registry.addStructuralReader(vppIfcAugId, VppInterfaceStateAugmentationBuilder.class);
// Ethernet
- registry.add(new GenericReader<>(vppIfcAugId.child(Ethernet.class), new EthernetCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(Ethernet.class), new EthernetCustomizer(jvpp, ifcNamingCtx)));
// Tap
- registry.add(new GenericReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcNamingCtx)));
// VhostUser
- registry.add(new GenericReader<>(vppIfcAugId.child(VhostUser.class), new VhostUserCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(VhostUser.class), new VhostUserCustomizer(jvpp, ifcNamingCtx)));
// Vxlan
- registry.add(new GenericReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcNamingCtx)));
// VxlanGpe
- registry.add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class), new VxlanGpeCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class), new VxlanGpeCustomizer(jvpp, ifcNamingCtx)));
// Gre
- registry.add(new GenericReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcNamingCtx)));
// L2
- registry.add(new GenericReader<>(vppIfcAugId.child(L2.class), new L2Customizer(jvpp, ifcCtx, bdCtx)));
+ registry.add(new GenericReader<>(vppIfcAugId.child(L2.class), new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx)));
// Acl(Subtree)
final InstanceIdentifier<Acl> aclIdRelative = InstanceIdentifier.create(Acl.class);
registry.subtreeAdd(
Sets.newHashSet(aclIdRelative.child(L2Acl.class), aclIdRelative.child(Ip4Acl.class), aclIdRelative.child(Ip6Acl.class)),
- new GenericReader<>(vppIfcAugId.child(Acl.class), new AclCustomizer(jvpp, ifcCtx, classifyCtx)));
+ new GenericReader<>(vppIfcAugId.child(Acl.class), new AclCustomizer(jvpp, ifcNamingCtx,
+ classifyNamingCtx)));
// Proxy ARP
registry.add(new GenericReader<>(vppIfcAugId.child(ProxyArp.class), new ProxyArpCustomizer(jvpp,
- ifcCtx)));
+ ifcNamingCtx)));
}
}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java
index bfef255ef..cc68d4dda 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java
@@ -83,34 +83,38 @@ public final class InterfacesWriterFactory implements WriterFactory {
private final FutureJVppCore jvpp;
private final IetfAClWriter aclWriter;
- private final NamingContext bdContext;
- private final NamingContext ifcContext;
- private final NamingContext classifyTableContext;
+ private final NamingContext bdNamingContext;
+ private final NamingContext ifcNamingContext;
+ private final NamingContext classifyTableNamingContext;
+ private final DisabledInterfacesManager ifcDisableContext;
@Inject
public InterfacesWriterFactory(final FutureJVppCore vppJvppIfcDependency,
final IetfAClWriter aclWriter,
@Named("bridge-domain-context") final NamingContext bridgeDomainContextDependency,
@Named("interface-context") final NamingContext interfaceContextDependency,
- @Named("classify-table-context") final NamingContext classifyTableContextDependency) {
+ @Named("classify-table-context") final NamingContext classifyTableContextDependency,
+ final DisabledInterfacesManager ifcDisableContext) {
this.jvpp = vppJvppIfcDependency;
this.aclWriter = aclWriter;
- this.bdContext = bridgeDomainContextDependency;
- this.ifcContext = interfaceContextDependency;
- this.classifyTableContext = classifyTableContextDependency;
+ this.bdNamingContext = bridgeDomainContextDependency;
+ this.ifcNamingContext = interfaceContextDependency;
+ this.ifcDisableContext = ifcDisableContext;
+ this.classifyTableNamingContext = classifyTableContextDependency;
}
@Override
public void init(final ModifiableWriterRegistryBuilder registry) {
// Interfaces
// Interface =
- registry.add(new GenericListWriter<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcContext)));
+ registry.add(new GenericListWriter<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingContext)));
// VppInterfaceAugmentation
addVppInterfaceAgmentationWriters(IFC_ID, registry);
// Interface1 (ietf-ip augmentation)
addInterface1AugmentationWriters(IFC_ID, registry);
// SubinterfaceAugmentation
- new SubinterfaceAugmentationWriterFactory(jvpp, aclWriter, ifcContext, bdContext, classifyTableContext).init(registry);
+ new SubinterfaceAugmentationWriterFactory(jvpp, aclWriter, ifcNamingContext, bdNamingContext,
+ classifyTableNamingContext).init(registry);
}
private void addInterface1AugmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -121,14 +125,15 @@ public final class InterfacesWriterFactory implements WriterFactory {
ifcId);
// Ipv4(after interface)
final InstanceIdentifier<Ipv4> ipv4Id = ifc1AugId.child(Ipv4.class);
- registry.addAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp, ifcContext)),
+ registry.addAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp, ifcNamingContext)),
ifcId);
// Address(after Ipv4) =
final InstanceIdentifier<Address> ipv4AddressId = ipv4Id.child(Address.class);
- registry.addAfter(new GenericListWriter<>(ipv4AddressId, new Ipv4AddressCustomizer(jvpp, ifcContext)),
+ registry.addAfter(new GenericListWriter<>(ipv4AddressId, new Ipv4AddressCustomizer(jvpp, ifcNamingContext)),
ipv4Id);
// Neighbor(after ipv4Address)
- registry.addAfter(new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp, ifcContext)),
+ registry.addAfter(new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp,
+ ifcNamingContext)),
ipv4AddressId);
}
@@ -136,24 +141,24 @@ public final class InterfacesWriterFactory implements WriterFactory {
final ModifiableWriterRegistryBuilder registry) {
// VhostUser(Needs to be executed before Interface customizer) =
final InstanceIdentifier<VhostUser> vhostId = VPP_IFC_AUG_ID.child(VhostUser.class);
- registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcContext)),
+ registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext)),
ifcId);
// Vxlan(Needs to be executed before Interface customizer) =
final InstanceIdentifier<Vxlan> vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class);
- registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcContext)),
+ registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext)),
ifcId);
// VxlanGpe(Needs to be executed before Interface customizer) =
final InstanceIdentifier<VxlanGpe> vxlanGpeId = VPP_IFC_AUG_ID.child(VxlanGpe.class);
- registry.addBefore(new GenericWriter<>(vxlanGpeId, new VxlanGpeCustomizer(jvpp, ifcContext)),
- ifcId);
+ registry.addBefore(new GenericWriter<>(vxlanGpeId,
+ new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId);
// Tap(Needs to be executed before Interface customizer) =
final InstanceIdentifier<Tap> tapId = VPP_IFC_AUG_ID.child(Tap.class);
- registry.addBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcContext)),
+ registry.addBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcNamingContext)),
ifcId);
// Gre(Needs to be executed before Interface customizer) =
final InstanceIdentifier<Gre> greId = VPP_IFC_AUG_ID.child(Gre.class);
- registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcContext)),
+ registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext)),
ifcId);
@@ -163,14 +168,14 @@ public final class InterfacesWriterFactory implements WriterFactory {
registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class), new EthernetCustomizer(jvpp)));
// Routing(Execute only after specific interface customizers) =
registry.addAfter(
- new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcContext)),
+ new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcNamingContext)),
specificIfcTypes);
// Routing(Execute only after specific interface customizers) =
- registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcContext, bdContext)),
+ registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcNamingContext, bdNamingContext)),
specificIfcTypes);
// Proxy Arp (execute after specific interface customizers)
registry.addAfter(
- new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp, ifcContext)),
+ new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp, ifcNamingContext)),
specificIfcTypes);
// ACL (execute after classify table and session writers)
// also handles L2Acl, Ip4Acl and Ip6Acl:
@@ -178,7 +183,7 @@ public final class InterfacesWriterFactory implements WriterFactory {
registry
.subtreeAddAfter(
Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)),
- new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcContext, classifyTableContext)),
+ new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcNamingContext, classifyTableNamingContext)),
Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
// IETF-ACL, also handles IetfAcl, AccessLists and Acl:
@@ -188,7 +193,7 @@ public final class InterfacesWriterFactory implements WriterFactory {
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class);
registry.subtreeAdd(
Sets.newHashSet(accessListsID, aclListId),
- new GenericWriter<>(IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcContext)));
+ new GenericWriter<>(IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcNamingContext)));
}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java
index 8485519f5..b0ff0eabb 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java
@@ -58,12 +58,16 @@ public class V3poModule extends AbstractModule {
// Utils
bind(IetfAClWriter.class).toProvider(IetfAClWriterProvider.class);
+ // Context utility for deleted interfaces
+ bind(DisabledInterfacesManager.class).toInstance(new DisabledInterfacesManager());
// Readers
final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
readerFactoryBinder.addBinding().to(InterfacesStateReaderFactory.class);
readerFactoryBinder.addBinding().to(VppStateHoneycombReaderFactory.class);
readerFactoryBinder.addBinding().to(VppClassifierReaderFactory.class);
+ // Expose disabled interfaces in operational data
+ readerFactoryBinder.addBinding().to(DisabledInterfacesManager.ContextsReaderFactory.class);
// Writers
final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizer.java
index 294fdad65..1513f7b15 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizer.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizer.java
@@ -19,11 +19,12 @@ package io.fd.honeycomb.translate.v3po.interfaces;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.net.InetAddresses;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.util.AbstractInterfaceTypeCustomizer;
-import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.v3po.util.NamingContext;
import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.WriteFailedException;
import java.net.InetAddress;
import java.util.concurrent.CompletionStage;
@@ -44,11 +45,16 @@ import org.slf4j.LoggerFactory;
public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> {
private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class);
- private final NamingContext interfaceContext;
- public VxlanCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ private final NamingContext interfaceNamingContext;
+ private final DisabledInterfacesManager interfaceDisableContext;
+
+ public VxlanCustomizer(@Nonnull final FutureJVppCore vppApi,
+ @Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
super(vppApi);
- this.interfaceContext = interfaceContext;
+ this.interfaceNamingContext = interfaceNamingContext;
+ this.interfaceDisableContext = interfaceDisableContext;
}
@Override
@@ -107,7 +113,7 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> {
final VxlanAddDelTunnelReply reply =
TranslateUtils.getReplyForWrite(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan);
- if(interfaceContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
+ if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
// VPP keeps vxlan tunnels present even after they are delete(reserving ID for next tunnel)
// This may cause inconsistencies in mapping context when configuring tunnels like this:
// 1. Add tunnel 2. Delete tunnel 3. Read interfaces (reserved mapping e.g. vxlan_tunnel0 -> 6
@@ -115,13 +121,22 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> {
// reserved ID and context is invalid)
// That's why a check has to be performed here removing mapping vxlan_tunnel0 -> 6 mapping and storing
// new name for that ID
- final String formerName = interfaceContext.getName(reply.swIfIndex, writeContext.getMappingContext());
+ final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
LOG.debug("Removing updated mapping of a vxlan tunnel, id: {}, former name: {}, new name: {}",
reply.swIfIndex, formerName, swIfName);
- interfaceContext.removeName(formerName, writeContext.getMappingContext());
+ interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
+
}
+
+ // Removing disability of an interface in case a vxlan tunnel formerly deleted is being reused in VPP
+ // further details in above comment
+ if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
+ LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
+ interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
+ }
+
// Add new interface to our interface context
- interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
}
private boolean isIpv6(final Vxlan vxlan) {
@@ -156,8 +171,14 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> {
TranslateUtils.getReplyForWrite(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
LOG.debug("Vxlan tunnel deleted successfully for: {}, vxlan: {}", swIfName, vxlan);
- // Remove interface from our interface context
- interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+
+ final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
+ // Mark this interface as disabled to not include it in operational reads
+ // because VPP will keep the interface there
+ LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
+ interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
+ // Remove interface from our interface naming context
+ interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
}
private static VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final byte[] srcAddr, final byte[] dstAddr,
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizer.java
index b97ce127e..699c33d21 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizer.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizer.java
@@ -19,6 +19,7 @@ package io.fd.honeycomb.translate.v3po.interfaces;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.net.InetAddresses;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.util.AbstractInterfaceTypeCustomizer;
import io.fd.honeycomb.translate.v3po.util.NamingContext;
import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
@@ -44,11 +45,15 @@ import org.slf4j.LoggerFactory;
public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe> {
private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
- private final NamingContext interfaceContext;
+ private final NamingContext interfaceNamingContext;
+ private final DisabledInterfacesManager interfaceDisableContext;
- public VxlanGpeCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) {
+ public VxlanGpeCustomizer(@Nonnull final FutureJVppCore vppApi,
+ @Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
super(vppApi);
- this.interfaceContext = interfaceContext;
+ this.interfaceNamingContext = interfaceNamingContext;
+ this.interfaceDisableContext = interfaceDisableContext;
}
@Override
@@ -110,24 +115,32 @@ public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe
final VxlanGpeAddDelTunnelReply reply =
TranslateUtils.getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
LOG.debug("VxlanGpe tunnel set successfully for: {}, VxlanGpe: {}", swIfName, vxlanGpe);
- if(interfaceContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
- final String formerName = interfaceContext.getName(reply.swIfIndex, writeContext.getMappingContext());
+ if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
+ final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
LOG.debug("Removing updated mapping of a vxlan-gpe tunnel, id: {}, former name: {}, new name: {}",
reply.swIfIndex, formerName, swIfName);
- interfaceContext.removeName(formerName, writeContext.getMappingContext());
+ interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
}
+
+ // Removing disability of an interface in case a vxlan-gpe tunnel formerly deleted is being reused in VPP
+ // further details in above comment
+ if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
+ LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
+ interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
+ }
+
// Add new interface to our interface context
- interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
+ interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
}
- private boolean isIpv6(final VxlanGpe VxlanGpe) {
- if (VxlanGpe.getLocal().getIpv4Address() == null) {
- checkArgument(VxlanGpe.getRemote().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s", VxlanGpe.getLocal(),
- VxlanGpe.getRemote());
+ private boolean isIpv6(final VxlanGpe vxlanGpe) {
+ if (vxlanGpe.getLocal().getIpv4Address() == null) {
+ checkArgument(vxlanGpe.getRemote().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s", vxlanGpe.getLocal(),
+ vxlanGpe.getRemote());
return true;
} else {
- checkArgument(VxlanGpe.getRemote().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s", VxlanGpe.getLocal(),
- VxlanGpe.getRemote());
+ checkArgument(vxlanGpe.getRemote().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s", vxlanGpe.getLocal(),
+ vxlanGpe.getRemote());
return false;
}
}
@@ -137,26 +150,31 @@ public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe
}
private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
- final VxlanGpe VxlanGpe, final WriteContext writeContext)
+ final VxlanGpe vxlanGpe, final WriteContext writeContext)
throws VppBaseCallException, WriteTimeoutException {
- final byte isIpv6 = (byte) (isIpv6(VxlanGpe) ? 1 : 0);
- final InetAddress local = InetAddresses.forString(getAddressString(VxlanGpe.getLocal()));
- final InetAddress remote = InetAddresses.forString(getAddressString(VxlanGpe.getRemote()));
+ final byte isIpv6 = (byte) (isIpv6(vxlanGpe) ? 1 : 0);
+ final InetAddress local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
+ final InetAddress remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
- int vni = VxlanGpe.getVni().getValue().intValue();
- byte protocol = (byte) VxlanGpe.getNextProtocol().getIntValue();
- int encapVrfId = VxlanGpe.getEncapVrfId().intValue();
- int decapVrfId = VxlanGpe.getDecapVrfId().intValue();
+ int vni = vxlanGpe.getVni().getValue().intValue();
+ byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
+ int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
+ int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
- LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, VxlanGpe);
+ LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, local.getAddress(),
remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
TranslateUtils.getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
- LOG.debug("VxlanGpe tunnel deleted successfully for: {}, VxlanGpe: {}", swIfName, VxlanGpe);
- // Remove interface from our interface context
- interfaceContext.removeName(swIfName, writeContext.getMappingContext());
+
+ final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
+ // Mark this interface as disabled to not include it in operational reads
+ // because VPP will keep the interface there
+ LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
+ interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
+ // Remove interface from our interface naming context
+ interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
}
private static VxlanGpeAddDelTunnel getVxlanGpeTunnelRequest(final byte isAdd, final byte[] local, final byte[] remote,
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizer.java
index b82a2ddc4..d0baf003a 100644
--- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizer.java
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizer.java
@@ -16,10 +16,12 @@
package io.fd.honeycomb.translate.v3po.interfacesstate;
-import io.fd.honeycomb.translate.read.ReadContext;
-import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.MappingContext;
import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer;
import io.fd.honeycomb.translate.v3po.util.NamingContext;
import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
@@ -27,6 +29,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@@ -57,11 +60,15 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
public static final String DUMPED_IFCS_CONTEXT_KEY =
InterfaceCustomizer.class.getName() + "dumpedInterfacesDuringGetAllIds";
- private final NamingContext interfaceContext;
+ private final NamingContext interfaceNamingContext;
+ private final DisabledInterfacesManager interfaceDisableContext;
- public InterfaceCustomizer(@Nonnull final FutureJVppCore jvpp, final NamingContext interfaceContext) {
+ public InterfaceCustomizer(@Nonnull final FutureJVppCore jvpp,
+ @Nonnull final NamingContext interfaceNamingContext,
+ @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
super(jvpp);
- this.interfaceContext = interfaceContext;
+ this.interfaceNamingContext = interfaceNamingContext;
+ this.interfaceDisableContext = interfaceDisableContext;
}
@Nonnull
@@ -76,9 +83,17 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
LOG.debug("Reading attributes for interface: {}", id);
final String ifaceName = id.firstKeyOf(id.getTargetType()).getName();
+ final int index = interfaceNamingContext.getIndex(ifaceName, ctx.getMappingContext());
+
+ // Ignore disabled interface (such as deleted VXLAN tunnels)
+ if (interfaceDisableContext.isInterfaceDisabled(index, ctx.getMappingContext())) {
+ LOG.debug("Skipping disabled interface: {}", id);
+ return;
+ }
+
// Pass cached details from getAllIds to getDetails to avoid additional dumps
final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), id, ifaceName,
- interfaceContext.getIndex(ifaceName, ctx.getMappingContext()), ctx.getModificationCache());
+ index, ctx.getModificationCache());
LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface);
if (!isRegularInterface(iface)) {
@@ -139,23 +154,42 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
context.getModificationCache().put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream()
.collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)));
- interfacesKeys = ifaces.swInterfaceDetails.stream()
- .filter(elt -> elt != null)
- .map((elt) -> {
- // Store interface name from VPP in context if not yet present
- if (!interfaceContext.containsName(elt.swIfIndex, context.getMappingContext())) {
- interfaceContext.addName(elt.swIfIndex, TranslateUtils.toString(elt.interfaceName),
- context.getMappingContext());
- }
- LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP",
- interfaceContext.getName(elt.swIfIndex, context.getMappingContext()), elt.interfaceName,
- elt.swIfIndex);
-
- return elt;
- })
- .filter(InterfaceCustomizer::isRegularInterface) // filter out sub-interfaces
- .map((elt) -> new InterfaceKey(interfaceContext.getName(elt.swIfIndex, context.getMappingContext())))
- .collect(Collectors.toList());
+ final MappingContext mappingCtx = context.getMappingContext();
+ final Set<Integer> interfacesIdxs = ifaces.swInterfaceDetails.stream()
+ .filter(elt -> elt != null)
+ // Filter out disabled interfaces, dont read them
+ // This also prevents child readers in being invoked such as vxlan (which relies on disabling interfaces)
+ .filter(elt -> !interfaceDisableContext
+ .isInterfaceDisabled(elt.swIfIndex, mappingCtx))
+ .map((elt) -> {
+ // Store interface name from VPP in context if not yet present
+ if (!interfaceNamingContext.containsName(elt.swIfIndex, mappingCtx)) {
+ interfaceNamingContext.addName(elt.swIfIndex, TranslateUtils.toString(elt.interfaceName),
+ mappingCtx);
+ }
+ LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP",
+ interfaceNamingContext.getName(elt.swIfIndex, mappingCtx),
+ elt.interfaceName,
+ elt.swIfIndex);
+
+ return elt;
+ })
+ // filter out sub-interfaces
+ .filter(InterfaceCustomizer::isRegularInterface)
+ .map(elt -> elt.swIfIndex)
+ .collect(Collectors.toSet());
+
+ // Clean disabled interfaces list
+ interfaceDisableContext.getDisabledInterfaces(mappingCtx).stream()
+ // Find indices not currently in VPP
+ .filter(interfacesIdxs::contains)
+ // Remove from disabled list ... not disabled if not existing
+ .forEach(idx -> interfaceDisableContext.removeDisabledInterface(idx, mappingCtx));
+
+ // Transform indices to keys
+ interfacesKeys = interfacesIdxs.stream()
+ .map(index -> new InterfaceKey(interfaceNamingContext.getName(index, context.getMappingContext())))
+ .collect(Collectors.toList());
LOG.debug("Interfaces found in VPP: {}", interfacesKeys);
return interfacesKeys;
@@ -174,5 +208,4 @@ public class InterfaceCustomizer extends FutureJVppCustomizer
@Nonnull final List<Interface> readData) {
((InterfacesStateBuilder) builder).setInterface(readData);
}
-
}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManagerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManagerTest.java
new file mode 100644
index 000000000..7381533e5
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/DisabledInterfacesManagerTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016 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.translate.v3po;
+
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class DisabledInterfacesManagerTest {
+
+ private static final InstanceIdentifier<DisabledInterfaces>
+ ROOT_ID = InstanceIdentifier.create(DisabledInterfaces.class);
+ private static final KeyedInstanceIdentifier<DisabledInterfaceIndex, DisabledInterfaceIndexKey> SPECIFIC_ID_1 =
+ ROOT_ID.child(DisabledInterfaceIndex.class, new DisabledInterfaceIndexKey(1));
+ private static final KeyedInstanceIdentifier<DisabledInterfaceIndex, DisabledInterfaceIndexKey> SPECIFIC_ID_4 =
+ ROOT_ID.child(DisabledInterfaceIndex.class, new DisabledInterfaceIndexKey(4));
+
+ @Mock
+ private MappingContext mappingContext;
+ private DisabledInterfacesManager manager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ manager = new DisabledInterfacesManager();
+ doReturn(Optional.of(new DisabledInterfacesBuilder().setDisabledInterfaceIndex(toIndices(1, 2, 3)).build()))
+ .when(mappingContext)
+ .read(ROOT_ID);
+ doReturn(Optional.of(toIndex(1)))
+ .when(mappingContext)
+ .read(SPECIFIC_ID_1);
+ doReturn(Optional.absent())
+ .when(mappingContext)
+ .read(SPECIFIC_ID_4);
+ }
+
+ @Test
+ public void testGetAll() throws Exception {
+ final List<Integer> disabledInterfaces = manager.getDisabledInterfaces(mappingContext);
+ assertThat(disabledInterfaces, hasItems(1, 2, 3));
+ }
+
+ @Test
+ public void testCheckOne() throws Exception {
+ assertTrue(manager.isInterfaceDisabled(1, mappingContext));
+ assertFalse(manager.isInterfaceDisabled(4, mappingContext));
+ }
+
+ @Test
+ public void testDisable() throws Exception {
+ manager.disableInterface(1, mappingContext);
+ verify(mappingContext).put(SPECIFIC_ID_1, toIndex(1));
+ }
+
+ @Test
+ public void testRemoveDisability() throws Exception {
+ manager.removeDisabledInterface(1, mappingContext);
+ verify(mappingContext).delete(SPECIFIC_ID_1);
+ }
+
+ private List<DisabledInterfaceIndex> toIndices(final int... indices) {
+ return Arrays.stream(indices)
+ .mapToObj(this::toIndex)
+ .collect(Collectors.toList());
+ }
+
+ private DisabledInterfaceIndex toIndex(final int idx) {
+ return new DisabledInterfaceIndexBuilder()
+ .setIndex(idx)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizerTest.java
index 40a6b53bd..0d954deaa 100644
--- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizerTest.java
+++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanCustomizerTest.java
@@ -35,11 +35,12 @@ import static org.mockito.MockitoAnnotations.initMocks;
import com.google.common.base.Optional;
import com.google.common.net.InetAddresses;
-import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.MappingContext;
import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.test.TestHelperUtils;
import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.WriteFailedException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -80,6 +81,8 @@ public class VxlanCustomizerTest {
private WriteContext writeContext;
@Mock
private MappingContext mappingContext;
+ @Mock
+ private DisabledInterfacesManager disableContext;
private VxlanCustomizer customizer;
private String ifaceName;
@@ -96,7 +99,7 @@ public class VxlanCustomizerTest {
doReturn(toBeReturned).when(writeContext).getModificationCache();
doReturn(mappingContext).when(writeContext).getMappingContext();
- customizer = new VxlanCustomizer(api, namingContext);
+ customizer = new VxlanCustomizer(api, namingContext, disableContext);
ifaceName = "eth0";
id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
@@ -175,6 +178,22 @@ public class VxlanCustomizerTest {
}
@Test
+ public void testWriteCurrentAttributesWithExistingVxlanPlaceholder() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenSuccess();
+
+ doReturn(Optional.absent())
+ .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
+ doReturn(true).when(disableContext).isInterfaceDisabled(0, mappingContext);
+
+ customizer.writeCurrentAttributes(id, vxlan, writeContext);
+ verifyVxlanAddWasInvoked(vxlan);
+ verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
+ verify(disableContext).removeDisabledInterface(0, mappingContext);
+ }
+
+ @Test
public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
final Vxlan vxlan = generateVxlan();
@@ -231,6 +250,7 @@ public class VxlanCustomizerTest {
customizer.deleteCurrentAttributes(id, vxlan, writeContext);
verifyVxlanDeleteWasInvoked(vxlan);
verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
+ verify(disableContext).disableInterface(1, mappingContext);
}
@Test
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizerTest.java
index 09e32ffe9..35dacab56 100644
--- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizerTest.java
+++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/VxlanGpeCustomizerTest.java
@@ -34,6 +34,7 @@ import static org.mockito.MockitoAnnotations.initMocks;
import com.google.common.base.Optional;
import com.google.common.net.InetAddresses;
import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.test.ContextTestUtils;
import io.fd.honeycomb.translate.v3po.test.TestHelperUtils;
import io.fd.honeycomb.translate.v3po.util.NamingContext;
@@ -80,6 +81,8 @@ public class VxlanGpeCustomizerTest {
private WriteContext writeContext;
@Mock
private MappingContext mappingContext;
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
private VxlanGpeCustomizer customizer;
private String ifaceName;
@@ -96,7 +99,7 @@ public class VxlanGpeCustomizerTest {
doReturn(toBeReturned).when(writeContext).getModificationCache();
doReturn(mappingContext).when(writeContext).getMappingContext();
- customizer = new VxlanGpeCustomizer(api, namingContext);
+ customizer = new VxlanGpeCustomizer(api, namingContext, interfaceDisableContext);
ifaceName = "eth0";
id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizerTest.java
index a9a2a3c74..f64d750fa 100644
--- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizerTest.java
+++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/InterfaceCustomizerTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
import io.fd.honeycomb.translate.v3po.test.ContextTestUtils;
import io.fd.honeycomb.translate.v3po.test.InterfaceTestUtils;
import io.fd.honeycomb.translate.v3po.test.ListReaderCustomizerTest;
@@ -38,6 +39,7 @@ import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
@@ -57,6 +59,8 @@ public class InterfaceCustomizerTest extends
ListReaderCustomizerTest<Interface, InterfaceKey, InterfaceBuilder> {
private NamingContext interfacesContext;
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
public InterfaceCustomizerTest() {
super(Interface.class);
@@ -89,7 +93,7 @@ public class InterfaceCustomizerTest extends
doReturn(eth1).when(mappingContext).read(eth1Id);
doReturn(subEth1).when(mappingContext).read(subEth1Id);
- return new InterfaceCustomizer(api, interfacesContext);
+ return new InterfaceCustomizer(api, interfacesContext, interfaceDisableContext);
}
@Test
@@ -208,4 +212,28 @@ public class InterfaceCustomizerTest extends
// sub-interface should not be on the list
assertEquals(expectedIds, actualIds);
}
+
+ @Test
+ public void testGetAllIdsWithDisabled() throws Exception {
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class);
+
+ doReturn(true).when(interfaceDisableContext).isInterfaceDisabled(1, mappingContext);
+
+ final String swIf0Name = "eth0";
+ final SwInterfaceDetails swIf0 = new SwInterfaceDetails();
+ swIf0.swIfIndex = 0;
+ swIf0.interfaceName = swIf0Name.getBytes();
+ final String swIf1Name = "eth1";
+ final SwInterfaceDetails swIf1 = new SwInterfaceDetails();
+ swIf1.swIfIndex = 1;
+ swIf1.interfaceName = swIf1Name.getBytes();
+ InterfaceTestUtils.whenSwInterfaceDumpThenReturn(api, Arrays.asList(swIf0, swIf1));
+
+ final List<InterfaceKey> expectedIds = Arrays.asList(new InterfaceKey(swIf0Name));
+ final List<InterfaceKey> actualIds = getCustomizer().getAllIds(id, ctx);
+
+ // disabled interface should not be on the list
+ assertEquals(expectedIds, actualIds);
+ }
}
diff --git a/vpp-common/naming-context-api/src/main/yang/naming-context.yang b/vpp-common/naming-context-api/src/main/yang/naming-context.yang
index fa44bdd12..c101b5c26 100644
--- a/vpp-common/naming-context-api/src/main/yang/naming-context.yang
+++ b/vpp-common/naming-context-api/src/main/yang/naming-context.yang
@@ -12,6 +12,8 @@ module naming-context {
}
container contexts {
+ config false;
+ // context data
list naming-context {