1

Solaris 10 SPARC
Sun Studio C编译器 12.3

在 SPARC64 机器上,如果您访问的变量在相关的 4 或 8 字节边界上未正确对齐,您将获得核心转储。这需要编码人员跳过几个环节来应对这个要求,(但也让你编写可移植的代码)。

如果我们有一个模拟网络协议头的C结构(即这 16 位是端口,这 8 位是标志等),如果我们使用对齐指令来适应 SPARC64 处理器,这是否仍然保留字节映射,否则一切都会破裂。是否有逻辑从结构的布局中隐藏字节存储的实现。

typedef struct TCPHdr_
{
    uint16_t th_sport;  /**< source port */
    uint16_t th_dport;  /**< destination port */
    uint32_t th_seq;    /**< sequence number */
    uint32_t th_ack;    /**< acknowledgement number */
    uint8_t th_offx2;   /**< offset and reserved */
    uint8_t th_flags;   /**< pkt flags */
    uint16_t th_win;    /**< pkt window */
    uint16_t th_sum;    /**< checksum */
    uint16_t th_urp;    /**< urgent pointer */
} TCPHdr;

像这样对齐:

typedef struct TCPHdr_
{
    uint16_t th_sport    __attribute__((aligned(8))); /**< source port */
    uint16_t th_dport    __attribute__((aligned(8))); /**< destination port */
    uint32_t th_seq      __attribute__((aligned(8))); /**< sequence number */
    uint32_t th_ack      __attribute__((aligned(8))); /**< acknowledgement number */
    uint8_t th_offx2     __attribute__((aligned(8))); /**< offset and reserved */
    uint8_t th_flags     __attribute__((aligned(8))); /**< pkt flags */
    uint16_t th_win      __attribute__((aligned(8))); /**< pkt window */
    uint16_t th_sum      __attribute__((aligned(8))); /**< checksum */
    uint16_t th_urp      __attribute__((aligned(8))); /**< urgent pointer */
} TCPHdr;

大多数情况下,它是关于这样的代码的查询:

SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(TCPHdr) + payload_len);

p1->tcph = (TCPHdr *)raw_tcp;

其中原始字节被转换为结构或sizeof()测试结构的大小。它还能工作还是新结构不能映射网络字节?

4

2 回答 2

0

作为记录,这是我正在使用的结构:

typedef struct TCPHdr_raw_ {
    union {
        uint16_t   th_sport;     /**< source port */
        uint8_t    th_sport8[2]; /**< source port */
    } sport;
    union {
        uint16_t   th_dport;     /**< destination port */
        uint8_t    th_dport8[2]; /**< destination port */
    } dport;
    union {
        uint32_t    th_seq;      /**< sequence number */
        uint8_t     th_seq8[4];  /**< sequence number */
    } seq;
    union {
        uint32_t    th_ack;      /**< acknowledgement number */
        uint8_t     th_ack8[4];  /**< acknowledgement number */
    } ack;
    uint8_t         th_offx2;    /**< offset and reserved */
    uint8_t         th_flags;    /**< pkt flags */
    union {
        uint16_t    th_win;      /**< pkt window */
        uint8_t     th_win8[2];  /**< pkt window */
    } win;
    union {
        uint16_t    th_sum;       /**< checksum */
        uint8_t     th_sum8[2];   /**< checksum */
    } sum;
    union {
        uint16_t    th_urp;       /**< urgent pointer */
        uint8_t     th_urp8[2];   /**< urgent pointer */
    } urp;
} TCPHdr_raw;

typedef struct TCPHdr_
{
    uint16_t th_sport  __attribute__((aligned(8))); /**< source port */
    uint16_t th_dport  __attribute__((aligned(8))); /**< destination port */
    uint32_t th_seq    __attribute__((aligned(8))); /**< sequence number */
    uint32_t th_ack    __attribute__((aligned(8))); /**< acknowledgement number */
    uint8_t th_offx2   __attribute__((aligned(8))); /**< offset and reserved */
    uint8_t th_flags   __attribute__((aligned(8))); /**< pkt flags */
    uint16_t th_win    __attribute__((aligned(8))); /**< pkt window */
    uint16_t th_sum    __attribute__((aligned(8))); /**< checksum */
    uint16_t th_urp    __attribute__((aligned(8))); /**< urgent pointer */
} TCPHdr;

和这样的例程:

copy_raw_tcp_header(&(p->tcph), &tcph);

void copy_raw_tcp_header(TCPHdr *tcph, uint8_t *pktdata) {
    TCPHdr_raw *raw_tcp_hdr = (TCPHdr_raw *)pktdata;

    memcpy(&tcph->sport,  &raw_tcp_hdr->sport.th_sport8, sizeof(uint16_t));
    memcpy(&tcph->dport,  &raw_tcp_hdr->dport.th_dport8, sizeof(uint16_t));
    memcpy(&tcph->seq,    &raw_tcp_hdr->seq.th_seq8,     sizeof(uint32_t));
    memcpy(&tcph->ack,    &raw_tcp_hdr->ack.th_ack8,     sizeof(uint32_t));
    tcph->th_offx2       = raw_tcp_hdr->th_offx2;
    tcph->th_flags       = raw_tcp_hdr->th_flags;
    memcpy(&tcph->th_win, &raw_tcp_hdr->win.th_win8,     sizeof(uint16_t));
    memcpy(&tcph->th_sum, &raw_tcp_hdr->sum.th_sum8,     sizeof(uint16_t));
    memcpy(&tcph->th_urp, &raw_tcp_hdr->urp.th_urp8,     sizeof(uint16_t));
}

像这样替换以前的代码:

p->tcph = &tcph;
于 2013-10-31T00:59:44.283 回答
0

您可以将未对齐的结构转换为其对齐的版本,但数据将是错误的。您需要手动将数据放在内存中的正确位置。例如,函数 *unaligned_to_aligned* 可以逐字段复制数据。它可以使用联合来避免核心转储。处理来自网络的原始数据时,请考虑字节序。网络协议和您的平台在内存中可以有不同的数字表示,您可能需要更改 *int*s、*short*s 等中的字节顺序。

于 2013-10-29T00:22:36.367 回答