HC2VPP-43: support for multiple DHCP servers for relay 90/5590/3
authorMarek Gradzki <mgradzki@cisco.com>
Thu, 2 Mar 2017 12:40:22 +0000 (13:40 +0100)
committerMarek Gradzki <mgradzki@cisco.com>
Wed, 8 Mar 2017 08:34:41 +0000 (09:34 +0100)
Depends on https://gerrit.fd.io/r/#/c/5515/

Change-Id: I76d1b37b9d9e866fc97f3cc35c1ac01e48b0ab57
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
12 files changed:
dhcp/dhcp-api/src/main/yang/dhcp.yang
dhcp/dhcp-impl/src/main/java/io/fd/hc2vpp/dhcp/read/DhcpReaderFactory.java
dhcp/dhcp-impl/src/main/java/io/fd/hc2vpp/dhcp/read/DhcpRelayCustomizer.java
dhcp/dhcp-impl/src/main/java/io/fd/hc2vpp/dhcp/write/DhcpRelayCustomizer.java
dhcp/dhcp-impl/src/main/java/io/fd/hc2vpp/dhcp/write/DhcpWriterFactory.java
dhcp/dhcp-impl/src/test/java/io/fd/hc2vpp/dhcp/read/DhcpRelayCustomizerTest.java
dhcp/dhcp-impl/src/test/java/io/fd/hc2vpp/dhcp/write/DhcpRelayCustomizerTest.java
dhcp/dhcp-impl/src/test/resources/relay/ipv4DhcpRelay.json
dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelay.json [deleted file]
dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayAfter.json [new file with mode: 0644]
dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayBefore.json [new file with mode: 0644]
dhcp/dhcp_postman_collection.json

index 9f2e644..4fa0a61 100644 (file)
@@ -42,19 +42,21 @@ module dhcp {
     }
 
     grouping relay-attributes {
-        leaf server-address {
-          // FIXME(HC2VPP-79): change to ip-address-no-zone after https://bugs.opendaylight.org/show_bug.cgi?id=6413 is resolved
-          type inet:ip-address;
-            mandatory true;
+        list server {
+          key "vrf-id address";
+          leaf address {
+            // FIXME(HC2VPP-79): change to ip-address-no-zone after https://bugs.opendaylight.org/show_bug.cgi?id=6413 is resolved
+            type inet:ip-address;
             description
-                "IP address of the server DHCP packets will be forwarded to.";
-        }
-        leaf server-vrf-id {
+              "IP address of the server DHCP packets will be forwarded to.";
+          }
+          leaf vrf-id {
             type uint32;
-            default 0;
             description
-                "Used to send DHCP messages to the server";
+              "Used to send DHCP messages to the server";
+          }
         }
+
         leaf gateway-address {
           // FIXME(HC2VPP-79): change to ip-address-no-zone after https://bugs.opendaylight.org/show_bug.cgi?id=6413 is resolved
           type inet:ip-address;
index db71906..2f71866 100644 (file)
@@ -16,6 +16,7 @@
 
 package io.fd.hc2vpp.dhcp.read;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
 import io.fd.honeycomb.translate.read.ReaderFactory;
@@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.Relays;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.RelaysBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.Relay;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.Server;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -45,6 +47,9 @@ public final class DhcpReaderFactory implements ReaderFactory {
     public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
         registry.addStructuralReader(DHCP_ID, DhcpBuilder.class);
         registry.addStructuralReader(RELAYS_ID, RelaysBuilder.class);
-        registry.add(new GenericInitListReader<>(RELAY_ID, new io.fd.hc2vpp.dhcp.read.DhcpRelayCustomizer(vppApi)));
+        registry.subtreeAdd(
+            ImmutableSet.of(InstanceIdentifier.create(Relay.class).child(Server.class)),
+            new GenericInitListReader<>(RELAY_ID, new io.fd.hc2vpp.dhcp.read.DhcpRelayCustomizer(vppApi))
+        );
     }
 }
index db7e714..875b939 100644 (file)
@@ -35,6 +35,7 @@ import io.fd.vpp.jvpp.core.dto.DhcpProxyDetails;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyDetailsReplyDump;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyDump;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletionStage;
@@ -47,6 +48,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.Relay;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.RelayBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.RelayKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.ServerBuilder;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -72,10 +74,10 @@ final class DhcpRelayCustomizer extends FutureJVppCustomizer
 
             final CompletionStage<DhcpProxyDetailsReplyDump> result = getFutureJVpp().dhcpProxyDump(new DhcpProxyDump())
                 .thenCombine(getFutureJVpp().dhcpProxyDump(request),
-                (ip4, ip6) -> {
-                    ip4.dhcpProxyDetails.addAll(ip6.dhcpProxyDetails);
-                    return ip4;
-                });
+                    (ip4, ip6) -> {
+                        ip4.dhcpProxyDetails.addAll(ip6.dhcpProxyDetails);
+                        return ip4;
+                    });
             return getReplyForRead(result.toCompletableFuture(), id);
         };
     }
@@ -136,8 +138,14 @@ final class DhcpRelayCustomizer extends FutureJVppCustomizer
             builder.setRxVrfId(key.getRxVrfId());
             final boolean isIp6 = byteToBoolean(detail.isIpv6);
             builder.setGatewayAddress(readAddress(detail.dhcpSrcAddress, isIp6));
-            builder.setServerAddress(readAddress(detail.dhcpServer, isIp6));
-            builder.setServerVrfId(UnsignedInts.toLong(detail.serverVrfId));
+            if (detail.servers != null) {
+                builder.setServer(Arrays.stream(detail.servers).map(
+                    server -> new ServerBuilder()
+                        .setAddress(readAddress(server.dhcpServer, isIp6))
+                        .setVrfId(UnsignedInts.toLong(server.serverVrfId))
+                        .build()
+                ).collect(Collectors.toList()));
+            }
         }
     }
 
index 58e3d58..cb99392 100644 (file)
@@ -16,6 +16,8 @@
 
 package io.fd.hc2vpp.dhcp.write;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
@@ -26,11 +28,13 @@ import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyConfig;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.Ipv6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.Relay;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.RelayKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.Server;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,7 +51,10 @@ final class DhcpRelayCustomizer extends FutureJVppCustomizer implements ListWrit
     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Relay> id, @Nonnull final Relay dataAfter,
                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
         LOG.debug("Writing Relay {} dataAfter={}", id, dataAfter);
-        setRelay(id, dataAfter, writeContext, true);
+        checkArgument(dataAfter.getServer() != null && !dataAfter.getServer().isEmpty(), "At least one DHCP server needs to be configured");
+        for (final Server server : dataAfter.getServer()) {
+            setRelay(id, dataAfter, server, true);
+        }
     }
 
     @Override
@@ -55,26 +62,50 @@ final class DhcpRelayCustomizer extends FutureJVppCustomizer implements ListWrit
                                         @Nonnull final Relay dataAfter, @Nonnull final WriteContext writeContext)
         throws WriteFailedException {
         LOG.debug("Updating Relay {} before={} after={}", id, dataBefore, dataAfter);
-        setRelay(id, dataAfter, writeContext, true);
+        final List<Server> serversBefore = dataBefore.getServer();
+        checkArgument(serversBefore != null && !serversBefore.isEmpty(),
+            "At least one DHCP server needs to be configured before update operation");
+        final List<Server> serversAfter = dataAfter.getServer();
+        checkArgument(serversAfter != null && !serversAfter.isEmpty(),
+            "At least one DHCP server needs to be configured after update operation");
+
+        // remove old servers (we do not expect many, so no need for efficient search):
+        for (final Server server : serversBefore) {
+            if (!serversAfter.contains(server)) {
+                setRelay(id, dataAfter, server, false);
+            }
+        }
+        // and add new ones:
+        for (final Server server : serversAfter) {
+            if (!serversBefore.contains(server)) {
+                setRelay(id, dataAfter, server, true);
+            }
+        }
     }
 
     @Override
     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Relay> id, @Nonnull final Relay dataBefore,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
         LOG.debug("Removing Relay {} dataBefore={}", id, dataBefore);
-        setRelay(id, dataBefore, writeContext, false);
+        checkArgument(dataBefore.getServer() != null && !dataBefore.getServer().isEmpty(),
+            "At least one DHCP server needs to be configured");
+        for (final Server server : dataBefore.getServer()) {
+            setRelay(id, dataBefore, server, false);
+        }
     }
 
-    private void setRelay(final InstanceIdentifier<Relay> id, final Relay relay, final WriteContext writeContext,
-                          final boolean isAdd) throws WriteFailedException {
+    private void setRelay(final InstanceIdentifier<Relay> id, final Relay relay, final Server server,
+                          final boolean isAdd)
+        throws WriteFailedException {
         final DhcpProxyConfig request = new DhcpProxyConfig();
         request.rxVrfId = relay.getRxVrfId().byteValue();
         final boolean isIpv6 = Ipv6.class == relay.getAddressType();
         request.isIpv6 = booleanToByte(isIpv6);
-        request.serverVrfId = relay.getServerVrfId().intValue();
+        request.serverVrfId = server.getVrfId().intValue();
         request.isAdd = booleanToByte(isAdd);
-        request.dhcpServer = parseAddress(relay.getServerAddress(), isIpv6);
+        request.dhcpServer = parseAddress(server.getAddress(), isIpv6);
         request.dhcpSrcAddress = parseAddress(relay.getGatewayAddress(), isIpv6);
+        LOG.debug("DHCP config change id={} request={}", id, request);
         getReplyForWrite(getFutureJVpp().dhcpProxyConfig(request).toCompletableFuture(), id);
     }
 
index 93dc804..062826a 100644 (file)
@@ -16,6 +16,7 @@
 
 package io.fd.hc2vpp.dhcp.write;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
@@ -25,6 +26,7 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.Dhcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.Relays;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.Relay;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.Server;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -32,13 +34,17 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  */
 public final class DhcpWriterFactory implements WriterFactory {
 
-    private static final InstanceIdentifier<Relay> RELAY_ID = InstanceIdentifier.create(Dhcp.class).child(Relays.class).child(Relay.class);
+    private static final InstanceIdentifier<Relay> RELAY_ID =
+        InstanceIdentifier.create(Dhcp.class).child(Relays.class).child(Relay.class);
 
     @Inject
     private FutureJVppCore vppApi;
 
     @Override
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
-        registry.add(new GenericListWriter<>(RELAY_ID, new DhcpRelayCustomizer(vppApi)));
+        registry.subtreeAdd(
+            ImmutableSet.of(InstanceIdentifier.create(Relay.class).child(Server.class)),
+            new GenericListWriter<>(RELAY_ID, new DhcpRelayCustomizer(vppApi))
+        );
     }
 }
index 79a1f44..0a64dd8 100644 (file)
@@ -28,6 +28,7 @@ import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyDetails;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyDetailsReplyDump;
 import io.fd.vpp.jvpp.core.dto.DhcpProxyDump;
+import io.fd.vpp.jvpp.core.types.DhcpServer;
 import java.util.List;
 import org.junit.Test;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.Dhcp;
@@ -38,19 +39,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.Relay;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.RelayBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.dhcp.attributes.relays.RelayKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.Server;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 public class DhcpRelayCustomizerTest extends InitializingListReaderCustomizerTest<Relay, RelayKey, RelayBuilder> {
+    private static InstanceIdentifier<Relays> RELAYS = InstanceIdentifier.create(Dhcp.class).child(Relays.class);
+    private KeyedInstanceIdentifier<Relay, RelayKey> IP4_IID =
+        RELAYS.child(Relay.class, new RelayKey(Ipv4.class, 123L));
+    private KeyedInstanceIdentifier<Relay, RelayKey> IP6_IID =
+        RELAYS.child(Relay.class, new RelayKey(Ipv6.class, 321L));
     public DhcpRelayCustomizerTest() {
         super(Relay.class, RelaysBuilder.class);
     }
 
-    private static InstanceIdentifier<Relays> RELAYS = InstanceIdentifier.create(Dhcp.class).child(Relays.class);
-
-    private KeyedInstanceIdentifier<Relay, RelayKey> IP4_IID = RELAYS.child(Relay.class, new RelayKey(Ipv4.class, 123L));
-    private KeyedInstanceIdentifier<Relay, RelayKey> IP6_IID = RELAYS.child(Relay.class, new RelayKey(Ipv6.class, 321L));
-
     @Override
     protected ReaderCustomizer<Relay, RelayBuilder> initCustomizer() {
         return new DhcpRelayCustomizer(api);
@@ -61,9 +63,14 @@ public class DhcpRelayCustomizerTest extends InitializingListReaderCustomizerTes
         final DhcpProxyDetailsReplyDump ip4 = new DhcpProxyDetailsReplyDump();
         final DhcpProxyDetails ip4Proxy = new DhcpProxyDetails();
         ip4Proxy.rxVrfId = 123;
-        ip4Proxy.dhcpSrcAddress = new byte[]{1,2,3,4};
-        ip4Proxy.serverVrfId = 11;
-        ip4Proxy.dhcpServer = new byte[]{8,8,8,8};
+        ip4Proxy.dhcpSrcAddress = new byte[] {1, 2, 3, 4};
+        final DhcpServer ip4server1 = new DhcpServer();
+        ip4server1.serverVrfId = 11;
+        ip4server1.dhcpServer = new byte[] {8, 8, 8, 8};
+        final DhcpServer ip4server2 = new DhcpServer();
+        ip4server2.serverVrfId = 12;
+        ip4server2.dhcpServer = new byte[] {8, 8, 8, 4};
+        ip4Proxy.servers = new DhcpServer[] {ip4server1, ip4server2};
         ip4.dhcpProxyDetails.add(ip4Proxy);
         when(api.dhcpProxyDump(new DhcpProxyDump())).thenReturn(future(ip4));
 
@@ -71,12 +78,15 @@ public class DhcpRelayCustomizerTest extends InitializingListReaderCustomizerTes
         final DhcpProxyDetails ip6Proxy = new DhcpProxyDetails();
         ip6Proxy.rxVrfId = 321;
         // 2001:0db8:0a0b:12f0:0000:0000:0000:0001
-        ip6Proxy.dhcpSrcAddress = new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, 0x0a, 0x0b, 0x12, (byte) 0xf0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x01};
-        ip6Proxy.serverVrfId = 22;
-        ip6Proxy.isIpv6  = 1;
+        ip6Proxy.dhcpSrcAddress =
+            new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, 0x0a, 0x0b, 0x12, (byte) 0xf0, 0, 0, 0, 0, 0, 0, 0, 0x01};
+        final DhcpServer ip6server = new DhcpServer();
+        ip6server.serverVrfId = 22;
         // 2001:0db8:0a0b:12f0:0000:0000:0000:0002
-        ip6Proxy.dhcpServer = new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, 0x0a, 0x0b, 0x12, (byte) 0xf0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x02};
-
+        ip6server.dhcpServer =
+            new byte[] {0x20, 0x01, 0x0d, (byte) 0xb8, 0x0a, 0x0b, 0x12, (byte) 0xf0, 0, 0, 0, 0, 0, 0, 0, 0x02};
+        ip6Proxy.servers = new DhcpServer[] {ip6server};
+        ip6Proxy.isIpv6 = 1;
         final DhcpProxyDump ip6Dump = new DhcpProxyDump();
         ip6Dump.isIp6 = 1;
         ip6.dhcpProxyDetails.add(ip6Proxy);
@@ -96,9 +106,13 @@ public class DhcpRelayCustomizerTest extends InitializingListReaderCustomizerTes
         getCustomizer().readCurrentAttributes(IP4_IID, builder, ctx);
         assertEquals(IP4_IID.getKey().getAddressType(), builder.getAddressType());
         assertEquals(IP4_IID.getKey().getRxVrfId(), builder.getRxVrfId());
-        assertEquals(11L, builder.getServerVrfId().longValue());
         assertArrayEquals("1.2.3.4".toCharArray(), builder.getGatewayAddress().getValue());
-        assertArrayEquals("8.8.8.8".toCharArray(), builder.getServerAddress().getValue());
+        final List<Server> server = builder.getServer();
+        assertEquals(2, server.size());
+        assertEquals(11L, server.get(0).getVrfId().longValue());
+        assertArrayEquals("8.8.8.8".toCharArray(), server.get(0).getAddress().getValue());
+        assertEquals(12L, server.get(1).getVrfId().longValue());
+        assertArrayEquals("8.8.8.4".toCharArray(), server.get(1).getAddress().getValue());
     }
 
     @Test
@@ -107,9 +121,9 @@ public class DhcpRelayCustomizerTest extends InitializingListReaderCustomizerTes
         getCustomizer().readCurrentAttributes(IP6_IID, builder, ctx);
         assertEquals(IP6_IID.getKey().getAddressType(), builder.getAddressType());
         assertEquals(IP6_IID.getKey().getRxVrfId(), builder.getRxVrfId());
-        assertEquals(22L, builder.getServerVrfId().longValue());
+        assertEquals(22L, builder.getServer().get(0).getVrfId().longValue());
         assertArrayEquals("2001:db8:a0b:12f0::1".toCharArray(), builder.getGatewayAddress().getValue());
-        assertArrayEquals("2001:db8:a0b:12f0::2".toCharArray(), builder.getServerAddress().getValue());
+        assertArrayEquals("2001:db8:a0b:12f0::2".toCharArray(), builder.getServer().get(0).getAddress().getValue());
     }
 
     @Test
index d13990c..a6a407a 100644 (file)
@@ -17,7 +17,6 @@
 package io.fd.hc2vpp.dhcp.write;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -43,7 +42,8 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 public class DhcpRelayCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper {
 
     private static final String RELAYS_PATH = "/dhcp:dhcp/dhcp:relays";
-    private static final InstanceIdentifier<Relays> RELAYS_IID = InstanceIdentifier.create(Dhcp.class).child(Relays.class);
+    private static final InstanceIdentifier<Relays> RELAYS_IID =
+        InstanceIdentifier.create(Dhcp.class).child(Relays.class);
 
     private DhcpRelayCustomizer customizer;
 
@@ -63,24 +63,29 @@ public class DhcpRelayCustomizerTest extends WriterCustomizerTest implements Sch
         request.rxVrfId = rxVrfId;
         request.isIpv6 = 0;
         request.isAdd = 1;
-        request.dhcpServer = new byte[]{1,2,3,4};
-        request.dhcpSrcAddress = new byte[]{5,6,7,8};
+        request.dhcpServer = new byte[] {1, 2, 3, 4};
+        request.dhcpSrcAddress = new byte[] {5, 6, 7, 8};
+        verify(api).dhcpProxyConfig(request);
+        request.dhcpServer = new byte[] {1, 2, 3, 5};
         verify(api).dhcpProxyConfig(request);
     }
 
     @Test
-    public void testUpdate(@InjectTestData(resourcePath = "/relay/ipv6DhcpRelay.json", id = RELAYS_PATH) Relays relays)
+    public void testUpdate(
+        @InjectTestData(resourcePath = "/relay/ipv6DhcpRelayBefore.json", id = RELAYS_PATH) Relays relaysBefore,
+        @InjectTestData(resourcePath = "/relay/ipv6DhcpRelayAfter.json", id = RELAYS_PATH) Relays relayAfter)
         throws WriteFailedException {
-        final Relay data = relays.getRelay().get(0);
+        final Relay before = relaysBefore.getRelay().get(0);
+        final Relay after = relayAfter.getRelay().get(0);
         final int rxVrfId = 1;
-        customizer.updateCurrentAttributes(getId(rxVrfId, Ipv6.class), mock(Relay.class), data, writeContext);
+        customizer.updateCurrentAttributes(getId(rxVrfId, Ipv6.class), before, after, writeContext);
         final DhcpProxyConfig request = new DhcpProxyConfig();
         request.rxVrfId = rxVrfId;
         request.serverVrfId = 2;
         request.isIpv6 = 1;
-        request.isAdd = 1;
-        request.dhcpServer = new byte[]{0x20, 0x01, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x01};
-        request.dhcpSrcAddress = new byte[]{0x20, 0x01, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x02};
+        request.isAdd = 0;
+        request.dhcpServer = new byte[] {0x20, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01};
+        request.dhcpSrcAddress = new byte[] {0x20, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02};
         verify(api).dhcpProxyConfig(request);
     }
 
@@ -94,8 +99,10 @@ public class DhcpRelayCustomizerTest extends WriterCustomizerTest implements Sch
         request.rxVrfId = rxVrfId;
         request.isIpv6 = 0;
         request.isAdd = 0;
-        request.dhcpServer = new byte[]{1,2,3,4};
-        request.dhcpSrcAddress = new byte[]{5,6,7,8};
+        request.dhcpServer = new byte[] {1, 2, 3, 4};
+        request.dhcpSrcAddress = new byte[] {5, 6, 7, 8};
+        verify(api).dhcpProxyConfig(request);
+        request.dhcpServer = new byte[] {1, 2, 3, 5};
         verify(api).dhcpProxyConfig(request);
     }
 
index 27550e4..2c7dda2 100644 (file)
@@ -4,8 +4,17 @@
       {
         "address-type": "ipv4",
         "rx-vrf-id": 0,
-        "server-address": "1.2.3.4",
-        "gateway-address": "5.6.7.8"
+        "gateway-address": "5.6.7.8",
+        "server" : [
+          {
+            "vrf-id": 0,
+            "address": "1.2.3.4"
+          },
+          {
+            "vrf-id": 0,
+            "address": "1.2.3.5"
+          }
+        ]
       }
     ]
   }
diff --git a/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelay.json b/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelay.json
deleted file mode 100644 (file)
index ca7e51a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "relays": {
-    "relay": [
-      {
-        "address-type": "ipv6",
-        "rx-vrf-id": 1,
-        "server-address": "2001::1",
-        "server-vrf-id": 2,
-        "gateway-address": "2001::2"
-      }
-    ]
-  }
-}
diff --git a/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayAfter.json b/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayAfter.json
new file mode 100644 (file)
index 0000000..7c2518b
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "relays": {
+    "relay": [
+      {
+        "address-type": "ipv6",
+        "rx-vrf-id": 1,
+        "gateway-address": "2001::2",
+        "server" : [
+          {
+            "vrf-id": 2,
+            "address": "2001::10"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayBefore.json b/dhcp/dhcp-impl/src/test/resources/relay/ipv6DhcpRelayBefore.json
new file mode 100644 (file)
index 0000000..94f7c65
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "relays": {
+    "relay": [
+      {
+        "address-type": "ipv6",
+        "rx-vrf-id": 1,
+        "gateway-address": "2001::2",
+        "server" : [
+          {
+            "vrf-id": 2,
+            "address": "2001::1"
+          },
+          {
+            "vrf-id": 2,
+            "address": "2001::10"
+          }
+        ]
+      }
+    ]
+  }
+}
index e7070ed..d2afc8c 100644 (file)
@@ -1,14 +1,16 @@
 {
-       "id": "a38b7e49-665c-4646-723d-d78bbf27080e",
+       "id": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
        "name": "DHCP",
        "description": "Provides DHCP configuration examples for hc2vpp.",
        "order": [
-               "e718ef1d-ec09-23a6-f644-7306545453bd",
-               "80aae885-6a8b-09b2-f3cc-8c52fa4e081e",
-               "8362683a-c911-27fa-c0bd-8a3515cc4bae",
-               "a76f4dce-f094-ecff-d1c1-28217de33494",
-               "c56f4661-f9ff-38ee-cf0b-0863e5809f4e",
-               "43ee4aca-717c-bfdb-7152-520474e5eef6"
+               "990feae9-d039-4f1e-6c2d-df1a16ee2ba5",
+               "4cf4fe5e-158f-a36d-0cc4-412e99475870",
+               "ca4b868e-dcab-b87e-f6d9-99ff297b9f38",
+               "24669f87-8005-8c09-c516-d9fa3ba4b470",
+               "c5791bcb-a98e-b6a9-e143-4f0af0453164",
+               "d312ab52-434d-2838-aa94-cea8eb1d2d50",
+               "45f81f14-e5d8-db5c-a8c3-12238b78c28d",
+               "3d271bcc-ca7b-aa7f-3446-c8fc52a9f1e9"
        ],
        "folders": [],
        "timestamp": 1487055938314,
        "public": false,
        "requests": [
                {
-                       "id": "43ee4aca-717c-bfdb-7152-520474e5eef6",
+                       "id": "24669f87-8005-8c09-c516-d9fa3ba4b470",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/0/server/0/1.2.3.4",
+                       "preRequestScript": null,
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": null,
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1488460094116,
+                       "name": "Delete one of DHCP servers",
+                       "description": "Equivalent of\n\nvppctl set dhcp proxy del server 1.2.3.4\n\nvppctl show dhcp proxy",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
+                       "responses": [],
+                       "rawModeData": ""
+               },
+               {
+                       "id": "3d271bcc-ca7b-aa7f-3446-c8fc52a9f1e9",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/",
+                       "pathVariables": {},
+                       "preRequestScript": null,
+                       "method": "GET",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
+                       "data": [],
+                       "dataMode": "raw",
+                       "name": "Show DHCP Relay oper",
+                       "description": "",
+                       "descriptionFormat": "html",
+                       "time": 1488193893443,
+                       "version": 2,
+                       "responses": [],
+                       "tests": null,
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+               },
+               {
+                       "id": "45f81f14-e5d8-db5c-a8c3-12238b78c28d",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
                        "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/",
                        "preRequestScript": null,
                        "time": 1487059202453,
                        "name": "Show DHCP Relay cfg",
                        "description": "",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
                        "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
                },
                {
-                       "id": "80aae885-6a8b-09b2-f3cc-8c52fa4e081e",
+                       "id": "4cf4fe5e-158f-a36d-0cc4-412e99475870",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
                        "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/1",
                        "preRequestScript": null,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1487059355510,
+                       "time": 1488458844687,
                        "name": "Add IP4 DHCP Relay #2",
-                       "description": "Equivalent of\n\nvppctl set dhcp proxy server 1.2.3.5 src-address 5.6.7.9 add-option-82\n\ncan be verified with\n\nvppctl show dhcp proxy",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "description": "Equivalent of\n\nvppctl set dhcp proxy server 1.2.3.6 src-address 5.6.7.9 rx-fib-id 1\n\ncan be verified with\n\nvppctl show dhcp proxy",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
-                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 1,\n\t\t\t\"server-address\": \"1.2.3.5\",\n\t\t\t\"gateway-address\": \"5.6.7.9\"}\n\t]\n}\n"
+                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 1,\n\t\t\t\"gateway-address\": \"5.6.7.9\",\n\t\t\t\"server\" : [\n\t\t\t\t{\n\t\t\t\t\t\"vrf-id\": 0,\n\t\t\t\t\t\"address\": \"1.2.3.6\"\n\t\t\t\t}\n        \t]\n\t\t}\n\t]\n}\n"
                },
                {
-                       "id": "8362683a-c911-27fa-c0bd-8a3515cc4bae",
+                       "id": "990feae9-d039-4f1e-6c2d-df1a16ee2ba5",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
-                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv6/1",
+                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/0",
                        "preRequestScript": null,
                        "pathVariables": {},
                        "method": "PUT",
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1487056567412,
-                       "name": "Configure IP6 DHCP Relay",
-                       "description": "Configuration of IP6 DHCP proxy is not supported trough CLI",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "time": 1488459981869,
+                       "name": "Add IP4 DHCP Relay #1",
+                       "description": "Equivalent of\n\nvppctl set dhcp proxy server 1.2.3.3 src-address 5.6.7.8\nvppctl set dhcp proxy server 1.2.3.4 src-address 5.6.7.8\nvppctl set dhcp proxy server 1.2.3.5 src-address 5.6.7.8 rx-fib-id 1\n\n\ncan be verified with\n\nvppctl show dhcp proxy",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
-                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t        \"address-type\": \"ipv6\",\n\t        \"rx-vrf-id\": 1,\n\t        \"server-address\": \"2001::1\",\n\t        \"server-vrf-id\": 2,\n\t        \"gateway-address\": \"2001::2\"}\n\t]\n}\n"
+                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"gateway-address\": \"5.6.7.8\",\n\t\t\t\"server\" : [\n\t\t\t\t{\n\t\t\t\t\t\"vrf-id\": 0,\n\t\t\t\t\t\"address\": \"1.2.3.3\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"vrf-id\": 0,\n\t\t\t\t\t\"address\": \"1.2.3.4\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"vrf-id\": 1,\n\t\t\t\t\t\"address\": \"1.2.3.5\"\n\t\t\t\t}\n        \t]\n\t\t}\n\t]\n}\n"
                },
                {
-                       "id": "a76f4dce-f094-ecff-d1c1-28217de33494",
+                       "id": "c5791bcb-a98e-b6a9-e143-4f0af0453164",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
                        "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/0",
                        "preRequestScript": null,
                        "helperAttributes": {},
                        "time": 1487059058881,
                        "name": "Delete IP4 DHCP Relay #1",
-                       "description": "Equivalent of\n\nvppctl set dhcp proxy del server 1.2.3.4\n\nvppctl show dhcp proxy",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "description": "Removes DHCP relay configuration for rx-fib-id=0\n\nCan be verified with:\n\nvppctl show dhcp proxy",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
                        "rawModeData": ""
                },
                {
-                       "id": "c56f4661-f9ff-38ee-cf0b-0863e5809f4e",
+                       "id": "ca4b868e-dcab-b87e-f6d9-99ff297b9f38",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
-                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/1",
+                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv6/1",
                        "preRequestScript": null,
                        "pathVariables": {},
-                       "method": "DELETE",
+                       "method": "PUT",
                        "data": [],
                        "dataMode": "raw",
                        "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1487059316221,
-                       "name": "Delete IP4 DHCP Relay #2",
-                       "description": "Equivalent of\n\nvppctl set dhcp proxy del server 1.2.3.5\n\nvppctl show dhcp proxy",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "time": 1488458977472,
+                       "name": "Configure IP6 DHCP Relay",
+                       "description": "Configuration of IP6 DHCP proxy is not supported trough CLI",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
-                       "rawModeData": ""
+                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t        \"address-type\": \"ipv6\",\n\t        \"rx-vrf-id\": 1,\n\t        \"gateway-address\": \"2001::2\",\n\t\t\t\"server\" : [\n\t\t\t\t{\n\t\t\t\t\t\"vrf-id\": 2,\n\t\t\t\t\t\"address\": \"2001::1\"\n\t\t\t\t}\n        \t]\n\t\t}\n\t]\n}\n"
                },
                {
-                       "id": "e718ef1d-ec09-23a6-f644-7306545453bd",
+                       "id": "d312ab52-434d-2838-aa94-cea8eb1d2d50",
                        "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
-                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/0",
+                       "url": "http://localhost:8183/restconf/config/dhcp:dhcp/relays/relay/dhcp:ipv4/1",
                        "preRequestScript": null,
                        "pathVariables": {},
-                       "method": "PUT",
+                       "method": "DELETE",
                        "data": [],
                        "dataMode": "raw",
                        "version": 2,
                        "tests": null,
                        "currentHelper": "normal",
                        "helperAttributes": {},
-                       "time": 1487056454396,
-                       "name": "Add IP4 DHCP Relay #1",
-                       "description": "Equivalent of\n\nvppctl set dhcp proxy server 1.2.3.4 src-address 5.6.7.8 add-option-82\n\ncan be verified with\n\nvppctl show dhcp proxy",
-                       "collectionId": "a38b7e49-665c-4646-723d-d78bbf27080e",
+                       "time": 1487059316221,
+                       "name": "Delete IP4 DHCP Relay #2",
+                       "description": "Removes DHCP relay configuration for rx-fib-id=1\n\nCan be verified with:\n\nvppctl show dhcp proxy",
+                       "collectionId": "f5441117-e55c-ba3b-6673-aaa6d383e33c",
                        "responses": [],
-                       "rawModeData": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-type\": \"ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n"
+                       "rawModeData": ""
                }
        ]
 }
\ No newline at end of file