2016-04-12 2 views
0

sには(uint16_t*)が使用されていますが、wには(uint32_t*)が使用されています。どうして?この機能はパケット内の宛先MACアドレスと送信元MACアドレスを入れ替えるために使用されますか?(uint16_t *)と(uint32_t *)の違いは何ですか?

static inline void  
swap_mac_addr(uint64_t pkt_ptr) 
{ 
    uint16_t s; 
    uint32_t w; 

    /* assuming an IP/IPV6 pkt i.e. L2 header is 2 byte aligned, 4 byte non-aligned */ 
    s = *(uint16_t*)pkt_ptr; 
    w = *(uint32_t*)(pkt_ptr+2); 
    *(uint16_t*)pkt_ptr = *(uint16_t*)(pkt_ptr+6);                     
    *(uint32_t*)(pkt_ptr+2) = *(uint32_t*)(pkt_ptr+8); 
    *(uint16_t*)(pkt_ptr+6) = s; 
    *(uint32_t*)(pkt_ptr+8) = w; 
} 
+6

このコードは厳密なエイリアシング規則に違反しているため、未定義の動作を示すものと見なす必要があります。 –

+0

@EugeneSh .:コメントに書かれていることを考慮に入れても(「*仮定していますか?」)? – alk

+0

@それでしょ? 16/32ビット整数へのポインタを持つ64ビット整数にアクセスする。これらは互換性のない型AFAIKへのポインタです。 –

答えて

1

コードは、イーサネットパケットへの応答を準備しているように見え、パケットヘッダーの宛先と送信元アドレスを入れ替えます。

MACアドレスは48ビットです。これは16 + 32で、開発者は16ビットデータ型と32ビットデータ型を使用することに決めました。既に指摘されているように、これは現代的で積極的に最適化されたコンパイラでは正しく動作しないかもしれません。それでも、32ビット値をメモリ(例えば、ARM)で32ビットに整列させたいと考えるアーキテクチャでは、動作しない可能性があります。

MACアドレスを多分バイトの配列とみなし、バイトを移動するためにmemcpyを使う方が良いでしょう。

パフォーマンスの観点から見ると、この構造体は、大規模なレジスタ転送を使用してデータを移動させる可能性があると認識しないかなりのダムコンパイラ(今日の基準を考慮)を使用すると役に立ちました。現代のコンパイラでは、たとえそれが適切に機能したとしても、そのようなものは性能に悪影響を及ぼすことさえあります。