HC2VPP-165 - Optional Local Eid support 87/6987/5
authorJan Srnicek <[email protected]>
Tue, 6 Jun 2017 10:51:42 +0000 (12:51 +0200)
committerJan Srnicek <[email protected]>
Tue, 6 Jun 2017 10:52:41 +0000 (12:52 +0200)
 - Support for optional local eid's for gpe entries
 - Fixes equality issues for mapping identificators
 - Fixed write request ordering of locator pairs

HC2VPP-160 - Use standard index to name mapping for gpe entries

 - Uses indexes returned from dump/write calls to bind context mapping

Change-Id: Ib69240044206dec21307a47981a63f415a16bbdd
Signed-off-by: Jan Srnicek <[email protected]>
14 files changed:
lisp/api/src/main/yang/gpe.yang
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/GpeModule.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryIdentifier.java [deleted file]
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContext.java [deleted file]
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContextImpl.java [deleted file]
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeLocatorPairMappingContextImpl.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/read/GpeForwardEntryCustomizer.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/read/GpeReaderFactory.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/GpeForwardEntryCustomizer.java
lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/write/GpeWriterFactory.java
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/GpeModuleTest.java [new file with mode: 0644]
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/read/GpeForwardEntryCustomizerTest.java
lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/write/GpeForwardEntryCustomizerTest.java
lisp/lisp2vpp/src/test/resources/gpe/invalid/invalid-gpe-fwd-entry-no-local-eid.json

index 91c476f..8a37771 100644 (file)
@@ -57,10 +57,12 @@ module gpe {
           description "Virtual Network Identifier";
         }
         container local-eid {
+          presence "Enforce mandatory only if present";
           uses lisp-types:lisp-address;
           description "Local EID that must be a local address";
         }
         container remote-eid {
+          presence "Enforce mandatory only if present";
           uses lisp-types:lisp-address;
           description "Remote EID";
         }
index 13bdbbd..efdc998 100644 (file)
@@ -20,8 +20,7 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Singleton;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContextImpl;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContextImpl;
 import io.fd.hc2vpp.lisp.gpe.translate.read.GpeReaderFactory;
@@ -38,8 +37,8 @@ public class GpeModule extends AbstractModule {
 
     @Override
     protected void configure() {
-        bind(GpeEntryMappingContext.class).annotatedWith(Names.named(GPE_ENTRY_MAPPING_CTX))
-                .toInstance(new GpeEntryMappingContextImpl(GPE_ENTRY_MAPPING_CTX));
+        bind(NamingContext.class).annotatedWith(Names.named(GPE_ENTRY_MAPPING_CTX))
+                .toInstance(new NamingContext("gpe-entry-", GPE_ENTRY_MAPPING_CTX));
 
         bind(GpeLocatorPairMappingContext.class).annotatedWith(Names.named(GPE_TO_LOCATOR_PAIR_CTX))
                 .toInstance(new GpeLocatorPairMappingContextImpl(GPE_TO_LOCATOR_PAIR_CTX));
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryIdentifier.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryIdentifier.java
deleted file mode 100644 (file)
index 466a422..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2017 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.hc2vpp.lisp.gpe.translate.ctx;
-
-import io.fd.hc2vpp.lisp.translate.read.dump.executor.params.MappingsDumpParams;
-import io.fd.hc2vpp.lisp.translate.util.EidTranslator;
-import io.fd.vpp.jvpp.core.types.GpeFwdEntry;
-import javax.annotation.Nonnull;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.GpeEntryIdentificator;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.gpe.entry.identificator.LocalEid;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.gpe.entry.identificator.LocalEidBuilder;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.gpe.entry.identificator.RemoteEid;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.gpe.entry.identificator.RemoteEidBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
-
-
-/**
- * Uniquely identifies gpe entry in mapping context
- */
-public final class GpeEntryIdentifier implements EidTranslator {
-
-    private final long vni;
-    private final LocalEid localEid;
-    private final RemoteEid remoteEid;
-
-    private GpeEntryIdentifier(final long vni,
-                               @Nonnull  final LocalEid localEid,
-                               @Nonnull  final RemoteEid remoteEid) {
-        this.vni = vni;
-        this.localEid = localEid;
-        this.remoteEid = remoteEid;
-    }
-
-    public long getVni() {
-        return vni;
-    }
-
-    public LocalEid getLocalEid() {
-        return localEid;
-    }
-
-    public RemoteEid getRemoteEid() {
-        return remoteEid;
-    }
-
-    public boolean isSame(@Nonnull final GpeEntryIdentificator identificator) {
-        return new EqualsBuilder()
-                .append(true, compareEids(this.getLocalEid(), identificator.getLocalEid()))
-                .append(true, compareEids(this.getRemoteEid(), identificator.getRemoteEid()))
-                .append(this.vni, identificator.getVni().longValue())
-                .isEquals();
-    }
-
-    public static GpeEntryIdentifier fromEntry(final GpeEntry data) {
-        return new GpeEntryIdentifier.GpeEntryIdentifierBuilder()
-                .setLocalEid(data.getLocalEid())
-                .setRemoteEid(data.getRemoteEid())
-                .setVni(data.getVni())
-                .createGpeEntryIdentifier();
-    }
-
-    public static GpeEntryIdentifier fromDumpDetail(final GpeFwdEntry entry) {
-        return new GpeEntryIdentifier.GpeEntryIdentifierBuilder()
-                .setVni(entry.vni)
-                .setLocalEid(
-                        INSTANCE.getArrayAsGpeLocalEid(MappingsDumpParams.EidType.valueOf(entry.eidType), entry.leid,
-                                entry.leidPrefixLen, entry.vni))
-                .setRemoteEid(
-                        INSTANCE.getArrayAsGpeRemoteEid(MappingsDumpParams.EidType.valueOf(entry.eidType), entry.reid,
-                                entry.reidPrefixLen, entry.vni))
-                .createGpeEntryIdentifier();
-    }
-
-    public static final class GpeEntryIdentifierBuilder {
-        private long vni;
-        private LocalEid localEid;
-        private RemoteEid remoteEid;
-
-        public GpeEntryIdentifierBuilder setVni(final long vni) {
-            this.vni = vni;
-            return this;
-        }
-
-        public GpeEntryIdentifierBuilder setLocalEid(
-                @Nonnull final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.gpe.entry.LocalEid localEid) {
-            this.localEid = new LocalEidBuilder()
-                    .setAddress(localEid.getAddress())
-                    .setAddressType(localEid.getAddressType())
-                    .setVirtualNetworkId(localEid.getVirtualNetworkId())
-                    .build();
-            return this;
-        }
-
-        public GpeEntryIdentifierBuilder setRemoteEid(
-                @Nonnull final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.gpe.entry.RemoteEid remoteEid) {
-            this.remoteEid = new RemoteEidBuilder()
-                    .setAddress(remoteEid.getAddress())
-                    .setAddressType(remoteEid.getAddressType())
-                    .setVirtualNetworkId(remoteEid.getVirtualNetworkId())
-                    .build();
-            return this;
-        }
-
-        public GpeEntryIdentifier createGpeEntryIdentifier() {
-            return new GpeEntryIdentifier(vni, localEid, remoteEid);
-        }
-    }
-
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        final GpeEntryIdentifier that = (GpeEntryIdentifier) o;
-
-        if (vni != that.vni) {
-            return false;
-        }
-        if (!localEid.equals(that.localEid)) {
-            return false;
-        }
-        return remoteEid.equals(that.remoteEid);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = (int) (vni ^ (vni >>> 32));
-        result = 31 * result + localEid.hashCode();
-        result = 31 * result + remoteEid.hashCode();
-        return result;
-    }
-}
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContext.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContext.java
deleted file mode 100644 (file)
index fb8982a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017 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.hc2vpp.lisp.gpe.translate.ctx;
-
-import io.fd.honeycomb.translate.MappingContext;
-import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.GpeEntryIdentificator;
-
-
-/**
- * Provides mapping context for gpe entries
- */
-public interface GpeEntryMappingContext {
-
-    /**
-     * Adds context mapping for specified id to gpe entry
-     */
-    void addMapping(@Nonnull final String id,
-                    @Nonnull final GpeEntryIdentifier identifier,
-                    @Nonnull final MappingContext mappingContext);
-
-    /**
-     * Remove context mapping for specified id
-     */
-    void removeMapping(@Nonnull final String id,
-                       @Nonnull final MappingContext mappingContext);
-
-    /**
-     * Returns identificator for specific id
-     */
-    GpeEntryIdentificator getIdentificatorById(@Nonnull final String id,
-                                               @Nonnull final MappingContext mappingContext);
-
-
-    /**
-     * Returns id for specified identifier
-     */
-    String getIdByEntryIdentifier(@Nonnull final GpeEntryIdentifier identifier,
-                                  @Nonnull final MappingContext mappingContext);
-}
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContextImpl.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/gpe/translate/ctx/GpeEntryMappingContextImpl.java
deleted file mode 100644 (file)
index 7599312..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2017 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.hc2vpp.lisp.gpe.translate.ctx;
-
-import static java.lang.String.format;
-
-import io.fd.honeycomb.translate.MappingContext;
-import java.util.Collection;
-import java.util.Optional;
-import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.GpeEntryIdentificationCtxAugmentation;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.GpeEntryIdentificationContexts;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.GpeEntryIdentification;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.GpeEntryIdentificationKey;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.Mappings;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.Mapping;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.MappingBuilder;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.MappingKey;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.GpeEntryIdentificator;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.GpeEntryIdentificatorBuilder;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class GpeEntryMappingContextImpl implements GpeEntryMappingContext {
-
-    private static final Logger LOG = LoggerFactory.getLogger(GpeEntryMappingContextImpl.class);
-
-    private final KeyedInstanceIdentifier<GpeEntryIdentification, GpeEntryIdentificationKey>
-            namingContextIid;
-
-    /**
-     * Create new naming context
-     *
-     * @param instanceName name of this context instance. Will be used as list item identifier within context data tree
-     */
-    public GpeEntryMappingContextImpl(@Nonnull final String instanceName) {
-        namingContextIid = InstanceIdentifier.create(Contexts.class)
-                .augmentation(GpeEntryIdentificationCtxAugmentation.class)
-                .child(GpeEntryIdentificationContexts.class)
-                .child(GpeEntryIdentification.class, new GpeEntryIdentificationKey(instanceName));
-    }
-
-    @Override
-    public void addMapping(@Nonnull final String id,
-                           @Nonnull final GpeEntryIdentifier identifier,
-                           @Nonnull final MappingContext mappingContext) {
-        LOG.debug("Adding mapping for gpe-entry[id={},entry-identifier={}]", id, identifier);
-        mappingContext.put(getMappingId(id), getMapping(id, identifier));
-        LOG.debug("Mapping for gp-entry[id={}] successfully added", id);
-    }
-
-    @Override
-    public void removeMapping(@Nonnull final String id,
-                              @Nonnull final MappingContext mappingContext) {
-        LOG.debug("Removing mapping for gpe-entry[id={}]", id);
-        mappingContext.delete(getMappingId(id));
-        LOG.debug("Mapping for gpe-entry[id={}] removed", id);
-    }
-
-    @Override
-    public GpeEntryIdentificator getIdentificatorById(@Nonnull final String id,
-                                                      @Nonnull final MappingContext mappingContext) {
-        final com.google.common.base.Optional<Mappings> read =
-                mappingContext.read(namingContextIid.child(Mappings.class));
-
-        if (read.isPresent()) {
-            return Optional.of(read.get())
-                    .map(Mappings::getMapping)
-                    .map(Collection::stream)
-                    .map(mappingStream -> mappingStream
-                            .filter(mapping -> mapping.getId().equals(id))
-                            .map(Mapping::getGpeEntryIdentificator)
-                            .findAny().orElse(null))
-                    .orElseThrow(() -> new IllegalStateException(format("No mapping for id %s", id)));
-
-        }
-        throw new IllegalStateException(format("No mapping for id %s", id));
-    }
-
-    @Override
-    public String getIdByEntryIdentifier(@Nonnull final GpeEntryIdentifier identifier,
-                                         @Nonnull final MappingContext mappingContext) {
-        final com.google.common.base.Optional<Mappings> read =
-                mappingContext.read(namingContextIid.child(Mappings.class));
-
-        if (read.isPresent()) {
-            return Optional.of(read.get())
-                    .map(Mappings::getMapping)
-                    .map(Collection::stream)
-                    .map(mappingStream -> mappingStream
-                            .filter(mapping -> identifier.isSame(mapping.getGpeEntryIdentificator()))
-                            .map(Mapping::getId)
-                            .findAny().orElse(null))
-                    .orElse(addArtificialMapping(identifier, mappingContext));
-        }
-
-        return addArtificialMapping(identifier, mappingContext);
-    }
-
-    private String addArtificialMapping(@Nonnull final GpeEntryIdentifier identifier,
-                                        @Nonnull final MappingContext mappingContext) {
-        final String artificialName = buildArtificialName(identifier);
-        addMapping(artificialName, identifier, mappingContext);
-        return artificialName;
-    }
-
-    private String buildArtificialName(@Nonnull final GpeEntryIdentifier identifier) {
-        return format("%s_%s_%s", identifier.getVni(), identifier.getLocalEid().getAddress(),
-                identifier.getRemoteEid().getAddress());
-    }
-
-    private KeyedInstanceIdentifier<Mapping, MappingKey> getMappingId(final String id) {
-        return namingContextIid.child(Mappings.class).child(Mapping.class, new MappingKey(id));
-    }
-
-    private Mapping getMapping(@Nonnull final String id,
-                               @Nonnull final GpeEntryIdentifier identifier) {
-        return new MappingBuilder()
-                .setId(id)
-                .setGpeEntryIdentificator(new GpeEntryIdentificatorBuilder()
-                        .setLocalEid(identifier.getLocalEid())
-                        .setRemoteEid(identifier.getRemoteEid())
-                        .setVni(identifier.getVni())
-                        .build())
-                .build();
-    }
-}
index 94b1999..a7d84d2 100644 (file)
@@ -19,6 +19,7 @@ package io.fd.hc2vpp.lisp.gpe.translate.ctx;
 import static java.lang.String.format;
 
 import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
 import java.util.Collections;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.locator.pair.identification.context.rev170517.GpeLocatorPairIdentificationCtxAugmentation;
@@ -76,16 +77,29 @@ public class GpeLocatorPairMappingContextImpl implements GpeLocatorPairMappingCo
     public LocatorPairMapping getMapping(@Nonnull final String entryId,
                                          @Nonnull final GpeLocatorPair pair,
                                          @Nonnull final MappingContext mappingContext) {
+
+        if (!contains(entryId, pair, mappingContext)) {
+            final String artificialLocatorId = artificialLocatorPairId(entryId, pair);
+            addMapping(entryId, artificialLocatorId, pair, mappingContext);
+            return getMapping(entryId, artificialLocatorId, mappingContext);
+        }
+
         return mappingContext.read(getMappingId(entryId))
                 .or(new MappingBuilder().setLocatorPairMapping(Collections.emptyList()).build())
                 .getLocatorPairMapping()
                 .stream()
                 .filter(mapping -> pair.isSame(mapping.getPair()))
-                .findAny().orElseGet(() -> {
-                    final String artificialLocatorId = artificialLocatorPairId(entryId, pair);
-                    addMapping(entryId, artificialLocatorId, pair, mappingContext);
-                    return getMapping(entryId, artificialLocatorId, mappingContext);
-                });
+                .collect(RWUtils.singleItemCollector());
+    }
+
+    private boolean contains(final String entryId,
+                             final GpeLocatorPair pair,
+                             final MappingContext mappingContext) {
+        return mappingContext.read(getMappingId(entryId))
+                .or(new MappingBuilder().setLocatorPairMapping(Collections.emptyList()).build())
+                .getLocatorPairMapping()
+                .stream()
+                .anyMatch(mapping -> pair.isSame(mapping.getPair()));
     }
 
     @Override
index 90ab65b..e6e4e44 100644 (file)
@@ -16,7 +16,6 @@
 
 package io.fd.hc2vpp.lisp.gpe.translate.read;
 
-import static io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryIdentifier.fromDumpDetail;
 import static io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPair.fromDumpDetail;
 import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
 import static java.lang.String.format;
@@ -24,8 +23,7 @@ import static java.lang.String.format;
 import com.google.common.base.Optional;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryIdentifier;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPair;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
@@ -52,7 +50,6 @@ import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.entry.identification.context.rev170517.gpe.entry.identification.context.attributes.gpe.entry.identification.contexts.gpe.entry.identification.mappings.mapping.GpeEntryIdentificator;
 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.gpe.locator.pair.identification.context.rev170517.gpe.locator.pair.identification.context.attributes.gpe.locator.pair.identification.contexts.gpe.locator.pair.identification.mappings.mapping.LocatorPairMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.Gpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.GpeEntryTable;
@@ -76,13 +73,13 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
     private final DumpCacheManager<GpeFwdEntriesGetReply, Integer> entryDumpManager;
     private final DumpCacheManager<GpeFwdEntryPathDetailsReplyDump, Integer> entryDumpCacheManager;
     private final DumpCacheManager<GpeFwdEntryVnisGetReply, Void> activeVnisDumpManager;
-    private final GpeEntryMappingContext gpeEntryMappingContext;
+    private final NamingContext gpeEntryMappingContext;
     private final GpeLocatorPairMappingContext gpeLocatorsMappingContext;
     private final GpeStateCheckService gpeStateCheckService;
 
     public GpeForwardEntryCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
                                      @Nonnull final GpeStateCheckService gpeStateCheckService,
-                                     @Nonnull final GpeEntryMappingContext gpeEntryMappingContext,
+                                     @Nonnull final NamingContext gpeEntryMappingContext,
                                      @Nonnull final GpeLocatorPairMappingContext gpeLocatorsMappingContext) {
         super(futureJVppCore);
         this.gpeStateCheckService = gpeStateCheckService;
@@ -159,23 +156,25 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
 
         final String entryId = id.firstKeyOf(GpeEntry.class).getId();
 
-        final GpeEntryIdentificator identificator =
-                gpeEntryMappingContext.getIdentificatorById(entryId, ctx.getMappingContext());
-
         // reads configured vni's, then reads entries for them and filter out current one
         final java.util.Optional<GpeFwdEntry> entryCandicate = activeVnis(id, ctx.getModificationCache())
                 .flatMap(vni -> getEntriesForVni(id, vni, ctx).stream())
-                .filter(entry -> fromDumpDetail(entry).isSame(identificator))
+                .filter(entry -> entryId
+                        .equals(gpeEntryMappingContext.getName(entry.fwdEntryIndex, ctx.getMappingContext())))
                 .findAny();
 
         if (entryCandicate.isPresent()) {
             final GpeFwdEntry gpeFwdEntry = entryCandicate.get();
 
             final int entryVni = gpeFwdEntry.vni;
+
+            if (!matchUndefinedEid(gpeFwdEntry.leid)) {
+                builder.setLocalEid(getArrayAsGpeLocalEid(MappingsDumpParams.EidType.valueOf(gpeFwdEntry.eidType),
+                        gpeFwdEntry.leid, gpeFwdEntry.leidPrefixLen, entryVni));
+            }
+
             builder.setId(entryId)
                     .setDpTable((long) gpeFwdEntry.dpTable)
-                    .setLocalEid(getArrayAsGpeLocalEid(MappingsDumpParams.EidType.valueOf(gpeFwdEntry.eidType),
-                            gpeFwdEntry.leid, gpeFwdEntry.leidPrefixLen, entryVni))
                     .setRemoteEid(getArrayAsGpeRemoteEid(MappingsDumpParams.EidType.valueOf(gpeFwdEntry.eidType),
                             gpeFwdEntry.reid, gpeFwdEntry.reidPrefixLen, entryVni))
                     .setVni((long) entryVni);
@@ -204,6 +203,12 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
         }
     }
 
+    // not matching by specifically sized array, easier to adapt if vpp going to change size of arrays they send
+    // addresses , because for lisp eid there are at least 3 possible sizes(v4 - 4,mac - 6,v6 - 16)
+    private static boolean matchUndefinedEid(byte[] addr) {
+        return addr == null || Arrays.equals(addr, new byte[addr.length]);
+    }
+
     private List<GpeFwdEntry> getEntriesForVni(final InstanceIdentifier<GpeEntry> id, final int vni,
                                                final ReadContext context) {
         final Optional<GpeFwdEntriesGetReply> dump = getEntiesDump(id, vni, context);
@@ -221,9 +226,7 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
         final Optional<GpeFwdEntriesGetReply> dump = getEntiesDump(id, vni, context);
         if (dump.isPresent()) {
             return Arrays.stream(java.util.Optional.ofNullable(dump.get().entries).orElse(new GpeFwdEntry[]{}))
-                    .map(GpeEntryIdentifier::fromDumpDetail)
-                    .map(identifier -> gpeEntryMappingContext
-                            .getIdByEntryIdentifier(identifier, context.getMappingContext()))
+                    .map(entry -> gpeEntryMappingContext.getName(entry.fwdEntryIndex, context.getMappingContext()))
                     .map(GpeEntryKey::new)
                     .collect(Collectors.toList());
         }
index 2362890..734b484 100644 (file)
@@ -19,8 +19,8 @@ package io.fd.hc2vpp.lisp.gpe.translate.read;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.GpeModule;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
@@ -60,7 +60,7 @@ public class GpeReaderFactory implements ReaderFactory {
 
     @Inject
     @Named(GpeModule.GPE_ENTRY_MAPPING_CTX)
-    private GpeEntryMappingContext gpeEntryMappingContext;
+    private NamingContext gpeEntryMappingContext;
 
     @Inject
     @Named(GpeModule.GPE_TO_LOCATOR_PAIR_CTX)
index 1749b56..cdd3887 100644 (file)
@@ -18,13 +18,12 @@ package io.fd.hc2vpp.lisp.gpe.translate.write;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
-import static io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryIdentifier.fromEntry;
 import static io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPair.fromLocatorPair;
 import static java.util.Objects.nonNull;
 
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
 import io.fd.hc2vpp.lisp.translate.read.dump.executor.params.MappingsDumpParams.EidType;
@@ -37,10 +36,12 @@ import io.fd.vpp.jvpp.core.dto.GpeAddDelFwdEntry;
 import io.fd.vpp.jvpp.core.dto.GpeAddDelFwdEntryReply;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import io.fd.vpp.jvpp.core.types.GpeLocator;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
@@ -55,12 +56,12 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
         implements ListWriterCustomizer<GpeEntry, GpeEntryKey>, EidTranslator, JvppReplyConsumer {
 
     private final GpeStateCheckService gpeStateCheckService;
-    private final GpeEntryMappingContext entryMappingCtx;
+    private final NamingContext entryMappingCtx;
     private final GpeLocatorPairMappingContext locatorPairCtx;
 
     public GpeForwardEntryCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
                                      @Nonnull final GpeStateCheckService gpeStateCheckService,
-                                     @Nonnull final GpeEntryMappingContext entryMappingCtx,
+                                     @Nonnull final NamingContext entryMappingCtx,
                                      @Nonnull final GpeLocatorPairMappingContext locatorPairCtx) {
         super(futureJVppCore);
         this.gpeStateCheckService = gpeStateCheckService;
@@ -73,8 +74,9 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
                                        @Nonnull final GpeEntry dataAfter,
                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
         gpeStateCheckService.checkGpeEnabledAfter(writeContext);
-        getReplyForWrite(sendRequestAndMap(true, dataAfter, writeContext.getMappingContext()).toCompletableFuture(),
-                id);
+        final GpeAddDelFwdEntryReply replyForWrite =
+                getReplyForWrite(sendRequestAndMap(true, dataAfter).toCompletableFuture(), id);
+        addDelMapping(true, dataAfter, replyForWrite, writeContext.getMappingContext());
     }
 
 
@@ -84,10 +86,13 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
                                         @Nonnull final GpeEntry dataAfter, @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
         gpeStateCheckService.checkGpeEnabledAfter(writeContext);
-        getReplyForDelete(sendRequestAndMap(false, dataBefore, writeContext.getMappingContext()).toCompletableFuture(),
-                id);
-        getReplyForUpdate(sendRequestAndMap(true, dataAfter, writeContext.getMappingContext()).toCompletableFuture(),
-                id, dataBefore, dataAfter);
+        final GpeAddDelFwdEntryReply replyForDelete = getReplyForDelete(
+                sendRequestAndMap(false, dataBefore).toCompletableFuture(), id);
+        addDelMapping(false, dataBefore, replyForDelete, writeContext.getMappingContext());
+
+        final GpeAddDelFwdEntryReply replyForUpdate = getReplyForUpdate(
+                sendRequestAndMap(true, dataAfter).toCompletableFuture(), id, dataBefore, dataAfter);
+        addDelMapping(true, dataAfter, replyForUpdate, writeContext.getMappingContext());
     }
 
     @Override
@@ -95,35 +100,37 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
                                         @Nonnull final GpeEntry dataBefore,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
         gpeStateCheckService.checkGpeEnabledBefore(writeContext);
-        getReplyForDelete(sendRequestAndMap(false, dataBefore, writeContext.getMappingContext()).toCompletableFuture(),
-                id);
+        final GpeAddDelFwdEntryReply replyForDelete =
+                getReplyForDelete(sendRequestAndMap(false, dataBefore).toCompletableFuture(), id);
+        addDelMapping(false, dataBefore, replyForDelete, writeContext.getMappingContext());
     }
 
     private CompletableFuture<GpeAddDelFwdEntryReply> sendRequestAndMap(final boolean add,
-                                                                        final GpeEntry data,
-                                                                        final MappingContext mappingContext) {
-        final CompletableFuture<GpeAddDelFwdEntryReply> reply =
-                getFutureJVpp().gpeAddDelFwdEntry(bindRequest(add, data)).toCompletableFuture();
+                                                                        final GpeEntry data) {
+        return getFutureJVpp().gpeAddDelFwdEntry(bindRequest(add, data)).toCompletableFuture();
+    }
 
-        /*
+    private void addDelMapping(final boolean add,
+                            final GpeEntry data,
+                            final GpeAddDelFwdEntryReply reply,
+                            final MappingContext mappingContext){
+         /*
          * sync to disallow synchronization issues
          */
         synchronized (entryMappingCtx) {
             synchronized (locatorPairCtx) {
                 if (add) {
-                    entryMappingCtx.addMapping(data.getId(), fromEntry(data), mappingContext);
+                    entryMappingCtx.addName(reply.fwdEntryIndex,data.getId(),mappingContext);
                     Optional.ofNullable(data.getLocatorPairs()).orElse(Collections.emptyList()).forEach(
                             locatorPair -> locatorPairCtx
                                     .addMapping(data.getId(), locatorPair.getId(), fromLocatorPair(locatorPair),
                                             mappingContext));
                 } else {
-                    entryMappingCtx.removeMapping(data.getId(), mappingContext);
+                    entryMappingCtx.removeName(data.getId(),mappingContext);
                     locatorPairCtx.removeMapping(data.getId(), mappingContext);
                 }
             }
         }
-
-        return reply;
     }
 
     private GpeAddDelFwdEntry bindRequest(final boolean add, @Nonnull final GpeEntry entry) {
@@ -132,21 +139,22 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
         request.vni = entry.getVni().byteValue();
         request.dpTable = entry.getDpTable().byteValue();
 
-        final LocalEid localEid = Optional.ofNullable(entry.getLocalEid())
-                .orElseThrow(() -> new IllegalArgumentException("Local eid cannot be null"));
         final RemoteEid remoteEid = Optional.ofNullable(entry.getRemoteEid())
                 .orElseThrow(() -> new IllegalArgumentException("Remote eid cannot be null"));
-
-        final EidType localEidType = getEidType(localEid);
         final EidType remoteEidType = getEidType(remoteEid);
-        checkArgument(localEidType == remoteEidType, "Different eid type detected - Local[%s]/Remote[%s]",
-                localEidType,
-                remoteEidType);
 
-        request.eidType = (byte) localEidType.getVppTypeBinding();
-        request.lclEid = getEidAsByteArray(localEid);
-        request.lclLen = getPrefixLength(localEid);
+        // for gpe entries, local eid does not have to be specified
+        final LocalEid localEid = entry.getLocalEid();
+        if (localEid != null) {
+            final EidType localEidType = getEidType(localEid);
+            checkArgument(localEidType == remoteEidType, "Different eid type detected - Local[%s]/Remote[%s]",
+                    localEidType,
+                    remoteEidType);
+            request.lclEid = getEidAsByteArray(localEid);
+            request.lclLen = getPrefixLength(localEid);
+        }
 
+        request.eidType = (byte) remoteEidType.getVppTypeBinding();
         request.rmtEid = getEidAsByteArray(remoteEid);
         request.rmtLen = getPrefixLength(remoteEid);
 
@@ -167,8 +175,8 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
     // Pair is translated to two locators, one(local) with local address and weight, second one(remote) with remote
     // address
     private GpeLocator[] toRequestLocators(final List<LocatorPairs> pairs) {
-        return pairs.stream()
-                .flatMap(locatorPairContainer -> {
+        final List<GpeLocator> localLocators = pairs.stream()
+                .map(locatorPairContainer -> {
                     final LocatorPair locatorPair =
                             checkNotNull(locatorPairContainer.getLocatorPair(), "Locator pair cannot be null");
 
@@ -183,21 +191,22 @@ public class GpeForwardEntryCustomizer extends FutureJVppCustomizer
                     localLocator.addr = ipAddressToArray(locatorPair.getLocalLocator());
                     localLocator.isIp4 = booleanToByte(!isLocalIpv6);
                     localLocator.weight = locatorPair.getWeight().byteValue();
+                    return localLocator;
+                }).collect(Collectors.toList());
+
+        final List<GpeLocator> remoteLocators = pairs.stream()
+                .map(locatorPairContainer -> {
+                    final LocatorPair locatorPair = locatorPairContainer.getLocatorPair();
+
+                    final boolean isRemoteIpv6 = isIpv6(locatorPair.getRemoteLocator());
+
 
                     GpeLocator remoteLocator = new GpeLocator();
                     remoteLocator.addr = ipAddressToArray(locatorPair.getRemoteLocator());
                     remoteLocator.isIp4 = booleanToByte(!isRemoteIpv6);
+                    return remoteLocator;
+                }).collect(Collectors.toList());
 
-                    return Stream.of(localLocator, remoteLocator);
-                })
-                .sorted((first, second) -> {
-                    if (first.weight == 0 && second.weight == 0) {
-                        return 0;
-                    } else if (first.weight == 0) {
-                        return 1;
-                    } else {
-                        return -1;
-                    }
-                }).toArray(GpeLocator[]::new);
+        return Stream.of(localLocators,remoteLocators).flatMap(Collection::stream).toArray(GpeLocator[]::new);
     }
 }
index cc5283b..2d9041d 100644 (file)
@@ -19,8 +19,8 @@ package io.fd.hc2vpp.lisp.gpe.translate.write;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.GpeModule;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
@@ -63,7 +63,7 @@ public class GpeWriterFactory implements WriterFactory {
 
     @Inject
     @Named(GpeModule.GPE_ENTRY_MAPPING_CTX)
-    private GpeEntryMappingContext gpeEntryMappingContext;
+    private NamingContext gpeEntryMappingContext;
 
     @Inject
     @Named(GpeModule.GPE_TO_LOCATOR_PAIR_CTX)
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/GpeModuleTest.java b/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/gpe/translate/GpeModuleTest.java
new file mode 100644 (file)
index 0000000..794ec29
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 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.hc2vpp.lisp.gpe.translate;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.testing.fieldbinder.Bind;
+import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.hc2vpp.lisp.gpe.GpeModule;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class GpeModuleTest {
+
+    @Bind
+    @Mock
+    private FutureJVppCore futureJVppCore;
+
+    @Inject
+    private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+    @Inject
+    private Set<WriterFactory> writerFactories = new HashSet<>();
+
+    @Before
+    public void setUp() throws Exception {
+        initMocks(this);
+        Guice.createInjector(new GpeModule(), BoundFieldModule.of(this)).injectMembers(this);
+    }
+
+    @Test
+    public void testReaderFactories() throws Exception {
+        assertThat(readerFactories, is(not(empty())));
+
+        // Test registration process (all dependencies present, topological order of readers does exist, etc.)
+        final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder();
+        readerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+        assertNotNull(registryBuilder.build());
+    }
+
+    @Test
+    public void testWriterFactories() throws Exception {
+        assertThat(writerFactories, is(not(empty())));
+
+        // Test registration process (all dependencies present, topological order of writers does exist, etc.)
+        final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder();
+        writerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+        assertNotNull(registryBuilder.build());
+    }
+}
index 9e19582..475fe2d 100644 (file)
@@ -18,14 +18,14 @@ package io.fd.hc2vpp.lisp.gpe.translate.read;
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
 import io.fd.hc2vpp.common.test.read.InitializingListReaderCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.AddressTranslator;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryIdentifier;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPair;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
@@ -83,6 +83,7 @@ public class GpeForwardEntryCustomizerTest
         implements AddressTranslator, EidTranslator {
 
     private static final String V4_ENTRY_ID = "v4-entry";
+    private static final String V4_ENTRY_NO_LEID_ID = "v4-entry-no-leid-id";
     private static final String V4_ENTRY_LOCATOR = "v4-entry-locator";
     private static final int V4_ENTRY_DP_TABLE = 10;
     private static final int V4_ENTRY_FWD_INDEX = 4;
@@ -90,6 +91,9 @@ public class GpeForwardEntryCustomizerTest
     private static final KeyedInstanceIdentifier<GpeEntry, GpeEntryKey> V4_IDENTIFIER =
             InstanceIdentifier.create(GpeEntryTable.class)
                     .child(GpeEntry.class, new GpeEntryKey(V4_ENTRY_ID));
+    private static final KeyedInstanceIdentifier<GpeEntry, GpeEntryKey> V4_NO_LEID_IDENTIFIER =
+            InstanceIdentifier.create(GpeEntryTable.class)
+                    .child(GpeEntry.class, new GpeEntryKey(V4_ENTRY_NO_LEID_ID));
     private static final Ipv4Prefix
             V4_ENTRY_LOCAL_ADDRESS = new Ipv4Prefix("192.168.2.0/24");
     private static final Ipv4Prefix
@@ -132,13 +136,14 @@ public class GpeForwardEntryCustomizerTest
             MAC_LOCATOR_LOCAL_ADDRESS = new Ipv4AddressNoZone("192.168.7.4");
     private static final Ipv4AddressNoZone
             MAC_LOCATOR_REMOTE_ADDRESS = new Ipv4AddressNoZone("192.168.2.4");
-    public static final int V6_LOCATOR_LOCAL_WEIGHT = 3;
-    public static final int MAC_LOCATOR_LOCAL_WEIGHT = 7;
-    public static final int V4_LOCATOR_LOCAL_WEIGHT = 2;
+    private static final int V6_LOCATOR_LOCAL_WEIGHT = 3;
+    private static final int MAC_LOCATOR_LOCAL_WEIGHT = 7;
+    private static final int V4_LOCATOR_LOCAL_WEIGHT = 2;
+    private static final int V4_ENTRY_NO_LEID_FWD_INDEX = 12;
 
+    private static final String GPE_ENTRY_CTX = "gpe-entry-ctx";
 
-    @Mock
-    private GpeEntryMappingContext gpeEntryMappingContext;
+    private NamingContext gpeEntryMappingContext;
 
     @Mock
     private GpeLocatorPairMappingContext gpeLocatorPairMappingContext;
@@ -158,6 +163,7 @@ public class GpeForwardEntryCustomizerTest
 
     @Override
     protected void setUp() throws Exception {
+        gpeEntryMappingContext = new NamingContext("gpe-entry-", GPE_ENTRY_CTX);
         when(gpeStateCheckService.isGpeEnabled(ctx)).thenReturn(true);
         when(api.gpeFwdEntriesGet(entryRequest(V4_ENTRY_VNI)))
                 .thenReturn(future(getGpeEntryDumpReply(getV4GpeEntry())));
@@ -166,7 +172,7 @@ public class GpeForwardEntryCustomizerTest
         when(api.gpeFwdEntriesGet(entryRequest(MAC_ENTRY_VNI)))
                 .thenReturn(future(getGpeEntryDumpReply(getMacGpeEntry())));
         when(api.gpeFwdEntryVnisGet(any())).thenReturn(future(activeVnisDump()));
-        mockMappingsForGpeEntries();
+        defineMappingsForGpeEntries();
         mockMappingsForLocators();
     }
 
@@ -209,6 +215,34 @@ public class GpeForwardEntryCustomizerTest
         assertEquals(V4_LOCATOR_LOCAL_WEIGHT, pair.getWeight().byteValue());
     }
 
+    @Test
+    public void testReadCurrentV4EntryNoLeid() throws ReadFailedException {
+        when(api.gpeFwdEntriesGet(entryRequest(V4_ENTRY_VNI)))
+                .thenReturn(future(getGpeEntryDumpReply(getV4GpeNoLeidEntry())));
+        mockLocatorDump();
+        final GpeEntryBuilder builder = new GpeEntryBuilder();
+        getCustomizer().readCurrentAttributes(V4_NO_LEID_IDENTIFIER, builder, ctx);
+
+        assertEquals(V4_ENTRY_NO_LEID_ID, builder.getId());
+        assertEquals(10, builder.getDpTable().intValue());
+        assertNull(builder.getLocalEid());
+        assertTrue(compareAddresses(new Ipv4PrefixBuilder()
+                .setIpv4Prefix(V4_ENTRY_REMOTE_ADDRESS)
+                .build(), builder.getRemoteEid().getAddress()));
+        assertEquals(Ipv4PrefixAfi.class, builder.getRemoteEid().getAddressType());
+        assertEquals(V4_ENTRY_VNI, builder.getRemoteEid().getVirtualNetworkId().getValue().intValue());
+        assertTrue(V4_ENTRY_VNI == builder.getVni());
+        assertEquals(1, builder.getLocatorPairs().size());
+
+        final LocatorPairs locatorPair = builder.getLocatorPairs().get(0);
+        assertEquals(V4_ENTRY_LOCATOR, locatorPair.getId());
+
+        final LocatorPair pair = locatorPair.getLocatorPair();
+        assertEquals(V4_LOCATOR_LOCAL_ADDRESS, pair.getLocalLocator().getIpv4Address());
+        assertEquals(V4_LOCATOR_REMOTE_ADDRESS, pair.getRemoteLocator().getIpv4Address());
+        assertEquals(V4_LOCATOR_LOCAL_WEIGHT, pair.getWeight().byteValue());
+    }
+
     @Test
     public void testReadCurrentV6Entry() throws ReadFailedException {
         mockLocatorDump();
@@ -313,6 +347,7 @@ public class GpeForwardEntryCustomizerTest
 
     private void mockLocatorDump() {
         when(api.gpeFwdEntryPathDump(pathRequest(V4_ENTRY_FWD_INDEX))).thenReturn(future(locatorDumpForV4EntryReply()));
+        when(api.gpeFwdEntryPathDump(pathRequest(V4_ENTRY_NO_LEID_FWD_INDEX))).thenReturn(future(locatorDumpForV4EntryReply()));
         when(api.gpeFwdEntryPathDump(pathRequest(V6_ENTRY_FWD_INDEX))).thenReturn(future(locatorDumpForV6EntryReply()));
         when(api.gpeFwdEntryPathDump(pathRequest(MAC_ENTRY_FWD_INDEX)))
                 .thenReturn(future(locatorDumpForMacEntryReply()));
@@ -324,25 +359,11 @@ public class GpeForwardEntryCustomizerTest
         return request;
     }
 
-    private void mockMappingsForGpeEntries() {
-        when(gpeEntryMappingContext
-                .getIdByEntryIdentifier(GpeEntryIdentifier.fromDumpDetail(getV4GpeEntry()), mappingContext))
-                .thenReturn(V4_ENTRY_ID);
-        when(gpeEntryMappingContext
-                .getIdentificatorById(V4_ENTRY_ID, mappingContext))
-                .thenReturn(fromDumpDetail(getV4GpeEntry()));
-        when(gpeEntryMappingContext
-                .getIdByEntryIdentifier(GpeEntryIdentifier.fromDumpDetail(getV6GpeEntry()), mappingContext))
-                .thenReturn(V6_ENTRY_ID);
-        when(gpeEntryMappingContext
-                .getIdentificatorById(V6_ENTRY_ID, mappingContext))
-                .thenReturn(fromDumpDetail(getV6GpeEntry()));
-        when(gpeEntryMappingContext
-                .getIdByEntryIdentifier(GpeEntryIdentifier.fromDumpDetail(getMacGpeEntry()), mappingContext))
-                .thenReturn(MAC_ENTRY_ID);
-        when(gpeEntryMappingContext
-                .getIdentificatorById(MAC_ENTRY_ID, mappingContext))
-                .thenReturn(fromDumpDetail(getMacGpeEntry()));
+    private void defineMappingsForGpeEntries() {
+        defineMapping(mappingContext, V4_ENTRY_ID, V4_ENTRY_FWD_INDEX, GPE_ENTRY_CTX);
+        defineMapping(mappingContext, V4_ENTRY_NO_LEID_ID, V4_ENTRY_NO_LEID_FWD_INDEX, GPE_ENTRY_CTX);
+        defineMapping(mappingContext, V6_ENTRY_ID, V6_ENTRY_FWD_INDEX, GPE_ENTRY_CTX);
+        defineMapping(mappingContext, MAC_ENTRY_ID, MAC_ENTRY_FWD_INDEX, GPE_ENTRY_CTX);
     }
 
     private void mockMappingsForLocators() {
@@ -357,6 +378,8 @@ public class GpeForwardEntryCustomizerTest
         final GpeLocatorPair v4LocatorPairOne = GpeLocatorPair.fromDumpDetail(v4LocatorOne);
         when(gpeLocatorPairMappingContext.getMapping(V4_ENTRY_ID, v4LocatorPairOne, mappingContext))
                 .thenReturn(fromDump(V4_ENTRY_LOCATOR, v4LocatorOne));
+        when(gpeLocatorPairMappingContext.getMapping(V4_ENTRY_NO_LEID_ID, v4LocatorPairOne, mappingContext))
+                .thenReturn(fromDump(V4_ENTRY_LOCATOR, v4LocatorOne));
     }
 
     private void mockV6LocatorMapping() {
@@ -387,25 +410,6 @@ public class GpeForwardEntryCustomizerTest
                 .build();
     }
 
-    private GpeEntryIdentificator fromDumpDetail(final GpeFwdEntry entry) {
-        final EidType eidType = EidType.valueOf(entry.eidType);
-        final Eid localEid = getArrayAsEidLocal(eidType, entry.leid, entry.leidPrefixLen, entry.vni);
-        final Eid remoteEid = getArrayAsEidLocal(eidType, entry.reid, entry.reidPrefixLen, entry.vni);
-        return new GpeEntryIdentificatorBuilder()
-                .setLocalEid(new LocalEidBuilder()
-                        .setAddress(localEid.getAddress())
-                        .setAddressType(localEid.getAddressType())
-                        .setVirtualNetworkId(localEid.getVirtualNetworkId())
-                        .build())
-                .setRemoteEid(new RemoteEidBuilder()
-                        .setAddress(remoteEid.getAddress())
-                        .setAddressType(remoteEid.getAddressType())
-                        .setVirtualNetworkId(remoteEid.getVirtualNetworkId())
-                        .build())
-                .setVni((long) entry.vni)
-                .build();
-    }
-
     private GpeFwdEntriesGetReply getGpeEntryDumpReply(final GpeFwdEntry entry) {
         GpeFwdEntriesGetReply reply = new GpeFwdEntriesGetReply();
         reply.entries = new GpeFwdEntry[]{entry};
@@ -517,4 +521,16 @@ public class GpeForwardEntryCustomizerTest
         entryOne.reidPrefixLen = 24;
         return entryOne;
     }
+
+    private GpeFwdEntry getV4GpeNoLeidEntry() {
+        GpeFwdEntry entryOne = new GpeFwdEntry();
+        entryOne.dpTable = V4_ENTRY_DP_TABLE;
+        entryOne.vni = V4_ENTRY_VNI;
+        entryOne.eidType = 0;
+        entryOne.action = 3;
+        entryOne.fwdEntryIndex = V4_ENTRY_NO_LEID_FWD_INDEX;
+        entryOne.reid = ipv4AddressPrefixToArray(V4_ENTRY_REMOTE_ADDRESS);
+        entryOne.reidPrefixLen = 24;
+        return entryOne;
+    }
 }
index 74c9bde..476c8a0 100644 (file)
@@ -17,6 +17,7 @@
 package io.fd.hc2vpp.lisp.gpe.translate.write;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.times;
@@ -27,8 +28,7 @@ import static org.mockito.Mockito.when;
 import com.google.common.collect.ImmutableSet;
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryIdentifier;
-import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeEntryMappingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPair;
 import io.fd.hc2vpp.lisp.gpe.translate.ctx.GpeLocatorPairMappingContext;
 import io.fd.hc2vpp.lisp.gpe.translate.service.GpeStateCheckService;
@@ -68,13 +68,14 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
     private static final byte[] PAIR_1_REMOTE_ADDRESS = {-64, -88, 4, 2};
     private static final int LOCAL_EID_PREFIX = 24;
     private static final int REMOTE_EID_PREFIX = 16;
+    public static final String GPE_ENTRY_CTX = "gpe-entry-ctx";
+    public static final int GPE_FWD_ENTRY_INDEX = 4;
+
+    private NamingContext gpeEntryMappingContext;
 
     @Captor
     private ArgumentCaptor<GpeAddDelFwdEntry> requestCaptor;
 
-    @Mock
-    private GpeEntryMappingContext gpeEntryMappingContext;
-
     @Mock
     private GpeLocatorPairMappingContext gpeLocatorPairMappingContext;
 
@@ -86,6 +87,7 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
 
     @Override
     protected void setUpTest() throws Exception {
+        gpeEntryMappingContext = new NamingContext("gpe-entry-", GPE_ENTRY_CTX);
         id = InstanceIdentifier.create(GpeEntryTable.class)
                 .child(GpeEntry.class, new GpeEntryKey(GPE_ENTRY_ID));
         customizer = new GpeForwardEntryCustomizer(api, gpeStateCheckService, gpeEntryMappingContext,
@@ -104,13 +106,13 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
     @Test
     public void testWriteCurrentAttributesFull(@InjectTestData(resourcePath = "/gpe/gpe-fwd-entry-full.json",
             id = GPE_ENTRY_PATH) GpeEntryTable entryTable) throws Exception {
-        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(new GpeAddDelFwdEntryReply()));
+        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(entryReply()));
         final GpeEntry entry = entryTable.getGpeEntry().get(0);
         customizer.writeCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedFullRequest(true), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .addMapping(entry.getId(), GpeEntryIdentifier.fromEntry(entry), mappingContext);
+        verify(mappingContext, times(1))
+                .put(mappingIid(entry.getId(), GPE_ENTRY_CTX), mapping(entry.getId(), GPE_FWD_ENTRY_INDEX).get());
 
         final LocatorPairs locatorPairFirst = entry.getLocatorPairs().get(0);
         final LocatorPairs locatorPairSecond = entry.getLocatorPairs().get(1);
@@ -122,17 +124,23 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
                         GpeLocatorPair.fromLocatorPair(locatorPairSecond), mappingContext);
     }
 
+    private static GpeAddDelFwdEntryReply entryReply() {
+        final GpeAddDelFwdEntryReply reply = new GpeAddDelFwdEntryReply();
+        reply.fwdEntryIndex = GPE_FWD_ENTRY_INDEX;
+        return reply;
+    }
+
     @Test
     public void testWriteCurrentAttributesWithoutLocators(
             @InjectTestData(resourcePath = "/gpe/gpe-fwd-entry-without-locators.json",
                     id = GPE_ENTRY_PATH) GpeEntryTable entryTable) throws Exception {
-        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(new GpeAddDelFwdEntryReply()));
+        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(entryReply()));
         final GpeEntry entry = entryTable.getGpeEntry().get(0);
         customizer.writeCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedLocatorLessRequest(true), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .addMapping(entry.getId(), GpeEntryIdentifier.fromEntry(entry), mappingContext);
+        verify(mappingContext, times(1))
+                .put(mappingIid(entry.getId(), GPE_ENTRY_CTX), mapping(entry.getId(), GPE_FWD_ENTRY_INDEX).get());
         verifyZeroInteractions(gpeLocatorPairMappingContext);
     }
 
@@ -140,27 +148,39 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
     public void testWriteCurrentAttributesWithoutAction(
             @InjectTestData(resourcePath = "/gpe/gpe-fwd-entry-without-action.json",
                     id = GPE_ENTRY_PATH) GpeEntryTable entryTable) throws Exception {
-        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(new GpeAddDelFwdEntryReply()));
+        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(entryReply()));
         final GpeEntry entry = entryTable.getGpeEntry().get(0);
         customizer.writeCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedActionLessRequest(true), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .addMapping(entry.getId(), GpeEntryIdentifier.fromEntry(entry), mappingContext);
+        verify(mappingContext, times(1))
+                .put(mappingIid(entry.getId(), GPE_ENTRY_CTX), mapping(entry.getId(), GPE_FWD_ENTRY_INDEX).get());
         verifyZeroInteractions(gpeLocatorPairMappingContext);
     }
 
+    /**
+     * Gpe entry allows no local eid
+     * */
     @Test
-    public void testWriteCurrentAttributesFailNoLocalEid(
+    public void testWriteCurrentAttributesNoLocalEid(
             @InjectTestData(resourcePath = "/gpe/invalid/invalid-gpe-fwd-entry-no-local-eid.json",
                     id = GPE_ENTRY_PATH) GpeEntryTable entryTable) throws Exception {
-        try {
-            customizer.writeCurrentAttributes(id, entryTable.getGpeEntry().get(0), writeContext);
-        } catch (IllegalArgumentException e) {
-            verifyZeroInteractions(api);
-            return;
-        }
-        fail("Test should have failed");
+        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(entryReply()));
+        final GpeEntry entry = entryTable.getGpeEntry().get(0);
+        customizer.writeCurrentAttributes(id, entry, writeContext);
+        verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
+        assertEquals(expectedActionLessNoLeidRequest(true), requestCaptor.getValue());
+        verify(mappingContext, times(1))
+                .put(mappingIid(entry.getId(), GPE_ENTRY_CTX), mapping(entry.getId(), GPE_FWD_ENTRY_INDEX).get());
+
+        final LocatorPairs locatorPairFirst = entry.getLocatorPairs().get(0);
+        final LocatorPairs locatorPairSecond = entry.getLocatorPairs().get(1);
+        verify(gpeLocatorPairMappingContext, times(1))
+                .addMapping(entry.getId(), locatorPairFirst.getId(),
+                        GpeLocatorPair.fromLocatorPair(locatorPairFirst), mappingContext);
+        verify(gpeLocatorPairMappingContext, times(1))
+                .addMapping(entry.getId(), locatorPairSecond.getId(),
+                        GpeLocatorPair.fromLocatorPair(locatorPairSecond), mappingContext);
     }
 
     @Test
@@ -184,8 +204,7 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
         customizer.deleteCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedFullRequest(false), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .removeMapping(entry.getId(), mappingContext);
+        verify(mappingContext, times(1)).delete(mappingIid(entry.getId(), GPE_ENTRY_CTX));
         verify(gpeLocatorPairMappingContext, times(1))
                 .removeMapping(entry.getId(), mappingContext);
     }
@@ -199,8 +218,7 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
         customizer.deleteCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedLocatorLessRequest(false), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .removeMapping(entry.getId(), mappingContext);
+        verify(mappingContext, times(1)).delete(mappingIid(entry.getId(), GPE_ENTRY_CTX));
         verify(gpeLocatorPairMappingContext, times(1))
                 .removeMapping(entry.getId(), mappingContext);
     }
@@ -214,23 +232,23 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
         customizer.deleteCurrentAttributes(id, entry, writeContext);
         verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
         assertEquals(expectedActionLessRequest(false), requestCaptor.getValue());
-        verify(gpeEntryMappingContext, times(1))
-                .removeMapping(entry.getId(), mappingContext);
+        verify(mappingContext, times(1)).delete(mappingIid(entry.getId(), GPE_ENTRY_CTX));
         verify(gpeLocatorPairMappingContext, times(1))
                 .removeMapping(entry.getId(), mappingContext);
     }
 
     @Test
-    public void testDeleteCurrentAttributesFailNoLocalEid(
+    public void testDeleteCurrentAttributesNoLocalEid(
             @InjectTestData(resourcePath = "/gpe/invalid/invalid-gpe-fwd-entry-no-local-eid.json",
                     id = GPE_ENTRY_PATH) GpeEntryTable entryTable) throws Exception {
-        try {
-            customizer.deleteCurrentAttributes(id, entryTable.getGpeEntry().get(0), writeContext);
-        } catch (IllegalArgumentException e) {
-            verifyZeroInteractions(api);
-            return;
-        }
-        fail("Test should have failed");
+        when(api.gpeAddDelFwdEntry(any())).thenReturn(future(new GpeAddDelFwdEntryReply()));
+        final GpeEntry entry = entryTable.getGpeEntry().get(0);
+        customizer.deleteCurrentAttributes(id, entry, writeContext);
+        verify(api, times(1)).gpeAddDelFwdEntry(requestCaptor.capture());
+        assertEquals(expectedActionLessNoLeidRequest(false), requestCaptor.getValue());
+        verify(mappingContext, times(1)).delete(mappingIid(entry.getId(), GPE_ENTRY_CTX));
+        verify(gpeLocatorPairMappingContext, times(1))
+                .removeMapping(entry.getId(), mappingContext);
     }
 
     @Test
@@ -246,6 +264,26 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
         fail("Test should have failed");
     }
 
+    private GpeAddDelFwdEntry expectedActionLessNoLeidRequest(final boolean add) {
+        final GpeAddDelFwdEntry request = new GpeAddDelFwdEntry();
+
+        request.isAdd = booleanToByte(add);
+        request.dpTable = 10;
+        request.vni = 12;
+        request.eidType = 0;
+        request.action = 0;
+        request.rmtEid = REMOTE_EID_ADDRESS;
+        request.rmtLen = REMOTE_EID_PREFIX;
+        request.locNum = 4;
+        request.locs = new GpeLocator[]{
+                gpeLocator(PAIR_1_LOCAL_ADDRESS, 1, 3),
+                gpeLocator(PAIR_2_LOCAL_ADDRESS, 1, 2),
+                gpeLocator(PAIR_1_REMOTE_ADDRESS, 1, 0),
+                gpeLocator(PAIR_2_REMOTE_ADDRESS, 1, 0)
+        };
+        return request;
+    }
+
     private GpeAddDelFwdEntry expectedActionLessRequest(final boolean add) {
         final GpeAddDelFwdEntry request = new GpeAddDelFwdEntry();
 
@@ -293,8 +331,8 @@ public class GpeForwardEntryCustomizerTest extends WriterCustomizerTest
         request.rmtLen = REMOTE_EID_PREFIX;
         request.locNum = 4;
         request.locs = new GpeLocator[]{
-                gpeLocator(PAIR_2_LOCAL_ADDRESS, 1, 2),
                 gpeLocator(PAIR_1_LOCAL_ADDRESS, 1, 3),
+                gpeLocator(PAIR_2_LOCAL_ADDRESS, 1, 2),
                 gpeLocator(PAIR_1_REMOTE_ADDRESS, 1, 0),
                 gpeLocator(PAIR_2_REMOTE_ADDRESS, 1, 0)
         };
index 25c12d6..7322dad 100644 (file)
@@ -26,8 +26,7 @@
             "weight": 2
           }
         }
-      ],
-      "action": "natively-forward"
+      ]
     }
   }
 }
\ No newline at end of file