summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Gradzki <mgradzki@cisco.com>2017-03-10 12:50:53 +0100
committerMarek Gradzki <mgradzki@cisco.com>2017-03-14 14:31:10 +0100
commit4616f0300655582153362a21910bd1f0b14937ae (patch)
tree651b317343fe2df592421cf7319ed3828c79990d
parente7903be79d4451f5b6e6f633b7ea20f8330ac0c1 (diff)
HC2VPP-55: policer&policer assignment CRUD support
Change-Id: I627d2a56ab2a282744ea0172b4a0c72240b0032f Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
-rw-r--r--vpp-classifier/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/policer/rev170315/DscpTypeBuilder.java39
-rw-r--r--vpp-classifier/api/src/main/yang/interface-policer.yang34
-rw-r--r--vpp-classifier/api/src/main/yang/policer.yang11
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/PolicerModule.java50
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerCustomizer.java122
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerReaderFactory.java59
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerCustomizer.java218
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerReaderFactory.java50
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerCustomizer.java97
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerWriterFactory.java60
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerCustomizer.java165
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerWriterFactory.java52
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/VppClassifierModule.java9
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java8
-rw-r--r--vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java45
-rw-r--r--vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java3
-rw-r--r--vpp-integration/minimal-distribution/pom.xml1
17 files changed, 984 insertions, 39 deletions
diff --git a/vpp-classifier/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/policer/rev170315/DscpTypeBuilder.java b/vpp-classifier/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/policer/rev170315/DscpTypeBuilder.java
new file mode 100644
index 000000000..f204f8c6b
--- /dev/null
+++ b/vpp-classifier/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/policer/rev170315/DscpTypeBuilder.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ *
+ */
+public class DscpTypeBuilder {
+
+ public static DscpType getDefaultInstance(java.lang.String defaultValue) {
+ final VppDscpType vppDscpType = VppDscpType.valueOf(defaultValue);
+ if (vppDscpType != null) {
+ return new DscpType(vppDscpType);
+ }
+ return new DscpType(Dscp.getDefaultInstance(defaultValue));
+ }
+}
diff --git a/vpp-classifier/api/src/main/yang/interface-policer.yang b/vpp-classifier/api/src/main/yang/interface-policer.yang
index d92faa9bf..2fd7b6b83 100644
--- a/vpp-classifier/api/src/main/yang/interface-policer.yang
+++ b/vpp-classifier/api/src/main/yang/interface-policer.yang
@@ -27,23 +27,25 @@ module interface-policer {
}
grouping interface-policer-attributes {
- description
- "Defines references to policer classify tables.
- At least one table reference should be specified.";
- leaf l2-table {
- type vpp-classifier:classify-table-ref;
+ container policer {
description
- "An L2 policer table";
- }
- leaf ip4-table {
- type vpp-classifier:classify-table-ref;
- description
- "An IPv4 policer table";
- }
- leaf ip6-table {
- type vpp-classifier:classify-table-ref;
- description
- "An IPv6 policer table";
+ "Defines references to policer classify tables.
+ At least one table reference should be specified.";
+ leaf l2-table {
+ type vpp-classifier:classify-table-ref;
+ description
+ "An L2 policer table";
+ }
+ leaf ip4-table {
+ type vpp-classifier:classify-table-ref;
+ description
+ "An IPv4 policer table";
+ }
+ leaf ip6-table {
+ type vpp-classifier:classify-table-ref;
+ description
+ "An IPv6 policer table";
+ }
}
}
diff --git a/vpp-classifier/api/src/main/yang/policer.yang b/vpp-classifier/api/src/main/yang/policer.yang
index 1f730b6a5..637967128 100644
--- a/vpp-classifier/api/src/main/yang/policer.yang
+++ b/vpp-classifier/api/src/main/yang/policer.yang
@@ -91,7 +91,7 @@ module policer {
"transmit action type in a meter";
}
- typedef vpp-dcsp-type {
+ typedef vpp-dscp-type {
description
"DSCP field values supported by VPP";
type enumeration {
@@ -162,9 +162,9 @@ module policer {
default CS0;
}
- typedef dcsp-type {
+ typedef dscp-type {
type union {
- type vpp-dcsp-type;
+ type vpp-dscp-type;
type inet:dscp;
}
}
@@ -182,7 +182,7 @@ module policer {
}
leaf dscp {
when "../meter-action-type = meter-action-mark-dscp";
- type dcsp-type;
+ type dscp-type;
description
"dscp marking";
}
@@ -217,12 +217,15 @@ module policer {
type boolean;
}
container conform-action {
+ presence "Defines conform action";
uses meter-action-params;
}
container exceed-action {
+ presence "Defines exceed action";
uses meter-action-params;
}
container violate-action {
+ presence "Defines violate action";
uses meter-action-params;
}
}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/PolicerModule.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/PolicerModule.java
new file mode 100644
index 000000000..86ad72a2c
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/PolicerModule.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.hc2vpp.policer.read.InterfacePolicerReaderFactory;
+import io.fd.hc2vpp.policer.read.PolicerReaderFactory;
+import io.fd.hc2vpp.policer.write.InterfacePolicerWriterFactory;
+import io.fd.hc2vpp.policer.write.PolicerWriterFactory;
+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;
+
+public class PolicerModule extends AbstractModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolicerModule.class);
+
+ @Override
+ protected void configure() {
+ LOG.debug("Installing PolicerModule module");
+ install(ConfigurationModule.create());
+
+ // Writers
+ final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+ writerFactoryBinder.addBinding().to(PolicerWriterFactory.class);
+ writerFactoryBinder.addBinding().to(InterfacePolicerWriterFactory.class);
+
+ // Readers
+ final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ readerFactoryBinder.addBinding().to(PolicerReaderFactory.class);
+ readerFactoryBinder.addBinding().to(InterfacePolicerReaderFactory.class);
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerCustomizer.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerCustomizer.java
new file mode 100644
index 000000000..c681758f1
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerCustomizer.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.read;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+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.ReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.PolicerClassifyDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.PolicerClassifyDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315.PolicerInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315._interface.policer.attributes.Policer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315._interface.policer.attributes.PolicerBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class InterfacePolicerCustomizer extends FutureJVppCustomizer
+ implements ReaderCustomizer<Policer, PolicerBuilder>,
+ JvppReplyConsumer, ByteDataTranslator {
+
+ private static final byte TABLE_IP4 = 0;
+ private static final byte TABLE_IP6 = 1;
+ private static final byte TABLE_L2 = 2;
+
+ private final DumpCacheManager<PolicerClassifyDetailsReplyDump, Byte> dumpManager;
+ private final NamingContext interfaceContext;
+ private final VppClassifierContextManager classifyTableContext;
+
+ InterfacePolicerCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final VppClassifierContextManager classifyTableContext) {
+ super(futureJVppCore);
+ this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+ this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+ dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<PolicerClassifyDetailsReplyDump, Byte>()
+ .withExecutor(executor())
+ .acceptOnly(PolicerClassifyDetailsReplyDump.class)
+ .build();
+ }
+
+ private EntityDumpExecutor<PolicerClassifyDetailsReplyDump, Byte> executor() {
+ return (id, type) -> {
+ PolicerClassifyDump request = new PolicerClassifyDump();
+ request.type = type;
+ return getReplyForRead(getFutureJVpp().policerClassifyDump(request).toCompletableFuture(), id);
+ };
+ }
+
+ @Nonnull
+ @Override
+ public PolicerBuilder getBuilder(@Nonnull final InstanceIdentifier<Policer> instanceIdentifier) {
+ return new PolicerBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final PolicerBuilder builder,
+ @Nonnull final ReadContext ctx)
+ throws ReadFailedException {
+ final String ifcName = id.firstKeyOf(Interface.class).getName();
+ final int ifcIndex = interfaceContext.getIndex(ifcName, ctx.getMappingContext());
+ // FIXME: only first dump will result in jvpp call, so either we improve
+ // DumpCacheManager(HONEYCOMB-348) or we need to do it directly (probably without caching):
+ final Optional<Integer> ip4 = readTableIndex(id, ifcIndex, TABLE_IP4, ctx.getModificationCache());
+ if (ip4.isPresent()) {
+ builder.setIp4Table(classifyTableContext.getTableName(ip4.get(), ctx.getMappingContext()));
+ }
+ final Optional<Integer> ip6 = readTableIndex(id, ifcIndex, TABLE_IP6, ctx.getModificationCache());
+ if (ip6.isPresent()) {
+ builder.setIp6Table(classifyTableContext.getTableName(ip6.get(), ctx.getMappingContext()));
+ }
+ final Optional<Integer> l2 = readTableIndex(id, ifcIndex, TABLE_L2, ctx.getModificationCache());
+ if (l2.isPresent()) {
+ builder.setL2Table(classifyTableContext.getTableName(l2.get(), ctx.getMappingContext()));
+ }
+ }
+
+ private Optional<Integer> readTableIndex(@Nonnull final InstanceIdentifier<Policer> id, final int ifcIndex,
+ final byte type,
+ final ModificationCache cache) throws ReadFailedException {
+ final com.google.common.base.Optional<PolicerClassifyDetailsReplyDump> dump =
+ dumpManager.getDump(id, cache, type);
+ if (!dump.isPresent() || dump.get().policerClassifyDetails.isEmpty()) {
+ return Optional.empty();
+ }
+ return dump.get().policerClassifyDetails.stream().filter(detail -> detail.swIfIndex == ifcIndex).findFirst()
+ .map(details -> details.tableIndex);
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final Policer policer) {
+ ((PolicerInterfaceStateAugmentationBuilder) builder).setPolicer(policer);
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerReaderFactory.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerReaderFactory.java
new file mode 100644
index 000000000..da027310a
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/InterfacePolicerReaderFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.read;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+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.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315.PolicerInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315.PolicerInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315._interface.policer.attributes.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacePolicerReaderFactory implements ReaderFactory {
+ private static final InstanceIdentifier<Interface> IFC_ID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ private static final InstanceIdentifier<PolicerInterfaceStateAugmentation> POLICER_IFC_ID =
+ IFC_ID.augmentation(PolicerInterfaceStateAugmentation.class);
+
+ private static final InstanceIdentifier<Policer> POLICER_IID = POLICER_IFC_ID.child(Policer.class);
+
+ @Inject
+ private FutureJVppCore vppApi;
+ @Inject
+ @Named("interface-context")
+ private NamingContext ifcContext;
+ @Inject
+ @Named("classify-table-context")
+ private VppClassifierContextManager classifyTableContext;
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ InstanceIdentifier<Policer> IID = InstanceIdentifier.create(Policer.class);
+ registry.addStructuralReader(POLICER_IFC_ID, PolicerInterfaceStateAugmentationBuilder.class);
+ registry.add(
+ new GenericReader<>(POLICER_IID, new InterfacePolicerCustomizer(vppApi, ifcContext, classifyTableContext)));
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerCustomizer.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerCustomizer.java
new file mode 100644
index 000000000..9d4c40f50
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerCustomizer.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.read;
+
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.UnsignedInts;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.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.InitializingListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.PolicerDetails;
+import io.fd.vpp.jvpp.core.dto.PolicerDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.PolicerDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.math.BigInteger;
+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.inet.types.rev130715.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.DscpType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionDrop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionMarkDscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionTransmit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.PolicerRateType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.PolicerRoundType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.Policers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.PolicersStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.VppDscpType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ConformAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ConformActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ExceedAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ExceedActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ViolateAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ViolateActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.state.Policer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.state.PolicerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.state.PolicerKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class PolicerCustomizer extends FutureJVppCustomizer
+ implements InitializingListReaderCustomizer<Policer, PolicerKey, PolicerBuilder>,
+ JvppReplyConsumer, ByteDataTranslator {
+
+ private final DumpCacheManager<PolicerDetailsReplyDump, Void> dumpManager;
+
+ PolicerCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+ super(futureJVppCore);
+ dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<PolicerDetailsReplyDump, Void>()
+ .withExecutor(
+ (id, param) -> getReplyForRead(getFutureJVpp().policerDump(new PolicerDump()).toCompletableFuture(),
+ id))
+ .acceptOnly(PolicerDetailsReplyDump.class)
+ .build();
+ }
+
+ @Nonnull
+ @Override
+ public List<PolicerKey> getAllIds(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ final Optional<PolicerDetailsReplyDump> dump = dumpManager.getDump(id, ctx.getModificationCache(), NO_PARAMS);
+
+ if (!dump.isPresent() || dump.get().policerDetails.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return dump.get().policerDetails.stream().map(detail -> new PolicerKey(toString(detail.name)))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Policer> list) {
+ ((PolicersStateBuilder) builder).setPolicer(list);
+ }
+
+ @Nonnull
+ @Override
+ public PolicerBuilder getBuilder(@Nonnull final InstanceIdentifier<Policer> id) {
+ return new PolicerBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final PolicerBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ final Optional<PolicerDetailsReplyDump> dump = dumpManager.getDump(id, ctx.getModificationCache(), NO_PARAMS);
+
+ if (!dump.isPresent() || dump.get().policerDetails.isEmpty()) {
+ return;
+ }
+ final PolicerKey key = id.firstKeyOf(Policer.class);
+ final java.util.Optional<PolicerDetails> result =
+ dump.get().policerDetails.stream().filter(detail -> key.equals(new PolicerKey(toString(detail.name)))).findFirst();
+ if (!result.isPresent()) {
+ return;
+ }
+ final PolicerDetails details = result.get();
+ builder.setName(toString(details.name));
+ builder.setCir(UnsignedInts.toLong(details.cir));
+ builder.setEir(UnsignedInts.toLong(details.eir));
+ // TODO(HC2VPP-117): policer init fails if cb is configured (looks like byte ordering issue on VPP side)
+ builder.setCb(toUnsignedBigInteger(details.cb));
+ builder.setEb(toUnsignedBigInteger(details.eb));
+ builder.setRateType(PolicerRateType.forValue(details.rateType));
+ builder.setRoundType(PolicerRoundType.forValue(details.roundType));
+ builder.setType(MeterType.forValue(details.type));
+ builder.setColorAware(byteToBoolean(details.colorAware));
+ builder.setConformAction(parseConformAction(details));
+ builder.setExceedAction(parseExceedAction(details));
+ builder.setViolateAction(parseViolateAction(details));
+
+ // operational only data:
+ builder.setSingleRate(byteToBoolean(details.singleRate));
+ builder.setScale(UnsignedInts.toLong(details.scale));
+ builder.setCirTokensPerPeriod(UnsignedInts.toLong(details.cirTokensPerPeriod));
+ builder.setPirTokensPerPeriod(UnsignedInts.toLong(details.pirTokensPerPeriod));
+ builder.setCurrentLimit(UnsignedInts.toLong(details.currentLimit));
+ builder.setCurrentBucket(UnsignedInts.toLong(details.currentBucket));
+ builder.setExtendedLimit(UnsignedInts.toLong(details.extendedLimit));
+ builder.setExtendedBucket(UnsignedInts.toLong(details.extendedBucket));
+ builder.setLastUpdateTime(toUnsignedBigInteger(details.lastUpdateTime));
+ }
+
+ private BigInteger toUnsignedBigInteger(final long value) {
+ return new BigInteger(1, Longs.toByteArray(value));
+ }
+
+ private Class<? extends MeterActionType> parseMeterActionType(final byte actionType) {
+ switch (actionType) {
+ case 0:
+ return MeterActionDrop.class;
+ case 1:
+ return MeterActionTransmit.class;
+ case 2:
+ return MeterActionMarkDscp.class;
+ default:
+ throw new IllegalArgumentException("Unsupported meter action type " + actionType);
+ }
+ }
+
+ private DscpType parseDscp(final byte dscp, final byte conformActionType) {
+ if (dscp == -1 || conformActionType != 2) {
+ return null;
+ }
+ VppDscpType vppDcspType = VppDscpType.forValue(dscp);
+ if (vppDcspType != null) {
+ return new DscpType(vppDcspType);
+ }
+ return new DscpType(new Dscp((short) dscp));
+ }
+
+ private ConformAction parseConformAction(final PolicerDetails details) {
+ ConformActionBuilder action = new ConformActionBuilder();
+ action.setMeterActionType(parseMeterActionType(details.conformActionType));
+ action.setDscp(parseDscp(details.conformDscp, details.conformActionType));
+ return action.build();
+ }
+
+
+ private ExceedAction parseExceedAction(final PolicerDetails details) {
+ ExceedActionBuilder action = new ExceedActionBuilder();
+ action.setMeterActionType(parseMeterActionType(details.exceedActionType));
+ action.setDscp(parseDscp(details.exceedDscp, details.conformActionType));
+ return action.build();
+ }
+
+ private ViolateAction parseViolateAction(final PolicerDetails details) {
+ ViolateActionBuilder action = new ViolateActionBuilder();
+ action.setMeterActionType(parseMeterActionType(details.violateActionType));
+ action.setDscp(parseDscp(details.violateDscp, details.conformActionType));
+ return action.build();
+ }
+
+ @Nonnull
+ @Override
+ public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer policer,
+ @Nonnull final ReadContext readContext) {
+ return Initialized.create(getCfgId(id),
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.PolicerBuilder(
+ policer)
+ .setName(policer.getName())
+ .build());
+ }
+
+ private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.Policer> getCfgId(
+ final InstanceIdentifier<Policer> id) {
+ final PolicerKey key = id.firstKeyOf(Policer.class);
+ return InstanceIdentifier.create(Policers.class).child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.Policer.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.PolicerKey(
+ key.getName()));
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerReaderFactory.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerReaderFactory.java
new file mode 100644
index 000000000..3636d0f95
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/read/PolicerReaderFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.read;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.PolicersState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.PolicersStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ConformAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ExceedAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ViolateAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.state.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicerReaderFactory implements ReaderFactory {
+ private static final InstanceIdentifier<PolicersState> ROOT_IID = InstanceIdentifier.create(PolicersState.class);
+ private static final InstanceIdentifier<Policer> POLICER_IID = ROOT_IID.child(Policer.class);
+
+ @Inject
+ private FutureJVppCore vppApi;
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ InstanceIdentifier<Policer> IID = InstanceIdentifier.create(Policer.class);
+ registry.addStructuralReader(ROOT_IID, PolicersStateBuilder.class);
+ registry.subtreeAdd(
+ Sets.newHashSet(IID.child(ConformAction.class), IID.child(ExceedAction.class),
+ IID.child(ViolateAction.class)),
+ new GenericInitListReader<>(POLICER_IID, new PolicerCustomizer(vppApi)));
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerCustomizer.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerCustomizer.java
new file mode 100644
index 000000000..d2c094f0d
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerCustomizer.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.PolicerClassifySetInterface;
+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.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315._interface.policer.attributes.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class InterfacePolicerCustomizer extends FutureJVppCustomizer implements WriterCustomizer<Policer>,
+ ByteDataTranslator, JvppReplyConsumer {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfacePolicerCustomizer.class);
+
+ private final NamingContext interfaceContext;
+ private final VppClassifierContextManager classifyTableContext;
+
+ InterfacePolicerCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext,
+ @Nonnull final VppClassifierContextManager classifyTableContext) {
+ super(vppApi);
+ this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+ this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Applying policer id={}: {} to interface", id, dataAfter);
+ assignPolicer(id, dataAfter, true, writeContext.getMappingContext());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer dataBefore, @Nonnull final Policer dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Updating policer-interface assignment id={} dataBefore={} dataAfter={}", id, dataBefore, dataAfter);
+ assignPolicer(id, dataAfter, true, writeContext.getMappingContext());
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer dataBefore, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Removing policer-interface assignment id={} dataBefore={}", id, dataBefore);
+ assignPolicer(id, dataBefore, true, writeContext.getMappingContext());
+ }
+
+ private void assignPolicer(final InstanceIdentifier<Policer> id, final Policer policer, final boolean isAdd,
+ final MappingContext ctx) throws WriteFailedException {
+ final PolicerClassifySetInterface request = new PolicerClassifySetInterface();
+ request.isAdd = booleanToByte(isAdd);
+
+ request.swIfIndex = interfaceContext.getIndex(id.firstKeyOf(Interface.class).getName(), ctx);
+ request.ip4TableIndex = ~0;
+ request.ip6TableIndex = ~0;
+ request.l2TableIndex = ~0;
+ if (policer.getL2Table() != null) {
+ request.l2TableIndex = classifyTableContext.getTableIndex(policer.getL2Table(), ctx);
+ }
+ if (policer.getIp4Table() != null) {
+ request.ip4TableIndex = classifyTableContext.getTableIndex(policer.getIp4Table(), ctx);
+ }
+ if (policer.getIp6Table() != null) {
+ request.ip6TableIndex = classifyTableContext.getTableIndex(policer.getIp6Table(), ctx);
+ }
+ getReplyForWrite(getFutureJVpp().policerClassifySetInterface(request).toCompletableFuture(), id);
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerWriterFactory.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerWriterFactory.java
new file mode 100644
index 000000000..f07998fe2
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerWriterFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.write;
+
+import static io.fd.hc2vpp.vpp.classifier.factory.write.VppClassifierHoneycombWriterFactory.CLASSIFY_SESSION_ID;
+import static io.fd.hc2vpp.vpp.classifier.factory.write.VppClassifierHoneycombWriterFactory.CLASSIFY_TABLE_ID;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.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 javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315.PolicerInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.policer.rev170315._interface.policer.attributes.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacePolicerWriterFactory implements WriterFactory {
+ private static final InstanceIdentifier<Interface> IFC_ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+ private static final InstanceIdentifier<PolicerInterfaceAugmentation> POLICER_IFC_ID =
+ IFC_ID.augmentation(PolicerInterfaceAugmentation.class);
+ static final InstanceIdentifier<Policer> POLICER_ID = POLICER_IFC_ID.child(Policer.class);
+
+ @Inject
+ private FutureJVppCore vppApi;
+ @Inject
+ @Named("interface-context")
+ private NamingContext ifcContext;
+ @Inject
+ @Named("classify-table-context")
+ private VppClassifierContextManager classifyTableContext;
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ registry.addAfter(
+ new GenericWriter<>(POLICER_ID, new InterfacePolicerCustomizer(vppApi, ifcContext, classifyTableContext)),
+ Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerCustomizer.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerCustomizer.java
new file mode 100644
index 000000000..69eff100a
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerCustomizer.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.PolicerAddDel;
+import io.fd.vpp.jvpp.core.dto.PolicerAddDelReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.DscpType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionDrop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionMarkDscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionTransmit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.MeterActionType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ConformAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ExceedAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ViolateAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.Policer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.PolicerKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PolicerCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Policer, PolicerKey>,
+ JvppReplyConsumer, ByteDataTranslator {
+ private static final Logger LOG = LoggerFactory.getLogger(PolicerCustomizer.class);
+ private final NamingContext policerContext;
+
+ public PolicerCustomizer(@Nonnull final FutureJVppCore futureJVppCore, @Nonnull final NamingContext policerContext) {
+ super(futureJVppCore);
+ this.policerContext = checkNotNull(policerContext, "policerContext should not be null");
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id, @Nonnull final Policer dataAfter,
+ @Nonnull final WriteContext ctx) throws WriteFailedException {
+ LOG.debug("Writing Policer {} dataAfter={}", id, dataAfter);
+ final int policerIndex = policerAddDel(id, dataAfter, true);
+ policerContext.addName(policerIndex, dataAfter.getName(), ctx.getMappingContext());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer dataBefore,
+ @Nonnull final Policer dataAfter, @Nonnull final WriteContext ctx)
+ throws WriteFailedException {
+ LOG.debug("Updating Policer {} dataBefore={} dataAfter={}", id, dataBefore, dataAfter);
+ policerAddDel(id, dataAfter, true);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
+ @Nonnull final Policer dataBefore,
+ @Nonnull final WriteContext ctx)
+ throws WriteFailedException {
+ LOG.debug("Removing Policer {} dataBefore={}", id, dataBefore);
+ policerAddDel(id, dataBefore, false);
+ policerContext.removeName(dataBefore.getName(), ctx.getMappingContext());
+ }
+
+ private int policerAddDel(final InstanceIdentifier<Policer> id, final Policer policer, final boolean isAdd)
+ throws WriteFailedException {
+ final PolicerAddDel request = new PolicerAddDel();
+ request.isAdd = booleanToByte(isAdd);
+ request.name = policer.getName().getBytes(StandardCharsets.US_ASCII);
+
+ // policer_add_del expects host order unlike most of the other VPP APIs
+ // jvpp by default converts ordering to network order, so we need additional reverse
+ if (policer.getCir() != null) {
+ request.cir = Integer.reverseBytes(policer.getCir().intValue());
+ }
+ if (policer.getEir() != null) {
+ request.eir = Integer.reverseBytes(policer.getEir().intValue());
+ }
+ if (policer.getCb() != null) {
+ request.cb = Long.reverseBytes(policer.getCb().longValue());
+ }
+ if (policer.getEb() != null) {
+ request.eb = Long.reverseBytes(policer.getEb().longValue());
+ }
+ if (policer.getRateType() != null) {
+ request.rateType = (byte) policer.getRateType().getIntValue();
+ }
+ if (policer.getRoundType() != null) {
+ request.roundType = (byte) policer.getRoundType().getIntValue();
+ }
+ if (policer.getType() != null) {
+ request.type = (byte) policer.getType().getIntValue();
+ }
+ request.colorAware = booleanToByte(policer.isColorAware());
+ final ConformAction conformAction = policer.getConformAction();
+ if (conformAction != null) {
+ request.conformActionType = parseActiontype(conformAction.getMeterActionType());
+ request.conformDscp = parseDscp(conformAction);
+ }
+ final ExceedAction exceedAction = policer.getExceedAction();
+ if (exceedAction != null) {
+ request.exceedActionType = parseActiontype(exceedAction.getMeterActionType());
+ request.exceedDscp = parseDscp(exceedAction);
+ }
+ final ViolateAction violateAction = policer.getViolateAction();
+ if (violateAction != null) {
+ request.violateActionType = parseActiontype(violateAction.getMeterActionType());
+ request.violateDscp = parseDscp(violateAction);
+ }
+ LOG.debug("Policer config change id={} request={}", id, request);
+ final PolicerAddDelReply reply =
+ getReplyForWrite(getFutureJVpp().policerAddDel(request).toCompletableFuture(), id);
+ return reply.policerIndex;
+ }
+
+ private byte parseDscp(@Nonnull MeterActionParams actionParams) {
+ final DscpType dscp = actionParams.getDscp();
+ if (dscp == null) {
+ return 0;
+ }
+ final Class<? extends MeterActionType> meterActionType = actionParams.getMeterActionType();
+ checkArgument(MeterActionMarkDscp.class == meterActionType,
+ "dcsp is supported only for meter-action-mark-dscp, but %s defined", meterActionType);
+ if (dscp.getVppDscpType() != null) {
+ return (byte) dscp.getVppDscpType().getIntValue();
+ }
+ if (dscp.getDscp() != null) {
+ return dscp.getDscp().getValue().byteValue();
+ }
+ return 0;
+ }
+
+ private byte parseActiontype(@Nonnull final Class<? extends MeterActionType> meterActionType) {
+ if (MeterActionDrop.class == meterActionType) {
+ return 0;
+ } else if (MeterActionTransmit.class == meterActionType) {
+ return 1;
+ } else if (MeterActionMarkDscp.class == meterActionType) {
+ return 2;
+ } else {
+ throw new IllegalArgumentException("Unsupported meter action type " + meterActionType);
+ }
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerWriterFactory.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerWriterFactory.java
new file mode 100644
index 000000000..43c2f5ef9
--- /dev/null
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerWriterFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.policer.write;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.Policers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ConformAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ExceedAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policer.base.attributes.ViolateAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.policer.rev170315.policers.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicerWriterFactory implements WriterFactory {
+ private static final InstanceIdentifier<Policer> POLICER_IID = InstanceIdentifier.create(Policers.class).child(Policer.class);
+
+ @Inject
+ private FutureJVppCore vppApi;
+ @Inject
+ @Named("policer-context")
+ private NamingContext policerContext;
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ InstanceIdentifier<Policer> IID = InstanceIdentifier.create(Policer.class);
+ registry.subtreeAdd(
+ Sets.newHashSet(IID.child(ConformAction.class), IID.child(ExceedAction.class),
+ IID.child(ViolateAction.class)),
+ new GenericListWriter<>(POLICER_IID, new PolicerCustomizer(vppApi, policerContext)));
+ }
+}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/VppClassifierModule.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/VppClassifierModule.java
index 088df72c2..8a1515ca4 100644
--- a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/VppClassifierModule.java
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/VppClassifierModule.java
@@ -19,6 +19,7 @@ package io.fd.hc2vpp.vpp.classifier;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManagerImpl;
import io.fd.hc2vpp.vpp.classifier.factory.read.VppClassifierReaderFactory;
@@ -39,8 +40,12 @@ public class VppClassifierModule extends AbstractModule {
install(ConfigurationModule.create());
bind(VppClassifierContextManager.class)
- .annotatedWith(Names.named("classify-table-context"))
- .toInstance(new VppClassifierContextManagerImpl("classify-table-"));
+ .annotatedWith(Names.named("classify-table-context"))
+ .toInstance(new VppClassifierContextManagerImpl("classify-table-"));
+
+ bind(NamingContext.class)
+ .annotatedWith(Names.named("policer-context"))
+ .toInstance(new NamingContext("policer-", "policer-context"));
// Writers
final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java
index cf34e910c..7f5d46471 100644
--- a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java
@@ -18,6 +18,7 @@ package io.fd.hc2vpp.vpp.classifier.factory.write;
import com.google.inject.Inject;
import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
import io.fd.hc2vpp.vpp.classifier.write.ClassifySessionWriter;
import io.fd.hc2vpp.vpp.classifier.write.ClassifyTableWriter;
@@ -41,12 +42,15 @@ public final class VppClassifierHoneycombWriterFactory implements WriterFactory
private final FutureJVppCore jvpp;
private final VppClassifierContextManager classifyTableContext;
+ private NamingContext policerContext;
@Inject
public VppClassifierHoneycombWriterFactory(@Nonnull final FutureJVppCore jvpp,
- @Named("classify-table-context") @Nonnull final VppClassifierContextManager classifyTableContext) {
+ @Named("classify-table-context") @Nonnull final VppClassifierContextManager classifyTableContext,
+ @Named("policer-context") @Nonnull final NamingContext policerContext) {
this.jvpp = jvpp;
this.classifyTableContext = classifyTableContext;
+ this.policerContext = policerContext;
}
@Override
@@ -58,7 +62,7 @@ public final class VppClassifierHoneycombWriterFactory implements WriterFactory
CLASSIFY_SESSION_ID);
// ClassifyTableSession
registry.addBefore(
- new GenericListWriter<>(CLASSIFY_SESSION_ID, new ClassifySessionWriter(jvpp, classifyTableContext)),
+ new GenericListWriter<>(CLASSIFY_SESSION_ID, new ClassifySessionWriter(jvpp, classifyTableContext, policerContext)),
InterfaceAclWriterFactory.ACL_ID);
}
}
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java
index 8b1db57b7..be9d944c6 100644
--- a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java
+++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java
@@ -22,6 +22,7 @@ import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
import io.fd.honeycomb.translate.MappingContext;
import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
@@ -36,6 +37,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.xml.bind.DatatypeConverter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.OpaqueIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.session.attributes.NextNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.session.attributes.next_node.Policer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.session.attributes.next_node.Standard;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySession;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySessionKey;
@@ -54,11 +57,14 @@ public class ClassifySessionWriter extends VppNodeWriter
private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionWriter.class);
private final VppClassifierContextManager classifyTableContext;
+ private final NamingContext policerContext;
public ClassifySessionWriter(@Nonnull final FutureJVppCore futureJVppCore,
- @Nonnull final VppClassifierContextManager classifyTableContext) {
+ @Nonnull final VppClassifierContextManager classifyTableContext,
+ @Nonnull final NamingContext policerContext) {
super(futureJVppCore);
this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+ this.policerContext = checkNotNull(policerContext, "policerContext should not be null");
}
@Override
@@ -109,19 +115,34 @@ public class ClassifySessionWriter extends VppNodeWriter
final ClassifyTable classifyTable =
getClassifyTable(writeContext, id.firstIdentifierOf(ClassifyTable.class), isAdd);
- final int hitNextIndex = getNodeIndex(((Standard)classifySession.getNextNode()).getHitNext(),
- classifyTable, classifyTableContext,
- writeContext.getMappingContext(), id);
- final int opaqueIndex =
- getOpaqueIndex(((Standard)classifySession.getNextNode()).getOpaqueIndex(), classifyTable, writeContext.getMappingContext(), id);
-
+ final ClassifyAddDelSession request = getClassifyAddDelSessionRequest(isAdd, classifySession, tableIndex);
+
+ // TODO(HC2VPP-9): registry of next_node translators would allow to weaken dependency between policer
+ // and vpp-classifier models
+ final NextNode nextNode = classifySession.getNextNode();
+ if (nextNode instanceof Standard) {
+ translateNode(request, id, (Standard)nextNode, classifyTable, writeContext.getMappingContext());
+ } else if (nextNode instanceof Policer) {
+ translateNode(request, (Policer)nextNode, writeContext.getMappingContext());
+ }
final CompletionStage<ClassifyAddDelSessionReply> createClassifyTableReplyCompletionStage = getFutureJVpp()
- .classifyAddDelSession(
- getClassifyAddDelSessionRequest(isAdd, classifySession, tableIndex, hitNextIndex, opaqueIndex));
+ .classifyAddDelSession(request);
getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id);
}
+ private void translateNode(final ClassifyAddDelSession request, final InstanceIdentifier<ClassifySession> id,
+ final Standard nextNode, final ClassifyTable classifyTable, final MappingContext ctx)
+ throws VppBaseCallException, WriteFailedException {
+ request.hitNextIndex = getNodeIndex(nextNode.getHitNext(), classifyTable, classifyTableContext, ctx, id);
+ request.opaqueIndex = getOpaqueIndex(nextNode.getOpaqueIndex(), classifyTable, ctx, id);
+ }
+
+ private void translateNode(final ClassifyAddDelSession request, final Policer policer, final MappingContext ctx) {
+ request.hitNextIndex = policerContext.getIndex(policer.getPolicerHitNext(), ctx);
+ request.opaqueIndex = policer.getColorClassfier().getIntValue();
+ }
+
private ClassifyTable getClassifyTable(final WriteContext writeContext,
@Nonnull final InstanceIdentifier<ClassifyTable> id,
final boolean isAdd) {
@@ -136,14 +157,10 @@ public class ClassifySessionWriter extends VppNodeWriter
private ClassifyAddDelSession getClassifyAddDelSessionRequest(final boolean isAdd,
@Nonnull final ClassifySession classifySession,
- final int tableIndex,
- final int hitNextIndex,
- final int opaqueIndex) {
+ final int tableIndex) {
ClassifyAddDelSession request = new ClassifyAddDelSession();
request.isAdd = booleanToByte(isAdd);
request.tableIndex = tableIndex;
- request.hitNextIndex = hitNextIndex;
- request.opaqueIndex = opaqueIndex;
// default 0:
request.advance = classifySession.getAdvance();
diff --git a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java
index abc3901b6..31d7ad7f7 100644
--- a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java
+++ b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
import com.google.common.base.Optional;
import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
import io.fd.honeycomb.translate.write.WriteFailedException;
import io.fd.vpp.jvpp.VppBaseCallException;
@@ -91,7 +92,7 @@ public class ClassifySessionWriterTest extends WriterCustomizerTest {
@Override
public void setUpTest() throws Exception {
- customizer = new ClassifySessionWriter(api, classfierContext);
+ customizer = new ClassifySessionWriter(api, classfierContext, new NamingContext("policer-", "policer-context-"));
when(classfierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
when(classfierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
diff --git a/vpp-integration/minimal-distribution/pom.xml b/vpp-integration/minimal-distribution/pom.xml
index 1e73862c6..3bfa03039 100644
--- a/vpp-integration/minimal-distribution/pom.xml
+++ b/vpp-integration/minimal-distribution/pom.xml
@@ -60,6 +60,7 @@
io.fd.hc2vpp.routing.RoutingModule,
io.fd.hc2vpp.acl.AclModule,
io.fd.hc2vpp.dhcp.DhcpModule,
+ io.fd.hc2vpp.policer.PolicerModule,
// io.fd.hc2vpp.vppnsh.impl.VppNshModule,
<!-- Nsh module by default disabled, because it needs vpp-nsh plugin, which is not part of vpp codebase.-->
// io.fd.hc2vpp.vppioam.impl.VppIoamModule