mbeckerle commented on a change in pull request #643:
URL: https://github.com/apache/daffodil/pull/643#discussion_r715812946



##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/layers/AISTransformer.scala
##########
@@ -77,6 +78,11 @@ class AISPayloadArmoringTransformer()
     val newJOS = new LayerBoundaryMarkInsertingJavaOutputStream(jos, 
layerBoundaryMark, iso8859)
     newJOS
   }
+
+  def startLayerForParse(s: PState): Unit = () // do nothing

Review comment:
       These should all have "override" keyword on them. 
   
   I believe so far we have only needed the start flavor for parse, and the end 
flavor for unparse, so end for parse, and start for unparse could be removed. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/layers/LayerTransformer.scala
##########
@@ -200,6 +214,54 @@ abstract class LayerTransformer()
   //    println("DIS hex dump = " + str)
   //    ???
   //  }

Review comment:
       Remove commented out code if no longer needed. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/layers/IPv4Checksum.scala
##########
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.daffodil.layers
+
+import org.apache.commons.io.IOUtils
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.processors.LayerLengthInBytesEv
+import org.apache.daffodil.processors.LayerBoundaryMarkEv
+import org.apache.daffodil.processors.LayerCharsetEv
+import org.apache.daffodil.processors.parsers.PState
+import org.apache.daffodil.processors.unparsers.UState
+
+import java.io._
+import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.RetryableException
+import org.apache.daffodil.io.DataInputStream
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.SuspendableOperation
+import org.apache.daffodil.util.ByteBufferOutputStream
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.xml.NS
+import org.apache.daffodil.xml.RefQName
+import passera.unsigned.UShort
+
+import java.nio.ByteBuffer
+import java.nio.ShortBuffer
+
+/**
+      The first layer transform, aka 'part1' computes the partial

Review comment:
       Investigate if this can be simplified to just one layer, instead of two. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
##########
@@ -74,6 +76,14 @@ abstract class UState(
   extends ParseOrUnparseState(vbox, diagnosticsArg, dataProcArg, tunable)
   with Cursor[InfosetAccessor] with ThrowsSDE with SavesErrorsAndWarnings {
 
+  final def setVariable(vrd: VariableRuntimeData, newValue: 
DataValuePrimitive, referringContext: ThrowsSDE) =
+    vbox.vmap.setVariable(vrd, newValue, referringContext, this)
+
+  final def getVariable(vrd: VariableRuntimeData, referringContext: 
ThrowsSDE): DataValuePrimitive =

Review comment:
       Add scaladoc explaining throw of RetryableException if the variable 
can't "yet" be read within a suspendableOperation. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/layers/IPv4Checksum.scala
##########
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.daffodil.layers
+
+import org.apache.commons.io.IOUtils
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.processors.LayerLengthInBytesEv
+import org.apache.daffodil.processors.LayerBoundaryMarkEv
+import org.apache.daffodil.processors.LayerCharsetEv
+import org.apache.daffodil.processors.parsers.PState
+import org.apache.daffodil.processors.unparsers.UState
+
+import java.io._
+import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.RetryableException
+import org.apache.daffodil.io.DataInputStream
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.SuspendableOperation
+import org.apache.daffodil.util.ByteBufferOutputStream
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.xml.NS
+import org.apache.daffodil.xml.RefQName
+import passera.unsigned.UShort
+
+import java.nio.ByteBuffer
+import java.nio.ShortBuffer
+
+/**
+      The first layer transform, aka 'part1' computes the partial
+      checksum of the first part of the data, per the checksum algorithm 
described
+      in IETF RFC791.
+
+      The data has a well-known fixed layer length. Hence, layerLengthKind is 
'implicit'.
+
+      (TBD: if the data doesn't match this expected fixed length, issue PE/UE)
+
+      This partial checksum is written into the result variable for part 1, as 
a
+      means of communicating it to the second layer transform for the 
remainder of the
+      data.
+
+      This 2-part computation is necessary because in IPv4 packets, the 
checksum
+      value actually lives in the middle of the data contributing to the 
checksum value.
+      That requires the split for unparsing, because the checksum value living 
between
+      parts 1 and 2 must be computed with a result from part 2, which 
computation depends
+      part 1's output variable. So the unparsing must first unparse part 1, 
(this can suspend
+      as it could have forward reference outputValueCalc elements). So the 
unparsing
+      does it's splitting thing, and then unparses the checksum element, which 
WILL
+      suspend, then unparse part 2, which also could suspend if it has OVC 
elements.
+
+      Eventually when part 1 is unblocked and completes, and assigns its output
+      variable, then part 2 can unblock and complete and assign its output 
variable,
+      and then the checksum value field can unblock, and at that point it all
+      can serialize to the output stream.
+ */
+
+final class IPv4Checksum private(srd: SequenceRuntimeData)
+extends Serializable {
+
+  private def ipHdrPart1LengthInBytes = 10
+
+  private def ipHdrPart2LengthInBytes = 8
+
+  private def varNamespace = NS("urn:org.apache.daffodil.layers.ipv4checksum")
+
+  private def part1ChecksumVarQName = RefQName(Some("chksum"), 
"ipV4ChecksumPart1Value", varNamespace).toGlobalQName
+
+  private def finalChecksumVarQName = RefQName(Some("chksum"), 
"ipV4ChecksumValue", varNamespace).toGlobalQName
+
+  private val part1ChecksumVRD = 
srd.variableMap.getVariableRuntimeData(part1ChecksumVarQName).getOrElse {
+    srd.SDE("Variable '%s' is not defined.", 
part1ChecksumVarQName.toExtendedSyntax)
+  }
+  srd.schemaDefinitionUnless(part1ChecksumVRD.primType == 
PrimType.UnsignedShort,
+    "Variable '%s' is not of type 'xs:unsignedShort.", 
part1ChecksumVarQName.toExtendedSyntax)
+  private val finalChecksumVRD = 
srd.variableMap.getVariableRuntimeData(finalChecksumVarQName).getOrElse {
+    srd.SDE("Variable '%s' is not defined.", 
finalChecksumVarQName.toExtendedSyntax)
+  }
+  srd.schemaDefinitionUnless(finalChecksumVRD.primType == 
PrimType.UnsignedShort,
+    "Variable '%s' is not of type 'xs:unsignedShort'.", 
part1ChecksumVarQName.toExtendedSyntax)
+
+  /**
+   * Common code used for part1 and part2.
+   * @param state The parser state
+   * @param optOriginalStream The original InputStream that this layer lives 
on top of.
+   * @param partByteArray An array of bytes sized to hold the bytes of the part
+   * @param shortBuf A ShortBuffer pre-set to use the partByteArray as source 
of Short values in network byte
+   *                 order (aka 'bigEndian')
+   * @param partLengthInBytes Length of the partByteArray (which is the part 
length)
+   * @param initialChecksumValue Starting value for computation of this 
checksum, that is, an
+   *                             earlier partial checksum, or 0 if no previous.
+   * @return The checksum value for this part as an Int (32 bits). The 
checksum is a 16-bit
+   *         quantity, but the addition can produce carries that occupy more 
than 16 bits.
+   *         This return value has not yet added in any overflow bits from the 
most-significant 16-bits
+   *         into the least-significant 16-bits.
+   */
+  private def startShared(
+    state: ParseOrUnparseState,
+    optOriginalStream: Maybe[InputStream],
+    partByteArray: Array[Byte],
+    shortBuf: ShortBuffer,
+    partLengthInBytes: Int,
+    initialChecksumValue: Int): Int = {
+    //
+    // For parsing, all the hard work happens here, allowing the layered input 
stream to
+    // just deliver the bytes
+    //
+    Assert.invariant(state.bitPos0b % 8 == 0) // we are byte aligned.
+    Assert.invariant(optOriginalStream.isDefined)
+    val bitLen = partLengthInBytes * 8
+
+    try
+      IOUtils.readFully(optOriginalStream.get, partByteArray)
+    catch {
+      case eof: EOFException =>
+        throw DataInputStream.NotEnoughDataException(bitLen)
+    }
+    computeChecksum(initialChecksumValue, shortBuf, partLengthInBytes)
+  }
+
+  private def computeChecksum(initialChecksumValue: Int, shortBuf: 
ShortBuffer, partLengthInBytes: Int): Int = {
+    var i = 0
+    var partChecksum: Int = initialChecksumValue
+    val partNShorts = partLengthInBytes / 2
+    while (i < partNShorts) {
+      partChecksum += UShort(shortBuf.get(i)).toInt
+      Assert.invariant(partChecksum >= 0)
+      i += 1
+    }
+    //
+    // now combine the carry bits in the most significant 16 bits into the 
lower 16 bits.
+    //
+    val checksumLow = partChecksum & 0xFFFF
+    val checksumHigh = partChecksum >>> 16
+    val checksumTotal: Int = checksumLow + checksumHigh
+    Assert.invariant(checksumTotal <= 0xFFFF && checksumTotal >= 0)
+    val checksumTotalShort = UShort(checksumTotal.toShort)
+
+    checksumTotalShort.toInt
+  }
+
+  object Part1 { def apply() = new Part1() }
+
+  final class Part1 private ()
+    extends LayerTransformer() {
+
+    private val hdrPart1ByteArr = new Array[Byte](ipHdrPart1LengthInBytes)
+
+    private var optOriginalInputStream: Maybe[InputStream] = Maybe.Nope
+
+    private val part1LimitingInputStream = new 
ByteArrayInputStream(hdrPart1ByteArr)
+
+    private val byteBuf = ByteBuffer.wrap(hdrPart1ByteArr) // default is 
bigEndian byte order
+    private val shortBuf = byteBuf.asShortBuffer()
+
+    override def startLayerForParse(s: PState): Unit = {
+      val part1Checksum: Int =
+        startShared(state = s,
+          optOriginalStream = optOriginalInputStream,
+          partByteArray = hdrPart1ByteArr,
+          shortBuf = shortBuf,
+          partLengthInBytes = ipHdrPart1LengthInBytes,
+          initialChecksumValue = 0)
+      s.setVariable(part1ChecksumVRD, part1Checksum, srd) // assign to the 
result variable.
+    }
+
+    override def endLayerForParse(s: PState): Unit = () // do nothing.
+
+    override def wrapLayerDecoder(jis: java.io.InputStream) = jis // no 
decoding. Just pass through the input stream
+
+    override def wrapLimitingStream(jis: java.io.InputStream, state: PState) = 
{
+      Assert.invariant(optOriginalInputStream.isEmpty)
+      // capture the original stream for use by the startLayerForParse method.
+      optOriginalInputStream = One(jis)
+      part1LimitingInputStream
+    }
+
+    private var optOriginalOutputStream: Maybe[OutputStream] = Maybe.Nope
+
+    private val part1LimitingOutputStream = new ByteBufferOutputStream(byteBuf)
+
+
+    final class SuspendablePart1UnparserOperation()
+      extends SuspendableOperation {
+      override def rd = srd
+
+      /**
+       * Test succeeds if all the data required has been written to the layer
+       * stream.
+       */
+      protected def test(ustate: UState) = {
+        part1LimitingOutputStream.size() == ipHdrPart1LengthInBytes
+      }
+
+      /**
+       * Computes part 1 checksum and assigns part 1 variable, then
+       * writes the layer data to the original output stream.
+       */
+      protected def continuation(ustate: UState): Unit = {
+        Assert.invariant(optOriginalOutputStream.isDefined)
+        val part1Checksum = computeChecksum(0, shortBuf, 
ipHdrPart1LengthInBytes)
+        ustate.setVariable(part1ChecksumVRD, part1Checksum, srd) // assign to 
the result variable.
+        optOriginalOutputStream.get.write(hdrPart1ByteArr)
+        optOriginalOutputStream.get.close()
+      }
+    }
+
+    override def startLayerForUnparse(s: UState): Unit = () // do nothing
+
+    private lazy val suspendableOperation =
+      new SuspendablePart1UnparserOperation()
+
+    override def endLayerForUnparse(s: UState): Unit = {
+      suspendableOperation.run(s)
+    }
+
+    override protected def wrapLayerEncoder(jos: OutputStream): OutputStream = 
jos
+
+    override protected def wrapLimitingStream(jos: OutputStream, state: 
UState): OutputStream = {
+      optOriginalOutputStream = One(jos)
+      part1LimitingOutputStream
+    }
+  }
+
+
+
+  object Part2 { def apply() = new Part2() }
+
+  final class Part2 private ()
+    extends LayerTransformer() {
+
+    private var optOriginalInputStream: Maybe[InputStream] = Maybe.Nope
+
+    private val hdrPart2ByteArr = new Array[Byte](ipHdrPart2LengthInBytes)
+
+    private val part2LimitingInputStream = new 
ByteArrayInputStream(hdrPart2ByteArr)
+
+    private val byteBuf =  ByteBuffer.wrap(hdrPart2ByteArr) // bigEndian byte 
order by default
+    private val shortBuf = byteBuf.asShortBuffer()
+
+    override def startLayerForParse(s: PState): Unit = {
+      val partialChecksumFromPart1 = UShort(s.getVariable(part1ChecksumVRD, 
srd).getInt.toShort).toInt
+      val checksum: Int =
+        startShared(
+          state = s,
+          optOriginalStream = optOriginalInputStream,
+          partByteArray = hdrPart2ByteArr,
+          shortBuf = shortBuf,
+          partLengthInBytes = ipHdrPart2LengthInBytes,
+          initialChecksumValue = partialChecksumFromPart1)
+      //
+      // take ones complement to get the final checksum
+      //
+      val finalChecksum: Int = (~checksum) & 0xFFFF
+      s.setVariable(finalChecksumVRD, finalChecksum, srd) // assign to result 
variable.
+    }
+
+    override def endLayerForParse(s: PState): Unit = () // do nothing
+
+    protected def wrapLayerDecoder(jis: InputStream) = jis
+
+    protected def wrapLimitingStream(jis: InputStream, state: PState) = {
+      optOriginalInputStream = One(jis)
+      part2LimitingInputStream
+    }
+
+    final class SuspendablePart2UnparserOperation()
+      extends SuspendableOperation {
+      override def rd = srd
+
+      /**
+       * Test succeeds if all the data required has been written to the layer
+       * AND the variable coming from part1 has its value.
+       */
+      protected def test(ustate: UState) = {
+        val areBytesWritten = part2LimitingOutputStream.size() == 
ipHdrPart2LengthInBytes
+        lazy val isIncomingPart1VariableWritten =
+          try {
+            ustate.getVariable(part1ChecksumVRD, srd)
+            true
+          } catch {
+            case r: RetryableException => false
+          }
+        val res = areBytesWritten && isIncomingPart1VariableWritten
+        res
+      }
+
+      /**
+       * Computes part 1 checksum and assigns part 1 variable, then
+       * writes the layer data to the original output stream.
+       */
+      protected def continuation(ustate: UState): Unit = {
+        Assert.invariant(optOriginalOutputStream.isDefined)
+        val part1Checksum = ustate.getVariable(part1ChecksumVRD, srd).getInt
+        val checksum = computeChecksum(part1Checksum, shortBuf, 
ipHdrPart2LengthInBytes)
+        //
+        // take ones complement to get the final checksum
+        //
+        val finalChecksum: Int = (~checksum) & 0xFFFF
+        ustate.setVariable(finalChecksumVRD, finalChecksum, srd) // assign to 
the result variable.
+        optOriginalOutputStream.get.write(hdrPart2ByteArr)
+        optOriginalOutputStream.get.close()
+      }
+    }
+
+    private var optOriginalOutputStream: Maybe[OutputStream] = Maybe.Nope
+
+    private val part2LimitingOutputStream = new ByteBufferOutputStream(byteBuf)
+
+    override def startLayerForUnparse(s: UState): Unit = () // do nothing
+
+    private lazy val suspendableOperation =
+      new SuspendablePart2UnparserOperation()
+
+    override def endLayerForUnparse(s: UState): Unit = {
+      suspendableOperation.run(s)
+    }
+
+    protected def wrapLayerEncoder(jos: OutputStream) = jos
+
+    protected def wrapLimitingStream(jos: OutputStream, state: UState) = {
+      optOriginalOutputStream = One(jos)
+      part2LimitingOutputStream
+    }
+  }
+}
+
+  object IPv4Checksum {
+
+    def apply(srd: SequenceRuntimeData) = new IPv4Checksum(srd)
+
+    private def check(
+      maybeLayerCharsetEv: Maybe[LayerCharsetEv],
+      maybeLayerLengthKind: Maybe[LayerLengthKind],
+      maybeLayerLengthInBytesEv: Maybe[LayerLengthInBytesEv],
+      maybeLayerLengthUnits: Maybe[LayerLengthUnits],
+      maybeLayerBoundaryMarkEv: Maybe[LayerBoundaryMarkEv],
+      srd: SequenceRuntimeData): Unit = {
+      srd.schemaDefinitionUnless(maybeLayerLengthKind.isEmpty || 
maybeLayerLengthKind.get == LayerLengthKind.Implicit,
+        "Must have dfdlx:layerLengthKind undefined or 'implicit', but was 
'%s'.", maybeLayerLengthKind.get.toString)
+      //
+      // ToDo: We can't issue SDW because we don't have a context object

Review comment:
       Not fixing as part of this change. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/layers/IPv4Checksum.scala
##########
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.daffodil.layers
+
+import org.apache.commons.io.IOUtils
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.processors.LayerLengthInBytesEv
+import org.apache.daffodil.processors.LayerBoundaryMarkEv
+import org.apache.daffodil.processors.LayerCharsetEv
+import org.apache.daffodil.processors.parsers.PState
+import org.apache.daffodil.processors.unparsers.UState
+
+import java.io._
+import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.RetryableException
+import org.apache.daffodil.io.DataInputStream
+import org.apache.daffodil.processors.ParseOrUnparseState
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.SuspendableOperation
+import org.apache.daffodil.util.ByteBufferOutputStream
+import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.xml.NS
+import org.apache.daffodil.xml.RefQName
+import passera.unsigned.UShort
+
+import java.nio.ByteBuffer
+import java.nio.ShortBuffer
+
+/**
+      The first layer transform, aka 'part1' computes the partial
+      checksum of the first part of the data, per the checksum algorithm 
described
+      in IETF RFC791.
+
+      The data has a well-known fixed layer length. Hence, layerLengthKind is 
'implicit'.
+
+      (TBD: if the data doesn't match this expected fixed length, issue PE/UE)
+
+      This partial checksum is written into the result variable for part 1, as 
a
+      means of communicating it to the second layer transform for the 
remainder of the
+      data.
+
+      This 2-part computation is necessary because in IPv4 packets, the 
checksum
+      value actually lives in the middle of the data contributing to the 
checksum value.
+      That requires the split for unparsing, because the checksum value living 
between
+      parts 1 and 2 must be computed with a result from part 2, which 
computation depends
+      part 1's output variable. So the unparsing must first unparse part 1, 
(this can suspend
+      as it could have forward reference outputValueCalc elements). So the 
unparsing
+      does it's splitting thing, and then unparses the checksum element, which 
WILL
+      suspend, then unparse part 2, which also could suspend if it has OVC 
elements.
+
+      Eventually when part 1 is unblocked and completes, and assigns its output
+      variable, then part 2 can unblock and complete and assign its output 
variable,
+      and then the checksum value field can unblock, and at that point it all
+      can serialize to the output stream.
+ */
+
+final class IPv4Checksum private(srd: SequenceRuntimeData)
+extends Serializable {
+
+  private def ipHdrPart1LengthInBytes = 10
+
+  private def ipHdrPart2LengthInBytes = 8
+
+  private def varNamespace = NS("urn:org.apache.daffodil.layers.ipv4checksum")
+
+  private def part1ChecksumVarQName = RefQName(Some("chksum"), 
"ipV4ChecksumPart1Value", varNamespace).toGlobalQName
+
+  private def finalChecksumVarQName = RefQName(Some("chksum"), 
"ipV4ChecksumValue", varNamespace).toGlobalQName
+
+  private val part1ChecksumVRD = 
srd.variableMap.getVariableRuntimeData(part1ChecksumVarQName).getOrElse {
+    srd.SDE("Variable '%s' is not defined.", 
part1ChecksumVarQName.toExtendedSyntax)
+  }
+  srd.schemaDefinitionUnless(part1ChecksumVRD.primType == 
PrimType.UnsignedShort,
+    "Variable '%s' is not of type 'xs:unsignedShort.", 
part1ChecksumVarQName.toExtendedSyntax)
+  private val finalChecksumVRD = 
srd.variableMap.getVariableRuntimeData(finalChecksumVarQName).getOrElse {
+    srd.SDE("Variable '%s' is not defined.", 
finalChecksumVarQName.toExtendedSyntax)
+  }
+  srd.schemaDefinitionUnless(finalChecksumVRD.primType == 
PrimType.UnsignedShort,
+    "Variable '%s' is not of type 'xs:unsignedShort'.", 
part1ChecksumVarQName.toExtendedSyntax)
+
+  /**
+   * Common code used for part1 and part2.
+   * @param state The parser state
+   * @param optOriginalStream The original InputStream that this layer lives 
on top of.
+   * @param partByteArray An array of bytes sized to hold the bytes of the part
+   * @param shortBuf A ShortBuffer pre-set to use the partByteArray as source 
of Short values in network byte
+   *                 order (aka 'bigEndian')
+   * @param partLengthInBytes Length of the partByteArray (which is the part 
length)
+   * @param initialChecksumValue Starting value for computation of this 
checksum, that is, an
+   *                             earlier partial checksum, or 0 if no previous.
+   * @return The checksum value for this part as an Int (32 bits). The 
checksum is a 16-bit
+   *         quantity, but the addition can produce carries that occupy more 
than 16 bits.
+   *         This return value has not yet added in any overflow bits from the 
most-significant 16-bits
+   *         into the least-significant 16-bits.
+   */
+  private def startShared(
+    state: ParseOrUnparseState,
+    optOriginalStream: Maybe[InputStream],
+    partByteArray: Array[Byte],
+    shortBuf: ShortBuffer,
+    partLengthInBytes: Int,
+    initialChecksumValue: Int): Int = {
+    //
+    // For parsing, all the hard work happens here, allowing the layered input 
stream to
+    // just deliver the bytes
+    //
+    Assert.invariant(state.bitPos0b % 8 == 0) // we are byte aligned.
+    Assert.invariant(optOriginalStream.isDefined)
+    val bitLen = partLengthInBytes * 8
+
+    try
+      IOUtils.readFully(optOriginalStream.get, partByteArray)
+    catch {
+      case eof: EOFException =>
+        throw DataInputStream.NotEnoughDataException(bitLen)
+    }
+    computeChecksum(initialChecksumValue, shortBuf, partLengthInBytes)
+  }
+
+  private def computeChecksum(initialChecksumValue: Int, shortBuf: 
ShortBuffer, partLengthInBytes: Int): Int = {
+    var i = 0
+    var partChecksum: Int = initialChecksumValue
+    val partNShorts = partLengthInBytes / 2
+    while (i < partNShorts) {
+      partChecksum += UShort(shortBuf.get(i)).toInt
+      Assert.invariant(partChecksum >= 0)
+      i += 1
+    }
+    //
+    // now combine the carry bits in the most significant 16 bits into the 
lower 16 bits.
+    //
+    val checksumLow = partChecksum & 0xFFFF
+    val checksumHigh = partChecksum >>> 16
+    val checksumTotal: Int = checksumLow + checksumHigh
+    Assert.invariant(checksumTotal <= 0xFFFF && checksumTotal >= 0)
+    val checksumTotalShort = UShort(checksumTotal.toShort)
+
+    checksumTotalShort.toInt
+  }
+
+  object Part1 { def apply() = new Part1() }
+
+  final class Part1 private ()
+    extends LayerTransformer() {
+
+    private val hdrPart1ByteArr = new Array[Byte](ipHdrPart1LengthInBytes)

Review comment:
       Add scaladoc explaining these members as their roles and the 
relationship between them is subtle. 

##########
File path: 
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/EvLayering.scala
##########
@@ -89,13 +100,7 @@ final class LayerTransformerEv(
   override def compute(state: State): LayerTransformer = {
     val layerTransform = layerTransformEv.evaluate(state)
     val factory = LayerTransformerFactory.find(layerTransform, state)
-    val xformer = factory.newInstance(
-      maybeLayerCharsetEv,
-      maybeLayerLengthKind,
-      maybeLayerLengthInBytesEv,
-      maybeLayerLengthUnits,
-      maybeLayerBoundaryMarkEv,
-      ci)
+    val xformer = factory.newInstance(maybeLayerCharsetEv, 
maybeLayerLengthKind, maybeLayerLengthInBytesEv, maybeLayerLengthUnits, 
maybeLayerBoundaryMarkEv, srd)

Review comment:
       too long line. 

##########
File path: daffodil-test/src/test/resources/org/apache/daffodil/layers/ais.tdml
##########
@@ -38,6 +38,9 @@ required to pad the data payload to a 6-bit boundary. So it 
is 0 to 5.
 The *5C is a NMEA 0183 data integrity checksum, preceded by "*" - computed on 
 the whole message including the AIVDM, but excluding the "!"
 
+According to the wikipedia article on NMEA 0183, this checksum is just an XOR 
of the
+specific message bytes.
+
 Seems another role for layers is computing checksums.

Review comment:
       Park a JIRA ticket for updating this AIS layer to implement the 
checksum. 
   
   Fix comment: remove word "Seems". 

##########
File path: 
daffodil-test/src/test/resources/org/apache/daffodil/layers/ipv4.dfdl.xsd
##########
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!--
+Copyright (c) 2012-2021 Owl Cyber Defense. All rights reserved.
+
+Developed by: Owl Cyber Defense
+              http://www.owlcyberdefense.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimers.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimers in the
+    documentation and/or other materials provided with the distribution.
+
+ 3. Neither the names of Owl Cyber Defense, nor the names of its contributors
+    may be used to endorse or promote products derived from this Software
+    without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions";
+           xmlns:fn="http://www.w3.org/2005/xpath-functions";
+           xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+           xmlns:chksum="urn:org.apache.daffodil.layers.ipv4checksum"
+           xmlns:eth="urn:ethernet"
+           xmlns:tns="urn:ethernet"
+           targetNamespace="urn:ethernet">
+
+  <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+  <xs:import namespace="urn:org.apache.daffodil.layers.ipv4checksum"
+             
schemaLocation="org/apache/daffodil/layers/xsd/ipv4checksumLayer.dfdl.xsd"/>
+
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/";>
+      <dfdl:defineFormat name="basicBigEndianBinary">
+        <dfdl:format
+          ref="tns:GeneralFormat"
+          representation="binary"
+          binaryNumberRep="binary"
+          byteOrder="bigEndian"
+          bitOrder="mostSignificantBitFirst"
+          alignmentUnits="bits"
+          alignment="1"
+          occursCountKind="implicit"/>
+      </dfdl:defineFormat>
+      <dfdl:format ref="tns:basicBigEndianBinary"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:element name="IPv4Header" type="tns:IPv4Header"/>
+
+  <xs:complexType name="IPv4Header">
+    <!--
+    Modified with proposed checksum computation via layer transforms
+
+    The xmlns:checksum prefix declaration would probably go on the xs:schema 
element more normally.
+    It is just here to show all the required things in this one location of 
the file.
+    -->
+    <xs:sequence>
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+          <!--
+          The checksum field in an ipV4 actually lives in the middle of the
+          data that it is a checksum of.
+
+          That is, some of the 16-bit words going into the checksum are before
+          the checksum itself. We call this "Part 1" of the data.
+
+          Other of the 16-bit words going into the checksum appear after the
+          checksum itself. We call this "Part 2" of the data.
+
+          So there are two layer transform calculations corresponding to
+          these two parts. This is required for unparsing, as detailed below.
+
+          For parsing: the first part computes the partial checksum of
+          the first data part and places that into the checksumPart1Value
+          variable.
+
+          Then the second part combines that part1 value from the variable with
+          the remaining checksum from the part 2 data, and places the final
+          result into the checksumValue variable.
+
+          At parse time we must check that this computed checksum value, and 
the
+          actual value of the element in the infoset are equal.
+
+          We have an option to place the computed checksum in another element
+          and then have a schematron validation rule or just a DFDL assert 
(recoverable)
+          check that the checksum element and computed checksum are equal.
+
+          Below, that element is called "ComputedChecksum".
+
+          When Unparsing, the first part transform computes the partial 
checksum of
+          the part 1 data, placing the result of that into the 
checksumPart1Value
+          just as when parsing. This doesn't suspend itself. It just
+          waits until all bytes of the first part of the header are written. 
That
+          itself can involve all sorts of suspensions though, as the header 
fields in this
+          part contain the length of the IP packet data, which likely involves 
a forward
+          reference to the dfdl:valueLength of the payload.
+
+          The second part transform computes the final checksum combining the 
checksumPart1Value
+          variable with the checksum computed from the part 2 data, placing 
the result into
+          checksumValue variable. This suspends if the checksumPart1Value 
variable is not
+          yet available, and also requires that all bytes of the layer itself 
have been written.
+
+          A dfdl:outputValueCalc puts this newly computed value from the 
variable into the checksum element.
+          Any prior value of the checksum element is discarded/overwritten 
with the new value.
+
+          -->
+          <dfdl:newVariableInstance ref="chksum:ipV4ChecksumPart1Value"/>
+          <dfdl:newVariableInstance ref="chksum:ipV4ChecksumValue"/>
+        </xs:appinfo>
+      </xs:annotation>
+
+      <xs:sequence dfdl:ref="chksum:ipv4ChecksumLayerPart1">
+        <xs:sequence>
+        <!--
+        Within this sequence, the data is all included in Part 1 of the
+        ipV4 checksum calculation
+
+        On parsing, the checksum algorithm computes the partial checksum for
+        this first part of the data, placing the value into the
+        variable chksum:checksumPart1Value, which must have a new variable
+        instance in scope.
+
+        This checksum calculation knows exactly how big this data must be
+        and if the representation turned out to be a different length than 
this, it
+        will be a runtime SDE.
+
+        Everything from here to the end of this sequence is unmodified from
+        the original IPV4 schema it is based on.
+        -->
+        <xs:element name="Version" type="tns:bit" dfdl:length="4"/>
+        <xs:element name="IHL" type="tns:bit" dfdl:length="4"/>
+        <xs:element name="DSCP" type="tns:bit" dfdl:length="6"/>
+        <xs:element name="ECN" type="tns:bit" dfdl:length="2"/>
+        <xs:element name="Length" type="tns:bit" dfdl:length="16"/>

Review comment:
       Enhance this schema so that length depends on an element later after the 
checksum layer. 
   This will exercise the ability to suspend while populating this part1 layer. 

##########
File path: 
daffodil-test/src/test/resources/org/apache/daffodil/layers/ipv4.dfdl.xsd
##########
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!--
+Copyright (c) 2012-2021 Owl Cyber Defense. All rights reserved.
+
+Developed by: Owl Cyber Defense
+              http://www.owlcyberdefense.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimers.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimers in the
+    documentation and/or other materials provided with the distribution.
+
+ 3. Neither the names of Owl Cyber Defense, nor the names of its contributors
+    may be used to endorse or promote products derived from this Software
+    without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions";
+           xmlns:fn="http://www.w3.org/2005/xpath-functions";
+           xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+           xmlns:chksum="urn:org.apache.daffodil.layers.ipv4checksum"
+           xmlns:eth="urn:ethernet"
+           xmlns:tns="urn:ethernet"
+           targetNamespace="urn:ethernet">
+
+  <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+  <xs:import namespace="urn:org.apache.daffodil.layers.ipv4checksum"
+             
schemaLocation="org/apache/daffodil/layers/xsd/ipv4checksumLayer.dfdl.xsd"/>
+
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/";>
+      <dfdl:defineFormat name="basicBigEndianBinary">
+        <dfdl:format
+          ref="tns:GeneralFormat"
+          representation="binary"
+          binaryNumberRep="binary"
+          byteOrder="bigEndian"
+          bitOrder="mostSignificantBitFirst"
+          alignmentUnits="bits"
+          alignment="1"
+          occursCountKind="implicit"/>
+      </dfdl:defineFormat>
+      <dfdl:format ref="tns:basicBigEndianBinary"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:element name="IPv4Header" type="tns:IPv4Header"/>
+
+  <xs:complexType name="IPv4Header">
+    <!--
+    Modified with proposed checksum computation via layer transforms
+
+    The xmlns:checksum prefix declaration would probably go on the xs:schema 
element more normally.
+    It is just here to show all the required things in this one location of 
the file.
+    -->
+    <xs:sequence>
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+          <!--
+          The checksum field in an ipV4 actually lives in the middle of the
+          data that it is a checksum of.
+
+          That is, some of the 16-bit words going into the checksum are before
+          the checksum itself. We call this "Part 1" of the data.
+
+          Other of the 16-bit words going into the checksum appear after the
+          checksum itself. We call this "Part 2" of the data.
+
+          So there are two layer transform calculations corresponding to
+          these two parts. This is required for unparsing, as detailed below.
+
+          For parsing: the first part computes the partial checksum of
+          the first data part and places that into the checksumPart1Value
+          variable.
+
+          Then the second part combines that part1 value from the variable with
+          the remaining checksum from the part 2 data, and places the final
+          result into the checksumValue variable.
+
+          At parse time we must check that this computed checksum value, and 
the
+          actual value of the element in the infoset are equal.
+
+          We have an option to place the computed checksum in another element
+          and then have a schematron validation rule or just a DFDL assert 
(recoverable)
+          check that the checksum element and computed checksum are equal.
+
+          Below, that element is called "ComputedChecksum".
+
+          When Unparsing, the first part transform computes the partial 
checksum of
+          the part 1 data, placing the result of that into the 
checksumPart1Value
+          just as when parsing. This doesn't suspend itself. It just
+          waits until all bytes of the first part of the header are written. 
That
+          itself can involve all sorts of suspensions though, as the header 
fields in this
+          part contain the length of the IP packet data, which likely involves 
a forward
+          reference to the dfdl:valueLength of the payload.
+
+          The second part transform computes the final checksum combining the 
checksumPart1Value
+          variable with the checksum computed from the part 2 data, placing 
the result into
+          checksumValue variable. This suspends if the checksumPart1Value 
variable is not
+          yet available, and also requires that all bytes of the layer itself 
have been written.
+
+          A dfdl:outputValueCalc puts this newly computed value from the 
variable into the checksum element.
+          Any prior value of the checksum element is discarded/overwritten 
with the new value.
+
+          -->
+          <dfdl:newVariableInstance ref="chksum:ipV4ChecksumPart1Value"/>
+          <dfdl:newVariableInstance ref="chksum:ipV4ChecksumValue"/>
+        </xs:appinfo>
+      </xs:annotation>
+
+      <xs:sequence dfdl:ref="chksum:ipv4ChecksumLayerPart1">
+        <xs:sequence>
+        <!--
+        Within this sequence, the data is all included in Part 1 of the
+        ipV4 checksum calculation
+
+        On parsing, the checksum algorithm computes the partial checksum for
+        this first part of the data, placing the value into the
+        variable chksum:checksumPart1Value, which must have a new variable
+        instance in scope.
+
+        This checksum calculation knows exactly how big this data must be
+        and if the representation turned out to be a different length than 
this, it
+        will be a runtime SDE.
+
+        Everything from here to the end of this sequence is unmodified from
+        the original IPV4 schema it is based on.
+        -->
+        <xs:element name="Version" type="tns:bit" dfdl:length="4"/>
+        <xs:element name="IHL" type="tns:bit" dfdl:length="4"/>
+        <xs:element name="DSCP" type="tns:bit" dfdl:length="6"/>
+        <xs:element name="ECN" type="tns:bit" dfdl:length="2"/>
+        <xs:element name="Length" type="tns:bit" dfdl:length="16"/>
+        <xs:element name="Identification" type="tns:bit" dfdl:length="16"/>
+        <xs:element name="Flags" type="tns:bit" dfdl:length="3"/>
+        <xs:element name="FragmentOffset" type="tns:bit" dfdl:length="13"/>
+        <xs:element name="TTL" type="tns:bit" dfdl:length="8"/>
+        <xs:element name="Protocol" type="tns:bit" dfdl:length="8"/>
+        </xs:sequence>
+      </xs:sequence>
+      <!--
+      Now the checksum element itself.
+
+      When unparsing: This is computed via a forward reference to the
+      checksum computation result in the
+      checksumValue variable, which is computed by the checksumLayerPart2 
transform.
+      -->
+      <xs:element name="Checksum" type="chksum:ipv4ChecksumType"
+                  dfdl:outputValueCalc='{ $chksum:ipV4ChecksumValue }'/>
+      <!--
+      Now the part 2 layer transform is computed. This combined the result from
+      the part 1 layer transform (from the checksumPart1Value variable) with 
the
+      remaining checksum computed from the sequence content.
+
+      This checksum calculation knows exactly how big this data must be
+      and if the representation turned out to be a different length than this, 
it
+      will be a runtime SDE.
+
+      The result is placed in the checksumValue variable.
+      -->
+      <xs:sequence dfdl:ref="chksum:ipv4ChecksumLayerPart2">
+      <xs:sequence>
+        <xs:element name="IPSrc" type="tns:hexByte" dfdl:length="4"/>

Review comment:
       enhance so at least one of these does a forward reference to a field 
later, so as to illustrate suspending during unparse during this part 2 layer 
transform. 

##########
File path: 
daffodil-test/src/test/resources/org/apache/daffodil/layers/ipv4.dfdl.xsd
##########
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+
+<!--
+Copyright (c) 2012-2021 Owl Cyber Defense. All rights reserved.
+
+Developed by: Owl Cyber Defense
+              http://www.owlcyberdefense.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimers.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimers in the
+    documentation and/or other materials provided with the distribution.
+
+ 3. Neither the names of Owl Cyber Defense, nor the names of its contributors
+    may be used to endorse or promote products derived from this Software
+    without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions";
+           xmlns:fn="http://www.w3.org/2005/xpath-functions";
+           xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+           xmlns:chksum="urn:org.apache.daffodil.layers.ipv4checksum"
+           xmlns:eth="urn:ethernet"
+           xmlns:tns="urn:ethernet"
+           targetNamespace="urn:ethernet">
+
+  <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+  <xs:import namespace="urn:org.apache.daffodil.layers.ipv4checksum"
+             
schemaLocation="org/apache/daffodil/layers/xsd/ipv4checksumLayer.dfdl.xsd"/>
+
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/";>
+      <dfdl:defineFormat name="basicBigEndianBinary">
+        <dfdl:format
+          ref="tns:GeneralFormat"
+          representation="binary"
+          binaryNumberRep="binary"
+          byteOrder="bigEndian"
+          bitOrder="mostSignificantBitFirst"
+          alignmentUnits="bits"
+          alignment="1"
+          occursCountKind="implicit"/>
+      </dfdl:defineFormat>
+      <dfdl:format ref="tns:basicBigEndianBinary"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:element name="IPv4Header" type="tns:IPv4Header"/>
+
+  <xs:complexType name="IPv4Header">
+    <!--
+    Modified with proposed checksum computation via layer transforms
+
+    The xmlns:checksum prefix declaration would probably go on the xs:schema 
element more normally.
+    It is just here to show all the required things in this one location of 
the file.
+    -->
+    <xs:sequence>
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+          <!--
+          The checksum field in an ipV4 actually lives in the middle of the

Review comment:
       Revisit if this can be done with just 1 layer, not two. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to