Add support for RA configuration 77/5077/4
authorMarek Gradzki <[email protected]>
Mon, 6 Feb 2017 15:54:07 +0000 (16:54 +0100)
committerJan Srnicek <[email protected]>
Mon, 13 Feb 2017 09:42:04 +0000 (09:42 +0000)
Includes:

* ietf-routing model augmentation that addresses
  VPP specific RA options (HC2VPP-64)
* writers for RA cfg (HC2VPP-65)

Change-Id: Iea523caaddcf03e38c8e5e7c586f1606a44d335b
Signed-off-by: Marek Gradzki <[email protected]>
routing/routing-api/src/main/yang/vpp-routing-ra.yang [new file with mode: 0644]
routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/PrefixCustomizer.java [new file with mode: 0644]
routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RouterAdvertisementsCustomizer.java [new file with mode: 0644]
routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInterfaceCustomizer.java [new file with mode: 0644]
routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingWriterFactory.java

diff --git a/routing/routing-api/src/main/yang/vpp-routing-ra.yang b/routing/routing-api/src/main/yang/vpp-routing-ra.yang
new file mode 100644 (file)
index 0000000..5bea1db
--- /dev/null
@@ -0,0 +1,103 @@
+module vpp-routing-ra {
+
+    namespace "urn:ietf:params:xml:ns:yang:vpp-routing";
+    prefix "vpp-routing";
+    description "General extensions for routing advertisments message configuration provided by VPP APIs";
+
+    revision 2017-03-15 {
+        description "Initial revision.";
+    }
+
+    import yang-ext {
+        prefix "ext";
+    }
+
+    import hc2vpp-ietf-routing {
+        prefix "ietf-r";
+    }
+
+    import hc2vpp-ietf-ipv6-unicast-routing {
+        prefix "v6ur";
+    }
+
+    grouping ipv6-router-advertisements-vpp-attributes {
+        leaf suppress-link-layer {
+            type boolean;
+            default false;
+            description
+                "Dicates not to include the optional source link-layer address
+                 in the ICMPv6 router-advertisement messages.";
+        }
+        leaf send-unicast {
+            type boolean;
+            default false;
+            description
+                "Use the source address of the router-solicitation message if availiable.";
+        }
+        leaf cease {
+            type boolean;
+            default false;
+            description
+                "Cease sending ICMPv6 router-advertisement messages.";
+        }
+        leaf initial-count {
+            type uint8 {
+                range "1..3";
+            }
+            default 3;
+            description
+                "Number of initial ICMPv6 router-advertisement messages sent.";
+        }
+        leaf initial-interval {
+            type uint8 {
+                range "1..16";
+            }
+            units "seconds";
+            default 16;
+            description
+                "Interval between initial ICMPv6 router-advertisement messages.";
+        }
+
+        description
+            "VPP specific configuration of RA messages. Mapped to sw_interface_ip6nd_ra_config API:
+             https://git.fd.io/vpp/tree/src/vnet/ip/ip.api#n196";
+
+        reference
+            "https://docs.fd.io/vpp/17.04/clicmd_src_vnet_ip.html#clicmd_ip6_nd";
+    }
+
+    grouping control-adv-prefixes-vpp-attributes {
+        leaf advertise-router-address {
+            type boolean;
+            default true;
+            description
+                "Send full router address in prefix advertisement.";
+        }
+        leaf vpp-default {
+            type boolean;
+            default false;
+            description
+                "Use VPP default values for prefix advertisment.";
+        }
+
+        description
+            "VPP specific configuration of prefixes in RA messages. Mapped to sw_interface_ip6nd_ra_prefix API:
+             https://git.fd.io/vpp/tree/src/vnet/ip/ip.api#n243";
+
+        reference
+            "https://docs.fd.io/vpp/17.04/clicmd_src_vnet_ip.html#clicmd_ip6_nd";
+    }
+
+    augment "/ietf-r:routing/ietf-r:routing-instance/ietf-r:interfaces/ietf-r:interface/"
+            + "v6ur:ipv6-router-advertisements" {
+        ext:augment-identifier "ipv6-router-advertisements-vpp-augmentation";
+        uses ipv6-router-advertisements-vpp-attributes;
+    }
+
+    augment "/ietf-r:routing/ietf-r:routing-instance/ietf-r:interfaces/ietf-r:interface/"
+            + "v6ur:ipv6-router-advertisements/v6ur:prefix-list/v6ur:prefix" {
+        // TODO control-adv-prefixes/advertise case should be target node (change after yangtools issues are solved)
+        ext:augment-identifier "control-adv-prefixes-vpp-augmentation";
+        uses control-adv-prefixes-vpp-attributes;
+    }
+}
\ No newline at end of file
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/PrefixCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/PrefixCustomizer.java
new file mode 100644 (file)
index 0000000..8d71922
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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.routing.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceIp6NdRaPrefix;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.PrefixKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.prefix.ControlAdvPrefixes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.prefix.control.adv.prefixes.Advertise;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.prefix.control.adv.prefixes.NoAdvertise;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev170315.ControlAdvPrefixesVppAugmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class PrefixCustomizer extends FutureJVppCustomizer
+    implements ListWriterCustomizer<Prefix, PrefixKey>, JvppReplyConsumer, ByteDataTranslator, Ipv6Translator {
+    private static final Logger LOG = LoggerFactory.getLogger(PrefixCustomizer.class);
+
+    private final NamingContext interfaceContext;
+
+    PrefixCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+        super(jvpp);
+        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> id,
+                                       @Nonnull final Prefix dataAfter, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        LOG.debug("Writing Prefix {} dataAfter={}", id, dataAfter);
+        setPrefix(id, dataAfter, writeContext, false);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> id,
+                                        @Nonnull final Prefix dataBefore, @Nonnull final Prefix dataAfter,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        LOG.debug("Updating Prefix {} before={} after={}", id, dataBefore, dataAfter);
+        setPrefix(id, dataAfter, writeContext, false);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> id,
+                                        @Nonnull final Prefix dataBefore, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        LOG.debug("Removing Prefix {} dataBefore={}", id, dataBefore);
+        setPrefix(id, dataBefore, writeContext, true);
+    }
+
+    private void setPrefix(final InstanceIdentifier<Prefix> id, final Prefix prefix, final WriteContext writeContext,
+                           final boolean isDelete) throws WriteFailedException {
+        final String ifcName = id.firstKeyOf(Interface.class).getName();
+        final int ifcIndex = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+        final SwInterfaceIp6NdRaPrefix request = new SwInterfaceIp6NdRaPrefix();
+        request.swIfIndex = ifcIndex;
+        request.address = ipv6AddressPrefixToArray(prefix.getPrefixSpec());
+        request.addressLength = extractPrefix(prefix.getPrefixSpec()); // prefix length (vpp api naming bug)
+
+        if (isDelete) {
+            request.isNo = 1;
+        } else {
+            parseControlAdvPrefixes(request, prefix.getControlAdvPrefixes(), prefix.getAugmentation(
+                ControlAdvPrefixesVppAugmentation.class));
+        }
+        LOG.debug("Setting Prefix for interface {}(id={}): {}", ifcName, ifcIndex, request);
+        getReplyForWrite(getFutureJVpp().swInterfaceIp6NdRaPrefix(request).toCompletableFuture(), id);
+        LOG.debug("Prefix: {} updated successfully", id);
+    }
+
+    private void parseControlAdvPrefixes(final SwInterfaceIp6NdRaPrefix request,
+                                         final ControlAdvPrefixes controlAdvPrefixes,
+                                         final ControlAdvPrefixesVppAugmentation vppAugmentation) {
+        if (controlAdvPrefixes instanceof Advertise) {
+            final Advertise advertise = (Advertise) controlAdvPrefixes;
+            request.noAutoconfig = booleanToByte(!advertise.isAutonomousFlag());
+            request.noOnlink = booleanToByte(!advertise.isOnLinkFlag());
+            // request.offLink controls L bit in the same way as noOnlink, but also controls if it is installed in FIB
+            if (advertise.getValidLifetime() != null) {
+                request.valLifetime = advertise.getValidLifetime().intValue();
+            }
+            if (advertise.getPreferredLifetime() != null) {
+                checkArgument(advertise.getValidLifetime() != null,
+                    "valid-lifetime needs to be configured if preferred-lifetime is given");
+                checkArgument(advertise.getPreferredLifetime() <= advertise.getValidLifetime(),
+                    "preferred-lifetime  MUST NOT be greater than valid-lifetime.");
+                request.prefLifetime = advertise.getPreferredLifetime().intValue();
+            }
+            if (vppAugmentation != null) {
+                request.useDefault = booleanToByte(vppAugmentation.isVppDefault());
+                request.noAdvertise = booleanToByte(!vppAugmentation.isAdvertiseRouterAddress());
+            }
+        } else if (controlAdvPrefixes instanceof NoAdvertise) {
+            throw new IllegalArgumentException(
+                "NoAdvertise control-adv-prefix is not supported." +
+                    "To remove prefix from set of advertised prefixes, use DELETE request.");
+        } else {
+            throw new IllegalArgumentException("Unsupported control-adv-prefix: " + controlAdvPrefixes);
+        }
+    }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RouterAdvertisementsCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RouterAdvertisementsCustomizer.java
new file mode 100644 (file)
index 0000000..f33272b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.routing.write;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceIp6NdRaConfig;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.Ipv6RouterAdvertisements;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev170315.Ipv6RouterAdvertisementsVppAugmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class RouterAdvertisementsCustomizer extends FutureJVppCustomizer
+    implements WriterCustomizer<Ipv6RouterAdvertisements>, JvppReplyConsumer, ByteDataTranslator {
+    private static final Logger LOG = LoggerFactory.getLogger(RouterAdvertisementsCustomizer.class);
+
+    private final NamingContext interfaceContext;
+
+    RouterAdvertisementsCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) {
+        super(jvpp);
+        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv6RouterAdvertisements> id,
+                                       @Nonnull final Ipv6RouterAdvertisements dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        LOG.debug("Writing RouterAdvertisements {} dataAfter={}", id, dataAfter);
+        setRouterAdvertisements(id, dataAfter, writeContext, false);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv6RouterAdvertisements> id,
+                                        @Nonnull final Ipv6RouterAdvertisements dataBefore,
+                                        @Nonnull final Ipv6RouterAdvertisements dataAfter,
+                                        @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        LOG.debug("Updating RouterAdvertisements {} dataBefore={} dataAfter={}", id, dataBefore, dataAfter);
+        setRouterAdvertisements(id, dataAfter, writeContext, false);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv6RouterAdvertisements> id,
+                                        @Nonnull final Ipv6RouterAdvertisements dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        LOG.debug("Removing RouterAdvertisements {} dataBefore={}", id, dataBefore);
+        setRouterAdvertisements(id, dataBefore, writeContext, true);
+    }
+
+    private void setRouterAdvertisements(@Nonnull final InstanceIdentifier<Ipv6RouterAdvertisements> id,
+                                        @Nonnull final Ipv6RouterAdvertisements data,
+                                        @Nonnull final WriteContext writeContext,
+                                        final boolean isDelete) throws WriteFailedException {
+        final String ifcName = id.firstKeyOf(Interface.class).getName();
+        final int ifcIndex = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
+        SwInterfaceIp6NdRaConfig request;
+        if (isDelete) {
+            request = new SwInterfaceIp6NdRaConfig();
+            request.swIfIndex = ifcIndex;
+            request.suppress = 1;
+        } else {
+            request = getRequest(data, ifcIndex);
+        }
+        LOG.debug("Updating RouterAdvertisements configuration for interface {}(id={}): {}", ifcName, ifcIndex, request);
+        getReplyForWrite(getFutureJVpp().swInterfaceIp6NdRaConfig(request).toCompletableFuture(), id);
+        LOG.debug("RouterAdvertisements: {} configuration updated successfully", id);
+    }
+
+    private SwInterfaceIp6NdRaConfig getRequest(final Ipv6RouterAdvertisements dataAfter, final int ifcIndex) {
+        final SwInterfaceIp6NdRaConfig request = new SwInterfaceIp6NdRaConfig();
+        request.swIfIndex = ifcIndex;
+        request.suppress = booleanToByte(!dataAfter.isSendAdvertisements());
+        request.managed = booleanToByte(dataAfter.isManagedFlag());
+        request.other = booleanToByte(dataAfter.isOtherConfigFlag());
+        final Ipv6RouterAdvertisementsVppAugmentation vppAugmentation =
+            dataAfter.getAugmentation(Ipv6RouterAdvertisementsVppAugmentation.class);
+        if (vppAugmentation != null) {
+            request.llOption = booleanToByte(vppAugmentation.isSuppressLinkLayer());
+            request.sendUnicast = booleanToByte(vppAugmentation.isSendUnicast());
+            request.cease = booleanToByte(vppAugmentation.isCease());
+            request.initialCount = vppAugmentation.getInitialCount();
+            request.initialInterval = vppAugmentation.getInitialInterval();
+        }
+        request.isNo = 0;
+        if (dataAfter.getMinRtrAdvInterval() != null) {
+            request.minInterval = dataAfter.getMinRtrAdvInterval();
+        }
+        if (dataAfter.getMaxRtrAdvInterval() != null) {
+            request.maxInterval = dataAfter.getMaxRtrAdvInterval();
+        }
+        if (dataAfter.getDefaultLifetime() != null && dataAfter.getDefaultLifetime() != 0) {
+            request.lifetime = dataAfter.getDefaultLifetime();
+            request.defaultRouter = 1;
+        }
+        return request;
+    }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInterfaceCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInterfaceCustomizer.java
new file mode 100644 (file)
index 0000000..d8737ce
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.routing.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import javax.annotation.Nonnull;
+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.routing.rev140524.routing.routing.instance.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Dummy customizer for Interfaces node responsible for validation only.
+ */
+public class RoutingInterfaceCustomizer implements ListWriterCustomizer<Interface, InterfaceKey> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RoutingInterfaceCustomizer.class);
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+                                       @Nonnull final Interface after, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        LOG.debug("Writing {} after={}", id, after);
+        checkIfcIsConfigured(after.getName(), writeContext);
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+                                        @Nonnull final Interface before, @Nonnull final Interface after,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        LOG.debug("Updating {} before={} after={}", id, before, after);
+        checkIfcIsConfigured(after.getName(), writeContext);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> id,
+                                        @Nonnull final Interface after, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        LOG.debug("Removing {}", id);
+        // here we do not care if the ifc exists or not, because we are removing reference to it
+    }
+
+    private static void checkIfcIsConfigured(@Nonnull final String ifcName, @Nonnull final WriteContext writeContext) {
+        final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey>
+            id = InstanceIdentifier.create(Interfaces.class)
+            .child(
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class,
+                new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey(
+                    ifcName));
+        checkArgument(writeContext.readAfter(id).isPresent(), "Interface %s is not configured");
+    }
+}
index 02fa7d1..e5487e5 100644 (file)
@@ -34,13 +34,21 @@ import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.Ipv6RouterAdvertisements;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.PrefixList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.interfaces._interface.ipv6.router.advertisements.prefix.list.Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.RoutingProtocols;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutes;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev170315.ControlAdvPrefixesVppAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev170315.Ipv6RouterAdvertisementsVppAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -49,6 +57,13 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 public final class RoutingWriterFactory implements WriterFactory, Ipv4WriteRoutingNodes, Ipv6WriteRoutingNodes {
 
     private static final InstanceIdentifier<Routing> ROOT_CONTAINER_ID = InstanceIdentifier.create(Routing.class);
+    private static final InstanceIdentifier<Interface> ROUTING_INTERFACE_ID =
+        ROOT_CONTAINER_ID.child(RoutingInstance.class).child(Interfaces.class).child(Interface.class);
+    private static final InstanceIdentifier<Ipv6RouterAdvertisements> ROUTING_ADVERTISMENT_ID =
+        ROUTING_INTERFACE_ID.augmentation(
+            Interface1.class).child(Ipv6RouterAdvertisements.class);
+    private static final InstanceIdentifier<Prefix> PREFIX_ID =
+        ROUTING_ADVERTISMENT_ID.child(PrefixList.class).child(Prefix.class);
 
     @Inject
     private FutureJVppCore vppApi;
@@ -97,6 +112,12 @@ public final class RoutingWriterFactory implements WriterFactory, Ipv4WriteRouti
         registry.subtreeAdd(ipv6RoutingHandledChildren(ipv6RouteSubtree()), new GenericWriter<>(ipv6RouteIdentifier,
                 new Ipv6RouteCustomizer(vppApi, interfaceContext, routeContext, routingProtocolContext, routHopContext,
                         vppClassifierContextManager)));
+        registry.add(new GenericWriter<>(ROUTING_INTERFACE_ID, new RoutingInterfaceCustomizer()));
+        registry.subtreeAdd(raHandledChildren(),
+            new GenericWriter<>(ROUTING_ADVERTISMENT_ID, new RouterAdvertisementsCustomizer(vppApi, interfaceContext)));
+        registry.subtreeAdd(prefixHandledChildren(),
+            new GenericWriter<>(PREFIX_ID, new PrefixCustomizer(vppApi, interfaceContext)));
+
     }
 
     private static ImmutableSet<InstanceIdentifier<?>> routingProtocolHandledChildren() {
@@ -107,7 +128,6 @@ public final class RoutingWriterFactory implements WriterFactory, Ipv4WriteRouti
     private static InstanceIdentifier<RoutingInstance> routingInstanceIdentifier() {
         return ROOT_CONTAINER_ID.child(RoutingInstance.class);
     }
-
     private static InstanceIdentifier<RoutingProtocol> routingProtocolIdentifier() {
         return routingInstanceIdentifier().child(RoutingProtocols.class).child(RoutingProtocol.class);
     }
@@ -119,4 +139,14 @@ public final class RoutingWriterFactory implements WriterFactory, Ipv4WriteRouti
     private static Set<InstanceIdentifier<?>> rootNodeHandledChildren(final InstanceIdentifier<Routing> parent) {
         return ImmutableSet.of(parent.child(RoutingInstance.class).child(RoutingProtocols.class));
     }
+
+    private static Set<InstanceIdentifier<?>> raHandledChildren() {
+        final InstanceIdentifier<Ipv6RouterAdvertisements> raIID = InstanceIdentifier.create(Ipv6RouterAdvertisements.class);
+        return ImmutableSet.of(raIID.augmentation(Ipv6RouterAdvertisementsVppAugmentation.class));
+    }
+
+    private static Set<InstanceIdentifier<?>> prefixHandledChildren() {
+        final InstanceIdentifier<Prefix> prefixIID = InstanceIdentifier.create(Prefix.class);
+        return ImmutableSet.of(prefixIID.augmentation(ControlAdvPrefixesVppAugmentation.class));
+    }
 }