HC2VPP-75 - vrf extraction fix 93/5393/3
authorJan Srnicek <[email protected]>
Fri, 17 Feb 2017 08:54:53 +0000 (09:54 +0100)
committerMarek Gradzki <[email protected]>
Fri, 17 Feb 2017 09:30:49 +0000 (09:30 +0000)
- fixed vrf extraction for Ipv6Neighbours + add test
- added vrf extraction for Ipv4Neighbours + add test

Change-Id: Ia7d1b6057c19e2f72139b3b0464f4a50a24b1c7b
Signed-off-by: Jan Srnicek <[email protected]>
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/ip/v4/Ipv4NeighbourCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/ip/v6/Ipv6NeighbourCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/v4/Ipv4NeighbourCustomizerTest.java [moved from v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java with 72% similarity]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/v6/Ipv6NeighbourCustomizerTest.java [new file with mode: 0644]

index b44a827..aedd442 100644 (file)
@@ -16,6 +16,7 @@
 
 package io.fd.hc2vpp.v3po.interfaces.ip.v4;
 
+import com.google.common.base.Optional;
 import io.fd.hc2vpp.common.translate.util.AddressTranslator;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
@@ -32,6 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.RoutingBaseAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -68,6 +71,8 @@ public class Ipv4NeighbourCustomizer extends FutureJVppCustomizer
             request.swIfIndex = interfaceContext
                     .getIndex(id.firstKeyOf(Interface.class).getName(), writeContext.getMappingContext());
 
+            bindVrfIfSpecified(writeContext, id, request);
+
             return request;
         }, getFutureJVpp());
         LOG.debug("Neighbour {} successfully written", id);
@@ -95,8 +100,26 @@ public class Ipv4NeighbourCustomizer extends FutureJVppCustomizer
             request.swIfIndex = interfaceContext
                     .getIndex(id.firstKeyOf(Interface.class).getName(), writeContext.getMappingContext());
 
+            bindVrfIfSpecified(writeContext, id, request);
+
             return request;
         }, getFutureJVpp());
         LOG.debug("Neighbour {} successfully deleted", id);
     }
+
+    private void bindVrfIfSpecified(final WriteContext writeContext,
+                                    final InstanceIdentifier<Neighbor> id,
+                                    IpNeighborAddDel request) {
+        final Optional<Interface> optIface = writeContext.readBefore(id.firstIdentifierOf(Interface.class));
+
+        // if routing set, reads vrf-id
+        // uses java.util.Optional(its internal behaviour suites this use better than guava one)
+        if (optIface.isPresent()) {
+            java.util.Optional.of(optIface.get())
+                    .map(iface -> iface.getAugmentation(VppInterfaceAugmentation.class))
+                    .map(VppInterfaceAugmentation::getRouting)
+                    .map(RoutingBaseAttributes::getIpv4VrfId)
+                    .ifPresent(vrf -> request.vrfId = vrf.byteValue());
+        }
+    }
 }
\ No newline at end of file
index dc059c3..b6948b5 100644 (file)
@@ -36,6 +36,7 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.Neighbor;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.RoutingBaseAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -118,10 +119,13 @@ public class Ipv6NeighbourCustomizer extends FutureJVppCustomizer
         final Optional<Interface> optIface = writeContext.readBefore(id.firstIdentifierOf(Interface.class));
 
         // if routing set, reads vrf-id
-        if (optIface.isPresent() && optIface.get().getAugmentation(VppInterfaceAugmentation.class) != null &&
-                optIface.get().getAugmentation(VppInterfaceAugmentation.class).getRouting() != null) {
-            request.vrfId = optIface.get().getAugmentation(VppInterfaceAugmentation.class).getRouting().getIpv4VrfId()
-                    .byteValue();
+        // uses java.util.Optional(its internal behaviour suites this use better than guava one)
+        if (optIface.isPresent()) {
+            java.util.Optional.of(optIface.get())
+                    .map(iface -> iface.getAugmentation(VppInterfaceAugmentation.class))
+                    .map(VppInterfaceAugmentation::getRouting)
+                    .map(RoutingBaseAttributes::getIpv6VrfId)
+                    .ifPresent(vrf -> request.vrfId = vrf.byteValue());
         }
         getReplyForWrite(getFutureJVpp().ipNeighborAddDel(request).toCompletableFuture(), id);
     }
  * limitations under the License.
  */
 
-package io.fd.hc2vpp.v3po.interfaces.ip;
+package io.fd.hc2vpp.v3po.interfaces.ip.v4;
 
 import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.base.Optional;
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
@@ -35,12 +37,16 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.RoutingBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
@@ -62,6 +68,7 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements
 
     @Test
     public void testWriteCurrentAttributes() throws WriteFailedException {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
         when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
         customizer.writeCurrentAttributes(IID, getData(), writeContext);
         verify(api).ipNeighborAddDel(getExpectedRequest(true));
@@ -69,6 +76,7 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements
 
     @Test
     public void testWriteCurrentAttributesFailed() {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
         when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
         try {
             customizer.writeCurrentAttributes(IID, getData(), writeContext);
@@ -86,6 +94,7 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements
 
     @Test
     public void testDeleteCurrentAttributes() throws WriteFailedException {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
         when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
         customizer.deleteCurrentAttributes(IID, getData(), writeContext);
         verify(api).ipNeighborAddDel(getExpectedRequest(false));
@@ -93,6 +102,7 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements
 
     @Test
     public void testDeleteCurrentAttributesFailed() {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
         when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
         try {
             customizer.deleteCurrentAttributes(IID, getData(), writeContext);
@@ -104,6 +114,29 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements
         fail("WriteFailedException expected");
     }
 
+    @Test
+    public void testVrfExtractionCornerCases() throws WriteFailedException {
+        when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class)))
+                // no augment
+                .thenReturn(Optional.of(new InterfaceBuilder().build()))
+                // empty augment
+                .thenReturn(Optional.of(new InterfaceBuilder()
+                        .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder().build()).build()))
+                //empty routing
+                .thenReturn(Optional.of(new InterfaceBuilder()
+                        .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder()
+                                .setRouting(new RoutingBuilder().build())
+                                .build()).build()));
+
+
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        verify(api, times(3)).ipNeighborAddDel(getExpectedRequest(true));
+    }
+
     private Neighbor getData() {
         final Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
         final PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22");
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/v6/Ipv6NeighbourCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/v6/Ipv6NeighbourCustomizerTest.java
new file mode 100644 (file)
index 0000000..ca6bae5
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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.hc2vpp.v3po.interfaces.ip.v6;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.IpNeighborAddDel;
+import io.fd.vpp.jvpp.core.dto.IpNeighborAddDelReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+public class Ipv6NeighbourCustomizerTest extends WriterCustomizerTest implements Ipv6Translator {
+
+    private static final String IFC_CTX_NAME = "ifc-test-instance";
+    private static final String IFACE_NAME = "parent";
+    private static final int IFACE_ID = 5;
+    private static final InstanceIdentifier<Neighbor> IID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(Interface1.class).child(Ipv6.class).child(Neighbor.class);
+
+    private Ipv6NeighbourCustomizer customizer;
+
+    @Override
+    public void setUpTest() {
+        defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+        customizer = new Ipv6NeighbourCustomizer(api, new NamingContext("prefix", IFC_CTX_NAME));
+    }
+
+    @Test
+    public void testWriteCurrentAttributes() throws WriteFailedException {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
+        when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        verify(api).ipNeighborAddDel(getExpectedRequest(true));
+    }
+
+    @Test
+    public void testWriteCurrentAttributesFailed() {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
+        when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
+        try {
+            customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        } catch (WriteFailedException e) {
+            assertTrue(e.getCause() instanceof VppBaseCallException);
+            verify(api).ipNeighborAddDel(getExpectedRequest(true));
+            return;
+        }
+        fail("WriteFailedException expected");
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testUpdateCurrentAttributes() throws WriteFailedException {
+        customizer.updateCurrentAttributes(IID, getData(), getData(), writeContext);
+    }
+
+    @Test
+    public void testDeleteCurrentAttributes() throws WriteFailedException {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
+        when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+        customizer.deleteCurrentAttributes(IID, getData(), writeContext);
+        verify(api).ipNeighborAddDel(getExpectedRequest(false));
+    }
+
+    @Test
+    public void testDeleteCurrentAttributesFailed() {
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class))).thenReturn(Optional.absent());
+        when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
+        try {
+            customizer.deleteCurrentAttributes(IID, getData(), writeContext);
+        } catch (WriteFailedException e) {
+            assertTrue(e.getCause() instanceof VppBaseCallException);
+            verify(api).ipNeighborAddDel(getExpectedRequest(false));
+            return;
+        }
+        fail("WriteFailedException expected");
+    }
+
+    @Test
+    public void testVrfExtractionCornerCases() throws WriteFailedException {
+        when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+
+        when(writeContext.readBefore(IID.firstIdentifierOf(Interface.class)))
+                // no augment
+                .thenReturn(Optional.of(new InterfaceBuilder().build()))
+                // empty augment
+                .thenReturn(Optional.of(new InterfaceBuilder()
+                        .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder().build()).build()))
+                //empty routing
+                .thenReturn(Optional.of(new InterfaceBuilder()
+                        .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder()
+                                .setRouting(new RoutingBuilder().build())
+                                .build()).build()));
+
+
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        customizer.writeCurrentAttributes(IID, getData(), writeContext);
+        verify(api, times(3)).ipNeighborAddDel(getExpectedRequest(true));
+    }
+
+    private Neighbor getData() {
+        final Ipv6AddressNoZone noZoneIp = new Ipv6AddressNoZone(new Ipv6Address("2001:0db8:0a0b:12f0:0000:0000:0000:0001"));
+        final PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22");
+        return new NeighborBuilder().setIp(noZoneIp).setLinkLayerAddress(mac).build();
+    }
+
+    private IpNeighborAddDel getExpectedRequest(final boolean isAdd) {
+        final IpNeighborAddDel request = new IpNeighborAddDel();
+        request.isIpv6 = 1;
+        request.isAdd = booleanToByte(isAdd);
+        request.isStatic = 1;
+        request.dstAddress = new byte[]{32, 1, 13, -72, 10, 11, 18, -16, 0, 0, 0, 0, 0, 0, 0, 1};
+        request.macAddress = new byte[]{(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xee, 0x11, 0x22};
+        request.swIfIndex = IFACE_ID;
+        return request;
+    }
+
+}
\ No newline at end of file