From 5003049edb722ad7c415981fa2c85c17ba876264 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Mon, 13 Aug 2018 11:56:17 +0200 Subject: Check length of classify session's match vector (HC2VPP-373) Change-Id: I45028349f81a756d03d46e02af40041a7cae1fec Signed-off-by: Marek Gradzki --- .../classifier/write/ClassifySessionWriter.java | 14 +++++++--- .../vpp/classifier/write/ClassifyTableWriter.java | 6 ++--- .../vpp/classifier/write/ClassifyWriter.java | 26 +++++++++++++++++++ .../write/ClassifySessionWriterTest.java | 30 ++++++++++++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyWriter.java 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 1e56afb5f..7a62e4a74 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 @@ -16,6 +16,7 @@ package io.fd.hc2vpp.vpp.classifier.write; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Optional; @@ -35,7 +36,6 @@ import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.concurrent.CompletionStage; 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.rev170327.OpaqueIndex; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev170327.classify.session.attributes.NextNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev170327.classify.session.attributes.next_node.Policer; @@ -53,7 +53,8 @@ import org.slf4j.LoggerFactory; * to VPP.
Equivalent to invoking {@code vppctl classify table} command. */ public class ClassifySessionWriter extends VppNodeWriter - implements ListWriterCustomizer, ByteDataTranslator, JvppReplyConsumer { + implements ListWriterCustomizer, ByteDataTranslator, ClassifyWriter, + JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionWriter.class); private final VppClassifierContextManager classifyTableContext; @@ -127,6 +128,13 @@ public class ClassifySessionWriter extends VppNodeWriter final CompletionStage createClassifyTableReplyCompletionStage = getFutureJVpp() .classifyAddDelSession(request); + // VPP requires to prepend classify session with skip_n_vectors*16 bytes: + final long expectedMatchLen = + 16 * classifyTable.getSkipNVectors() + getBinaryVector(classifyTable.getMask()).length; + final long actualMatchLen = Integer.toUnsignedLong(request.matchLen); + checkArgument(actualMatchLen == expectedMatchLen, + "Match length should be equal to table.skipNVectors*16 + table.mask length (" + + expectedMatchLen + ") but was: " + actualMatchLen); getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id); } @@ -168,7 +176,7 @@ public class ClassifySessionWriter extends VppNodeWriter // default 0: request.advance = classifySession.getAdvance(); - request.match = DatatypeConverter.parseHexBinary(classifySession.getMatch().getValue().replace(":", "")); + request.match = getBinaryVector(classifySession.getMatch()); request.matchLen = request.match.length; return request; } diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java index 8e72df46a..a80d23a5c 100644 --- a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java +++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java @@ -33,7 +33,6 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; -import javax.xml.bind.DatatypeConverter; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTable; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTableKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -45,7 +44,8 @@ import org.slf4j.LoggerFactory; * VPP.
Equivalent to invoking {@code vppctl classify table} command. */ public class ClassifyTableWriter extends VppNodeWriter - implements ListWriterCustomizer, ByteDataTranslator, JvppReplyConsumer { + implements ListWriterCustomizer, ByteDataTranslator, ClassifyWriter, + JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableWriter.class); private final VppClassifierContextManager classifyTableContext; @@ -144,7 +144,7 @@ public class ClassifyTableWriter extends VppNodeWriter } else { request.nextTableIndex = ~0; // value not specified } - request.mask = DatatypeConverter.parseHexBinary(table.getMask().getValue().replace(":", "")); + request.mask = getBinaryVector(table.getMask()); request.maskLen = request.mask.length; checkArgument(request.mask.length % 16 == 0, "Number of mask bytes must be multiple of 16."); request.matchNVectors = request.mask.length / 16; diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyWriter.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyWriter.java new file mode 100644 index 000000000..8eded739d --- /dev/null +++ b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyWriter.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 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.vpp.classifier.write; + +import javax.xml.bind.DatatypeConverter; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; + +interface ClassifyWriter { + default byte[] getBinaryVector(final HexString hexString) { + return DatatypeConverter.parseHexBinary(hexString.getValue().replace(":", "")); + } +} 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 ccb02708e..68d20a728 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 @@ -99,6 +99,8 @@ public class ClassifySessionWriterTest extends WriterCustomizerTest { when(classfierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX); final ClassifyTable table = mock(ClassifyTable.class); + when(table.getMask()).thenReturn(new HexString("00:00:00:00:00:00:ff:FF:ff:ff:ff:FF:00:00:00:00")); + when(table.getSkipNVectors()).thenReturn(0L); when(table.getClassifierNode()).thenReturn(new VppNodeName("ip4-classifier")); when(writeContext.readAfter(ArgumentMatchers.any())).thenReturn(Optional.of(table)); when(writeContext.readBefore(ArgumentMatchers.any())).thenReturn(Optional.of(table)); @@ -190,4 +192,32 @@ public class ClassifySessionWriterTest extends WriterCustomizerTest { final InstanceIdentifier id = getClassifySessionId(TABLE_NAME, match); customizer.writeCurrentAttributes(id, classifySession, writeContext); } + + @Test(expected = IllegalArgumentException.class) + public void testCreateInvalidMatchLength() throws WriteFailedException { + final ClassifyTable table = mock(ClassifyTable.class); + when(table.getMask()).thenReturn(new HexString("00:00:00:00:00:00:ff:FF:ff:ff:ff:FF:00:00:00:00")); + when(table.getSkipNVectors()).thenReturn(1L); + when(writeContext.readAfter(ArgumentMatchers.any())).thenReturn(Optional.of(table)); + + final String match = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"; + final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match); + final InstanceIdentifier id = getClassifySessionId(TABLE_NAME, match); + customizer.writeCurrentAttributes(id, classifySession, writeContext); + } + + @Test + public void testCreateSkipOneVector() throws WriteFailedException { + final ClassifyTable table = mock(ClassifyTable.class); + when(table.getMask()).thenReturn(new HexString("00:00:00:00:00:00:ff:FF:ff:ff:ff:FF:00:00:00:00")); + when(table.getSkipNVectors()).thenReturn(1L); + when(writeContext.readAfter(ArgumentMatchers.any())).thenReturn(Optional.of(table)); + whenClassifyAddDelSessionThenSuccess(); + + final String match = + "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"; + final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match); + final InstanceIdentifier id = getClassifySessionId(TABLE_NAME, match); + customizer.writeCurrentAttributes(id, classifySession, writeContext); + } } \ No newline at end of file -- cgit 1.2.3-korg