Browse Source

[trac703] Re-implement header fields to omit bit array

Suspect that problems on the Sun regarding ordering are caused by
the use of a bit field array and the layout of the fields in it.
Stephen Morris 14 years ago
parent
commit
cdf229b32e
1 changed files with 79 additions and 42 deletions
  1. 79 42
      tests/tools/badpacket/header_flags.h

+ 79 - 42
tests/tools/badpacket/header_flags.h

@@ -28,17 +28,27 @@ public:
 
     // The following declaration describes the various fields in the DNS
     // packet header.
-    struct Flags {
-        unsigned int rc : 4;
-        unsigned int cd : 1;
-        unsigned int ad : 1;
-        unsigned int z  : 1;    // Reserved
-        unsigned int ra : 1;
-        unsigned int rd : 1;
-        unsigned int tc : 1;
-        unsigned int aa : 1;
-        unsigned int op : 4;
-        unsigned int qr : 1;
+    enum FieldParameter {
+        QR_MASK = 0x8000,   // To get the value
+        QR_OFF  = 15,       // Shift this number of bits left to set the value
+        OP_MASK = 0x7800,
+        OP_OFF  = 11,
+        AA_MASK = 0x0400,
+        AA_OFF  = 10,
+        TC_MASK = 0x0200,
+        TC_OFF  = 9,
+        RD_MASK = 0x0100,
+        RD_OFF  = 8,
+        RA_MASK = 0x0080,
+        RA_OFF  = 7,
+        Z_MASK  = 0x0040,
+        Z_OFF   = 6,
+        AD_MASK = 0x0020,
+        AD_OFF  = 5,
+        CD_MASK = 0x0010,
+        CD_OFF  = 4,
+        RC_MASK = 0x000F,
+        RC_OFF  = 0
     };
 
     /// \brief Constructor
@@ -53,22 +63,22 @@ public:
         setValue(0);
     }
 
+    /// \brief Get Header Flags as 16-bit Value
+    uint16_t getValue() const {
+        return (flags_);
+    }
+
     /// \brief Set Header Flags as 16-Bit Value
     ///
     /// \param value 16-bit value to put into object as representing the
     ///        header flags.
     void setValue(uint16_t value) {
-        flags_.value = value;
-    }
-
-    /// \brief Get Header Flags as 16-bit Value
-    uint16_t getValue() const {
-        return flags_.value;
+        flags_ = value;
     }
 
     /// \brief Get QR Bit
     uint16_t getQR() const {
-        return flags_.fields.qr;
+        return (getField(QR_MASK, QR_OFF));
     }
 
     /// \brief Set QR Bit
@@ -76,12 +86,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setQR(uint16_t value) {
-        flags_.fields.qr = (value > 1) ? 1 : value;
+        setField(value, QR_MASK, QR_OFF);
     }
 
     /// \brief Get OP Value
     uint16_t getOP() const {
-        return flags_.fields.op;
+        return (getField(OP_MASK, OP_OFF));
     }
 
     /// \brief Set OP Value
@@ -89,12 +99,12 @@ public:
     /// \param value New value of the field, which must in the range 0 to 15:
     ///        values outside that range are coerced to the nearest boundary.
     void setOP(uint16_t value) {
-        flags_.fields.op = (value > 15) ? 15 : value;
+        setField(value, OP_MASK, OP_OFF);
     }
 
     /// \brief Get AA Bit
     uint16_t getAA() const {
-        return flags_.fields.aa;
+        return (getField(AA_MASK, AA_OFF));
     }
 
     /// \brief Set AA Bit
@@ -102,12 +112,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setAA(uint16_t value) {
-        flags_.fields.aa = (value > 1) ? 1 : value;
+        setField(value, AA_MASK, AA_OFF);
     }
 
     /// \brief Get TC Bit
     uint16_t getTC() const {
-        return flags_.fields.tc;
+        return (getField(TC_MASK, TC_OFF));
     }
 
     /// \brief Set TC Bit
@@ -115,12 +125,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setTC(uint16_t value) {
-        flags_.fields.tc = (value > 1) ? 1 : value;
+        setField(value, TC_MASK, TC_OFF);
     }
 
     /// \brief Get RD Bit
     uint16_t getRD() const {
-        return flags_.fields.rd;
+        return (getField(RD_MASK, RD_OFF));
     }
 
     /// \brief Set RD Bit
@@ -128,12 +138,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setRD(uint16_t value) {
-        flags_.fields.rd = (value > 1) ? 1 : value;
+        setField(value, RD_MASK, RD_OFF);
     }
 
     /// \brief Get RA Bit
     uint16_t getRA() const {
-        return flags_.fields.ra;
+        return (getField(RA_MASK, RA_OFF));
     }
 
     /// \brief Set RA Bit
@@ -141,12 +151,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setRA(uint16_t value) {
-        flags_.fields.ra = (value > 1) ? 1 : value;
+        setField(value, RA_MASK, RA_OFF);
     }
 
     /// \brief Get Z Bit
     uint16_t getZ() const {
-        return flags_.fields.z;
+        return (getField(Z_MASK, Z_OFF));
     }
 
     /// \brief Set Z Bit
@@ -154,12 +164,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setZ(uint16_t value) {
-        flags_.fields.z = (value > 1) ? 1 : value;
+        setField(value, Z_MASK, Z_OFF);
     }
 
     /// \brief Get AD Bit
     uint16_t getAD() const {
-        return flags_.fields.ad;
+        return (getField(AD_MASK, AD_OFF));
     }
 
     /// \brief Set AD Bit
@@ -167,12 +177,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setAD(uint16_t value) {
-        flags_.fields.ad = (value > 1) ? 1 : value;
+        setField(value, AD_MASK, AD_OFF);
     }
 
     /// \brief Get CD Bit
     uint16_t getCD() const {
-        return flags_.fields.cd;
+        return (getField(CD_MASK, CD_OFF));
     }
 
     /// \brief Set CD Bit
@@ -180,12 +190,12 @@ public:
     /// \param value New value of the field, which must be 0 or 1: values
     ///        outside that range are coerced to the nearest boundary.
     void setCD(uint16_t value) {
-        flags_.fields.cd = (value > 1) ? 1 : value;
+        setField(value, CD_MASK, CD_OFF);
     }
 
     /// \brief Get RC Value
     uint16_t getRC() const {
-        return flags_.fields.rc;
+        return (getField(RC_MASK, RC_OFF));
     }
 
     /// \brief Set RC Value
@@ -193,16 +203,43 @@ public:
     /// \param value New value of the field, which must be in the range 0 to 15:
     ///        values outside that range are coerced to the nearest boundary.
     void setRC(uint16_t value) {
-        flags_.fields.rc = (value > 15) ? 15 : value;
+        setField(value, RC_MASK, RC_OFF);
     }
 
 private:
 
-    // The variable that performs the conversion
-    union {
-        uint16_t        value;
-        Flags           fields;
-    } flags_;
+    /// \brief Get Field
+    ///
+    /// Return the value of a bit field in the flags word.
+    ///
+    /// \param mask Bit mask identifying the field.
+    /// \param offset Offset of the field in the flags word.
+    ///
+    /// \return Value of the field.
+    uint16_t getField(FieldParameter mask, FieldParameter offset) const {
+        return ((flags_ & mask) >> offset);
+    }
+
+    /// \brief Set Field
+    ///
+    /// Sets the value of a bit field.
+    ///
+    /// \param value Value to set.  If the value is more than the field can
+    ///        hold, it is set to the maximum.
+    /// \param mask Bit mask identifying the field.
+    /// \param offset Offset of the field in the flags word.
+    void setField(uint16_t value, FieldParameter mask, FieldParameter offset) {
+
+        // Ensure the value is within limits.
+        uint16_t maxval = mask >> offset;
+        uint16_t val = (value > maxval) ? maxval : value;
+
+        // Clear the field then set it with the value.
+        flags_ &= ~mask;
+        flags_ |= (val << offset);
+    }
+
+    uint16_t        flags_;     ///< Variable holding field values
 };
 
 } // namespace badpacket