rfc963.txt

来自「RFC 的详细文档!」· 文本 代码 · 共 1,084 行 · 第 1/3 页

TXT
1,084
字号
      is the last fragment, since the routine reassembly, which actually
      sets these bits, has not yet been called for this fragment.  This
      statement must therefore skip the bits corresponding to the
      incoming fragment.  In specifying the range to be tested,
      allowance must be made for whether these bits fall at the
      beginning of the bit map or in the middle (the case where they
      fall at the end has already been tested). The statement must
      therefore be changed to read

         if from_SNP.dtgm.fragment_offset = 0 then
           if (all reassembly map from
             from_SNP.dtgm.fragment_offset +
               ((from_SNP.dtgm.total_length -
                 from_SNP.dtgm.header_length * 4) + 7) / 8
             to ((state_vector.total_data_length + 7) / 8 - 1) is set)
           then return YES;
           else return NO;
           end if;

           else
           if (all reassembly map from 0 to
             (from_SNP.dtgm.fragment_offset - 1) is set)
             and (all reassembly map from
               from_SNP.dtgm.fragment_offset +
                 ((from_SNP.dtgm.total_length -
                   from_SNP.dtgm.header_length * 4) + 7) / 8
               to ((state_vector.total_data_length + 7) / 8 - 1) is set)
           then return YES;
           else return NO;
           end if;
           end if;




Sidhu                                                           [Page 7]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


      Note that here again it is necessary to subtract 1 from the upper
      bound.

   Problem 4: Errors in fragment_and_send

      The action procedure fragment_and_send [MILS83a, sec 9.4.6.3.7] is
      used to break up datagrams that are too large to be sent through
      the subnetwork as a single packet.  The specification requires
      [MILS83a sec 9.2.2, sec 9.4.6.3.7] each fragment, except possibly
      the "tail" fragment, to contain a whole number of 8-octet groups
      (called "blocks"); moreover, each fragment must begin at a block
      boundary.

      In the algorithm set forth in fragment_and_send, all fragments
      except the tail fragment are set to the same size; the procedure
      begins by calculating this size.  This is done by the following
      statement:

         data_per_fragment := maximum subnet transmission unit
                                - (20 + number of bytes of option data);

      Besides the failure to allow for header padding, which is
      discussed in the next section, this statement makes the serious
      error of not assuring that the result is an integral multiple of
      the block size, i.e., a multiple of eight octets.  The consequence
      of this would be that as many as seven octets per fragment would
      never be sent at all. To correct this problem, and to allow for
      header padding, this statement must be changed to

         data_per_fragment := (maximum subnet transmission unit
                  - (((20 + number of bytes of option data)+3)/4*4)/8*8;

      Another problem in this procedure is the failure to provide for
      the case in which the length of the data is an exact multiple of
      eight.  The procedure contains the statements

         number_of fragments := (from_ULP.length +
                           (data_per_fragment - 1)) / data_per_fragment;

         data_in_last_frag := from_ULP.length modulo data_per_fragment;

      (Note that in our terminology we would rename data_in_last_frag as
      data_in_tail_frag; notice, also, that the proper spelling of the
      Ada operator is mod [ADA83, sec 4.5.5].)

      If data_in_last_frag is zero, some serious difficulties arise.
      One result might be that the datagram will be broken into one more


Sidhu                                                           [Page 8]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


      fragment than necessary, with the tail fragment containing no data
      bytes.  The assignment of data into the tail fragment will succeed
      even though it will now take the form

         output_data [i..i-1] := input_data [j..j-1];

      because Ada makes provision for so-called "null slices" [ADA83,
      sec 4.1.2] and will treat this assignment as a no-op [ADA83, sec
      5.2.1].

      This does, however, cause the transmission of an unnecessary
      packet, and also creates difficulties for the reassembly
      procedure, which must now be prepared to handle empty packets, for
      which not even one bit of the reassembly map should be set.
      Moreover, as the procedure is now written, even this will not
      occur.  This is because the calculation of the number of fragments
      is incorrect.

      A numerical example will clarify this point.  Suppose that the
      total datagram length is 16 bytes and that the number of bytes per
      fragment is to be 8.  Then the above statements will compute
      number_of_fragments = (16 + 7)/8 = 2 and data_in_last_frag = 16
      mod 8 = 0.  The result of the inconsistency between
      number_of_fragments and data_in_last_frag will be that instead of
      sending three fragments, of lengths 8, 8, and 0, the procedure
      will send only two fragments, of lengths 8 and 0; the last eight
      octets will never be sent.

      To avoid these difficulties, the specification should add the
      following statement, immediately after computing
      data_in_last_frag:

         if data_in_last_frag = 0 then
                                 data_in_last_frag := data_per_fragment;
         end if;

      This procedure also contains several minor errors.  In addition to
      failures to account for packet header padding, which are
      enumerated in the next section, there is a failure to convert the
      header length from words (four octets) to octets in one statement.
      This statement, which calculates the total length of the non-tail
      fragments, is

         to_SNP.dtgm.total_length := to_SNP.dtgm.header_length
                                                    + data_per_fragment;




Sidhu                                                           [Page 9]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


      Since header length is expressed  in  units  of  words,  this
      statement should read

         to_SNP.dtgm.total_length := to_SNP.dtgm.header_length * 4
                                                    + data_per_fragment;

      This is apparently no more than a misprint, since the
      corresponding calculation for the tail fragment is done correctly.

   Problem 5: Errors in reassembly

      The action procedure reassembly [MILS83a, sec 9.4.6.3.9], which is
      referred to as reassemble elsewhere in the specification [MILS83a,
      sec 9.4.6.1.2, sec 9.4.6.1.3], inserts an incoming fragment into a
      datagram being reassembled.  This procedure contains several
      relatively minor errors.

      In two places in this procedure, a range is written to contain one
      more member than it ought to have.  In the first, data from the
      fragment is to be inserted into the datagram being reassembled:

         state_vector.data [from_SNP.dtgm.fragment_offset*8 ..
             from_SNP.dtgm.fragment_offset*8 + data_in_frag] :=
                     from_SNP.dtgm.data [0..data_in_frag-1];

      In this statement, the slice on the left contains one more byte
      than the slice on the right.  This will cause a run-time exception
      to be raised [ADA83, sec 5.2.1].  The statement should read

         state_vector.data [from_SNP.dtgm.fragment_offset*8 ..
             from_SNP.dtgm.fragment_offset*8 + data_in_frag - 1] :=
                     from_SNP.dtgm.data [0..data_in_frag-1];

      A similar problem occurs in the computation of the range of bits
      in the reassembly map that corresponds to the incoming fragment.
      This statement begins

         for j in (from_SNP.dtgm.fragment_offset) ..
                  ((from_SNP.dtgm.fragment_offset +
                 data_in_frag + 7)/8) loop

      Not only are the parentheses in this statement located incorrectly
      (because the function f(x) = (x + 7) / 8 should be executed only
      on the argument data_in_frag), but also this range contains one
      extra member.  The statement should read




Sidhu                                                          [Page 10]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


         for j in (from_SNP.dtgm.fragment_offset) ..
                  (from_SNP.dtgm.fragment_offset +
                 (data_in_frag + 7)/8) - 1 loop

      Note that if the statement is corrected in this manner it will
      also handle the case of a zero-length fragment, mentioned above,
      since the loop will not be executed even once [ADA83, sS 5.5].

      Another minor problem occurs when this procedure attempts to save
      the header of the leading fragment.  The relevant statement is

         state_vector.header := from_SNP.dtgm;

      This statement attempts to transfer the entire incoming fragment
      into a record that is big enough to contain only the header.  The
      result, in Ada, is not truncation, but a run-time exception
      [ADA83, sec 5.2]. The correction should be something like

         state_vector.header := from_SNP.dtgm.header;

      This correction cannot be made without also defining the header
      portion of the datagram as a subrecord in [MILS83a, sec 9.4.4.6];
      such a definition would also necessitate changing many other
      statements. For example, from_SNP.dtgm.fragment_offset would now
      have to be written as from_SNP.dtgm.header.fragment_offset.
      Another possible solution is to write the above statement as a
      series of assignments for each field in the header, in the
      following fashion:

         state_vector.header.version :=
                                                  from_SNP.dtgm.version;
         state_vector.header.header_length :=
                                            from_SNP.dtgm.header_length;
         state_vector.header.type_of_service :=
                                          from_SNP.dtgm.type_of_service;

         -- etc.

      Note also that this procedure will fail if an incoming fragment,
      other than the tail fragment, does not contain a multiple of eight
      characters.  Implementors must be careful to check for this in the
      decision function SNP_params_valid [MILS83a, sec 9.4.6.2.7].







Sidhu                                                          [Page 11]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


   Problem 6: Incorrect Data Length for Fragmented Datagrams

      The procedure reassembled_delivery [MILS83a, sec 9.4.6.3.10] does
      not deliver the proper data length to the upper-level protocol.
      This is because the assignment is

         to_ULP.length := state_vector.header.total_length
                                - state_vector.header.header_length * 4;

      The fields in state_vector.header have been filled in by the
      reassembly procedure, discussed above, by copying the header of
      the leading fragment.  The field total_length in this fragment,
      however, refers only to this particular fragment, and not to the
      entire datagram (this is not entirely clear from it definition in
      [MILS83a, sec 9.3.4], but the fragment_and_send procedure
      [MILS83a, sec 9.4.6.3.7] insures that this is the case).

      The length of the entire datagram can only be computed from the
      length and offset of the tail fragment.  This computation is
      actually done in the reassembly procedure [MILS83a, sec
      9.4.6.3.9], and the result saved in state_vector.total_data_length
      (see above).  It is impossible, however, for reassembly to fill in
      state_vector.header.total_length at this time, because
      state_vector.header.header_length is filled in from the lead
      fragment, which may not yet have been received.

      Therefore, reassembled_delivery must replace the above statement
      with

         to_ULP.length := state_vector.total_data_length;

      The consequence of leaving this error uncorrected is that the
      upper-level protocol will be informed only of the delivery of as
      many octets as there are in the lead fragment.

5.  Implementation Difficulties of MIL Standard IP

   In addition to the problems discussed above, there are several
   features of the MIL standard IP specification [MILS83a] which lead to
   difficulties for the implementor.  These difficulties, while not
   actually errors in the specification, take the form of assumptions
   which are not explicitly stated, but of which implementors must be
   aware.






Sidhu                                                          [Page 12]



RFC 963                                                    November 1985
Some Problems with MIL-STD IP


   5.1  Header Padding

      In several places, the specification makes a computation of the
      length of a packet header without explicitly allowing for padding.
      The padding is needed because the specification requires [MILS83a,
      sec 9.3.14] that each header end on a 32-bit boundary.

      One place this problem arises is in the need_to_frag decision
      function [MILS83a, sec 9.4.6.2.5].  This function is used to
      determine whether fragmentation is required for an outgoing
      datagram. It consists of the single statement

         if ((from_ULP.length + (number of bytes of option data)
               + 20) > maximum transmission unit of the local subnetwork
         then return YES
         else return NO;
         end if;

      (A minor syntax error results from not terminating the first
      return statement with a semicolon [ADA83, sec 5.1, sec 5.3, sec
      5.9].) In order to allow for padding, the expression for the
      length of the outgoing datagram should be

         (((from_ULP.length + (number of bytes of option data) + 20)
                                                             + 3)/4 * 4)

      Another place that this problem arises is in the action procedure
      build_and_send [MILS83a, sec 9.4.6.3.2], which prepares
      unfragmented datagrams for transmission.  To compute the header
      field header_length, which is expressed in words, i.e., units of
      four octets [MILS83a, sec 9.3.2], this procedure contains the
      statement

         to_SNP.dtgm.header_length := 5 +

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?