mordorwww 发表于 2016-06-22 17:48

tcp报文收发时, data offset 的ushort是否需要做字节序转换?

如下的黑体部分

0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Data |         |U|A|P|R|S|F |                               |
   | Offset | Res   |R|C|S|S|Y |I |            Window             |
   |         |          |G|K|H|T|N |N |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Checksum            |         Urgent Pointer      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  Options                  |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



struct tcphdr {
        __be16        source;
        __be16        dest;
        __be32        seq;
        __be32        ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u16        res1:4,
                doff:4,
                fin:1,
                syn:1,
                rst:1,
                psh:1,
                ack:1,
                urg:1,
                ece:1,
                cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
        __u16        doff:4,
                res1:4,
                cwr:1,
                ece:1,
                urg:1,
                ack:1,
                psh:1,
                rst:1,
                syn:1,
                fin:1;
#else

Godbach 发表于 2016-06-22 18:19

回复 1# mordorwww

就 4 个 bit,不需要转换的。直接用。字节序,是超过一个 byte 时需要考虑的。


   

mordorwww 发表于 2016-06-23 08:48

Godbach 发表于 2016-06-22 18:19 static/image/common/back.gif
回复 1# mordorwww

就 4 个 bit,不需要转换的。直接用。字节序,是超过一个 byte 时需要考虑的。


我是问她所在的这个 ___u16不用转换吧

Godbach 发表于 2016-06-23 10:47

回复 3# mordorwww

所在的 _u16 已经按照 bitfield 分出去了,你直接通过结构体对应的各自成员去访问就成了。你没有必要一下子读取整个 _u16 的值啊,或者是这个 _u16 的数值对你来说没有用处。

只有你需要一次读取超过 1 个 bytes 的数值时,才需要考虑字节序的转换。

mordorwww 发表于 2016-06-23 11:33

本帖最后由 mordorwww 于 2016-06-23 11:45 编辑

Godbach 发表于 2016-06-23 10:47 static/image/common/back.gif
回复 3# mordorwww

所在的 _u16 已经按照 bitfield 分出去了,你直接通过结构体对应的各自成员去访问就 ...

下面这种奇葩的定义见过没

我觉得应该是要对整个64bits做字节序转换,虽然位域没有超过或者达到8bits,但是好几个都跨bytes甚至跨short了。手头上没有big的CPU,没法验证

#if __BYTE_ORDER != __LITTLE_ENDIAN

      uint32_t Odo:32;
      uint16_t BmprHghtFnt:7;
      uint16_t BmprHghtRear:7;
      uint16_t VehHght:7;
      uint16_t VehMass:7;
      uint16_t VehType:4;

#else// __BYTE_ORDER != __BIG_ENDIAN
      uint16_t VehType:4;
      uint16_t VehMass:7;
      uint16_t VehHght:7;
      uint16_t BmprHghtRear:7;
      uint16_t BmprHghtFnt:7;
      uint32_t Odo:32;

#endif

_nosay 发表于 2016-06-23 12:38

回复 5# mordorwww

那你把数字反着写不能验证么?

_nosay 发表于 2016-06-23 12:39

那你把数字反着写不能验证么?

Godbach 发表于 2016-06-23 16:45

回复 5# mordorwww
这个人家结构体定义的时候已经考虑好了。你就按照单个成员访问就行了。超过一个字节的,要考虑这个问题。


   

karma303 发表于 2016-06-26 09:22

本帖最后由 karma303 于 2016-06-26 09:27 编辑

结构体内bitfield的顺序是对byte endian敏感的。
并不是说x86或MIPS除了byte order之外,还有bit order的区别。
这个问题的根源在于编译器。纯粹是编译器作怪。展开讲话就多了。暂且不表。
不过我可以告诉你一个技巧,如果位域不跨字节的,大小端的变换是有规律的。
像小端模式的一个结构体:
struct abcdef {
        int a: 4;
        int b: 4;
        int c: 4;
        int d: 2;
        int e: 2;
};
你想让它在MIPS上的gcc编译后有同样的内存布局,方法是:从上到下,位域每8个bit一组,反转组内的成员顺序。结果是这样:
struct abcdef {
        int b: 4;
        int a: 4;
        int e: 2;
        int d: 2;
        int c: 4;
};
如果位域跨字节,那我就没有办法了。你贴出来的那个struct video什么的代码,我是看不懂的。

一般这种针对big/little endian的条件编译,是出于两种场合的需要。
(1)网络底层协议的传输,从host A传到 host B上,相当于一份远程的内存拷贝,网络协议必须规定这段内存(记作xxx)该以big or little endian的方式存放数据。 我们上面代码里#if #else条件编译,其实都是折腾编译器。我们希望我们的代码在MIPS和x86机器编译后,希望类似下面的代码的输出是一致的:
----------------------------------------------
struct tcphdr *hdr = (void *)xxx;
printf( "%d\n", hdr->res1);
---------------------------------------------

(2) 驱动代码里,我们要把bitfield与寄存器对应死。

自己写的一篇帖子,希望对题主有帮助。http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4248004&extra=
页: [1]
查看完整版本: tcp报文收发时, data offset 的ushort是否需要做字节序转换?