summaryrefslogtreecommitdiffstats
path: root/routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.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/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.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/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java')
-rw-r--r--routing/routing-impl/src/main/java/io/fd/hc2vpp/routing/write/Ipv6RouteCustomizer.java211
1 files changed, 211 insertions, 0 deletions
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()));
+ }
+}