summaryrefslogtreecommitdiffstats
path: root/routing/routing-impl/src/main/java
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2016-12-01 18:15:52 +0100
committerJan Srnicek <jsrnicek@cisco.com>2016-12-01 18:16:47 +0100
commit32aa07e5517fba7f78ae79d2ba83b56f72a53293 (patch)
tree26256f30f2dc5c3521403ef3fcd2e038b2f9bca6 /routing/routing-impl/src/main/java
parent9c9935c83ce9869ca36cbde7865423ef02f19db8 (diff)
HONEYCOMB-58 - Routing Plugin Structure
Read/Write support for ipv4/6 static routes. Restriction due to vpp implementation described in readme. Change-Id: I328f406a9b7cb8781f8becf98eca293cebe66859 Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'routing/routing-impl/src/main/java')
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingConfiguration.java60
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingModule.java71
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv4RouteNamesFactory.java108
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv6RouteNamesFactory.java122
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4ReadRoutingNodes.java95
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4RouteCustomizer.java162
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6ReadRoutingNodes.java94
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6RouteCustomizer.java159
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingInstanceCustomizer.java73
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingProtocolCustomizer.java136
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateCustomizer.java149
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateReaderFactory.java136
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv4RoutePathParser.java120
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv6RoutePathParser.java136
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/RouteMapper.java92
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4RouteCustomizer.java213
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4WriteRoutingNodes.java169
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java211
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6WriteRoutingNodes.java168
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingCustomizer.java55
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInstanceCustomizer.java75
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingProtocolCustomizer.java103
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingWriterFactory.java122
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/MultipathHopRequestFactory.java154
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SimpleHopRequestFactory.java145
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SpecialNextHopRequestFactory.java120
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/BasicHopRequestFactory.java49
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/ClassifierContextHolder.java38
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/trait/RouteRequestProducer.java138
29 files changed, 3473 insertions, 0 deletions
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingConfiguration.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingConfiguration.java
new file mode 100644
index 000000000..c8f0ba634
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingConfiguration.java
@@ -0,0 +1,60 @@
+/*
+ * 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.routing;
+
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+@BindConfig(value = "routing", syntax = Syntax.JSON)
+public class RoutingConfiguration {
+
+ /**
+ * Route ids start from
+ */
+ public static final int MULTI_MAPPING_START_INDEX = 1;
+
+ /**
+ * Contains routing protocol to table id mapping
+ */
+ public static final String ROUTING_PROTOCOL_CONTEXT = "routing-protocol-context";
+
+ /**
+ * Used to map routes to routing-protocols
+ */
+ public static final String ROUTE_CONTEXT = "route-context";
+
+ /**
+ * Used to map hop ids to routes
+ */
+ public static final String ROUTE_HOP_CONTEXT = "route-hop-context";
+
+
+ @InjectConfig("default-routing-instance-name")
+ private String defaultRoutingInstanceName;
+
+ @InjectConfig("learned-route-name-prefix")
+ private String learnedRouteNamePrefix;
+
+ public String getDefaultRoutingInstanceName() {
+ return defaultRoutingInstanceName;
+ }
+
+ public String getLearnedRouteNamePrefix() {
+ return learnedRouteNamePrefix;
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingModule.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingModule.java
new file mode 100644
index 000000000..a6fadf78c
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/RoutingModule.java
@@ -0,0 +1,71 @@
+/*
+ * 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.routing;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.read.RoutingStateReaderFactory;
+import io.fd.hc2vpp.routing.write.RoutingWriterFactory;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import net.jmob.guice.conf.core.ConfigurationModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * RoutingModule class instantiating routing plugin components.
+ */
+public final class RoutingModule extends AbstractModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RoutingModule.class);
+
+ @Override
+ protected void configure() {
+ LOG.info("Starting initialization");
+ // requests injection of properties
+ install(ConfigurationModule.create());
+ requestInjection(RoutingConfiguration.class);
+
+ bind(NamingContext.class)
+ .annotatedWith(Names.named(RoutingConfiguration.ROUTING_PROTOCOL_CONTEXT))
+ .toInstance(new NamingContext("learned-protocol-", RoutingConfiguration.ROUTING_PROTOCOL_CONTEXT));
+
+ bind(NamingContext.class)
+ .annotatedWith(Names.named(RoutingConfiguration.ROUTE_CONTEXT))
+ .toInstance(new NamingContext("route-", RoutingConfiguration.ROUTE_CONTEXT));
+
+ bind(MultiNamingContext.class)
+ .annotatedWith(Names.named(RoutingConfiguration.ROUTE_HOP_CONTEXT))
+ .toInstance(new MultiNamingContext(RoutingConfiguration.ROUTE_HOP_CONTEXT,
+ RoutingConfiguration.MULTI_MAPPING_START_INDEX));
+
+ LOG.info("Injecting reader factories");
+ // creates reader factory binding
+ final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ readerFactoryBinder.addBinding().to(RoutingStateReaderFactory.class);
+
+ LOG.info("Injecting writers factories");
+ // create writer factory binding
+ final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+ writerFactoryBinder.addBinding().to(RoutingWriterFactory.class);
+
+ LOG.info("Started successfully");
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv4RouteNamesFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv4RouteNamesFactory.java
new file mode 100644
index 000000000..5d3d76ff6
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv4RouteNamesFactory.java
@@ -0,0 +1,108 @@
+/*
+ * 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.routing.naming;
+
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.hc2vpp.routing.write.trait.RouteRequestProducer;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.IpFibDetails;
+import io.fd.vpp.jvpp.core.types.FibPath;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+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.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.next.hop.list.NextHop;
+
+
+public final class Ipv4RouteNamesFactory implements RouteMapper, RouteRequestProducer {
+
+ private static final String DOT = ".";
+ private static final String EMPTY = "";
+
+ private final NamingContext interfaceContext;
+ private final NamingContext routingProtocolContext;
+
+ public Ipv4RouteNamesFactory(@Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ this.interfaceContext = interfaceContext;
+ this.routingProtocolContext = routingProtocolContext;
+ }
+
+ /**
+ * Construct unique name from provided {@code Route}
+ */
+ public String uniqueRouteName(@Nonnull final String parentProtocolName, @Nonnull final Route route) {
+ return bindName(parentProtocolName, dotlessAddress(route.getDestinationPrefix()),
+ String.valueOf(extractPrefix(route.getDestinationPrefix())));
+ }
+
+ /**
+ * Construct unique name from provided {@code IpFibDetails}
+ */
+ public String uniqueRouteName(@Nonnull final IpFibDetails details, @Nonnull final MappingContext mappingContext) {
+ return bindName(routingProtocolContext.getName(details.tableId, mappingContext),
+ dotlessAddress(details.address),
+ String.valueOf(details.addressLength));
+ }
+
+
+ public String uniqueRouteHopName(@Nonnull final NextHop hop) {
+ return bindName(hop.getOutgoingInterface(),
+ dotlessAddress(hop.getAddress()),
+ String.valueOf(hop.getWeight()));
+ }
+
+
+ public String uniqueRouteHopName(@Nonnull final FibPath path,
+ @Nonnull final MappingContext mappingContext) {
+ return bindName(interfaceContext.getName(path.swIfIndex, mappingContext),
+ dotlessAddress(path.nextHop), String.valueOf(path.weight));
+ }
+
+ private String dotlessAddress(final byte[] address) {
+ // trimming in case of ipv4 address beeing sent as 16 byte array
+ byte[] trimmed = address;
+ if (trimmed.length > 4) {
+ trimmed = Arrays.copyOfRange(trimmed, 0, 4);
+ }
+
+ //no reverting, just takes address as it is and converts it
+ try {
+ return dotless(InetAddress.getByAddress(trimmed).getHostAddress());
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private String dotlessAddress(@Nonnull final Ipv4Prefix address) {
+ final String addressValue = address.getValue();
+ return dotless(addressValue.substring(0, addressValue.indexOf("/")));
+ }
+
+ private String dotlessAddress(@Nonnull final Ipv4Address address) {
+ return dotless(address.getValue());
+ }
+
+ private String dotless(@Nonnull final String input) {
+ return input.replace(DOT, EMPTY);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv6RouteNamesFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv6RouteNamesFactory.java
new file mode 100644
index 000000000..8408c82b6
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/naming/Ipv6RouteNamesFactory.java
@@ -0,0 +1,122 @@
+/*
+ * 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.routing.naming;
+
+import com.google.common.net.InetAddresses;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetails;
+import io.fd.vpp.jvpp.core.types.FibPath;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.annotation.Nonnull;
+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.Ipv6Prefix;
+
+
+public final class Ipv6RouteNamesFactory implements RouteMapper {
+
+ private static final String DOUBLE_DOT = ":";
+ private static final String EMPTY = "";
+
+ private final NamingContext interfaceContext;
+ private final NamingContext routingProtocolContext;
+
+ public Ipv6RouteNamesFactory(@Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ this.interfaceContext = interfaceContext;
+ this.routingProtocolContext = routingProtocolContext;
+ }
+
+ /**
+ * Construct unique name from provided {@code Route}
+ */
+ public String uniqueRouteName(@Nonnull final String parentProtocolName,
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route route) {
+ return bindName(parentProtocolName,
+ // to have address in compressed form
+ doubleDotlessAddress(route.getDestinationPrefix()),
+ String.valueOf(extractPrefix(route.getDestinationPrefix())));
+ }
+
+ /**
+ * Construct unique name from provided {@code IpFibDetails}
+ */
+ public String uniqueRouteName(@Nonnull final Ip6FibDetails details, @Nonnull final MappingContext mappingContext) {
+ return bindName(routingProtocolContext.getName(details.tableId, mappingContext),
+ doubleDotlessAddress(details.address),
+ String.valueOf(details.addressLength));
+ }
+
+ public String uniqueRouteHopName(
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHop hop) {
+ return bindName(hop.getOutgoingInterface(),
+ doubleDotlessAddress(hop.getAddress()),
+ String.valueOf(hop.getWeight()));
+ }
+
+ public String uniqueRouteHopName(@Nonnull final FibPath path, @Nonnull final MappingContext mappingContext) {
+ return bindName(interfaceContext.getName(path.swIfIndex, mappingContext),
+ doubleDotlessAddress(path.nextHop),
+ String.valueOf(path.weight));
+ }
+
+ /**
+ * Uses combination of standard java.net.InetAddress and com.google.common.net.InetAddresses for following reasons
+ * <ul>
+ * <li>
+ * InetAddresses.toAddrString uses maximal ipv6 compression - eliminate possibility of mismatch between same
+ * addresses with different compression
+ * </li>
+ * <li>
+ * InetAddress.getByAddress just converts byte array to address, that's
+ * why InetAddresses.fromLittleEndianByteArray is not used, because it internaly reverts order of address
+ * bytes,which is something that is not needed here
+ * </li>
+ * </ul>
+ */
+ private String doubleDotlessAddress(final byte[] address) {
+ try {
+ return doubleDotless(InetAddresses.toAddrString(InetAddress.getByAddress(address)));
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private String doubleDotlessAddress(@Nonnull final Ipv6Prefix address) {
+ final String addressValue = address.getValue();
+ return doubleDotless(compressedIpv6(addressValue.substring(0, addressValue.indexOf("/"))));
+ }
+
+ private String doubleDotlessAddress(@Nonnull final Ipv6Address address) {
+ // converted to use maximal compression
+ // for details - https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/net/InetAddresses.html#toAddrString-java.net.InetAddress
+ return doubleDotless(compressedIpv6(address.getValue()));
+ }
+
+ /**
+ * Use maximal compresion of ipv6 address string
+ */
+ private String compressedIpv6(@Nonnull final String input) {
+ return InetAddresses.toAddrString(InetAddresses.forString(input));
+ }
+
+ private String doubleDotless(@Nonnull final String input) {
+ return input.replace(DOUBLE_DOT, EMPTY);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4ReadRoutingNodes.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4ReadRoutingNodes.java
new file mode 100644
index 000000000..dde2f9c46
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4ReadRoutingNodes.java
@@ -0,0 +1,95 @@
+/*
+ * 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.routing.read;
+
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.IpFibDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpFibDump;
+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.StaticRoutes2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes2Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.VppIpv4RouteState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.NextHopList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol.StaticRoutes;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+interface Ipv4ReadRoutingNodes extends JvppReplyConsumer {
+
+ static InstanceIdentifier<StaticRoutes2> staticRoutesInstanceIdentifier(
+ final InstanceIdentifier<StaticRoutes> staticRoutesInstanceIdentifier) {
+ return staticRoutesInstanceIdentifier.augmentation(StaticRoutes2.class);
+ }
+
+ static InstanceIdentifier<Ipv4> ipv4Identifier(
+ final InstanceIdentifier<StaticRoutes2> staticRoutes2InstanceIdentifier) {
+ return staticRoutes2InstanceIdentifier.child(Ipv4.class);
+ }
+
+ default DumpCacheManager<IpFibDetailsReplyDump, Void> newIpv4RoutesDumpManager(
+ @Nonnull final FutureJVppCore vppApi) {
+ return new DumpCacheManager.DumpCacheManagerBuilder<IpFibDetailsReplyDump, Void>()
+ .withExecutor(
+ (identifier, params) -> getReplyForRead(vppApi.ipFibDump(new IpFibDump()).toCompletableFuture(),
+ identifier))
+ .acceptOnly(IpFibDetailsReplyDump.class)
+ .build();
+ }
+
+ default void registerIpv4Routes(@Nonnull final InstanceIdentifier<StaticRoutes> subTreeId,
+ @Nonnull final ModifiableReaderRegistryBuilder registry,
+ @Nonnull final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4DumpManager,
+ @Nonnull final RoutingConfiguration configuration,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routeContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+
+ final InstanceIdentifier<StaticRoutes2> staticRoutes2InstanceIdentifier =
+ staticRoutesInstanceIdentifier(subTreeId);
+ final InstanceIdentifier<Ipv4> ipv4InstanceIdentifier = ipv4Identifier(staticRoutes2InstanceIdentifier);
+
+ registry.addStructuralReader(staticRoutes2InstanceIdentifier, StaticRoutes2Builder.class);
+
+ registry.addStructuralReader(ipv4InstanceIdentifier, Ipv4Builder.class);
+ registry.subtreeAdd(ipv4RoutingHandledChildren(InstanceIdentifier.create(Route.class)),
+ new GenericListReader<>(ipv4InstanceIdentifier.child(Route.class),
+ new Ipv4RouteCustomizer(ipv4DumpManager, configuration, routeHopContext, interfaceContext,
+ routeContext, routingProtocolContext)));
+ }
+
+ default Set<InstanceIdentifier<?>> ipv4RoutingHandledChildren(
+ final InstanceIdentifier<Route> parent) {
+ return ImmutableSet.of(parent.child(NextHopList.class),
+ parent.child(NextHopList.class).child(NextHop.class),
+ parent.child(VppIpv4RouteState.class));
+ }
+
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4RouteCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4RouteCustomizer.java
new file mode 100644
index 000000000..71758b4fe
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv4RouteCustomizer.java
@@ -0,0 +1,162 @@
+/*
+ * 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.routing.read;
+
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.hc2vpp.routing.naming.Ipv4RouteNamesFactory;
+import io.fd.hc2vpp.routing.trait.Ipv4RoutePathParser;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.IpFibDetails;
+import io.fd.vpp.jvpp.core.dto.IpFibDetailsReplyDump;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.VppIpv4RouteStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ipv4RouteCustomizer
+ implements ListReaderCustomizer<Route, RouteKey, RouteBuilder>, RouteMapper, Ipv4RoutePathParser {
+
+
+ private final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4RoutesDumpManager;
+ private final RoutingConfiguration configuration;
+ private final MultiNamingContext routeHopContext;
+ private final NamingContext interfaceContext;
+ private final NamingContext routesContext;
+ private final NamingContext routingProtocolContext;
+
+ private final Ipv4RouteNamesFactory namesFactory;
+
+ public Ipv4RouteCustomizer(@Nonnull final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4RoutesDumpManager,
+ @Nonnull final RoutingConfiguration configuration,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routesContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ this.ipv4RoutesDumpManager = ipv4RoutesDumpManager;
+ this.configuration = configuration;
+ this.interfaceContext = interfaceContext;
+ this.routeHopContext = routeHopContext;
+ this.routesContext = routesContext;
+ this.routingProtocolContext = routingProtocolContext;
+ this.namesFactory = new Ipv4RouteNamesFactory(interfaceContext, routingProtocolContext);
+ }
+
+ @Nonnull
+ @Override
+ public List<RouteKey> getAllIds(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+
+ final Optional<IpFibDetailsReplyDump> ipv4RoutesDump =
+ ipv4RoutesDumpManager.getDump(instanceIdentifier, readContext.getModificationCache(), NO_PARAMS);
+
+ final String protocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final int protocolTableId = routingProtocolContext.getIndex(protocolName, readContext.getMappingContext());
+
+ return ipv4RoutesDump.isPresent()
+ ? ipv4RoutesDump.get().ipFibDetails.stream()
+ .filter(details -> protocolTableId == details.tableId)
+ .map(ipFibDetails -> toKey(ipFibDetails, readContext.getMappingContext()))
+ .collect(Collectors.toList())
+ : Collections.emptyList();
+ }
+
+ /**
+ * route id is represented as number, but there's no index in dumped data,
+ * so index is assigned to name formatted as tableId_address_addressLength(should be unique combination)
+ */
+ private RouteKey toKey(final IpFibDetails details, final MappingContext mappingContext) {
+ String routeName = namesFactory.uniqueRouteName(details, mappingContext);
+ // first condition excludes data written manually, second one data that has been already learned
+ if (!routesContext.containsIndex(routeName, mappingContext)) {
+ String learnedRouteName = nameWithPrefix(configuration.getLearnedRouteNamePrefix(), routeName);
+ if (!routesContext.containsIndex(learnedRouteName, mappingContext)) {
+ routesContext.addName(learnedRouteName, mappingContext);
+ }
+ return keyForName(mappingContext, learnedRouteName);
+ }
+ return keyForName(mappingContext, routeName);
+ }
+
+ private RouteKey keyForName(final MappingContext mappingContext, final String name) {
+ return new RouteKey(
+ Long.valueOf(routesContext.getIndex(name, mappingContext)));
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Route> list) {
+ Ipv4Builder.class.cast(builder).setRoute(list);
+ }
+
+ @Nonnull
+ @Override
+ public RouteBuilder getBuilder(@Nonnull final InstanceIdentifier<Route> instanceIdentifier) {
+ return new RouteBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final RouteBuilder routeBuilder, @Nonnull final ReadContext readContext)
+ throws ReadFailedException {
+ final RouteKey key = instanceIdentifier.firstKeyOf(Route.class);
+ final String mappedName = routesContext.getName(key.getId().intValue(), readContext.getMappingContext());
+ final String protocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final int protocolTableId = routingProtocolContext.getIndex(protocolName, readContext.getMappingContext());
+ final Optional<IpFibDetailsReplyDump> ipv4RoutesDump =
+ ipv4RoutesDumpManager.getDump(instanceIdentifier, readContext.getModificationCache(), NO_PARAMS);
+
+ if (ipv4RoutesDump.isPresent() && !ipv4RoutesDump.get().ipFibDetails.isEmpty()) {
+
+ final java.util.Optional<IpFibDetails> opDetail = ipv4RoutesDump.get().ipFibDetails.stream()
+ .filter(details -> protocolTableId == details.tableId)
+ .filter(details -> equalsWithConfigOrLearned(configuration.getLearnedRouteNamePrefix(), mappedName,
+ namesFactory.uniqueRouteName(details, readContext.getMappingContext())))
+ .findAny();
+
+ if (opDetail.isPresent()) {
+ final IpFibDetails detail = opDetail.get();
+
+ routeBuilder.setNextHopOptions(
+ resolveHopType(mappedName, Arrays.asList(detail.path), interfaceContext, routeHopContext,
+ readContext.getMappingContext(), namesFactory))
+ .setKey(key)
+ .setId(key.getId())
+ .setDestinationPrefix(toIpv4Prefix(detail.address, toJavaByte(detail.addressLength)))
+ .setVppIpv4RouteState(new VppIpv4RouteStateBuilder().build());
+ }
+ }
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6ReadRoutingNodes.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6ReadRoutingNodes.java
new file mode 100644
index 000000000..06eaaf913
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6ReadRoutingNodes.java
@@ -0,0 +1,94 @@
+/*
+ * 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.routing.read;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDump;
+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.ipv6.unicast.routing.rev140525.StaticRoutes2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.StaticRoutes2Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6RouteState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol.StaticRoutes;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+interface Ipv6ReadRoutingNodes extends JvppReplyConsumer {
+
+ static InstanceIdentifier<StaticRoutes2> staticRoutesInstanceIdentifier(
+ final InstanceIdentifier<StaticRoutes> staticRoutesInstanceIdentifier) {
+ return staticRoutesInstanceIdentifier.augmentation(StaticRoutes2.class);
+ }
+
+ static InstanceIdentifier<Ipv6> ipv6Identifier(
+ final InstanceIdentifier<StaticRoutes2> staticRoutes2InstanceIdentifier) {
+ return staticRoutes2InstanceIdentifier.child(Ipv6.class);
+ }
+
+ default DumpCacheManager<Ip6FibDetailsReplyDump, Void> newIpv6RoutesDumpManager(
+ @Nonnull final FutureJVppCore vppApi) {
+ return new DumpCacheManager.DumpCacheManagerBuilder<Ip6FibDetailsReplyDump, Void>()
+ .withExecutor(
+ (identifier, params) -> getReplyForRead(
+ vppApi.ip6FibDump(new Ip6FibDump()).toCompletableFuture(), identifier))
+ .acceptOnly(Ip6FibDetailsReplyDump.class)
+ .build();
+ }
+
+ default void registerIpv6Routes(@Nonnull final InstanceIdentifier<StaticRoutes> subTreeId,
+ @Nonnull final ModifiableReaderRegistryBuilder registry,
+ @Nonnull final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6DumpManager,
+ @Nonnull final RoutingConfiguration configuration,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routeContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+
+ final InstanceIdentifier<StaticRoutes2> staticRoutes2InstanceIdentifier =
+ staticRoutesInstanceIdentifier(subTreeId);
+ final InstanceIdentifier<Ipv6> ipv6InstanceIdentifier = ipv6Identifier(staticRoutes2InstanceIdentifier);
+
+ registry.addStructuralReader(staticRoutes2InstanceIdentifier, StaticRoutes2Builder.class);
+
+ registry.addStructuralReader(ipv6InstanceIdentifier, Ipv6Builder.class);
+ registry.subtreeAdd(ipv6RoutingHandledChildren(InstanceIdentifier.create(Route.class)),
+ new GenericListReader<>(ipv6InstanceIdentifier.child(Route.class),
+ new Ipv6RouteCustomizer(ipv6DumpManager, configuration, routeHopContext, interfaceContext,
+ routeContext, routingProtocolContext)));
+ }
+
+ default Set<InstanceIdentifier<?>> ipv6RoutingHandledChildren(
+ final InstanceIdentifier<Route> parent) {
+ return ImmutableSet.of(parent.child(NextHopList.class),
+ parent.child(NextHopList.class).child(NextHop.class),
+ parent.child(VppIpv6RouteState.class));
+ }
+
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6RouteCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6RouteCustomizer.java
new file mode 100644
index 000000000..c83891d85
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/Ipv6RouteCustomizer.java
@@ -0,0 +1,159 @@
+/*
+ * 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.routing.read;
+
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.hc2vpp.routing.naming.Ipv6RouteNamesFactory;
+import io.fd.hc2vpp.routing.trait.Ipv6RoutePathParser;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetails;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetailsReplyDump;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.RouteKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6RouteStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ipv6RouteCustomizer
+ implements ListReaderCustomizer<Route, RouteKey, RouteBuilder>, RouteMapper, Ipv6RoutePathParser {
+
+ private final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6RoutesDumpManager;
+ private final RoutingConfiguration configuration;
+ private final MultiNamingContext routeHopContext;
+ private final NamingContext interfaceContext;
+ private final NamingContext routesContext;
+ private final NamingContext routingProtocolContext;
+ private final Ipv6RouteNamesFactory namesFactory;
+
+ public Ipv6RouteCustomizer(@Nonnull final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6RoutesDumpManager,
+ @Nonnull final RoutingConfiguration configuration,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routesContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ this.ipv6RoutesDumpManager = ipv6RoutesDumpManager;
+ this.configuration = configuration;
+ this.interfaceContext = interfaceContext;
+ this.routeHopContext = routeHopContext;
+ this.routesContext = routesContext;
+ this.routingProtocolContext = routingProtocolContext;
+ this.namesFactory = new Ipv6RouteNamesFactory(interfaceContext, routingProtocolContext);
+ }
+
+ @Nonnull
+ @Override
+ public List<RouteKey> getAllIds(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+
+ final Optional<Ip6FibDetailsReplyDump> ipv6RoutesDump =
+ ipv6RoutesDumpManager.getDump(instanceIdentifier, readContext.getModificationCache(), NO_PARAMS);
+
+ final String protocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final int protocolTableId = routingProtocolContext.getIndex(protocolName, readContext.getMappingContext());
+
+ return ipv6RoutesDump.isPresent()
+ ? ipv6RoutesDump.get().ip6FibDetails.stream()
+ .filter(details -> protocolTableId == details.tableId)
+ .map(ip6FibDetails -> toKey(ip6FibDetails, readContext.getMappingContext()))
+ .collect(Collectors.toList())
+ : Collections.emptyList();
+ }
+
+ /**
+ * route id is represented as number, but there's no index in dumped data,
+ * so index is assigned to name formatted as tableId_address_addressLength(should be unique combination)
+ */
+ private RouteKey toKey(final Ip6FibDetails details, final MappingContext mappingContext) {
+ String routeName = namesFactory.uniqueRouteName(details, mappingContext);
+ // first condition excludes data written manually, second one data that has been already learned
+ if (!routesContext.containsIndex(routeName, mappingContext)) {
+ String learnedRouteName = nameWithPrefix(configuration.getLearnedRouteNamePrefix(), routeName);
+ if (!routesContext.containsIndex(learnedRouteName, mappingContext)) {
+ routesContext.addName(learnedRouteName, mappingContext);
+ }
+ return keyForName(mappingContext, learnedRouteName);
+ }
+ return keyForName(mappingContext, routeName);
+ }
+
+ private RouteKey keyForName(final MappingContext mappingContext, final String name) {
+ return new RouteKey(Long.valueOf(routesContext.getIndex(name, mappingContext)));
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Route> list) {
+ Ipv6Builder.class.cast(builder).setRoute(list);
+ }
+
+ @Nonnull
+ @Override
+ public RouteBuilder getBuilder(@Nonnull final InstanceIdentifier<Route> instanceIdentifier) {
+ return new RouteBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final RouteBuilder routeBuilder, @Nonnull final ReadContext readContext)
+ throws ReadFailedException {
+ final RouteKey key = instanceIdentifier.firstKeyOf(Route.class);
+ final String mappedName = routesContext.getName(key.getId().intValue(), readContext.getMappingContext());
+ final String protocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final int protocolTableId = routingProtocolContext.getIndex(protocolName, readContext.getMappingContext());
+ final Optional<Ip6FibDetailsReplyDump> ipv6RoutesDump =
+ ipv6RoutesDumpManager.getDump(instanceIdentifier, readContext.getModificationCache(), NO_PARAMS);
+
+ if (ipv6RoutesDump.isPresent() && !ipv6RoutesDump.get().ip6FibDetails.isEmpty()) {
+
+ final java.util.Optional<Ip6FibDetails> opDetail = ipv6RoutesDump.get().ip6FibDetails.stream()
+ .filter(details -> protocolTableId == details.tableId)
+ .filter(details -> equalsWithConfigOrLearned(configuration.getLearnedRouteNamePrefix(), mappedName,
+ namesFactory.uniqueRouteName(details, readContext.getMappingContext())))
+ .findAny();
+
+ if (opDetail.isPresent()) {
+ final Ip6FibDetails detail = opDetail.get();
+
+ routeBuilder.setNextHopOptions(
+ resolveHopType(mappedName, Arrays.asList(detail.path), interfaceContext, routeHopContext,
+ readContext.getMappingContext(), namesFactory))
+ .setKey(key)
+ .setId(key.getId())
+ .setDestinationPrefix(toIpv6Prefix(detail.address, toJavaByte(detail.addressLength)))
+ .setVppIpv6RouteState(new VppIpv6RouteStateBuilder().build());
+ }
+ }
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingInstanceCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingInstanceCustomizer.java
new file mode 100644
index 000000000..78e869f9a
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingInstanceCustomizer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.routing.read;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.RoutingStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.StandardRoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.RoutingInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.RoutingInstanceKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Returns default instance of routing instance
+ */
+public class RoutingInstanceCustomizer
+ implements ListReaderCustomizer<RoutingInstance, RoutingInstanceKey, RoutingInstanceBuilder> {
+
+ private RoutingInstanceKey defaultKey;
+
+ public RoutingInstanceCustomizer(@Nonnull final RoutingConfiguration configuration) {
+ defaultKey = new RoutingInstanceKey(configuration.getDefaultRoutingInstanceName());
+ }
+
+ @Nonnull
+ @Override
+ public List<RoutingInstanceKey> getAllIds(@Nonnull final InstanceIdentifier<RoutingInstance> instanceIdentifier,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+ return ImmutableList.of(defaultKey);
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<RoutingInstance> list) {
+ RoutingStateBuilder.class.cast(builder).setRoutingInstance(list);
+ }
+
+ @Nonnull
+ @Override
+ public RoutingInstanceBuilder getBuilder(@Nonnull final InstanceIdentifier<RoutingInstance> instanceIdentifier) {
+ return new RoutingInstanceBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingInstance> instanceIdentifier,
+ @Nonnull final RoutingInstanceBuilder routingInstanceBuilder,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+ routingInstanceBuilder.setType(StandardRoutingInstance.class)
+ .setKey(defaultKey)
+ .setName(defaultKey.getName());
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingProtocolCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingProtocolCustomizer.java
new file mode 100644
index 000000000..c8a379b83
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingProtocolCustomizer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.routing.read;
+
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpFibDetailsReplyDump;
+import java.util.Collection;
+import java.util.Collections;
+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.ietf.params.xml.ns.yang.ietf.routing.rev140524.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.RoutingProtocolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolStateVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolStateVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.state.routing.instance.routing.protocols.routing.protocol.VppProtocolStateAttributesBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+
+public class RoutingProtocolCustomizer
+ implements ListReaderCustomizer<RoutingProtocol, RoutingProtocolKey, RoutingProtocolBuilder>, RouteMapper {
+
+ private final NamingContext routingProtocolContext;
+ private final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4RoutesDumpManager;
+ private final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6RoutesDumpManager;
+
+
+ public RoutingProtocolCustomizer(@Nonnull final NamingContext routingProtocolContext,
+ @Nonnull final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4RoutesDumpManager,
+ @Nonnull final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6RoutesDumpManager) {
+ this.routingProtocolContext = routingProtocolContext;
+ this.ipv4RoutesDumpManager = ipv4RoutesDumpManager;
+ this.ipv6RoutesDumpManager = ipv6RoutesDumpManager;
+ }
+
+ @Nonnull
+ @Override
+ public List<RoutingProtocolKey> getAllIds(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+
+ final ModificationCache modificationCache = readContext.getModificationCache();
+
+ // builds keys from routing protocol prefix and unique set of table ids
+ return Stream.of(
+ ipv4TableIds(instanceIdentifier, modificationCache),
+ ipv6TableIds(instanceIdentifier, modificationCache))
+ .flatMap(Collection::stream)
+ .map(tableId -> routingProtocolContext.getName(tableId, readContext.getMappingContext()))
+ .distinct()
+ .map(RoutingProtocolKey::new)
+ .collect(Collectors.toList());
+ }
+
+ private List<Integer> ipv4TableIds(final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ final ModificationCache modificationCache) throws ReadFailedException {
+ final Optional<IpFibDetailsReplyDump>
+ ipv4Routes = ipv4RoutesDumpManager.getDump(instanceIdentifier, modificationCache, NO_PARAMS);
+
+ if (ipv4Routes.isPresent()) {
+ return ipv4Routes.get().ipFibDetails.stream()
+ .map(ipFibDetails -> ipFibDetails.tableId)
+ .collect(Collectors.toList());
+ }
+ return Collections.emptyList();
+ }
+
+ private List<Integer> ipv6TableIds(final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ final ModificationCache modificationCache) throws ReadFailedException {
+ final Optional<Ip6FibDetailsReplyDump>
+ ipv6Routes = ipv6RoutesDumpManager.getDump(instanceIdentifier, modificationCache, NO_PARAMS);
+
+ if (ipv6Routes.isPresent()) {
+ return ipv6Routes.get().ip6FibDetails.stream()
+ .map(ipFibDetails -> ipFibDetails.tableId)
+ .collect(Collectors.toList());
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<RoutingProtocol> list) {
+ RoutingProtocolsBuilder.class.cast(builder).setRoutingProtocol(list);
+ }
+
+ @Nonnull
+ @Override
+ public RoutingProtocolBuilder getBuilder(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier) {
+ return new RoutingProtocolBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ @Nonnull final RoutingProtocolBuilder routingProtocolBuilder,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+
+ final RoutingProtocolKey key = instanceIdentifier.firstKeyOf(RoutingProtocol.class);
+ routingProtocolBuilder.setName(key.getName()).setKey(key).setType(Static.class)
+ .addAugmentation(RoutingProtocolStateVppAttr.class, new RoutingProtocolStateVppAttrBuilder()
+ .setVppProtocolStateAttributes(new VppProtocolStateAttributesBuilder()
+ .setPrimaryVrf(new VniReference(Long.valueOf(routingProtocolContext
+ .getIndex(key.getName(), readContext.getMappingContext()))))
+ .build())
+ .build());
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateCustomizer.java
new file mode 100644
index 000000000..5a6b23b7d
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateCustomizer.java
@@ -0,0 +1,149 @@
+/*
+ * 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.routing.read;
+
+import io.fd.hc2vpp.routing.write.Ipv4WriteRoutingNodes;
+import io.fd.hc2vpp.routing.write.Ipv6WriteRoutingNodes;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+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.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.RoutingState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.RoutingStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.StandardRoutingInstance;
+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.RoutingInstanceBuilder;
+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.RoutingProtocolsBuilder;
+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.RoutingProtocolBuilder;
+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.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolStateVppAttr;
+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.RoutingProtocolVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributesBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RoutingStateCustomizer
+ implements InitializingReaderCustomizer<RoutingState, RoutingStateBuilder>, Ipv4WriteRoutingNodes {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RoutingStateCustomizer.class);
+
+ private static RoutingInstance mapRoutingInstances(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.RoutingInstance state) {
+ return new RoutingInstanceBuilder()
+ .setName(state.getName())
+ .setEnabled(true)
+ .setRouterId(state.getRouterId())
+ .setType(StandardRoutingInstance.class)
+ .setRoutingProtocols(RoutingStateCustomizer.mapRoutingProtocols(state.getRoutingProtocols()))
+ .build();
+ }
+
+ private static RoutingProtocols mapRoutingProtocols(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.RoutingProtocols state) {
+
+ if (state != null) {
+ return new RoutingProtocolsBuilder()
+ .setRoutingProtocol(state.getRoutingProtocol() != null
+ ? RoutingStateCustomizer.mapRoutingProtocol(state.getRoutingProtocol())
+ : null)
+ .build();
+ } else {
+ return null;
+ }
+ }
+
+ private static List<RoutingProtocol> mapRoutingProtocol(
+ final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocol> state) {
+ return state.stream()
+ .map(routingProtocol -> new RoutingProtocolBuilder()
+ .setName(routingProtocol.getName())
+ .setEnabled(true)
+ .setType(routingProtocol.getType())
+ .setStaticRoutes(RoutingStateCustomizer.mapStaticRoutes(routingProtocol.getStaticRoutes()))
+ .addAugmentation(RoutingProtocolVppAttr.class,
+ mapVppAttr(routingProtocol.getAugmentation(RoutingProtocolStateVppAttr.class)))
+ .build())
+ .collect(Collectors.toList());
+ }
+
+ private static RoutingProtocolVppAttr mapVppAttr(final RoutingProtocolStateVppAttr attrState) {
+ return new RoutingProtocolVppAttrBuilder()
+ .setVppProtocolAttributes(attrState.getVppProtocolStateAttributes() == null
+ ? null
+ :
+ new VppProtocolAttributesBuilder()
+ .setPrimaryVrf(attrState.getVppProtocolStateAttributes().getPrimaryVrf())
+ .build())
+ .build();
+ }
+
+ private static StaticRoutes mapStaticRoutes(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol.StaticRoutes state) {
+ return new StaticRoutesBuilder()
+ .addAugmentation(CONFIG_IPV4_AUG_CLASS,
+ Ipv4WriteRoutingNodes.INSTANCE.mapIpv4Augmentation(state.getAugmentation(STATE_IPV4_AUG_CLASS)))
+ .addAugmentation(Ipv6WriteRoutingNodes.CONFIG_IPV6_AUG_CLASS,
+ Ipv6WriteRoutingNodes.INSTANCE.mapIpv6Augmentation(state.getAugmentation(
+ Ipv6WriteRoutingNodes.STATE_IPV6_AUG_CLASS)))
+ .build();
+ }
+
+ @Nonnull
+ @Override
+ public RoutingStateBuilder getBuilder(@Nonnull final InstanceIdentifier<RoutingState> instanceIdentifier) {
+ return new RoutingStateBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingState> instanceIdentifier,
+ @Nonnull final RoutingStateBuilder routingStateBuilder,
+ @Nonnull final ReadContext readContext) throws ReadFailedException {
+ // does nothing
+ LOG.info("Reading {}", instanceIdentifier);
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final RoutingState routingState) {
+ //Routing state is root
+ }
+
+ @Nonnull
+ @Override
+ public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<RoutingState> id,
+ @Nonnull final RoutingState readValue,
+ @Nonnull final ReadContext ctx) {
+
+ return Initialized.create(InstanceIdentifier.create(Routing.class), new RoutingBuilder()
+ .setRoutingInstance(readValue.getRoutingInstance()
+ .stream()
+ .map(routingInstance -> mapRoutingInstances(routingInstance))
+ .collect(Collectors.toList()))
+ .build());
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateReaderFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateReaderFactory.java
new file mode 100644
index 000000000..c26de124e
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/read/RoutingStateReaderFactory.java
@@ -0,0 +1,136 @@
+/*
+ * 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.routing.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.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.Ip6FibDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpFibDetailsReplyDump;
+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.routing.rev140524.RoutingState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.RoutingProtocols;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.RoutingProtocolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol.StaticRoutes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolStateVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.state.routing.instance.routing.protocols.routing.protocol.VppProtocolStateAttributes;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing readers for routing plugin's data.
+ */
+public final class RoutingStateReaderFactory implements ReaderFactory, Ipv4ReadRoutingNodes, Ipv6ReadRoutingNodes {
+
+ private static final InstanceIdentifier<RoutingState> ROOT_STATE_CONTAINER_ID =
+ InstanceIdentifier.create(RoutingState.class);
+
+ @Inject
+ private RoutingConfiguration configuration;
+
+ @Inject
+ @Named("interface-context")
+ private NamingContext interfaceContext;
+
+ @Inject
+ @Named(RoutingConfiguration.ROUTING_PROTOCOL_CONTEXT)
+ private NamingContext routingProtocolContext;
+
+ @Inject
+ @Named(RoutingConfiguration.ROUTE_CONTEXT)
+ private NamingContext routeContext;
+
+ @Inject
+ @Named(RoutingConfiguration.ROUTE_HOP_CONTEXT)
+ private MultiNamingContext routeHopContext;
+
+ @Inject
+ private FutureJVppCore vppApi;
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ final DumpCacheManager<IpFibDetailsReplyDump, Void> ipv4DumpManager = newIpv4RoutesDumpManager(vppApi);
+ final DumpCacheManager<Ip6FibDetailsReplyDump, Void> ipv6DumpManager = newIpv6RoutesDumpManager(vppApi);
+
+ final InstanceIdentifier<RoutingInstance> routingInstanceInstanceIdentifier =
+ routingInstanceIdentifier(ROOT_STATE_CONTAINER_ID);
+ final InstanceIdentifier<RoutingProtocols> routingProtocolsInstanceIdentifier =
+ routingProtocolsId(routingInstanceInstanceIdentifier);
+ final InstanceIdentifier<RoutingProtocol> routingProtocolInstanceIdentifier =
+ routingProtocolInstanceIdentifier(routingProtocolsInstanceIdentifier);
+ final InstanceIdentifier<StaticRoutes> staticRoutesInstanceIdentifier =
+ staticRoutesInstanceIdentifier(routingProtocolInstanceIdentifier);
+
+ // RoutingState
+ registry.add(new GenericReader<>(ROOT_STATE_CONTAINER_ID, new RoutingStateCustomizer()));
+ // RoutingInstance
+ registry.add(new GenericListReader<>(routingInstanceInstanceIdentifier,
+ new RoutingInstanceCustomizer(configuration)));
+
+ // RoutingProtocols
+ registry.addStructuralReader(routingProtocolsInstanceIdentifier, RoutingProtocolsBuilder.class);
+
+ // RoutingProtocol
+ registry.subtreeAdd(routingProtocolHandledChildren(), new GenericListReader<>(routingProtocolInstanceIdentifier,
+ new RoutingProtocolCustomizer(routingProtocolContext, ipv4DumpManager, ipv6DumpManager)));
+
+ // StaticRoutes
+ registry.addStructuralReader(staticRoutesInstanceIdentifier, StaticRoutesBuilder.class);
+
+ registerIpv4Routes(staticRoutesInstanceIdentifier, registry, ipv4DumpManager, configuration, routeHopContext,
+ interfaceContext, routeContext, routingProtocolContext);
+ registerIpv6Routes(staticRoutesInstanceIdentifier, registry, ipv6DumpManager, configuration, routeHopContext,
+ interfaceContext, routeContext, routingProtocolContext);
+ }
+
+ private static ImmutableSet<InstanceIdentifier<?>> routingProtocolHandledChildren() {
+ return ImmutableSet
+ .of(InstanceIdentifier.create(RoutingProtocol.class).augmentation(RoutingProtocolStateVppAttr.class)
+ .child(VppProtocolStateAttributes.class));
+ }
+
+ private InstanceIdentifier<StaticRoutes> staticRoutesInstanceIdentifier(
+ final InstanceIdentifier<RoutingProtocol> routingProtocolInstanceIdentifier) {
+ return routingProtocolInstanceIdentifier.child(StaticRoutes.class);
+ }
+
+ private InstanceIdentifier<RoutingProtocol> routingProtocolInstanceIdentifier(
+ final InstanceIdentifier<RoutingProtocols> routingProtocolsInstanceIdentifier) {
+ return routingProtocolsInstanceIdentifier.child(RoutingProtocol.class);
+ }
+
+ private InstanceIdentifier<RoutingProtocols> routingProtocolsId(
+ final InstanceIdentifier<RoutingInstance> routingInstanceInstanceIdentifier) {
+ return routingInstanceInstanceIdentifier.child(RoutingProtocols.class);
+ }
+
+ private InstanceIdentifier<RoutingInstance> routingInstanceIdentifier(
+ final InstanceIdentifier<RoutingState> routingStateId) {
+ return routingStateId.child(RoutingInstance.class);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv4RoutePathParser.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv4RoutePathParser.java
new file mode 100644
index 000000000..58dee232b
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv4RoutePathParser.java
@@ -0,0 +1,120 @@
+/*
+ * 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.routing.trait;
+
+import static io.fd.hc2vpp.routing.trait.RouteMapper.isDefaultInterfaceIndex;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.naming.Ipv4RouteNamesFactory;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.types.FibPath;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.NextHopOptions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SpecialNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SpecialNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.NextHopListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.next.hop.list.NextHopBuilder;
+
+public interface Ipv4RoutePathParser extends RouteMapper {
+
+ static NextHopOptions resolveOption(final String routeName,
+ final List<FibPath> parsedHops,
+ final NamingContext interfaceContext,
+ final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext,
+ final Ipv4RouteNamesFactory namesFactory) {
+ return parsedHops.size() == 1
+ ? RouteMapper.INSTANCE.isSpecialHop(parsedHops.get(0))
+ ? specialHop(parsedHops.get(0))
+ : simpleHop(parsedHops.get(0), interfaceContext, mappingContext)
+ : hopList(routeName, parsedHops, interfaceContext, routeHopContext, mappingContext, namesFactory);
+ }
+
+ static SpecialNextHop specialHop(final FibPath singlePath) {
+ return new SpecialNextHopBuilder()
+ .setSpecialNextHop(RouteMapper.INSTANCE.specialHopType(singlePath))
+ .build();
+ }
+
+ static SimpleNextHop simpleHop(final FibPath path, final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ return resolveInterfaceIfSpecified(new SimpleNextHopBuilder(), path.swIfIndex, interfaceContext, mappingContext)
+ .setNextHop(AddressTranslator.INSTANCE.arrayToIpv4AddressNoZone(path.nextHop))
+ .build();
+ }
+
+ static SimpleNextHopBuilder resolveInterfaceIfSpecified(final SimpleNextHopBuilder builder, final int index,
+ final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ if (!isDefaultInterfaceIndex(index)) {
+ builder.setOutgoingInterface(interfaceContext.getName(index, mappingContext));
+ }
+ return builder;
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.NextHopList hopList(
+ final String routeName,
+ final List<FibPath> parsedHops,
+ final NamingContext interfaceContext,
+ final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext,
+ final Ipv4RouteNamesFactory namesFactory) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.NextHopListBuilder()
+ .setNextHopList(
+ new NextHopListBuilder().setNextHop(parsedHops.stream()
+ .map(fibPath -> resolveInterfaceIfSpecified(new NextHopBuilder(), fibPath.swIfIndex,
+ interfaceContext, mappingContext)
+ .setId((long) (routeHopContext.getChildIndex(routeName,
+ namesFactory.uniqueRouteHopName(fibPath, mappingContext),
+ mappingContext)))
+ .setWeight(((short) fibPath.weight))
+ .setAddress(
+ AddressTranslator.INSTANCE
+ .arrayToIpv4AddressNoZone(fibPath.nextHop))
+ .build())
+ .collect(Collectors.toList()))
+ .build())
+ .build();
+ }
+
+ static NextHopBuilder resolveInterfaceIfSpecified(final NextHopBuilder builder, final int index,
+ final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ if (!isDefaultInterfaceIndex(index)) {
+ builder.setOutgoingInterface(interfaceContext.getName(index, mappingContext));
+ }
+ return builder;
+ }
+
+ default NextHopOptions resolveHopType(@Nonnull final String routeName,
+ final List<FibPath> parsedHops,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final MappingContext mappingContext,
+ @Nonnull final Ipv4RouteNamesFactory namesFactory) {
+
+ return parsedHops == null || parsedHops.isEmpty()
+ ? null
+ : resolveOption(routeName, parsedHops, interfaceContext, routeHopContext, mappingContext, namesFactory);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv6RoutePathParser.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv6RoutePathParser.java
new file mode 100644
index 000000000..908472931
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/Ipv6RoutePathParser.java
@@ -0,0 +1,136 @@
+/*
+ * 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.routing.trait;
+
+import static io.fd.hc2vpp.routing.trait.RouteMapper.isDefaultInterfaceIndex;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.naming.Ipv6RouteNamesFactory;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.types.FibPath;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.NextHopOptions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHopBuilder;
+
+public interface Ipv6RoutePathParser extends RouteMapper {
+
+ static NextHopOptions resolveOption(final String routeName,
+ final List<FibPath> parsedHops,
+ final NamingContext interfaceContext,
+ final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext,
+ final Ipv6RouteNamesFactory namesFactory) {
+ return parsedHops.size() == 1
+ ? INSTANCE.isSpecialHop(parsedHops.get(0))
+ ? specialHop(parsedHops.get(0))
+ : simpleHop(parsedHops.get(0), interfaceContext, mappingContext)
+ : hopList(routeName, parsedHops, interfaceContext, routeHopContext, mappingContext, namesFactory);
+ }
+
+ static SpecialNextHop specialHop(final FibPath fibPath) {
+ return new SpecialNextHopBuilder()
+ .setSpecialNextHop(INSTANCE.specialHopType(fibPath))
+ .build();
+ }
+
+ static SimpleNextHop simpleHop(final FibPath path, final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ return resolveInterfaceIfSpecified(new SimpleNextHopBuilder(), path.swIfIndex, interfaceContext, mappingContext)
+ .setNextHop(AddressTranslator.INSTANCE.arrayToIpv6AddressNoZone(path.nextHop))
+ .build();
+ }
+
+ static SimpleNextHopBuilder resolveInterfaceIfSpecified(SimpleNextHopBuilder builder, final int index,
+ final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ if (!isDefaultInterfaceIndex(index)) {
+ builder.setOutgoingInterface(interfaceContext.getName(index, mappingContext));
+ }
+
+ return builder;
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList hopList(
+ final String routeName,
+ final List<FibPath> parsedHops,
+ final NamingContext interfaceContext,
+ final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext,
+ final Ipv6RouteNamesFactory namesFactory) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopListBuilder()
+ .setNextHopList(
+ buildNextHopList(routeName, parsedHops, interfaceContext, routeHopContext, mappingContext,
+ namesFactory))
+ .build();
+ }
+
+ static NextHopList buildNextHopList(final String routeName, final List<FibPath> parsedHops,
+ final NamingContext interfaceContext,
+ final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext,
+ final Ipv6RouteNamesFactory namesFactory) {
+ return new NextHopListBuilder().setNextHop(parsedHops.stream()
+ .map(fibPath -> resolveInterfaceIfSpecified(new NextHopBuilder(), fibPath.swIfIndex, interfaceContext,
+ mappingContext)
+ .setId(findIdWithinRouteContext(routeName, routeHopContext, mappingContext, fibPath,
+ namesFactory))
+ .setWeight((short) fibPath.weight)
+ .setAddress(AddressTranslator.INSTANCE.arrayToIpv6AddressNoZone(fibPath.nextHop))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ static NextHopBuilder resolveInterfaceIfSpecified(NextHopBuilder builder, final int index,
+ final NamingContext interfaceContext,
+ final MappingContext mappingContext) {
+ if (!isDefaultInterfaceIndex(index)) {
+ builder.setOutgoingInterface(interfaceContext.getName(index, mappingContext));
+ }
+
+ return builder;
+ }
+
+ static long findIdWithinRouteContext(final String routeName, final MultiNamingContext routeHopContext,
+ final MappingContext mappingContext, final FibPath fibPath,
+ final Ipv6RouteNamesFactory namesFactory) {
+ return (long) (routeHopContext
+ .getChildIndex(routeName, namesFactory.uniqueRouteHopName(fibPath, mappingContext), mappingContext));
+ }
+
+ default NextHopOptions resolveHopType(@Nonnull final String routeName,
+ final List<FibPath> parsedHops,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final MultiNamingContext routeHopContext,
+ @Nonnull final MappingContext mappingContext,
+ @Nonnull final Ipv6RouteNamesFactory namesFactory) {
+
+ return parsedHops == null || parsedHops.isEmpty()
+ ? null
+ : resolveOption(routeName, parsedHops, interfaceContext, routeHopContext, mappingContext, namesFactory);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/RouteMapper.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/RouteMapper.java
new file mode 100644
index 000000000..deabdacee
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/trait/RouteMapper.java
@@ -0,0 +1,92 @@
+/*
+ * 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.routing.trait;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.vpp.jvpp.core.types.FibPath;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.SpecialNextHopGrouping;
+
+public interface RouteMapper extends AddressTranslator, ByteDataTranslator {
+
+ int DEFAULT_INTERFACE_INDEX = -1;
+ RouteMapper INSTANCE = new RouteMapper() {
+ };
+
+ static boolean isDefaultInterfaceIndex(final int index) {
+ return DEFAULT_INTERFACE_INDEX == index;
+ }
+
+ static boolean flagEnabled(final byte flag) {
+ return ByteDataTranslator.INSTANCE.byteToBoolean(flag);
+ }
+
+ /**
+ * Verifies whether provided table id is for provided protocol name
+ */
+ default boolean isWithinProtocol(@Nonnull final String protocolName,
+ @Nonnull final String routingProtocolNamePrefix,
+ @Nonnull final Integer tableId) {
+ return protocolName.equals(fullRoutingProtocolName(routingProtocolNamePrefix, tableId));
+ }
+
+ /**
+ * Return full protocol name in form routing_protocol_name_prefix + table
+ */
+ default String fullRoutingProtocolName(@Nonnull final String routingProtocolNamePrefix,
+ @Nonnull final Integer tableId) {
+ return nameWithPrefix(routingProtocolNamePrefix, String.valueOf(tableId));
+ }
+
+ default String bindName(@Nonnull final String first, @Nonnull final String second, @Nonnull final String third) {
+ return String.format("%s_%s_%s", first, second, third);
+ }
+
+ default String nameWithPrefix(@Nonnull final String prefix, @Nonnull final String name) {
+ return String.format("%s_%s", prefix, name);
+ }
+
+ default boolean equalsWithConfigOrLearned(@Nonnull final String learnedPrefix, @Nonnull final String searched,
+ @Nonnull final String name) {
+ return searched.equals(name) || searched.equals(nameWithPrefix(learnedPrefix, name));
+ }
+
+ /**
+ * Resolve if provided {@link FibPath} should be considered as special hop.
+ * Special hop is hop that has any of special flags turned on(drop,local,prohibit,unreachable)
+ */
+ default boolean isSpecialHop(@Nonnull final FibPath path) {
+ return byteToBoolean(path.isDrop) || byteToBoolean(path.isLocal) || byteToBoolean(path.isProhibit) ||
+ byteToBoolean(path.isUnreach);
+ }
+
+ default SpecialNextHopGrouping.SpecialNextHop specialHopType(final FibPath singlePath) {
+ if (flagEnabled(singlePath.isDrop)) {
+ return SpecialNextHopGrouping.SpecialNextHop.Blackhole;
+ } else if (flagEnabled(singlePath.isLocal)) {
+ return SpecialNextHopGrouping.SpecialNextHop.Receive;
+ } else if (flagEnabled(singlePath.isProhibit)) {
+ return SpecialNextHopGrouping.SpecialNextHop.Prohibit;
+ } else if (flagEnabled(singlePath.isUnreach)) {
+ return SpecialNextHopGrouping.SpecialNextHop.Unreachable;
+ } else {
+ throw new IllegalArgumentException(
+ String.format("An attempt to resolve illegal path %s detected ", singlePath.toString()));
+ }
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4RouteCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4RouteCustomizer.java
new file mode 100644
index 000000000..6252b8d3a
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4RouteCustomizer.java
@@ -0,0 +1,213 @@
+/*
+ * 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.routing.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.naming.Ipv4RouteNamesFactory;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.hc2vpp.routing.write.factory.MultipathHopRequestFactory;
+import io.fd.hc2vpp.routing.write.factory.SimpleHopRequestFactory;
+import io.fd.hc2vpp.routing.write.factory.SpecialNextHopRequestFactory;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+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.IpAddDelRoute;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import java.util.stream.Collectors;
+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;
+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.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteKey;
+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.next.hop.options.NextHopList;
+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.next.hop.options.SimpleNextHop;
+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.next.hop.options.SpecialNextHop;
+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.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for handling write operations for {@link Ipv4} according to ietf-ipv4-unicast-routing.yang
+ */
+public class Ipv4RouteCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<Route, RouteKey>, JvppReplyConsumer, RouteMapper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Ipv4RouteCustomizer.class);
+
+
+ private final NamingContext routesContext;
+ private final MultiNamingContext routesHopsContext;
+ /**
+ * Request factories
+ */
+ private final SimpleHopRequestFactory simpleHopRequestFactory;
+ private final MultipathHopRequestFactory multipathHopRequestFactory;
+ private final SpecialNextHopRequestFactory specialNextHopRequestFactory;
+
+ /**
+ * Names factory
+ */
+ private final Ipv4RouteNamesFactory routeNamesFactory;
+
+ public Ipv4RouteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routesContext,
+ @Nonnull final NamingContext routingProtocolContext,
+ @Nonnull final MultiNamingContext routesHopsContext,
+ @Nonnull final VppClassifierContextManager classifierContextManager) {
+ super(futureJVppCore);
+
+ this.routesContext = routesContext;
+ this.routesHopsContext = routesHopsContext;
+ simpleHopRequestFactory =
+ SimpleHopRequestFactory.forContexts(classifierContextManager, interfaceContext, routingProtocolContext);
+ multipathHopRequestFactory = MultipathHopRequestFactory
+ .forContexts(classifierContextManager, interfaceContext, routingProtocolContext);
+ specialNextHopRequestFactory = SpecialNextHopRequestFactory.forClassifierContext(classifierContextManager);
+ routeNamesFactory = new Ipv4RouteNamesFactory(interfaceContext, routingProtocolContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String parentProtocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final String routeName = routeNamesFactory.uniqueRouteName(parentProtocolName, route);
+ writeRoute(instanceIdentifier, parentProtocolName, routeName, route, writeContext, true);
+
+ // maps new route by next available index,
+ routesContext.addName(routeName, writeContext.getMappingContext());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route routeBefore,
+ @Nonnull final Route routeAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ throw new WriteFailedException.UpdateFailedException(instanceIdentifier, routeBefore, routeAfter,
+ new UnsupportedOperationException("Operation not supported"));
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String parentProtocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final String routeName = routeNamesFactory.uniqueRouteName(parentProtocolName, route);
+ writeRoute(instanceIdentifier, parentProtocolName, routeName, route, writeContext, false);
+ routesContext.removeName(routeName, writeContext.getMappingContext());
+ }
+
+ private void writeRoute(@Nonnull final InstanceIdentifier<Route> identifier,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final String routeName,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext,
+ final boolean isAdd) throws WriteFailedException {
+ if (route.getNextHopOptions() instanceof SimpleNextHop) {
+ writeRoute(
+ simpleHopRequestFactory.createIpv4SimpleHopRequest(isAdd, parentProtocolName, route,
+ writeContext.getMappingContext()),
+ identifier);
+ } else if (route.getNextHopOptions() instanceof NextHopList) {
+ final List<NextHop> createdHops =
+ writeMultihopRoute(identifier, parentProtocolName, route, writeContext, isAdd);
+
+ // after all hops has been added, add mappings to preserve hop ids, or remove them
+ if (isAdd) {
+ addMappingForEachHop(routeName, writeContext, createdHops);
+ } else {
+ removeMappingForEachHop(routeName, writeContext, createdHops);
+ }
+ } else if (route.getNextHopOptions() instanceof SpecialNextHop) {
+ writeSpecialHopRoute(identifier, route, writeContext, isAdd);
+ } else {
+ throw new IllegalArgumentException("Unsupported next-hop type");
+ }
+ }
+
+ private void removeMappingForEachHop(final @Nonnull String routeName, final @Nonnull WriteContext writeContext,
+ final List<NextHop> createdHops) {
+ createdHops.forEach(nextHop -> routesHopsContext.removeChild(routeName,
+ routeNamesFactory.uniqueRouteHopName(nextHop),
+ writeContext.getMappingContext()));
+ }
+
+ private void addMappingForEachHop(final @Nonnull String routeName, final @Nonnull WriteContext writeContext,
+ final List<NextHop> createdHops) {
+ createdHops.forEach(nextHop -> routesHopsContext.addChild(routeName,
+ nextHop.getId().intValue(),
+ routeNamesFactory.uniqueRouteHopName(nextHop),
+ writeContext.getMappingContext()));
+ }
+
+ private List<NextHop> writeMultihopRoute(@Nonnull final InstanceIdentifier<Route> identifier,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext,
+ final boolean isAdd)
+ throws WriteFailedException {
+ // list of next hops
+ final NextHopList hopList = NextHopList.class.cast(route.getNextHopOptions());
+ final MappingContext mappingContext = writeContext.getMappingContext();
+ LOG.debug("Writing hop list {} for route {}", hopList, identifier);
+
+ // order hops to preserve order by ids(even that model is not ordered)
+ final List<NextHop> orderedHops = hopList.getNextHopList().getNextHop()
+ .stream()
+ .sorted((left, right) -> (int) (left.getId() - right.getId()))
+ .collect(Collectors.toList());
+
+ for (NextHop hop : orderedHops) {
+ LOG.debug("Writing hop {} for route {}", hop, identifier);
+
+ final IpAddDelRoute request = multipathHopRequestFactory
+ .createIpv4MultipathHopRequest(isAdd, parentProtocolName, route, hop, mappingContext);
+
+ writeRoute(request, identifier);
+ }
+
+ return orderedHops;
+ }
+
+
+ private void writeSpecialHopRoute(final @Nonnull InstanceIdentifier<Route> identifier, final @Nonnull Route route,
+ final @Nonnull WriteContext writeContext, final boolean isAdd)
+ throws WriteFailedException {
+ final SpecialNextHop hop = SpecialNextHop.class.cast(route.getNextHopOptions());
+ final MappingContext mappingContext = writeContext.getMappingContext();
+
+ final IpAddDelRoute request = specialNextHopRequestFactory
+ .createIpv4SpecialHopRequest(isAdd, route, mappingContext, hop.getSpecialNextHop());
+
+ writeRoute(request, identifier);
+ }
+
+
+ private void writeRoute(final IpAddDelRoute request, final InstanceIdentifier<Route> identifier)
+ throws WriteFailedException {
+ LOG.debug("Writing request {} for path {}", request, identifier);
+ getReplyForWrite(getFutureJVpp().ipAddDelRoute(request).toCompletableFuture(), identifier);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4WriteRoutingNodes.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4WriteRoutingNodes.java
new file mode 100644
index 000000000..a7a7e94b6
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv4WriteRoutingNodes.java
@@ -0,0 +1,169 @@
+/*
+ * 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.routing.write;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes2;
+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;
+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.Ipv4Builder;
+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.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+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.RouteKey;
+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.NextHopOptions;
+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.VppIpv4Route;
+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.VppIpv4RouteBuilder;
+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.next.hop.options.NextHopList;
+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.next.hop.options.NextHopListBuilder;
+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.next.hop.options.SimpleNextHop;
+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.next.hop.options.SimpleNextHopBuilder;
+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.next.hop.options.SpecialNextHop;
+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.next.hop.options.SpecialNextHopBuilder;
+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.next.hop.options.next.hop.list.next.hop.list.NextHop;
+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.next.hop.options.next.hop.list.next.hop.list.NextHopBuilder;
+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.next.hop.options.next.hop.list.next.hop.list.NextHopKey;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+public interface Ipv4WriteRoutingNodes {
+
+ Ipv4WriteRoutingNodes INSTANCE = new Ipv4WriteRoutingNodes() {
+ };
+
+ Class<StaticRoutes1> CONFIG_IPV4_AUG_CLASS = StaticRoutes1.class;
+ Class<StaticRoutes2> STATE_IPV4_AUG_CLASS = StaticRoutes2.class;
+
+ static Ipv4 mapIpv4(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4 state) {
+ return new Ipv4Builder()
+ .setRoute(state.getRoute()
+ .stream()
+ .map(route -> new RouteBuilder()
+ .setKey(new RouteKey(route.getKey().getId()))
+ .setDestinationPrefix(route.getDestinationPrefix())
+ .setDescription(route.getDescription())
+ .setId(route.getId())
+ .setVppIpv4Route(mapVppIpv4Route(route.getVppIpv4RouteState()))
+ .setNextHopOptions(mapNextHopOptions(route.getNextHopOptions()))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ static VppIpv4Route mapVppIpv4Route(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.VppIpv4RouteState state) {
+
+ return state == null
+ ? null
+ : new VppIpv4RouteBuilder()
+ // false is default
+ .setSecondaryVrf(state.getSecondaryVrf())
+ .setClassifyTable(state.getClassifyTable())
+ .build();
+ }
+
+ static NextHopOptions mapNextHopOptions(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.NextHopOptions state) {
+ if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHop) {
+ return mapSimpleNextHop(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHop.class
+ .cast(state));
+ } else if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.NextHopList) {
+ return mapNextHopList(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.NextHopList.class
+ .cast(state));
+ } else if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SpecialNextHop) {
+ return mapSpecialNextHop(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SpecialNextHop.class
+ .cast(state));
+ } else {
+ throw new UnsupportedOperationException("Unsupported next hop type");
+ }
+ }
+
+ static SimpleNextHop mapSimpleNextHop(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHop hop) {
+ return new SimpleNextHopBuilder()
+ .setNextHop(hop.getNextHop())
+ .setOutgoingInterface(hop.getOutgoingInterface())
+ .build();
+ }
+
+ static NextHopList mapNextHopList(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.NextHopList state) {
+ return new NextHopListBuilder()
+ .setNextHopList(mapNextHopListList(state.getNextHopList()))
+ .build();
+ }
+
+ static 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.next.hop.options.next.hop.list.NextHopList mapNextHopListList(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.next.hop.list.NextHopList state) {
+ return new 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.next.hop.options.next.hop.list.NextHopListBuilder()
+ .setNextHop(state.getNextHop()
+ .stream()
+ .map(nextHop -> new NextHopBuilder()
+ .setId(nextHop.getId())
+ .setOutgoingInterface(nextHop.getOutgoingInterface())
+ .setWeight(nextHop.getWeight())
+ .setPriority(nextHop.getPriority())
+ .setAddress(nextHop.getAddress())
+ .setKey(new NextHopKey(nextHop.getKey().getId()))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ static SpecialNextHop mapSpecialNextHop(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SpecialNextHop hop) {
+ return new SpecialNextHopBuilder()
+ .setSpecialNextHop(hop.getSpecialNextHop())
+ .build();
+ }
+
+ default InstanceIdentifier<Route> ipv4RouteIdentifier(
+ final InstanceIdentifier<StaticRoutes> staticRoutesIdentifier) {
+ return staticRoutesIdentifier
+ .augmentation(StaticRoutes1.class)
+ .child(Ipv4.class)
+ .child(Route.class);
+ }
+
+ default Set<InstanceIdentifier<?>> ipv4RoutingHandledChildren(final InstanceIdentifier<Route> parent) {
+ return ImmutableSet.of(parent
+ .child(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.next.hop.options.next.hop.list.NextHopList.class),
+ parent.child(
+ 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.next.hop.options.next.hop.list.NextHopList.class)
+ .child(NextHop.class),
+ parent.child(VppIpv4Route.class));
+ }
+
+ default InstanceIdentifier<Route> ipv4RouteSubtree() {
+ return InstanceIdentifier.create(Route.class);
+ }
+
+ default StaticRoutes1 mapIpv4Augmentation(final StaticRoutes2 state) {
+ if (state == null) {
+ return null;
+ }
+ return new StaticRoutes1Builder()
+ .setIpv4(mapIpv4(state.getIpv4()))
+ .build();
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java
new file mode 100644
index 000000000..aa7138624
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java
@@ -0,0 +1,211 @@
+/*
+ * 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.routing.write;
+
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.naming.Ipv6RouteNamesFactory;
+import io.fd.hc2vpp.routing.trait.RouteMapper;
+import io.fd.hc2vpp.routing.write.factory.MultipathHopRequestFactory;
+import io.fd.hc2vpp.routing.write.factory.SimpleHopRequestFactory;
+import io.fd.hc2vpp.routing.write.factory.SpecialNextHopRequestFactory;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+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.IpAddDelRoute;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.RouteKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for handling write operations for {@link Ipv6} according to ietf-ipv6-unicast-routing.yang
+ */
+public class Ipv6RouteCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<Route, RouteKey>, JvppReplyConsumer, RouteMapper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Ipv6RouteCustomizer.class);
+
+ private final NamingContext routesContext;
+ private final MultiNamingContext routesHopsContext;
+ /**
+ * Request factories
+ */
+ private final SimpleHopRequestFactory simpleHopRequestFactory;
+ private final MultipathHopRequestFactory multipathHopRequestFactory;
+ private final SpecialNextHopRequestFactory specialNextHopRequestFactory;
+
+ /**
+ * Naming factory
+ */
+ private final Ipv6RouteNamesFactory namesFactory;
+
+ public Ipv6RouteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routesContext,
+ @Nonnull final NamingContext routingProtocolContext,
+ @Nonnull final MultiNamingContext routesHopsContext,
+ @Nonnull final VppClassifierContextManager classifierContextManager) {
+ super(futureJVppCore);
+
+ this.routesContext = routesContext;
+ this.routesHopsContext = routesHopsContext;
+ simpleHopRequestFactory =
+ SimpleHopRequestFactory.forContexts(classifierContextManager, interfaceContext, routingProtocolContext);
+ multipathHopRequestFactory = MultipathHopRequestFactory
+ .forContexts(classifierContextManager, interfaceContext, routingProtocolContext);
+ specialNextHopRequestFactory = SpecialNextHopRequestFactory.forClassifierContext(classifierContextManager);
+ namesFactory = new Ipv6RouteNamesFactory(interfaceContext, routingProtocolContext);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String parentProtocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final String routeName = namesFactory.uniqueRouteName(parentProtocolName, route);
+ writeRoute(instanceIdentifier, parentProtocolName, routeName, route, writeContext, true);
+
+ // maps new route by next available index,
+ routesContext.addName(routeName, writeContext.getMappingContext());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route route,
+ @Nonnull final Route d1, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ throw new WriteFailedException(instanceIdentifier,
+ new UnsupportedOperationException("Operation not supported"));
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Route> instanceIdentifier,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final String parentProtocolName = instanceIdentifier.firstKeyOf(RoutingProtocol.class).getName();
+ final String routeName = namesFactory.uniqueRouteName(parentProtocolName, route);
+ writeRoute(instanceIdentifier, parentProtocolName, routeName, route, writeContext, false);
+ routesContext.removeName(routeName, writeContext.getMappingContext());
+ }
+
+ private void writeRoute(@Nonnull final InstanceIdentifier<Route> identifier,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final String routeName,
+ @Nonnull final Route route,
+ @Nonnull final WriteContext writeContext,
+ final boolean isAdd) throws WriteFailedException {
+ if (route.getNextHopOptions() instanceof SimpleNextHop) {
+ writeRoute(
+ simpleHopRequestFactory.createIpv6SimpleHopRequest(isAdd, parentProtocolName, route,
+ writeContext.getMappingContext()),
+ identifier);
+ } else if (route.getNextHopOptions() instanceof NextHopList) {
+ final List<NextHop> createdHops =
+ writeMultihopRoute(identifier, parentProtocolName, route, writeContext, isAdd);
+
+ // after all hops has been added, add mappings to preserve hop ids, or remove them
+ if (isAdd) {
+ addMappingForEachHop(routeName, writeContext, createdHops);
+ } else {
+ removeMappingForEachHop(routeName, writeContext, createdHops);
+ }
+ } else if (route.getNextHopOptions() instanceof SpecialNextHop) {
+ writeSpecialHopRoute(identifier, route, writeContext, isAdd);
+ } else {
+ throw new IllegalArgumentException("Unsupported next-hop type");
+ }
+ }
+
+ private List<NextHop> writeMultihopRoute(final InstanceIdentifier<Route> identifier,
+ final String parentProtocolName,
+ final Route route,
+ final WriteContext writeContext, final boolean isAdd)
+ throws WriteFailedException {
+ // list of next hops
+ final NextHopList hopList = NextHopList.class.cast(route.getNextHopOptions());
+ final MappingContext mappingContext = writeContext.getMappingContext();
+ LOG.debug("Writing hop list {} for route {}", hopList, identifier);
+
+ // order hops to preserve order by ids(even that model is not ordered)
+ final List<NextHop> orderedHops = hopList.getNextHopList().getNextHop()
+ .stream()
+ .sorted((left, right) -> (int) (left.getId() - right.getId()))
+ .collect(Collectors.toList());
+
+ for (NextHop hop : orderedHops) {
+ LOG.debug("Writing hop {} for route {}", hop, identifier);
+
+ final IpAddDelRoute request = multipathHopRequestFactory
+ .createIpv6MultipathHopRequest(isAdd, parentProtocolName, route, hop, mappingContext);
+
+ writeRoute(request, identifier);
+ }
+
+ return orderedHops;
+ }
+
+
+ private void writeSpecialHopRoute(final @Nonnull InstanceIdentifier<Route> identifier, final @Nonnull Route route,
+ final @Nonnull WriteContext writeContext, final boolean isAdd)
+ throws WriteFailedException {
+ final SpecialNextHop hop = SpecialNextHop.class.cast(route.getNextHopOptions());
+ final MappingContext mappingContext = writeContext.getMappingContext();
+
+ final IpAddDelRoute request = specialNextHopRequestFactory
+ .createIpv6SpecialHopRequest(isAdd, route, mappingContext, hop.getSpecialNextHop());
+
+ writeRoute(request, identifier);
+ }
+
+ private void writeRoute(final IpAddDelRoute request, final InstanceIdentifier<Route> identifier)
+ throws WriteFailedException {
+ LOG.debug("Writing request {} for path {}", request, identifier);
+ getReplyForWrite(getFutureJVpp().ipAddDelRoute(request).toCompletableFuture(), identifier);
+ }
+
+ private void removeMappingForEachHop(final @Nonnull String routeName, final @Nonnull WriteContext writeContext,
+ final List<NextHop> createdHops) {
+ createdHops.forEach(nextHop -> routesHopsContext.removeChild(routeName,
+ namesFactory.uniqueRouteHopName(nextHop),
+ writeContext.getMappingContext()));
+ }
+
+ private void addMappingForEachHop(final @Nonnull String routeName, final @Nonnull WriteContext writeContext,
+ final List<NextHop> createdHops) {
+ createdHops.forEach(nextHop -> routesHopsContext.addChild(routeName,
+ nextHop.getId().intValue(),
+ namesFactory.uniqueRouteHopName(nextHop),
+ writeContext.getMappingContext()));
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6WriteRoutingNodes.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6WriteRoutingNodes.java
new file mode 100644
index 000000000..2c9bbada2
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6WriteRoutingNodes.java
@@ -0,0 +1,168 @@
+/*
+ * 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.routing.write;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.StaticRoutes2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.RouteKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.NextHopOptions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHopKey;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+
+public interface Ipv6WriteRoutingNodes {
+
+ Ipv6WriteRoutingNodes INSTANCE = new Ipv6WriteRoutingNodes() {
+ };
+
+ Class<StaticRoutes1> CONFIG_IPV6_AUG_CLASS = StaticRoutes1.class;
+ Class<StaticRoutes2> STATE_IPV6_AUG_CLASS = StaticRoutes2.class;
+
+ static Ipv6 mapIpv6(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv6 state) {
+ return new Ipv6Builder()
+ .setRoute(state.getRoute()
+ .stream()
+ .map(route -> new RouteBuilder()
+ .setKey(new RouteKey(route.getKey().getId()))
+ .setDestinationPrefix(route.getDestinationPrefix())
+ .setDescription(route.getDescription())
+ .setId(route.getId())
+ .setVppIpv6Route(mapVppIpv6Route(route.getVppIpv6RouteState()))
+ .setNextHopOptions(mapNextHopOptions(route.getNextHopOptions()))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ static VppIpv6Route mapVppIpv6Route(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6RouteState state) {
+ return state == null
+ ? null
+ : new VppIpv6RouteBuilder()
+ .setSecondaryVrf(state.getSecondaryVrf())
+ .setClassifyTable(state.getClassifyTable())
+ .build();
+ }
+
+ static NextHopOptions mapNextHopOptions(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.NextHopOptions state) {
+ if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop) {
+ return mapSimpleNextHop(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop.class
+ .cast(state));
+ } else if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList) {
+ return mapNextHopList(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList.class
+ .cast(state));
+ } else if (state instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop) {
+ return mapSpecialNextHop(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop.class
+ .cast(state));
+ } else {
+ throw new UnsupportedOperationException("Unsupported next hop type");
+ }
+ }
+
+ static SimpleNextHop mapSimpleNextHop(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop hop) {
+ return new SimpleNextHopBuilder()
+ .setNextHop(hop.getNextHop())
+ .setOutgoingInterface(hop.getOutgoingInterface())
+ .build();
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList mapNextHopList(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.NextHopList state) {
+ return new NextHopListBuilder()
+ .setNextHopList(mapNextHopListList(state.getNextHopList()))
+ .build();
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopList mapNextHopListList(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopList state) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.NextHopListBuilder()
+ .setNextHop(state.getNextHop()
+ .stream()
+ .map(nextHop -> new NextHopBuilder()
+ .setId(nextHop.getId())
+ .setOutgoingInterface(nextHop.getOutgoingInterface())
+ .setWeight(nextHop.getWeight())
+ .setPriority(nextHop.getPriority())
+ .setAddress(nextHop.getAddress())
+ .setKey(new NextHopKey(nextHop.getKey().getId()))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ static SpecialNextHop mapSpecialNextHop(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.state.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SpecialNextHop hop) {
+ return new SpecialNextHopBuilder()
+ .setSpecialNextHop(hop.getSpecialNextHop())
+ .build();
+ }
+
+ default InstanceIdentifier<Route> ipv6RouteIdentifier(
+ final InstanceIdentifier<StaticRoutes> staticRoutesIdentifier) {
+ return staticRoutesIdentifier
+ .augmentation(StaticRoutes1.class)
+ .child(Ipv6.class)
+ .child(Route.class);
+ }
+
+ default InstanceIdentifier<Route> ipv6RouteSubtree() {
+ return InstanceIdentifier
+ .create(Route.class);
+ }
+
+ default Set<InstanceIdentifier<?>> ipv6RoutingHandledChildren(
+ final InstanceIdentifier<Route> parent) {
+ return ImmutableSet.of(parent.child(NextHopList.class),
+ parent.child(NextHopList.class).child(NextHop.class),
+ parent.child(VppIpv6Route.class));
+ }
+
+ default org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.StaticRoutes1 mapIpv6Augmentation(
+ final StaticRoutes2 state) {
+ if (state == null) {
+ return null;
+ }
+ return new StaticRoutes1Builder()
+ .setIpv6(mapIpv6(state.getIpv6()))
+ .build();
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingCustomizer.java
new file mode 100644
index 000000000..bd50ce77b
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingCustomizer.java
@@ -0,0 +1,55 @@
+/*
+ * 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.routing.write;
+
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+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.routing.rev140524.Routing;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Dummy customizer for Root node,to "handle" non-operational changes
+ */
+public class RoutingCustomizer implements WriterCustomizer<Routing> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class);
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Writing {}", instanceIdentifier);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing before, @Nonnull final Routing after,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Updating {} to {}", instanceIdentifier, after);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
+ @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Removing {}", instanceIdentifier);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInstanceCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInstanceCustomizer.java
new file mode 100644
index 000000000..fa6885d5d
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingInstanceCustomizer.java
@@ -0,0 +1,75 @@
+/*
+ * 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.routing.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+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.routing.rev140524.routing.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstanceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Only ensures that requests are written under singleton instance
+ */
+public class RoutingInstanceCustomizer implements ListWriterCustomizer<RoutingInstance, RoutingInstanceKey> {
+
+ private final RoutingConfiguration configuration;
+
+ public RoutingInstanceCustomizer(@Nonnull final RoutingConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingInstance> id,
+ @Nonnull final RoutingInstance dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ checkSingletonInstance(dataAfter);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingInstance> id,
+ @Nonnull final RoutingInstance dataBefore,
+ @Nonnull final RoutingInstance dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
+ new UnsupportedOperationException("Operation not supported"));
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingInstance> id,
+ @Nonnull final RoutingInstance dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ checkSingletonInstance(dataBefore);
+ }
+
+ private void checkSingletonInstance(final RoutingInstance data) {
+ final String defaultRoutingInstanceName = configuration.getDefaultRoutingInstanceName();
+ final String instanceName = data.getName();
+
+ checkArgument(defaultRoutingInstanceName.equals(instanceName),
+ "Attempt to write/delete data for different than default routing instance detected." +
+ "Vpp allows only single instance, configured with name %s, request contains name %s",
+ defaultRoutingInstanceName, instanceName);
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingProtocolCustomizer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingProtocolCustomizer.java
new file mode 100644
index 000000000..220f07690
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingProtocolCustomizer.java
@@ -0,0 +1,103 @@
+/*
+ * 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.routing.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+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.routing.rev140524.Static;
+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.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Customizer for handling of write operations for {@link RoutingProtocol}
+ */
+public class RoutingProtocolCustomizer
+ implements ListWriterCustomizer<RoutingProtocol, RoutingProtocolKey> {
+
+ private final NamingContext routingProtocolContext;
+
+ public RoutingProtocolCustomizer(@Nonnull final NamingContext routingProtocolContext) {
+ this.routingProtocolContext = routingProtocolContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ @Nonnull final RoutingProtocol routingProtocol,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ checkIsStatic(routingProtocol);
+
+ final int tableId = extractTableId(routingProtocol);
+ final MappingContext mappingContext = writeContext.getMappingContext();
+ final String newProtocolName = routingProtocol.getName();
+
+ // enclosed in synchronized block to prevent change of state after containsName/before addName
+ synchronized (routingProtocolContext) {
+ if (!routingProtocolContext.containsName(tableId, mappingContext)) {
+ // if not present in mapping,create assignment to table id. This works only with auto-create flag enabled
+ // while using ip_add_del_table
+ routingProtocolContext.addName(tableId, newProtocolName, mappingContext);
+ } else {
+ throw new IllegalStateException(String.format(
+ "An attempt to assign protocol %s to table id %s. Table id already assigned to protocol %s",
+ newProtocolName, tableId, routingProtocolContext.getName(tableId, mappingContext)));
+ }
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ @Nonnull final RoutingProtocol routingProtocolBefore,
+ @Nonnull final RoutingProtocol routingProtocolAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ throw new WriteFailedException.UpdateFailedException(instanceIdentifier, routingProtocolBefore,
+ routingProtocolAfter, new UnsupportedOperationException("Operation not supported"));
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<RoutingProtocol> instanceIdentifier,
+ @Nonnull final RoutingProtocol routingProtocol,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ routingProtocolContext.removeName(routingProtocol.getName(), writeContext.getMappingContext());
+ }
+
+ /**
+ * Checks whether routing protocol is static(we support only static ones for now)
+ */
+ private void checkIsStatic(final RoutingProtocol routingProtocol) {
+ checkArgument(routingProtocol.getType() == Static.class, "Only static routes are allowed");
+ }
+
+ private int extractTableId(final RoutingProtocol protocol) {
+ final RoutingProtocolVppAttr vppAttr = protocol.getAugmentation(RoutingProtocolVppAttr.class);
+
+ checkState(vppAttr != null && vppAttr.getVppProtocolAttributes() != null,
+ "Vpp routing protocol attributes not defined");
+
+ return vppAttr.getVppProtocolAttributes().getPrimaryVrf().getValue().intValue();
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingWriterFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingWriterFactory.java
new file mode 100644
index 000000000..02fa7d1b2
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/RoutingWriterFactory.java
@@ -0,0 +1,122 @@
+/*
+ * 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.routing.write;
+
+import static io.fd.hc2vpp.routing.RoutingConfiguration.ROUTE_CONTEXT;
+import static io.fd.hc2vpp.routing.RoutingConfiguration.ROUTE_HOP_CONTEXT;
+import static io.fd.hc2vpp.routing.RoutingConfiguration.ROUTING_PROTOCOL_CONTEXT;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.RoutingConfiguration;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+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.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.RoutingProtocols;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing writers for routing plugin's data.
+ */
+public final class RoutingWriterFactory implements WriterFactory, Ipv4WriteRoutingNodes, Ipv6WriteRoutingNodes {
+
+ private static final InstanceIdentifier<Routing> ROOT_CONTAINER_ID = InstanceIdentifier.create(Routing.class);
+
+ @Inject
+ private FutureJVppCore vppApi;
+
+ @Inject
+ private RoutingConfiguration configuration;
+
+ @Inject
+ @Named("interface-context")
+ private NamingContext interfaceContext;
+
+ @Inject
+ @Named(ROUTING_PROTOCOL_CONTEXT)
+ private NamingContext routingProtocolContext;
+
+ @Inject
+ @Named(ROUTE_CONTEXT)
+ private NamingContext routeContext;
+
+ @Inject
+ @Named("classify-table-context")
+ private VppClassifierContextManager vppClassifierContextManager;
+
+ @Inject
+ @Named(ROUTE_HOP_CONTEXT)
+ private MultiNamingContext routHopContext;
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+
+ registry.subtreeAdd(rootNodeHandledChildren(ROOT_CONTAINER_ID),
+ new GenericWriter<>(ROOT_CONTAINER_ID, new RoutingCustomizer()));
+
+ registry.add(new GenericWriter<>(routingInstanceIdentifier(), new RoutingInstanceCustomizer(configuration)));
+
+ registry.subtreeAdd(routingProtocolHandledChildren(),new GenericWriter<>(routingProtocolIdentifier(),
+ new RoutingProtocolCustomizer(routingProtocolContext)));
+
+ final InstanceIdentifier<StaticRoutes> staticRoutesInstanceIdentifier = staticRoutesIdentifier();
+ final InstanceIdentifier<Route> ipv4RouteIdentifier = ipv4RouteIdentifier(staticRoutesInstanceIdentifier);
+ final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route>
+ ipv6RouteIdentifier = ipv6RouteIdentifier(staticRoutesInstanceIdentifier);
+ registry.subtreeAdd(ipv4RoutingHandledChildren(ipv4RouteSubtree()), new GenericWriter<>(ipv4RouteIdentifier,
+ new Ipv4RouteCustomizer(vppApi, interfaceContext, routeContext, routingProtocolContext, routHopContext,
+ vppClassifierContextManager)));
+ registry.subtreeAdd(ipv6RoutingHandledChildren(ipv6RouteSubtree()), new GenericWriter<>(ipv6RouteIdentifier,
+ new Ipv6RouteCustomizer(vppApi, interfaceContext, routeContext, routingProtocolContext, routHopContext,
+ vppClassifierContextManager)));
+ }
+
+ private static ImmutableSet<InstanceIdentifier<?>> routingProtocolHandledChildren() {
+ return ImmutableSet
+ .of(InstanceIdentifier.create(RoutingProtocol.class).augmentation(RoutingProtocolVppAttr.class).child(VppProtocolAttributes.class));
+ }
+
+ 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);
+ }
+
+ private static InstanceIdentifier<StaticRoutes> staticRoutesIdentifier() {
+ return routingProtocolIdentifier().child(StaticRoutes.class);
+ }
+
+ private static Set<InstanceIdentifier<?>> rootNodeHandledChildren(final InstanceIdentifier<Routing> parent) {
+ return ImmutableSet.of(parent.child(RoutingInstance.class).child(RoutingProtocols.class));
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/MultipathHopRequestFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/MultipathHopRequestFactory.java
new file mode 100644
index 000000000..4599c8b82
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/MultipathHopRequestFactory.java
@@ -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.routing.write.factory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.write.factory.base.BasicHopRequestFactory;
+import io.fd.hc2vpp.routing.write.trait.RouteRequestProducer;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.IpAddDelRoute;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+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.Ipv6Prefix;
+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.VppIpv4Route;
+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.next.hop.options.next.hop.list.next.hop.list.NextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6Route;
+
+
+/**
+ * Factory for creating requests to create route with multiple hops
+ */
+public class MultipathHopRequestFactory extends BasicHopRequestFactory implements RouteRequestProducer {
+
+ private MultipathHopRequestFactory(final VppClassifierContextManager classifierContextManager,
+ final NamingContext interfaceContext,
+ final NamingContext routingProtocolContext) {
+ super(classifierContextManager, interfaceContext, routingProtocolContext);
+ }
+
+ public static MultipathHopRequestFactory forContexts(
+ @Nonnull final VppClassifierContextManager classifierContextManager,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ return new MultipathHopRequestFactory(classifierContextManager, interfaceContext, routingProtocolContext);
+ }
+
+ public IpAddDelRoute createIpv4MultipathHopRequest(final boolean add,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final 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 route,
+ @Nonnull final NextHop hop,
+ @Nonnull final MappingContext mappingContext) {
+
+ final VppIpv4Route routingAttributes = checkNotNull(route.getVppIpv4Route(), "VppIpv4Route not defined");
+
+ final int nextHopInterfaceIndex =
+ getInterfaceNamingContext().getIndex(hop.getOutgoingInterface(), mappingContext);
+
+ if (classifyTablePresent(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext)) {
+ return getMultipathHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getAddress(),
+ toByte(hop.getWeight()),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ classifyTableIndex(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext),
+ true);
+ } else {
+ return getMultipathHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getAddress(),
+ toByte(hop.getWeight()),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ 0,
+ false);
+ }
+ }
+
+ public IpAddDelRoute createIpv6MultipathHopRequest(final boolean add,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route route,
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.next.hop.list.next.hop.list.NextHop hop,
+ @Nonnull final MappingContext mappingContext) {
+ final VppIpv6Route routingAttributes = checkNotNull(route.getVppIpv6Route(), "VppIpv6Route not defined");
+
+ final int nextHopInterfaceIndex =
+ getInterfaceNamingContext().getIndex(hop.getOutgoingInterface(), mappingContext);
+
+ if (classifyTablePresent(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext)) {
+ return getMultipathHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getAddress(),
+ toByte(hop.getWeight()),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ classifyTableIndex(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext),
+ true);
+ } else {
+ return getMultipathHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getAddress(),
+ toByte(hop.getWeight()),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ 0,
+ false);
+ }
+ }
+
+
+ private IpAddDelRoute getMultipathHopRequest(final boolean isAdd, @Nonnull final Ipv6Prefix destinationAddress,
+ final int nextHopInterfaceIndex,
+ @Nonnull final Ipv6Address nextHopAddress,
+ final byte nextHopWeight,
+ final int primaryVrf, final int secondaryVrf,
+ final int classifyTableIndex, final boolean classifyIndexSet) {
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), nextHopInterfaceIndex,
+ ipv6AddressNoZoneToArray(nextHopAddress.getValue()), nextHopWeight, toByte(1),
+ ipv6AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), toByte(1),
+ primaryVrf, secondaryVrf, classifyTableIndex,
+ booleanToByte(classifyIndexSet));
+ }
+
+ private IpAddDelRoute getMultipathHopRequest(final boolean isAdd, @Nonnull final Ipv4Prefix destinationAddress,
+ final int nextHopInterfaceIndex,
+ @Nonnull final Ipv4Address nextHopAddress,
+ final byte nextHopWeight,
+ final int primaryVrf, final int secondaryVrf,
+ final int classifyTableIndex, final boolean classifyIndexSet) {
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), nextHopInterfaceIndex,
+ ipv4AddressNoZoneToArray(nextHopAddress.getValue()), nextHopWeight, toByte(0),
+ ipv4AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), toByte(1),
+ primaryVrf, secondaryVrf, classifyTableIndex,
+ booleanToByte(classifyIndexSet));
+ }
+
+
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SimpleHopRequestFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SimpleHopRequestFactory.java
new file mode 100644
index 000000000..68a5f3d71
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SimpleHopRequestFactory.java
@@ -0,0 +1,145 @@
+/*
+ * 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.routing.write.factory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.routing.write.factory.base.BasicHopRequestFactory;
+import io.fd.hc2vpp.routing.write.trait.RouteRequestProducer;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.IpAddDelRoute;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+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.Ipv6Prefix;
+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.VppIpv4Route;
+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.next.hop.options.SimpleNextHop;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.VppIpv6Route;
+
+
+/**
+ * Factory for creating requests to create route with hop simple hop
+ */
+public class SimpleHopRequestFactory extends BasicHopRequestFactory implements RouteRequestProducer {
+
+ private SimpleHopRequestFactory(final VppClassifierContextManager classifierContextManager,
+ final NamingContext interfaceContext,
+ final NamingContext routingProtocolContext) {
+ super(classifierContextManager, interfaceContext, routingProtocolContext);
+ }
+
+ public static SimpleHopRequestFactory forContexts(
+ @Nonnull final VppClassifierContextManager classifierContextManager,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ return new SimpleHopRequestFactory(classifierContextManager, interfaceContext, routingProtocolContext);
+ }
+
+ public IpAddDelRoute createIpv4SimpleHopRequest(final boolean add,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final 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 route,
+ @Nonnull final MappingContext mappingContext) {
+
+ final SimpleNextHop hop = SimpleNextHop.class.cast(route.getNextHopOptions());
+ final VppIpv4Route routingAttributes = checkNotNull(route.getVppIpv4Route(), "VppIpv4Route not defined");
+ final int nextHopInterfaceIndex =
+ getInterfaceNamingContext().getIndex(hop.getOutgoingInterface(), mappingContext);
+
+ if (classifyTablePresent(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext)) {
+ return getSimpleHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getNextHop(),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ classifyTableIndex(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext),
+ true);
+ } else {
+ return getSimpleHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getNextHop(),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ 0,
+ false);
+ }
+ }
+
+ public IpAddDelRoute createIpv6SimpleHopRequest(final boolean add,
+ @Nonnull final String parentProtocolName,
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route route,
+ @Nonnull final MappingContext mappingContext) {
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop
+ hop =
+ (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.route.next.hop.options.SimpleNextHop) route
+ .getNextHopOptions();
+ final VppIpv6Route routingAttributes = checkNotNull(route.getVppIpv6Route(), "VppIpv6Route not defined");
+ final int nextHopInterfaceIndex =
+ getInterfaceNamingContext().getIndex(hop.getOutgoingInterface(), mappingContext);
+
+ if (classifyTablePresent(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext)) {
+ return getSimpleHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getNextHop(),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ classifyTableIndex(routingAttributes.getClassifyTable(), getVppClassifierContextManager(),
+ mappingContext),
+ true);
+ } else {
+ return getSimpleHopRequest(add,
+ route.getDestinationPrefix(),
+ nextHopInterfaceIndex,
+ hop.getNextHop(),
+ getRoutingProtocolContext().getIndex(parentProtocolName, mappingContext),
+ optionalVni(routingAttributes.getSecondaryVrf()),
+ 0,
+ false);
+ }
+ }
+
+
+ private IpAddDelRoute getSimpleHopRequest(final boolean isAdd, @Nonnull final Ipv6Prefix destinationAddress,
+ final int nextHopInterfaceIndex,
+ @Nonnull final Ipv6Address nextHopAddress,
+ final int primaryVrf, final int secondaryVrf,
+ final int classifyTableIndex, final boolean classifyIndexSet) {
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), nextHopInterfaceIndex,
+ ipv6AddressNoZoneToArray(nextHopAddress.getValue()), DEFAULT_HOP_WEIGHT, BYTE_TRUE,
+ ipv6AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), BYTE_FALSE,
+ primaryVrf, secondaryVrf, classifyTableIndex, booleanToByte(classifyIndexSet));
+ }
+
+ private IpAddDelRoute getSimpleHopRequest(final boolean isAdd, @Nonnull final Ipv4Prefix destinationAddress,
+ final int nextHopInterfaceIndex,
+ @Nonnull final Ipv4Address nextHopAddress,
+ final int primaryVrf, final int secondaryVrf,
+ final int classifyTableIndex, final boolean classifyIndexSet) {
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), nextHopInterfaceIndex,
+ ipv4AddressNoZoneToArray(nextHopAddress.getValue()), DEFAULT_HOP_WEIGHT, BYTE_FALSE,
+ ipv4AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), BYTE_FALSE,
+ primaryVrf, secondaryVrf, classifyTableIndex, booleanToByte(classifyIndexSet));
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SpecialNextHopRequestFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SpecialNextHopRequestFactory.java
new file mode 100644
index 000000000..2a5ab9821
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/SpecialNextHopRequestFactory.java
@@ -0,0 +1,120 @@
+/*
+ * 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.routing.write.factory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.routing.write.factory.base.ClassifierContextHolder;
+import io.fd.hc2vpp.routing.write.trait.RouteRequestProducer;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.IpAddDelRoute;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.SpecialNextHopGrouping;
+
+public class SpecialNextHopRequestFactory extends ClassifierContextHolder
+ implements RouteRequestProducer {
+
+ private SpecialNextHopRequestFactory(final VppClassifierContextManager classifierContextManager) {
+ super(classifierContextManager);
+ }
+
+ public static SpecialNextHopRequestFactory forClassifierContext(
+ @Nonnull final VppClassifierContextManager classifierContextManager) {
+ return new SpecialNextHopRequestFactory(classifierContextManager);
+ }
+
+ public IpAddDelRoute createIpv4SpecialHopRequest(final boolean add,
+ @Nonnull final 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 route,
+ @Nonnull final MappingContext mappingContext,
+ @Nonnull final SpecialNextHopGrouping.SpecialNextHop flagsVariant) {
+ checkNotNull(route, "Route cannot be null");
+ checkNotNull(mappingContext, "Mapping Context cannot be null");
+ checkNotNull(flagsVariant, "Flags variant cannot be null");
+
+ return resolveFlags(getSpecialHopRequest(add, route.getDestinationPrefix()), flagsVariant);
+ }
+
+ public IpAddDelRoute createIpv6SpecialHopRequest(final boolean add,
+ @Nonnull final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv6.unicast.routing.rev140525.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv6.Route route,
+ @Nonnull final MappingContext mappingContext,
+ @Nonnull final SpecialNextHopGrouping.SpecialNextHop flagsVariant) {
+
+ checkNotNull(route, "Route cannot be null");
+ checkNotNull(mappingContext, "Mapping Context cannot be null");
+ checkNotNull(flagsVariant, "Flags variant cannot be null");
+
+ return resolveFlags(getSpecialHopRequest(add, route.getDestinationPrefix()), flagsVariant);
+ }
+
+ private IpAddDelRoute getSpecialHopRequest(final boolean isAdd, @Nonnull final Ipv6Prefix destinationAddress) {
+
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), 0, null, DEFAULT_HOP_WEIGHT, BYTE_TRUE,
+ ipv6AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), BYTE_FALSE,
+ DEFAULT_VNI, DEFAULT_VNI, DEFAULT_CLASSIFY_TABLE_INDEX, BYTE_FALSE);
+ }
+
+ private IpAddDelRoute getSpecialHopRequest(final boolean isAdd, @Nonnull final Ipv4Prefix destinationAddress) {
+ return flaglessAddDelRouteRequest(booleanToByte(isAdd), 0, null, DEFAULT_HOP_WEIGHT, BYTE_FALSE,
+ ipv4AddressPrefixToArray(destinationAddress), extractPrefix(destinationAddress.getValue()), BYTE_FALSE,
+ DEFAULT_VNI, DEFAULT_VNI, DEFAULT_CLASSIFY_TABLE_INDEX, BYTE_FALSE);
+ }
+
+ private IpAddDelRoute resolveFlags(IpAddDelRoute request,
+ final SpecialNextHopGrouping.SpecialNextHop flagsVariant) {
+ switch (flagsVariant) {
+ case Blackhole:
+ return resolveAsBlackholeVariant(request);
+ case Unreachable:
+ return resolveAsUnreachableVariant(request);
+ case Prohibit:
+ return resolveAsProhibitedVariant(request);
+ case Receive:
+ return resolveAsReceiveVariant(request);
+ default:
+ throw new IllegalArgumentException("Unsupported type");
+ }
+ }
+
+ private IpAddDelRoute resolveAsBlackholeVariant(IpAddDelRoute request) {
+ return bindFlags(request, true, false, false, false);
+ }
+
+ private IpAddDelRoute resolveAsReceiveVariant(IpAddDelRoute request) {
+ return bindFlags(request, false, true, false, false);
+ }
+
+ private IpAddDelRoute resolveAsUnreachableVariant(IpAddDelRoute request) {
+ return bindFlags(request, false, false, true, false);
+ }
+
+ private IpAddDelRoute resolveAsProhibitedVariant(IpAddDelRoute request) {
+ return bindFlags(request, false, false, false, true);
+ }
+
+ private IpAddDelRoute bindFlags(IpAddDelRoute request, final boolean isDrop, final boolean isReceive,
+ final boolean isUnreachable, final boolean isProhibited) {
+ request.isDrop = booleanToByte(isDrop);
+ request.isLocal = booleanToByte(isReceive);
+ request.isUnreach = booleanToByte(isUnreachable);
+ request.isProhibit = booleanToByte(isProhibited);
+
+ return request;
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/BasicHopRequestFactory.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/BasicHopRequestFactory.java
new file mode 100644
index 000000000..abaf0fa84
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/BasicHopRequestFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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.routing.write.factory.base;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import javax.annotation.Nonnull;
+
+/**
+ * Extension to {@code ClassifierContextHolder} to hold also {@code NamingContext}
+ */
+public abstract class BasicHopRequestFactory extends ClassifierContextHolder {
+
+ private final NamingContext interfaceNamingContext;
+ private final NamingContext routingProtocolContext;
+
+ protected BasicHopRequestFactory(
+ @Nonnull final VppClassifierContextManager classifierContextManager,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext routingProtocolContext) {
+ super(classifierContextManager);
+ this.interfaceNamingContext = checkNotNull(interfaceContext, "Interface context cannot be null");
+ this.routingProtocolContext = checkNotNull(routingProtocolContext, "Routing protocol context cannot be null");
+ }
+
+ protected NamingContext getInterfaceNamingContext() {
+ return interfaceNamingContext;
+ }
+
+ protected NamingContext getRoutingProtocolContext() {
+ return routingProtocolContext;
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/ClassifierContextHolder.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/ClassifierContextHolder.java
new file mode 100644
index 000000000..0b11a9b3b
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/factory/base/ClassifierContextHolder.java
@@ -0,0 +1,38 @@
+/*
+ * 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.routing.write.factory.base;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import javax.annotation.Nonnull;
+
+/**
+ * Holds reference for
+ */
+public abstract class ClassifierContextHolder {
+
+ private final VppClassifierContextManager classifierContextManager;
+
+ protected ClassifierContextHolder(@Nonnull final VppClassifierContextManager classifierContextManager) {
+ this.classifierContextManager = checkNotNull(classifierContextManager, "Classifier context cannot be null");
+ }
+
+ protected VppClassifierContextManager getVppClassifierContextManager() {
+ return this.classifierContextManager;
+ }
+}
diff --git a/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/trait/RouteRequestProducer.java b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/trait/RouteRequestProducer.java
new file mode 100644
index 000000000..63ee5a13e
--- /dev/null
+++ b/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/trait/RouteRequestProducer.java
@@ -0,0 +1,138 @@
+/*
+ * 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.routing.write.trait;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.isNull;
+import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+
+import com.google.common.collect.ImmutableSet.Builder;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.vpp.jvpp.core.dto.IpAddDelRoute;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+
+
+/**
+ * Common logic for writing of routes
+ */
+public interface RouteRequestProducer extends ByteDataTranslator, AddressTranslator, JvppReplyConsumer {
+
+ Set<String> allowedPrefixPatterns = new Builder<String>().addAll(Ipv4Prefix.PATTERN_CONSTANTS)
+ .addAll(Ipv6Prefix.PATTERN_CONSTANTS).build();
+
+ byte DEFAULT_VNI = 0;
+ byte DEFAULT_CLASSIFY_TABLE_INDEX = 0;
+ byte DEFAULT_HOP_WEIGHT = 0;
+
+ default int mandatoryVni(final VniReference vniReference) {
+ return checkNotNull(vniReference, "Vni reference cannot be null").getValue().intValue();
+ }
+
+ default int optionalVni(final VniReference vniReference) {
+ return isNull(vniReference)
+ ? DEFAULT_VNI
+ : vniReference.getValue().intValue();
+ }
+
+ default byte extractPrefix(final String value) {
+ checkArgument(
+ allowedPrefixPatterns.stream().anyMatch(pattern -> Pattern.compile(pattern).matcher(value).matches()),
+ "%s is not a valid Ip-prefix value");
+ return Byte.valueOf(value.substring(value.indexOf("/") + 1));
+ }
+
+ default boolean classifyTablePresent(final String classifyTableName,
+ final VppClassifierContextManager classifierContextManager,
+ final MappingContext mappingContext) {
+ return isNotEmpty(classifyTableName) &&
+ classifierContextManager.containsTable(classifyTableName, mappingContext);
+ }
+
+ default int classifyTableIndex(final String classifyTableName,
+ final VppClassifierContextManager classifierContextManager,
+ final MappingContext mappingContext) {
+ return classifierContextManager.getTableIndex(classifyTableName, mappingContext);
+ }
+
+ /**
+ * Creates fully bind {@code IpAddDelRoute} request
+ *
+ * @param add 1 if add,delete otherwise
+ * @param nextHopInterfaceIndex interface for <b>nextHopAddress</b>
+ * @param nextHopAddress address of hop
+ * @param nextHopWeight if <b>mutlipath</b>, then set to "order" hops
+ * @param ipv6 determine if writing ipv4/ipv6 route
+ * @param destinationAddress address of destination for hop
+ * @param destinationAddressPrefixLength prefix length of <b>destinationAddress</b>
+ * @param multipath You can only write one next-hop at a time. set this to true when you are
+ * adding paths/next-hops to an existing route. It can be true when adding a
+ * new route.
+ * @param primaryVrf primary vrf for configured route
+ * @param secondaryVrf lookup vrf for route
+ * @param classifyTableIndex index of classify table
+ * @param classifyTableSet set if classify table index was set
+ */
+ default IpAddDelRoute flaglessAddDelRouteRequest(final byte add,
+ final int nextHopInterfaceIndex,
+ final byte[] nextHopAddress,
+ final byte nextHopWeight,
+ final byte ipv6,
+ final byte[] destinationAddress,
+ final byte destinationAddressPrefixLength,
+ final byte multipath,
+ final int primaryVrf,
+ final int secondaryVrf,
+ final int classifyTableIndex,
+ final byte classifyTableSet) {
+
+ final IpAddDelRoute request = new IpAddDelRoute();
+ request.isAdd = add;
+ request.nextHopSwIfIndex = nextHopInterfaceIndex;
+ request.dstAddress = destinationAddress;
+ request.dstAddressLength = destinationAddressPrefixLength;
+ request.isIpv6 = ipv6;
+ request.isMultipath = multipath;
+ request.nextHopAddress = nextHopAddress;
+
+ // Model contains also priority but VPP does not support the concept of priority next-hops
+ request.nextHopWeight = nextHopWeight;
+
+ // vrf_id - fib table /vrf associated with the route Not mentioned in model
+ request.tableId = primaryVrf;
+
+ // create vrf if needed needs to be turned on all the time,due to how we map table ids on routing protocols
+ request.createVrfIfNeeded = 1;
+
+ // nextHopTableId - this is used when you want to have a second lookup done in another table.
+ request.nextHopTableId = secondaryVrf;
+
+ // classify_table_index
+ request.classifyTableIndex = classifyTableIndex;
+ request.isClassify = classifyTableSet;
+
+ return request;
+ }
+}