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 ) ); } };
精彩评论