Check length of classify session's match vector (HC2VPP-373) 68/14168/1
authorMarek Gradzki <mgradzki@cisco.com>
Mon, 13 Aug 2018 09:56:17 +0000 (11:56 +0200)
committerMarek Gradzki <mgradzki@cisco.com>
Mon, 13 Aug 2018 10:41:49 +0000 (12:41 +0200)
Change-Id: I45028349f81a756d03d46e02af40041a7cae1fec
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyWriter.java [new file with mode: 0644]
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java

index 1e56afb..7a62e4a 100644 (file)
@@ -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.<br> Equivalent to invoking {@code vppctl classify table} command.
  */
 public class ClassifySessionWriter extends VppNodeWriter
-        implements ListWriterCustomizer<ClassifySession, ClassifySessionKey>, ByteDataTranslator, JvppReplyConsumer {
+    implements ListWriterCustomizer<ClassifySession, ClassifySessionKey>, 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<ClassifyAddDelSessionReply> 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;
     }
index 8e72df4..a80d23a 100644 (file)
@@ -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.<br> Equivalent to invoking {@code vppctl classify table} command.
  */
 public class ClassifyTableWriter extends VppNodeWriter
-        implements ListWriterCustomizer<ClassifyTable, ClassifyTableKey>, ByteDataTranslator, JvppReplyConsumer {
+    implements ListWriterCustomizer<ClassifyTable, ClassifyTableKey>, 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 (file)
index 0000000..8eded73
--- /dev/null
@@ -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(":", ""));
+    }
+}
index ccb0270..68d20a7 100644 (file)
@@ -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<ClassifySession> 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<ClassifySession> 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<ClassifySession> id = getClassifySessionId(TABLE_NAME, match);
+        customizer.writeCurrentAttributes(id, classifySession, writeContext);
+    }
 }
\ No newline at end of file