Subject: [rohc] TCP/IP EPIC profile

From: Julije Ozegovic <[email-masked]>
Date: Tue, 26 Feb 2002 21:58:08 +0100

Dear ROHCers,

here we include "expanded" TCP/IP profile as published in

TCP/IP Header Compression for ROHC (ROHC-TCP)
<draft-ietf-rohc-tcp-00.txt>

The purpose of this posting is to point out the complexity of 
whole thing, regarding the fact that almost every line of 
profile ends up with (at least) one data structure in end user 
application.

The questions are:
    do we really want this?
    do we really need this?
    is it worth the effort?
    is it applicable to target machine (GSM)?
    do we really need (48+2)*60=3000 formats?

Besides this, comments about inconsistencies of the profile are 
listed inline.

We also want to raise discussion about usage of FORMAT method.

The questions are:

    - what about difference in FORMAT structure
      between CO and IR/DYN packets,
      shouldn't they be the same (by EPIC draft)?

    - what about usage of IRREGULAR method in all sets
      (except last one where it should be used),
      this way first set will always be selected

    - what about syntax and usage of FORMAT SELECTOR,
      it is actually not needed (can be identified from
      ID-bits of IR/DYN packet)

Best regards,
Julije Ozegovic
TCP-IP EPIC-LITE profile expanded according to
TCP/IP Header Compression for ROHC (ROHC-TCP) 
<draft-ietf-rohc-tcp-00.txt>

;**uses much more, but need be digged out :)
only uses the following toolbox methods:  
 - STATIC-KNOWN  
 - STATIC-UNKNOWN  
 - STATIC  
 - IRREGULAR  
 - LSB  
 - VALUE  
 - C  

 profile_identifier      0xFFFF  
 max_formats             60 
 max_sets                48 
 bit_alignment           8  
 npatterns               224  
 CO_packet               TCP-IP-CO 
 IR_packet               TCP-IP-IR 
 IR-DYN_packet           TCP-IP-DYN 

TCP-IP-CO       =      

;**IP checksum treated later anyway
;**not in current EPIC-lite toolbox
  INFERRED-IP-CHECKSUM(IPv4-co-header) 
    IPv4-co-header  =
      version         =  VALUE(4,4,100%) 
      header_len      =  VALUE(4,5,100%) 
      tos-co          =  STATIC(99%) | IRREGULAR(6,1%)
      ecn             =  STACK-TO-CONTROL(2) 
      length          =  INFERRED-SIZE(16,128) 
      ip-id-co        =
;**NBO not in EPIC-lite toolbox
        NBO(16) ; check byte-order 
        FORMAT(ip-id-seq-co, ip-id-rnd) 
;**130% ??
          ip-id-seq-co    =  LSB(4,3,70%) | LSB(6,8,15%) | 
                             LSB(8,8,15%) | IRREGULAR(16,30%) 
          ip-id-rnd       =  IRREGULAR(16,100%) 
;**compiler should read comments or what ?
        STATIC(100%) ; nbo flag 
      rf_flag         =  STACK-TO-CONTROL(1) 
      df_flag-co      =  STATIC(80%) | IRREGULAR(20%) 
      mf_flag         =  VALUE(1,0,100%) 
      offset          =  VALUE(13,0,100%) 
      ttl-co          =  STATIC(99%) | IRREGULAR(8,1%)  
      protocol        =  VALUE(8,6,100%)  
      ip_chksum       =  VALUE(16,0,100%) 
      src_address-co  =  STATIC(100%) 
      dst_address-co  =  STATIC(100%) 

;**TCP-co-header assumed same as TCP-header-co
  TCP-co-header   =
    source_port-co  =  STATIC(100%) 
    dest_port-co    =  STATIC(100%) 
;**seqno assumed to be seqno-co
;**get-seq-ack not used, expanded later for reference
    seqno-co        =  LSB(8,63,5%) | LSB(14,4096,80%) |  
                       LSB(20,16384,10%) | IRREGULAR(32,5%)  
;**ackno assumed to be ackno-co
;**get-seq-ack not used, expanded later for reference
    ackno-co        =  LSB(8,0,10%) | LSB(14,0,80%) |  
                       LSB(20,0,5%) | IRREGULAR(32,5%)  
    data_offset     =  STACK-TO-CONTTROL(4) 
    flags-co        =    
      reserved-co  =    
        get-rf    =    ROTATE(4,1) 
                       STACK-FROM-CONTROL(1) 
        FORMAT(reserved-unused, reserved-used) 
          reserved-unused =    VALUE(5,0,100%) 
          reserved-used   =
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
;**compiler should read comments or what ?
;**format selector in CO packet ??!!
        STATIC(100%) ; format selector 
      cwr        =  IRREGULAR(1,100%) 
      ece        =  IRREGULAR(1,100%) 
      urg        =  STACK-TO-CONTROL(1) 
;**ack assumed to be ack-co
;**ack STACK-TO-CONTROL not defined
      ack-co     =  VALUE(1,1,99.9%) | VALUE(1,0,0.1%) 
;++psh assumed to be psh-co
;**psh STACK-TO-CONTROL not defined
      psh-co     =  
        FORMAT(reg-psh-co, irreg-psh) 
;**108% ??
          reg-psh-co      =  STATIC(90%) | N(IRREGULAR(1,9%) | IRREGULAR(1,9%) 
          irreg-psh       =  IRREGULAR(1,100%) 
;**compiler should read comments or what ?
;**format selector in CO packet ??!!
        STATIC(100%) ; format selector 
      rst-syn-fin-co  =    no-flag(98%) | rst-only(1%) | fin-only(1%) 
        no-flag         =    VALUE(3,0x0,100%) 
        rst-only        =    VALUE(3,0x4,100%) 
        fin-only        =    VALUE(3,0x1,100%) 
;**syn-only defined, but not used
    window-co  =  STATIC(80%) | LSB(12,63,10%) | IRREGULAR(16,10%)  
    tcp_chksum =  IRREGULAR(16,100%)  
;**urg-ptr defined, but not used
    urg_ptr-co =  STATIC(99%) | IRREGULAR(16,1%)  

;**options not referenced in TCP-CO header, but included here
;**change in syntax, field_name = METHOD abandoned, field names in comments!!
;**experimental, need further discussion
  tcp-options-co = 
    ROTATE(3,1) ; get TCP data offset 
    LIST(4,1,32,-160,8, 
      U(OPTIONAL(tcp-sack-co)),
        tcp-sack-co = 
          VALUE(8,5,100%) ; type
          STACK-TO-CONTROL(8) ; length 
          LIST(8,1,8,-16,0, 
            OPTIONAL(sack-block-co), 
              sack-block-co = 
;**assumed sack-element-co = sack-element
                sack-element-co
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
                sack-element-co 
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
            OPTIONAL(sack-block-co), 
              sack-block-co = 
                sack-element-co
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
                sack-element-co 
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
            OPTIONAL(sack-block-co), 
              sack-block-co = 
                sack-element-co
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
                sack-element-co 
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
            OPTIONAL(sack-block-co))
              sack-block-co = 
                sack-element-co
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
                sack-element-co 
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
                  sack-element-co = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    STATIC(50%) | LSB(16,32768,30%) | LSB(24,1048576,20%)
            STATIC(90%) | IRREGULAR(8,10%) ; order 
            sack-block-presence = VALUE(1,1,100%)
                      VALUE(1,1,50%) | VALUE(1,0,50%)
                      VALUE(1,1,20%) | VALUE(1,0,80%)
                      VALUE(1,1,5%) | VALUE(1,0,95%)
      U(OPTIONAL(tcp-timestamp-co)),
          tcp-timestamp-co = 
            VALUE(8,8,100%)  ; type
            VALUE(8,10,100%) ; length
;**ts-entry assumed to be ts-entry-co
            ts-entry
              ts-entry-co = LSB(12,0,60%) | LSB(16,0,30%) |IRREGULAR(32,10%)
            ts-entry
              ts-entry-co = LSB(12,0,60%) | LSB(16,0,30%) |IRREGULAR(32,10%)
      U(OPTIONAL(tcp-mss)),
          tcp-mss = 
            VALUE(8,2,100%) ; type
            VALUE(8,4,100%) ; length
            IRREGULAR-PADDED(16,11,99%) | IRREGULAR(16,1%)
      U(OPTIONAL(tcp-end)), 
          tcp-end = VALUE(8,0,100%) ; type 
      U(OPTIONAL(tcp-wscale)), 
          tcp-wscale = 
            VALUE(8,3,100%) ; type
            VALUE(8,3,100%) ; length 
            IRREGULAR-PADDED(8,4,100%) ; scale
      U(OPTIONAL(sack-permitted)), 
          tcp-sack-permitted = 
            VALUE(8,4,100%) ; type
            VALUE(8,2,100%) ; length
      U(OPTIONAL(tcp-generic-co)), 
          tcp-generic-co = 
            STATIC(100%) ; type 
            STACK-TO-CONTROL(8) ; length
            UNCOMPRESSED(8,1,8,-16) ; value
      U(OPTIONAL(tcp-generic-co)), 
          tcp-generic-co = 
            STATIC(100%) ; type 
            STACK-TO-CONTROL(8) ; length
            UNCOMPRESSED(8,1,8,-16) ; value
      5,8,2,0,3,4) 
    STATIC(100%) ; option order 
    STATIC(95%) | IRREGULAR(8,5%) ; option presence

;**not defined, but self-explanatory :)
  skip-msn 

  CRC(3,80%) | CRC(7,20%) 

;**get-seq-ack not used, expanded here for reference
   get-seq-ack      =   
     ROTATE(2,1)
     STACK-FROM-CONTROL(2) ; cwr/ece
     ROTATE(4,1)
     STACK-FROM-CONTROL(2) ; ecn
     STACK-FROM-CONTROL(32) ; ack
     STACK-FROM-CONTROL(32) ; seq

;**seqno-and-ackno-co not used, expanded here for reference
   seqno-and-ackno-co = 
     FORMAT(bulk-data-co, bulk-ack-co, interactive-co)
       bulk-data-co     =    
         data-seqno-co    =    LSB(14,0,50%) | LSB(16,32768,30%) |LSB(20,65536,20%)
         data-ackno-co    =    STATIC(50%) | LSB(10,0,30%) | LSB(16,0,20%)
         ecn-co           =    
           FORMAT(no-ecn-co, use-ecn-co) 
             no-ecn-co        =    VALUE(2,0,100%)
                                   VALUE(2,0,100%)
             use-ecn-co       =    IRREGULAR(4,100%) 
       bulk-ack-co      =    
         ack-seqno-co     =    STATIC(50%) | LSB(10,0,30%) | LSB(16,0,20%)
         ack-ackno-co     =    LSB(14,0,50%) | LSB(16,0,30%) | LSB(20,0,20%) 
         ecn-co           =    
           FORMAT(no-ecn-co, use-ecn-co) 
             no-ecn-co        =    VALUE(2,0,100%)
                                   VALUE(2,0,100%)
             use-ecn-co       =    IRREGULAR(4,100%) 
       interactive-co   =    
         interact-seqno-co =   LSB(10,256,35%) | LSB(14,2048,50%) | LSB(18,4096,15%)
         interact-ackno-co =   LSB(10,0,35%) | LSB(14,0,50%) | LSB(18,0,15%) 
         ecn-co           =    
           FORMAT(no-ecn-co, use-ecn-co) 
             no-ecn-co        =    VALUE(2,0,100%)
                                   VALUE(2,0,100%)
             use-ecn-co       =    IRREGULAR(4,100%) 
     STATIC(100%) ; format selector

TCP-IP-IR       =    

;**IP checksum treated later anyway
;**not in current EPIC-lite toolbox
  INFERRED-IP-CHECKSUM(IPv4-ir-header)
    IPv4-ir-header  =  
      version         =  VALUE(4,4,100%) 
      header_len      =  VALUE(4,5,100%) 
      tos-dyn         =  IRREGULAR(6,100%) 
      ecn             =  STACK-TO-CONTROL(2) 
      length          =  INFERRED-SIZE(16,128) 
      ip-id-dyn       =  
;**NBO not in EPIC-lite toolbox
        NBO(16) ; check byte-order 
        FORMAT(ip-id-seq-dyn, ip-id-rnd)
          ip-id-seq-dyn  =  IRREGULAR(16,100%) 
          ip-id-rnd      =  IRREGULAR(16,100%) 
;**what is this meant for??
        IRREGULAR(16,100%) 
;**compiler should read comments or what ?
        IRREGULAR(1,100%) ; nbo flag 
      rf_flag         =  STACK-TO-CONTROL(1) 
      df-flag-dyn     =  IRREGULAR(1,100%) 
      mf_flag         =  VALUE(1,0,100%) 
      offset          =  VALUE(13,0,100%) 
      ttl-dyn         =  IRREGULAR(8,100%) 
      protocol        =  VALUE(8,6,100%)  
      ip_chksum       =  VALUE(16,0,100%) 
      src_address-ir  =  IRREGULAR(32,100%) 
      dst_address-ir  =  IRREGULAR(32,100%) 

;**TCP-ir-header assumed to be TCP-header IR
  TCP-header-ir   =  
    source_port-ir  =  IRREGULAR(16,100%) 
    dest_port-ir    =  IRREGULAR(16,100%) 
;**seqno assumed to be seqno-dyn
;**get-seq-ack not used, expanded later
    seqno-dyn       =  IRREGULAR(32,100%) 
;**ackno assumed to be ackno-dyn
;**get-seq-ack not used, expanded later
    ackno-dyn       =  IRREGULAR(32,100%) 
    data_offset     =  STACK-TO-CONTROL(4) 
    flags-dyn       =  
      reserved-dyn    =  
        get-rf          =  
          ROTATE(4,1) 
          STACK-FROM-CONTROL(1) 
        FORMAT(reserved-unused, reserved-used) 
          reserved-unused =    VALUE(5,0,100%) 
          reserved-used   =
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
;**compiler should read comments or what ?
        IRREGULAR(1,100%) ; format selector 
;**what is this??, possibly cwr, ece
      IRREGULAR(2,100%) 
      urg             =  STACK-TO-CONTROL(1) 
;**what is this??, possibly ack
      IRREGULAR(1,100%) 
      psh-dyn         =  
        FORMAT(reg-psh-dyn, irreg-psh) 
          reg-psh-dyn     =  IRREGULAR(1,100%) 
          irreg-psh       =  IRREGULAR(1,100%) 
        IRREGULAR(1,100%) ; format selector 
      rst-syn-fin-dyn =  IRREGULAR(3,100%) 
    window-dyn      =  IRREGULAR(16,100%) 
    tcp_chksum      =  IRREGULAR(16,100%)  
    urg_ptr-dyn     =  IRREGULAR(16,100%)  

;**options not referenced in TCP-IR header, but included here
;**tcp-options IR not defined, tcp-options dyn used instead
;**change in syntax, field_name = METHOD abandoned, field names in comments!!
;**experimental, need further discussion
  tcp-options-dyn = 
    ROTATE(3,1) ; get TCP data offset
    LIST(4,1,32,-160,8, 
      U(OPTIONAL(tcp-sack-dyn)),
        tcp-sack-dyn = 
          VALUE(8,5,100%) ; type
          STACK-TO-CONTROL(8) ; length
          LIST(8,1,8,-16,0, 
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
;**should it be 100%
          IRREGULAR(8,10%) ; order
               sack-block-presence-dyn  = 
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
      U(OPTIONAL(tcp-timestamp-dyn)), 
;** tcp-timestamp-dyn not defined, possibly uses ts-entry-dyn
        tcp-timestamp-dyn = 
      U(OPTIONAL(tcp-mss)),
        tcp-mss = 
          VALUE(8,2,100%) ; type
          VALUE(8,4,100%) ; length
          IRREGULAR-PADDED(16,11,99%) | IRREGULAR(16,1%)
      U(OPTIONAL(tcp-end)), 
        tcp-end = VALUE(8,0,100%) ; type 
      U(OPTIONAL(tcp-wscale)), 
        tcp-wscale = VALUE(8,3,100%) ; type
        VALUE(8,3,100%) ; length 
        IRREGULAR-PADDED(8,4,100%) ; scale
      U(OPTIONAL(sack-permitted)), 
        tcp-sack-permitted = 
          VALUE(8,4,100%) ; type
          VALUE(8,2,100%) ; length
      U(OPTIONAL(tcp-generic-dyn)), 
        tcp-generic-dyn = 
          IRREGULAR(8,100%) ; type
          STACK-TO-CONTROL(8) ; length 
          UNCOMPRESSED(8,1,8,-16) ; value
      U(OPTIONAL(tcp-generic-dyn)), 
        tcp-generic-dyn = 
          IRREGULAR(8,100%) ; type
          STACK-TO-CONTROL(8) ; length 
          UNCOMPRESSED(8,1,8,-16) ; value
      5,8,2,0,3,4) 
    IRREGULAR(24,100%) ; option order 
    IRREGULAR(8,100%) ; option presence 

  msn-ir          =  MSN-IRREGULAR(16,10%) 

  CRC(8,100%) 

TCP-IP-DYN      =    

;**IP checksum treated later anyway
;**not in current EPIC-lite toolbox
    IPv4-dyn-header =    
      version         =  VALUE(4,4,100%) 
      header_len      =  VALUE(4,5,100%)
      tos-dyn         =  IRREGULAR(6,100%) 
      ecn             =  STACK-TO-CONTROL(2) 
      length          =  INFERRED-SIZE(16,128)
      ip-id-dyn       =  
;**NBO not in EPIC-lite toolbox
        NBO(16) ; check byte-order 
        FORMAT(ip-id-seq-dyn, ip-id-rnd)
          ip-id-seq-dyn  =  IRREGULAR(16,100%) 
          ip-id-rnd      =  IRREGULAR(16,100%) 
;**what is this meant for??
        IRREGULAR(16,100%) 
;**compiler should read comments or what ?
        IRREGULAR(1,100%) ; nbo flag 
      rf_flag         =  STACK-TO-CONTROL(1)
      df_flag-dyn     =  IRREGULAR(1,100%)
      mf_flag         =  VALUE(1,0,100%)
      offset          =  VALUE(13,0,100%)   
      ttl-dyn         =  IRREGULAR(8,100%)   
      protocol        =  VALUE(8,6,100%)  
      ip_chksum       =  VALUE(16,0,100%) 
      src_address-co  =  STATIC(100%)
      dst_address-co  =  STATIC(100%) 

;**assumed TCP-dyn-header = TCP-header-dyn
  TCP-dyn-header  =
    source_port-co  = STATIC(100%) 
    dest_port-co    = STATIC(100%) 
;**seqno assumed to be seqno-dyn
;**get-seq-ack not used
    seqno-dyn       =  IRREGULAR(32,100%) 
;**ackno assumed to be ackno-dyn
;**get-seq-ack not used
    ackno-dyn       =  IRREGULAR(32,100%) 
    data_offset     =  STACK-TO-CONTROL(4) 
    flags-dyn       =  
      reserved-dyn    =  
        get-rf          =  
          ROTATE(4,1) 
          STACK-FROM-CONTROL(1) 
        FORMAT(reserved-unused, reserved-used) 
          reserved-unused =    VALUE(5,0,100%) 
          reserved-used   =
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
            reserved-flag   =    IRREGULAR(1,100%) 
;**compiler should read comments or what ?
        IRREGULAR(1,100%) ; format selector 
;**what is this?? possibly cwr, ece 
      IRREGULAR(2,100%) 
      urg             =  STACK-TO-CONTROL(1) 
;**what is this?? possibly ack
      IRREGULAR(1,100%) 
      psh-dyn         =  
        FORMAT(reg-psh-dyn, irreg-psh) 
          reg-psh-dyn     =  IRREGULAR(1,100%) 
          irreg-psh       =  IRREGULAR(1,100%) 
        IRREGULAR(1,100%) ; format selector 
      rst-syn-fin-dyn =  IRREGULAR(3,100%) 
    window-dyn      =  IRREGULAR(16,100%) 
    tcp_chksum      =  IRREGULAR(16,100%)  
    urg_ptr-dyn     =  IRREGULAR(16,100%)  

;**options not referenced in TCP-DYN header, but included here
;**change in syntax, field_name = METHOD abandoned, field names in comments!!
;**experimental, need further discussion
  tcp-options-dyn = 
    ROTATE(3,1) ; get TCP data offset
    LIST(4,1,32,-160,8, 
      U(OPTIONAL(tcp-sack-dyn)),
        tcp-sack-dyn = 
          VALUE(8,5,100%) ; type
          STACK-TO-CONTROL(8) ; length
          LIST(8,1,8,-16,0, 
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
            OPTIONAL(sack-block-dyn),
              sack-block-dyn = 
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
                sack-element-dyn
                  sack-element-dyn = 
                    INFERRED-OFFSET-LIST(32) ; offset from base
                    STACK-TO-CONTROL(32) ; preserve new base
                    IRREGULAR(32,100%)
;**should it be 100%
          IRREGULAR(8,10%) ; order
               sack-block-presence-dyn  = 
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
                 IRREGULAR(1,100%)
      U(OPTIONAL(tcp-timestamp-dyn)), 
;** tcp-timestamp-dyn not defined, possibly uses ts-entry-dyn
        tcp-timestamp-dyn = 
      U(OPTIONAL(tcp-mss)),
        tcp-mss = 
          VALUE(8,2,100%) ; type
          VALUE(8,4,100%) ; length
          IRREGULAR-PADDED(16,11,99%) | IRREGULAR(16,1%)
      U(OPTIONAL(tcp-end)), 
        tcp-end = VALUE(8,0,100%) ; type 
      U(OPTIONAL(tcp-wscale)), 
        tcp-wscale = VALUE(8,3,100%) ; type
        VALUE(8,3,100%) ; length 
        IRREGULAR-PADDED(8,4,100%) ; scale
      U(OPTIONAL(sack-permitted)), 
        tcp-sack-permitted = 
          VALUE(8,4,100%) ; type
          VALUE(8,2,100%) ; length
      U(OPTIONAL(tcp-generic-dyn)), 
        tcp-generic-dyn = 
          IRREGULAR(8,100%) ; type
          STACK-TO-CONTROL(8) ; length 
          UNCOMPRESSED(8,1,8,-16) ; value
      U(OPTIONAL(tcp-generic-dyn)), 
        tcp-generic-dyn = 
          IRREGULAR(8,100%) ; type
          STACK-TO-CONTROL(8) ; length 
          UNCOMPRESSED(8,1,8,-16) ; value
      5,8,2,0,3,4) 
    IRREGULAR(24,100%) ; option order 
    IRREGULAR(8,100%) ; option presence 

  msn-dyn        =  MSN-LSB(3,0,90%) | MSN-LSB(7,0,9%) | MSN-IRREGULAR(16,1%) 

  CRC(8,100%) 

;**seqno-and-ackno-dyn expanded here for reference
   seqno-and-ackno-dyn = 
     FORMAT(bulk-data-dyn, bulk-ack-dyn, interactive-dyn)
       bulk-data-dyn    =
         seqno-dyn        =    IRREGULAR(32,100%)
         ackno-dyn        =    IRREGULAR(32,100%)
         ecn-dyn          =
           FORMAT(no-ecn-dyn, use-ecn-dyn)
             no-ecn-dyn       =
               VALUE(2,0,100%) 
               VALUE(2,0,100%) 
             use-ecn-dyn      =
               IRREGULAR(2,100%) 
               IRREGULAR(2,100%) 
           IRREGULAR(1,100%) ; format selector 
       bulk-ack-dyn     =
         seqno-dyn        =    IRREGULAR(32,100%)
         ackno-dyn        =    IRREGULAR(32,100%)
         ecn-dyn          =
           FORMAT(no-ecn-dyn, use-ecn-dyn)
             no-ecn-dyn       =
               VALUE(2,0,100%) 
               VALUE(2,0,100%) 
             use-ecn-dyn      =
               IRREGULAR(2,100%) 
               IRREGULAR(2,100%) 
           IRREGULAR(1,100%) ; format selector 
       interactive-dyn  =
         seqno-dyn        =    IRREGULAR(32,100%)
         ackno-dyn        =    IRREGULAR(32,100%)
         ecn-dyn          =
           FORMAT(no-ecn-dyn, use-ecn-dyn)
             no-ecn-dyn       =
               VALUE(2,0,100%) 
               VALUE(2,0,100%) 
             use-ecn-dyn      =
               IRREGULAR(2,100%) 
               IRREGULAR(2,100%) 
           IRREGULAR(1,100%) ; format selector 
    IRREGULAR(2,100%) ; format-selector

---

From: "West, Mark (ITN)" <[email-masked]>
Date: Wed, 27 Feb 2002 10:07:13 +0000

Hi Julije,

Some brief comments inline...

Cheers,

Mark.

> 
> The purpose of this posting is to point out the complexity of whole 
> thing, regarding the fact that almost every line of profile ends up with 
> (at least) one data structure in end user application.

Yes, it is quite complex.  So is RFC 3095 ;-)
I would agree that it is more 'dense' than RFC 3095, for example, as 
most of the information is packed into the profile.

Certainly every field (or meta-field) requires a data-structure.  Again, 
I'm not sure how this is different from any other header compression scheme?

>    do we really want this?

I won't answer this one -- I guess you could say I'm biased!

>    do we really need this?

That depends what you want.  Don't forget that the profile contains 
sufficient information to compress TCP/IP.  Given that, I would say it 
is quite compact.
Or, rather, if you don't have the information in this structure then, 
*yes*, you *absolutely* need to capture it in some way.

(I should point out that it isn't complicated enough yet ;-) as we still 
need to add the IPv6/extension header handling...)

>    is it worth the effort?

Again, that's a judgement call.  Also, don't forget that you can 
trade-off the effort against the efficiency.

And I'm not quite sure what you are referring to by 'effort'.  It's hard 
to write the profile, I'm not going to deny that.  But a lot of this is 
about understanding how the protocol works and should be compressed. 
Then you have to work out how to express this in an EPIC profile.  It's 
clear that, for example, it would be helpful to have more comments in 
the profile.  But it's not actually that complex.

Also (given the set of encoding methods defined in the EPIC(-lite) 
framework, there doesn't seem to be any more effort involved in using a 
'complex' profile over a 'simple' one.  The basic structure of the 
processing is exactly the same.

If you don't care too much about efficiency and only want to write a 
simple profile, then you can!

>    is it applicable to target machine (GSM)?

I haven't compared the size of our RFC 3095 implementation with our EPIC 
implementation recently, but neither of them are 'trivial' pieces of 
code!  Also, I think we're looking at this more for 2.5G / 3G (or, 
indeed, other arbitrary wireless links) than GSM .

Also, staying with the 'write-a-new-chunk-of-code-for-every-profile' 
approach is likely to add as least as much as the data for an EPIC profile.

>    do we really need (48+2)*60=3000 formats?

I don't know!  I think this is a matter for experimentation and 
selection.  The number of different format sets and packets per format 
set is clearly important, but it's hard to have a final view on this at 
the moment.  However, formats can (and should) be stored efficiently. 
3000 formats is a big number.  But it's not a lot of memory.

> 
> Besides this, comments about inconsistencies of the profile are listed 
> inline.

Ok, I'll reply to these later when I've had a chance to go through them

> We also want to raise discussion about usage of FORMAT method.

Ok!

>      shouldn't they be the same (by EPIC draft)?

I'm not sure that I understand the question.

The intent (unless I've really messed up the profile!) is that a FORMAT 
encoding occurs at the same point in the profile for each of CO, IR, and 
IR-DYN.  This is, of course, important as the profile needs to have a 
consistent structure.
Is that what you mean?

>      this way first set will always be selected

Well, if you read the pseudo-code you will see that the FORMAT encoding 
uses the form 'choose' to pick the format set.  This is 'defined' as an 
implementation dependent selection process -- it can use any criteria 
you want.

There is no rule that says that, when using FORMAT, each format set 
should be an exact match for only one case.  The important point here is 
that if encoding succeeds, then the compressed packet can be 
tranparently decompressed.  This is a critical requirement.  If there 
are multiple possible encodings that can fulfill this, then that's not a 
problem.

So, the simplest, most naive implementation of FORMAT just says 'pick 
the first format set that successfully encodes the packet'.  This will 
work fine.  However, it will also not be as efficienct as a more complex 
implementation.  Hopefully you can see, though, that this doesn't affect 
interoperability.  It's a free choice at the compressor and you can make 
it as good or as bad as you like!

>      ID-bits of IR/DYN packet)

That's a good question and one that we've been discussing a bit 
ourselves.  Rest assured that the update of the EPIC-lite draft (which 
will be submitted this week) will contain an updated FORMAT encoding.

-- 
Mark A. West, Consultant Engineer
Roke Manor Research Ltd., Romsey, Hants.  SO51 0ZN
Phone +44 (0)1794 833311   Fax  +44 (0)1794 833433

(Yes, I do know that my disclaimer is in an attachment.  And, no, I 
didn't ask for it to be that way)

---

From: "West, Mark (ITN)" <[email-masked]>
Date: Wed, 27 Feb 2002 17:32:19 +0000

Hi Julije,

I've just waded through your comments on the 'expanded' profile, and 
I'll try and summarise the points you raise and make some comments...

- IP checksum treated later / INFERRED-IP-CHECKSUM not defined

The current draft does not define INFERRED-IP-CHECKSUM.  (It was defined 
in an older 'EPIC for TCP' draft, but I realise that's not much help!) 
It is in the new version that will be submitted this week, though.
When you see how this works, you will appreciate that the IP checksum is 
not actually treated later, but simply ignored.  (On compression, 
INFERRED-IP-CHECKSUM sets the checksum bits to 0; on decompression is 
fills them in with the computed checksum).

- NBO not in the toolbox

Again, true.  We have removed INFERRED-SCALED and replaced it with NBO 
and SCALE operations, which gives more flexibility.  Again, these are 
described in the draft that will be submitted.  (I agree that it might 
have been nice to synchronise things a little better...)

- Some percentages don't add up to 100%

That's what we profile writers refer to as a 'mistake' ;-)
Actually, it shouldn't matter - but it should be fixed!

- Compiler should read comments or what?

Well, the compiler is free to read the comments.  But it probably ought 
to ignore what they say...

- Various mis-named method names

Sorry - these are typos and need to be fixed.

- Various unused methods

Again, they should be referenced so this is an error in the profile.

- FORMAT appears in 'CO' packet

Yes, it certainly does.  Otherwise, how would you know what different 
formats to build?  I don't quite see the problem here...

- ack STACK-TO-CONTROL not defined
- psh STACK-TO-CONTROL not defined

I don't understand the comments.

- skip-msn is not defined (but self-explanatory)

Tend to agree!  (This is, of course, a TCP specific method and should be 
defined along with the profile).

- An IRREGULAR(16,100%) is used to encode a format selector

This should be IRREGULAR(1,100%) - it's a typo...

- Not clear what is being encoded at each point

This could be overcome by better commenting (whether or not the compiler 
reads them) or splitting up the methods to a finer granularity.  This 
should be taken care of in the profile, though, I agree.

Cheers,

Mark.

---

From: Julije Ozegovic <[email-masked]>
Date: Thu, 28 Feb 2002 14:24:51 +0100

Hi Mark,

thank you for comments. Here I want to clarify some of my questions.

First of all, I think that TCP/IP header compression is needed. 
Also I think that EPIC(-lite) high level "compression definition 
language" is right approach. Also, I support EPIC "protocol 
independence". However, all this did motivate me for profile 
'expansion'.

EPIC provides total freedom of profile writing, when profile 
author has possibility to deal with header on bit-by-bit basis.

Detailed profiles tend to result in complex applications/protocols.

Just to remember, Internet is major technology today because of 
its simplicity: IP routers are more efficient than X.25 or ATM 
ones (for the same technology).

In my opinion, central point is to write profiles that will give 
optimal trade-off between complexity and compression efficiency. 
I think that profile in <draft-ietf-rohc-tcp-00.txt> is not one 
of that kind.

When writing profiles, authors should keep in mind that headers 
to be compressed are just lists of fields, and that 
compressor/decomressor actually treat them as such. This can 
provide simple and computation efficient profiles.

Now about some questions/answers:

** NBO:

can we introduce something like SWAP-LSB in the toolbox and let 
normal method choice take place, e.g.:

    IP_ID = LSB(80%,x,y) | SWAP-LSB(20%,x,y)

** Comments:

in the proposed profile, some important information is contained 
in comments. That implies that syntax is not stable yet. Since 
we try to implement EPIC-lite TCP/IP compression, input syntax 
changes force us to change "profile compiler" on weekly basis - 
lot of frustration results :)

** FORMAT in CO:
    actually was FORMAT SELECTOR in CO:

When transmitting CO packet, compressor is using the same format 
set that has already been communicated to decompressor through 
the IR/DYN packet. It is obsolete to send this selector in CO 
packet, because decompressor should be informed in forward, to 
be able to decompress the header... STATIC test is obsolete too, 
because it will fail on multiple contexts, so compressor must 
erase all previous contexts (if any) when changing to another 
format set.

** difference in FORMAT between CO/IR/DYN:

by draft, all methods in format should be available for IR/DYN 
processing. This means that:

field = FORMAT((method1 | method2);(method3 | method4))

should be in IR/DYN interpreted as:

field = (method1 | method2 | method3 | method4)

Consequences are:
   - FORMAT should be the same in all three profiles (CO/IR/DYN)
   - NO format selector is needed, i.e. "method3" when selected
     in IR/DYN implies second format set
   - since "choose" in most applications simply tries one by one
     method from the list, IRREGULAR should not be included
     before the last method (i.e. only "method4" can be
     IRREGULAR), otherwise methods after IRREGULAR
     will newer be chosen

** ack STACK-TO-CONTROL not defined

since following exists in the profile (although not used):

    get-seq-ack      =   ROTATE(2,1)

ack and sack should be pushed before :)

Cheers,
Julije

West, Mark (ITN) wrote:

> ------------------------------------------------------------------------
> 
> The information contained in this e-mail and any attachments is confidential to Roke 
> Manor Research Ltd and must not be passed to any third party without permission. This 
> communication is for information only and shall not create or change any contractual 
> relationship.
> 
> RMRL-Disclaimer.txt
> 
> Content-Type:
> 
> text/plain
> Content-Encoding:
> 
> 7bit
> 
> 

_______________________________________________
Rohc mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/rohc

---

From: "West, Mark (ITN)" <[email-masked]>
Date: Thu, 28 Feb 2002 16:53:25 +0000

Hi Julije,

More comments, inline...

Cheers,

Mark.

Julije Ozegovic wrote:

> First of all, I think that TCP/IP header compression is needed. Also I 
> think that EPIC(-lite) high level "compression definition language" is 
> right approach. Also, I support EPIC "protocol independence". However, 
> all this did motivate me for profile 'expansion'.

So far, so good ;-)

> 
> EPIC provides total freedom of profile writing, when profile author has 
> possibility to deal with header on bit-by-bit basis.

> Detailed profiles tend to result in complex applications/protocols.

I'd have put that the other way around (complex protocols => detailed 
profiles), but I think I agree...

> 
> Just to remember, Internet is major technology today because of its 
> simplicity: IP routers are more efficient than X.25 or ATM ones (for the 
> same technology).
> 
> In my opinion, central point is to write profiles that will give optimal 
> trade-off between complexity and compression efficiency. I think that 
> profile in <draft-ietf-rohc-tcp-00.txt> is not one of that kind.

Well, ok, it looks like we're going to disagree about this one.  Believe 
me when I say that I could make the TCP profile a whole lot more 
complicated.  Or, rather, detailed.  However, I am making the assumption 
(and, at the moment, it *is* an assumption) that if the profile were 
much more complex it would be a case of 'diminishing returns'.  That is, 
the effort of writing/verifying/maintaining/executing the profile would 
increase far faster than any compression gain.

It may be that the profile could be simplified from the current form 
without (noticably) sacrificing efficiency.  That, though, requires some 
experimentation.  As it stands, I don't believe that the protocol is 
excessively complex and I believe that it is a reasonable description of 
TCP.  Like I say, when I get a chance to experiment with the profile, I 
may change my mind.

Unless you've got some comparative figures from different variants of a 
profile, I don't think you can make that judgement.  Specifically, you 
can give a measure of the complexity of the profile but, without running 
it, by what metric are you measuring efficiency?

> 
> When writing profiles, authors should keep in mind that headers to be 
> compressed are just lists of fields, and that compressor/decomressor 
> actually treat them as such. This can provide simple and computation 
> efficient profiles.

I'm curious to know where I've deviated from treating the header as a 
list of fields.  (In fact, I'm curious to know how it's even possible to 
deviate from treating the header as a list of fields!)

> Now about some questions/answers:

ok...

> 
> ** NBO:
> 
> can we introduce something like SWAP-LSB in the toolbox and let normal 
> method choice take place, e.g.:
> 

Are you saying that you would like to have a 'SWAP-' version of *every* 
method in the toolbox?  Isn't this adding just a little more complexity 
than a simple, in-place transformation?  The whole point is that the 
byte-swappedness of a field is orthogonal to the encoding method. 
That's why it got split from the INFERRED-SCALED method in the first place.

In fact, your example perfectly illustrates that orthogonality.  It is 
clear that the IP ID is going to use LSB encoding.  However, you are 
saying that (a priori) you know that 20% of the IP ID values will be 
byte swapped and 80% will be in NBO.  My crystal-ball gazing just isn't 
that good at predicting what's going to appear as input ;-)

Contrast this with our current suggestion:
	foo = byte-swap
	      encode-foo
               encode-swap-flag

	byte-swap = NBO(16)
	encode-foo = LSB(...)
	encode-swap-flag = STATIC(99%) | IRREGULAR(1,1%)

What I am saying here is that the field is put into NBO.  Then I encode 
the (NBO'd) field with LSB (or whatever).  Then I encode the swap-flag. 
  Now, what I saying here is that the probability that the byte-swap 
state *changes* is 1%.  This is very different from saying that the 
probability of byte-swapping *is* 1%, for example.

I can be confident that the byte-swap state won't change frequently.  I 
have no idea what the ratio of byte-swapped to non-byte-swapped values 
will be...

> 
> ** Comments:
> 
> in the proposed profile, some important information is contained in 
> comments. That implies that syntax is not stable yet. Since we try to 
> implement EPIC-lite TCP/IP compression, input syntax changes force us to 
> change "profile compiler" on weekly basis - lot of frustration results :)
> 

There is *no*, repeat *no* 'important information' in the comments. 
(Excepting making the profile more human readable.  Which I admit I may 
have failed to do!)

The input syntax in the current draft looks like BNF.  The input syntax 
in the draft we'll release on Friday looks like BNF.  I don't think that 
anything of consequence has changed.

I apologise for adding/removing methods - unfortunately as we look at 
writing 'real' profiles, we are working out which methods are useful and 
how they are employed.  However, this has no change on the syntax.

> When transmitting CO packet, compressor is using the same format set 
> that has already been communicated to decompressor through the IR/DYN 
> packet. It is obsolete to send this selector in CO packet, because 
> decompressor should be informed in forward, to be able to decompress the 
> header... STATIC test is obsolete too, because it will fail on multiple 
> contexts, so compressor must erase all previous contexts (if any) when 
> changing to another format set.

The format selector is there to avoid mucking up the context. 
(Although, of course, you could do the context in a more complex fashion).

[There are still some details about FORMAT that we're working out, but...]

FORMAT has to be in the CO packet, for the reasons I explained in the 
last e-mail.  FORMAT generates a format selector.  It is important that 
every time that FORMAT is encountered it generates the meta-value, which 
must itself be compressed in order to keep the context aligned.  This is 
essentially the case because of the sequential context indexing.

However, the whole point is that the STATIC test is also a way of saying 
that the FORMAT cannot change within the compressed packet.

The compressor does not need to erase contexts when it changes FORMAT 
(if the profile has been written properly), as the context histories 
should still align.  Only the sets of encoding methods used change.

>     IRREGULAR), otherwise methods after IRREGULAR

These are good points - and, as I say, we are currently discussing them. 
  We will have an answer before the draft gets issued..!

> ack and sack should be pushed before :)

Ah, ok, I see what you mean.  Yes!  If I want to pull something off the 
stack, I should have pushed it first...  Oh well, another bug to fix ;-)