开发者

Bigendian/Littleendian confusion

开发者 https://www.devze.com 2023-02-19 18:51 出处:网络
i am working on the legacy code, which is written for ipv4. Now i have added the similar code for ipv6. i have tried and tested on host machine..but i have concern whether it will work on the powerpc

i am working on the legacy code, which is written for ipv4. Now i have added the similar code for ipv6. i have tried and tested on host machine..but i have concern whether it will work on the powerpc , because of endianness...the code is to extract the ip header from the incoming stream and compress it..any comments will be helpful

开发者_如何学运维class st_ipv6
{
  //==================================================================================================
public:
  //==================================================================================================

#ifdef _BIG_ENDIAN
  uint32  version:4;              // version 
  uint32  trafficclass:8;         // header length 
  uint32  flowlabel:20;           // flow label
#else
  uint32  trafficclass_1:4;
  uint32  version:4;              // version 
  uint32  flowlabel_1:4; 
  uint32  trafficclass_2:4;         // traffic class
  uint32  flowlabel_2:4;           // flow label 
  uint32  flowlabel_3:4;           // flow label 
  uint32  flowlabel_4:4;           // flow label 
  uint32  flowlabel_5:4;           // flow label 
#endif
  uint16  payloadlength;          // payload length
  uint8   nextheader;             // next header
  uint8   hoplimit;               // hop limit
  uint32  sourceaddress[4];       // source address 
  uint32  destinationaddress[4];  // destination address 




#ifdef _BIG_ENDIAN
  //**********************************************************************************************
  //* Description:
  /**  Specify/Return IPv6 Version
  */
  //**********************************************************************************************
  inline void setVersion(uint8 ubyVersion)
  {
    version = ubyVersion;
  }
  inline uint8 getVersion()
  {
    return version;
  }


Bitfields and portability are generally a nightmare. It is usually better to use and/or/shift.

See e.g. below.

As long as you call hton*()/ntoh*() on the various integers as you read/write them you will (hopefully) have no problems.

I'd also write the rest of the accessors and make the data fields private.

class st_ipv6
{
public:
    uint32 version_info;
    uint16 payloadlength;          
    uint8  nextheader;             
    uint8  hoplimit;               
    uint32 sourceaddress[4];       
    uint32 destinationaddress[4]; 

    uint8 GetVersion() 
    { 
        return version_info & 0xF; 
    }
    void  SetVersion(uint8 v) 
    {
        version_info = (version_info & ~0xF) | (v & 0xF);
    }
    uint8 GetTrafficClass() 
    { 
        return (version_info & 0xFF0)>>4; 
    }
    void  SetTrafficClass(uint8 c) 
    {
        version_info = (version_info & ~0xFF0) | ((c & 0xFF) << 4);
    }
    uint32 GetFlowLabel() 
    { 
        return (version_info & 0xFFFFF000)>>12; 
    }
    void  SetFlowLabel(uint32 f) 
    {
        version_info = (version_info & ~0xFFFFF000) | ((f & 0xFFFFF) << 12);
    }
};


I would recommend using a struct rather a class as things like RTTI could insert extra things in the memory layout.

and I think this should be sufficient

#ifdef _BIG_ENDIAN
  uint32  version:4;              // version 
  uint32  trafficclass:8;         // header length 
  uint32  flowlabel:20;           // flow label
#else
  uint32  flowlabel:20;           // flow label
  uint32  trafficclass:8;         // header length 
  uint32  version:4;              // version 
#endif

...but you should ntohl(flowlabel) when reading the flowlabel and htonl(flowlabel) when setting it.


Be careful with different compilers and using bitfields. Some compilers start the bitfield at the high bit and work downward while others work from the low bit. You are better off doing the masking from the raw bytes yourself unless you test carefully across the different compilers you are using.


thanks a lot Michael. Based on inputs i wrote a simple version of the function and tried to do the basic test and it looks ok for the version fields. My program looks like this. Only concern now is, when we have array of uint32's like src and dst address

class ip_v6{

public: uint32 version_info; uint16 payload_len; uint8 next_header; uint8 hop_limit; uint32 src_addr[4]; uint32 dst_addr[4];

uint32 GetVersionInfo() { return ( ntohl(version_info)); }

void SetVersionInfo(uint32 vinfo) { version_info = htonl(vinfo); }

uint8 GetVersion() { return ( ( (GetVersionInfo() )& (0xf0000000)) >> 28); }

void SetVersion(uint8 v) { SetVersionInfo( ( GetVersionInfo() & 0x0fffffff ) | (v<<28)); }

uint8 GetTrafficClass() { return ( ( (GetVersionInfo() )& (0x0ff00000)) >> 20); }

void SetTrafficClass(uint8 c) { SetVersionInfo( (GetVersionInfo() & 0xf00fffff) |(c<<20 )) ; }

uint32 GetFlowLabel() { return ( (GetVersionInfo() )& (0x000fffff)) ; }

void SetFlowLabel(uint32 f) { SetVersionInfo( (GetVersionInfo() & 0xfff00000) |(f ) ); } };

0

精彩评论

暂无评论...
验证码 换一张
取 消