Hi all,

I'm currently working on the PROFINET ... here I have the challenge, that I 
have multiple layers of different protocols.

UDP -> DCE/RPC -> PROFINET IO CM (Block Container) -> PROFINET IO CM Blocks

The problem is:


  *   UDP is Big Endian
  *   PROFINET IO CM Blocks are Big Endian
  *   DCE/RPC is big or little endian depending on a variable inside the 
DCE/RPC packet
  *   Profinet IO CM (block container) is the same encoding as the DCE/RPC 
packet

At first I thought if I force my request to big endian, then the response would 
be accordingly.
Unfortunately that's not the case ... So if I send a request with Big Endian 
DCE/RPC (Hence, makeing the entire message Big endian). I still get a response 
back with DCE/RPC in Little Endian. So I have to be able to handle both.

Now I had multiple ideas:

  *   A new sort of block "endianessSwitch" (or a better name) ... which takes 
an argument and which simply switches the endianess of the buffers to the given 
one. This would probably be pretty simple to implement with a "try-finally" 
block in Java.
  *   We add an optional additional option to the complex-type declarations. 
This would however have us split types into two.

Here comes the example of the PN DCE/RPC packet with an endianessSwitch:

[discriminatedType 'DceRpc_Packet'
    [const         uint 8            'version'           '0x04'                 
]
    [discriminator DceRpc_PacketType 'packetType'                               
]
    [typeSwitch 'packetType'
        ['REQUEST'  DceRpc_Packet_Req
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '1'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '0'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '0'     
]
            [reserved uint 1         '0x0'                                      
]
        ]

        ['RESPONSE' DceRpc_Packet_Res
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '0'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '1'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '1'     
]
            [reserved uint 1         '0x0'                                      
]
        ]

        ['REJECT' DceRpc_Packet_Rej
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '0'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '0'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '0'     
]
            [reserved uint 1         '0x0'                                      
]
        ]
    ]
    [reserved      uint 6            '0x00'                                     
   ]
    [const         uint 1            'cancelWasPending'                 '0'     
   ]
    [reserved      uint 1            '0x0'                                      
   ]
    [simple        IntegerEncoding   'integerEncoding'                          
   ]
    [simple        CharacterEncoding 'characterEncoding'                        
   ]
    [simple        FloatingPointEncoding 'floatingPointEncoding'                
   ]
    [endianessSwitch 'integerEncoding == IntegerEncoding.BIG_ENDIAN'
        [const         uint 8            'serialHigh'        '0x00'             
   ]
        [const         uint 8            'serialLow'         '0x00'             
   ]
        // 4.10.3.2.8 Coding of the field RPCObjectUUID 
DEA00000-6C97-11D1-8271-{instanceOrNodeNumber}{deviceId}{vendorId}
        // Apache Vendor Id: 0x060B
        // PLC4X Profinet Driver Device ID (can be chosen freely): 0xCAFE
        // NOTE: We can get the Device-Id and Vendor-Id from the PN-DCP search 
result of the browser.
        [const        uint 32           'uuid1'             '0xDEA00000'        
   ]
        [const        uint 16           'uuid2'             '0x6C97'            
   ]
        [const        uint 16           'uuid3'             '0x11D1'            
   ]
        [const        uint 16           'uuid4'             '0x8271'            
   ]
        [simple       uint 16           'instanceOrNodeNumber'                  
   ]
        [simple       uint 16           'deviceId'                              
   ]
        [simple       uint 16           'vendorId'                              
   ]
        // 4.10.3.2.9
        // Device Interface:            DEA00001-6C97-11D1-8271-00A02442DF7D
        // Controller Interface:        DEA00002-6C97-11D1-8271-00A02442DF7D
        // Supervisor Interface:        DEA00003-6C97-11D1-8271-00A02442DF7D
        // Parameter Server Interface:  DEA00004-6C97-11D1-8271-00A02442DF7D
        [const        uint 32           'interface1'        '0xDEA00001'        
   ]
        [const        uint 16           'interface2'        '0x6C97'            
   ]
        [const        uint 16           'interface3'        '0x11D1'            
   ]
        [const        uint 16           'interface4'        '0x8271'            
   ]
        [const        uint 16           'interface5'        '0x00A0'            
   ]
        [const        uint 32           'interface6'        '0x2442DF7D'        
   ]
        // 4.10.3.2.10
        // The Controller and the Device generate the uuid for each AR 
(Application Relationship) and use them as long as the AR exists
        [const        uint 32           'activity'                              
   ]
        [const        uint 16           'activity2'         '0x0000'            
   ]
        [const        uint 16           'activity3'         '0x1010'            
   ]
        [const        uint 16           'activity4'        '0xAA25'             
   ]
        [const        uint 32           'activity5'        '0x606D3C3D'         
   ]
        [const        uint 16           'activity6'        '0xA9A3'             
   ]
        [const        uint 32           'serverBootTime'                        
   ]
        [const        uint 32           'interfaceVer'      '0x00000001'        
   ]
        [const        uint 32           'sequenceNumber'                        
   ]
        [const        DceRpc_Operation  'operation'                             
   ]
        [const        uint 16           'interfaceHint'     '0xFFFF'            
   ]
        [const        uint 16           'activityHint'      '0xFFFF'            
   ]
        [const        uint 16           'fragmentLength'    
'payload.lengthInBytes']
        [const        uint 16           'fragmentNum'       '0x0000'            
   ]
        [const        uint 8            'authProto'         '0x00'              
   ]
        [const        uint 8            'serialLow2'        '0x00'              
   ]// TODO: Check this ...
        [simple       PnIoCm_Packet     'payload'           ['packetType']      
   ]
    ]
]

The endianess switching would also apply tot he PnIoCm_Packet automatically.


The other option would be:

[discriminatedType 'DceRpc_Packet'
    [const         uint 8            'version'           '0x04'                 
]
    [discriminator DceRpc_PacketType 'packetType'                               
]
    [typeSwitch 'packetType'
        ['REQUEST'  DceRpc_Packet_Req
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '1'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '0'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '0'     
]
            [reserved uint 1         '0x0'                                      
]
        ]

        ['RESPONSE' DceRpc_Packet_Res
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '0'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '1'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '1'     
]
            [reserved uint 1         '0x0'                                      
]
        ]

        ['REJECT' DceRpc_Packet_Rej
            [reserved uint 1         '0x0'                                      
]
            [const    uint 1         'broadcast'                        '0'     
]
            [const    uint 1         'idempotent'                       '0'     
]
            [const    uint 1         'maybe'                            '0'     
]
            [const    uint 1         'noFragmentAcknowledgeRequested'   '0'     
]
            [const    uint 1         'fragment'                         '0'     
]
            [const    uint 1         'lastFragment'                     '0'     
]
            [reserved uint 1         '0x0'                                      
]
        ]
    ]
    [reserved      uint 6            '0x00'                                     
]
    [const         uint 1            'cancelWasPending'                 '0'     
]
    [reserved      uint 1            '0x0'                                      
]
    [simple        IntegerEncoding   'integerEncoding'                          
]
    [simple        CharacterEncoding 'characterEncoding'                        
]
    [simple        FloatingPointEncoding 'floatingPointEncoding'                
]
    [simple        DceRpc_PacketPayload 'payload' endianess='integerEncoding'   
]
]

[type 'DceRpc_PacketPayload'
    [const         uint 8            'serialHigh'        '0x00'                ]
    [const         uint 8            'serialLow'         '0x00'                ]
    // 4.10.3.2.8 Coding of the field RPCObjectUUID 
DEA00000-6C97-11D1-8271-{instanceOrNodeNumber}{deviceId}{vendorId}
    // Apache Vendor Id: 0x060B
    // PLC4X Profinet Driver Device ID (can be chosen freely): 0xCAFE
    // NOTE: We can get the Device-Id and Vendor-Id from the PN-DCP search 
result of the browser.
    [const        uint 32           'uuid1'             '0xDEA00000'           ]
    [const        uint 16           'uuid2'             '0x6C97'               ]
    [const        uint 16           'uuid3'             '0x11D1'               ]
    [const        uint 16           'uuid4'             '0x8271'               ]
    [simple       uint 16           'instanceOrNodeNumber'                     ]
    [simple       uint 16           'deviceId'                                 ]
    [simple       uint 16           'vendorId'                                 ]
    // 4.10.3.2.9
    // Device Interface:            DEA00001-6C97-11D1-8271-00A02442DF7D
    // Controller Interface:        DEA00002-6C97-11D1-8271-00A02442DF7D
    // Supervisor Interface:        DEA00003-6C97-11D1-8271-00A02442DF7D
    // Parameter Server Interface:  DEA00004-6C97-11D1-8271-00A02442DF7D
    [const        uint 32           'interface1'        '0xDEA00001'           ]
    [const        uint 16           'interface2'        '0x6C97'               ]
    [const        uint 16           'interface3'        '0x11D1'               ]
    [const        uint 16           'interface4'        '0x8271'               ]
    [const        uint 16           'interface5'        '0x00A0'               ]
    [const        uint 32           'interface6'        '0x2442DF7D'           ]
    // 4.10.3.2.10
    // The Controller and the Device generate the uuid for each AR (Application 
Relationship) and use them as long as the AR exists
    [const        uint 32           'activity'                                 ]
    [const        uint 16           'activity2'         '0x0000'               ]
    [const        uint 16           'activity3'         '0x1010'               ]
    [const        uint 16           'activity4'        '0xAA25'                ]
    [const        uint 32           'activity5'        '0x606D3C3D'            ]
    [const        uint 16           'activity6'        '0xA9A3'                ]
    [const        uint 32           'serverBootTime'                           ]
    [const        uint 32           'interfaceVer'      '0x00000001'           ]
    [const        uint 32           'sequenceNumber'                           ]
    [const        DceRpc_Operation  'operation'                                ]
    [const        uint 16           'interfaceHint'     '0xFFFF'               ]
    [const        uint 16           'fragmentNum'       '0x0000'               ]
    [const        uint 16           'activityHint'      '0xFFFF'               ]
    [const        uint 16           'fragmentLength'    'payload.lengthInBytes']
    [const        uint 8            'authProto'         '0x00'                 ]
    [const        uint 8            'serialLow2'        '0x00'                 
]// TODO: Check this ...
    [simple       PnIoCm_Packet     'payload'           ['packetType']         ]
]

Thinking about it ... we might even have a third option: Explicitly defininig 
the endianess in the complex type (Just a quick thought perhaps name things 
differently):


// Big Endian
[discriminatedType 'PnIoCm_Block' endianess=BIG_ENDIAN
    [discriminator PnIoCm_BlockType 'blockType'                           ]
    [implicit      uint 16          'blockLength'      'lengthInBytes - 4']
    [simple        uint 8           'blockVersionHigh'                    ]
    [simple        uint 8           'blockVersionLow'                     ]
 ...

I have to admit, that I sort of like option 1 and 3 ... but we might even 
support all 3 variants. The implementation shouldn't be too hard.

And thinking even more about it ... perhaps this concept of adding name=value 
pairs to the type declaration and the fields could also be used to controll 
Sebasitan's "try" flag.

Chris


Reply via email to