Subject: Re: ECN and the DSCP field
To: None <tech-net@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 06/06/2006 12:13:11
On Tue, Jun 06, 2006 at 05:49:39PM +0100, Rui Paulo wrote:
> Hi,
> As you might know, RFC 2474 introduces a new field called
> "Differentiated Services".
> 
> Quoting the RFC:
> 
>    The DS field structure is presented below:
> 
> 
>         0   1   2   3   4   5   6   7
>       +---+---+---+---+---+---+---+---+
>       |         DSCP          |  CU   |
>       +---+---+---+---+---+---+---+---+
> 
>         DSCP: differentiated services codepoint
>         CU:   currently unused
> 
> This replaces the ip_tos field with a more fine grained type of
> service control.
> DSCP can have serveral values, assigned from IANA and available from:
> http://www.iana.org/assignments/dscp-registry.
> 
> The CU bits are now used by ECN indicating (from RFC 3168):
> 
>    Bits 6-7, ECN Field:
> 
>    Binary  Keyword                                  References
>    ------  -------                                  ----------
>      00     Not-ECT (Not ECN-Capable Transport)     [RFC 3168]
>      01     ECT(1) (ECN-Capable Transport(1))       [RFC 3168]
>      10     ECT(0) (ECN-Capable Transport(0))       [RFC 3168]
>      11     CE (Congestion Experienced)             [RFC 3168]
> 
> So, what I was thinking was replacing our ip_tos field in 'struct ip'
> by something like:
> 
> struct ip {
> 
> 	[...]
> 
> 	union {
> 		struct ip_ds {		/* differentiated services */
> #if BYTE_ORDER == LITTLE_ENDIAN
> 			u_int8_t  ds_ecn:2;	/* ecn field */
> 			u_int8_t  ds_cp:6;	/* diffserv codepoint */
> #endif
> #if BYTE_ORDER == BIG_ENDIAN
> 			u_int8_t  ds_cp:6;	/* diffserv codepoint */
> 			u_int8_t  ds_ecn:2;	/* ecn field */
> #endif
> 		} ip_ds __attribute__((__packed__));

I think bitfields are just fine for flags and other tiny fields, but
I object to the use of bitfields to define any binary format.  I don't
think the C standard guarantees any particular bit order, and I would
have to pull out GCC's manual to interpret your ip_ds definition, above.
At a glance, the LITTLE_ENDIAN definition looks backwards.

For defining bitfields, I prefer to use the __BITS() and __BIT() macros.
The resulting definitions are easy to read, to write, and to cross-check
with an RFC or a datasheet:

>         0   1   2   3   4   5   6   7
>       +---+---+---+---+---+---+---+---+
>       |         DSCP          |  CU   |
>       +---+---+---+---+---+---+---+---+

struct ip {

	[...]

	union {
		uint8_t	ip_ds;		/* differentiated services */
#define	IP_DS_ECN_MASK	__BITS(7,6)	/* ecn field */
#define	IP_DS_CP_MASK	__BITS(5,0)	/* diffserv codepoint */
		uint8_t	ip_tos;	/* type of service */
	} ip_dsf __attribute__((__packed__));
}

Reading/writing the fields is easy with SHIFTIN()/SHIFTOUT().

(I still owe NetBSD a manual page on these macros....)

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933