dhcp ip: DSCP settings for transmitted DHCP packets

Type: feature

- Define the ip_dscp_t and use in the IP headers
- Add DSCP setting to the DHCP client for use with packet TX

Change-Id: If220dde0017ea78793747d65f53e11daf23a28fa
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ip/ip.c b/src/vnet/ip/ip.c
index 6e8ac7c..133767b 100644
--- a/src/vnet/ip/ip.c
+++ b/src/vnet/ip/ip.c
@@ -294,6 +294,23 @@
   return (format (s, "unknown"));
 }
 
+u8 *
+format_ip_dscp (u8 * s, va_list * va)
+{
+  ip_dscp_t dscp = va_arg (*va, u32);	// int promotion of u8
+
+  switch (dscp)
+    {
+#define _(n,v)                                                  \
+    case IP_DSCP_##v:                                           \
+      return (format (s, "%s", #v));
+      foreach_ip_dscp
+#undef _
+    }
+
+  return (format (s, "unknon"));
+}
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
diff --git a/src/vnet/ip/ip4_packet.h b/src/vnet/ip/ip4_packet.h
index 2ce6763..c1852fc 100644
--- a/src/vnet/ip/ip4_packet.h
+++ b/src/vnet/ip/ip4_packet.h
@@ -138,7 +138,7 @@
     u8 ip_version_and_header_length;
 
     /* Type of service. */
-    u8 tos;
+    ip_dscp_t tos;
 
     /* Total layer 3 packet length including this header. */
     u16 length;
diff --git a/src/vnet/ip/ip6_packet.h b/src/vnet/ip/ip6_packet.h
index c8bc4c8..c1bd2aa 100644
--- a/src/vnet/ip/ip6_packet.h
+++ b/src/vnet/ip/ip6_packet.h
@@ -383,13 +383,13 @@
   ip6_address_t src_address, dst_address;
 } ip6_header_t;
 
-always_inline u8
+always_inline ip_dscp_t
 ip6_traffic_class (const ip6_header_t * i)
 {
   return (i->ip_version_traffic_class_and_flow_label & 0x0FF00000) >> 20;
 }
 
-static_always_inline u8
+static_always_inline ip_dscp_t
 ip6_traffic_class_network_order (const ip6_header_t * ip6)
 {
   return (clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label)
@@ -397,7 +397,7 @@
 }
 
 static_always_inline void
-ip6_set_traffic_class_network_order (ip6_header_t * ip6, u8 dscp)
+ip6_set_traffic_class_network_order (ip6_header_t * ip6, ip_dscp_t dscp)
 {
   u32 tmp =
     clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label);
diff --git a/src/vnet/ip/ip_packet.h b/src/vnet/ip/ip_packet.h
index c499097..97b3c96 100644
--- a/src/vnet/ip/ip_packet.h
+++ b/src/vnet/ip/ip_packet.h
@@ -84,6 +84,44 @@
 #undef _
 } ip_multicast_group_t;
 
+
+/**
+ * The set of RFC defined DSCP values.
+ */
+#define foreach_ip_dscp                       \
+  _(0, CS0)                                   \
+  _(8, CS1)                                   \
+  _(10, AF11)                                 \
+  _(12, AF12)                                 \
+  _(14, AF13)                                 \
+  _(16, CS2)                                  \
+  _(18, AF21)                                 \
+  _(20, AF22)                                 \
+  _(22, AF23)                                 \
+  _(24, CS3)                                  \
+  _(26, AF31)                                 \
+  _(28, AF32)                                 \
+  _(30, AF33)                                 \
+  _(32, CS4)                                  \
+  _(34, AF41)                                 \
+  _(36, AF42)                                 \
+  _(38, AF43)                                 \
+  _(40, CS5)                                  \
+  _(46, EF)                                   \
+  _(48, CS6)                                  \
+  _(50, CS7)
+
+typedef enum ip_dscp_t_
+{
+#define _(n,f) IP_DSCP_##f = n,
+  foreach_ip_dscp
+#undef _
+} __clib_packed ip_dscp_t;
+
+STATIC_ASSERT_SIZEOF (ip_dscp_t, 1);
+
+extern u8 *format_ip_dscp (u8 * s, va_list * va);
+
 /* IP checksum support. */
 
 static_always_inline u16
diff --git a/src/vnet/ip/ip_types.api b/src/vnet/ip/ip_types.api
index 8b46a1d..13c6a4a 100644
--- a/src/vnet/ip/ip_types.api
+++ b/src/vnet/ip/ip_types.api
@@ -34,8 +34,8 @@
 
 /* DSCP code points - RFC 2474
    https://tools.ietf.org/html/rfc2474
+   Values other than these RFC defined values are accepted.
 */
-
 enum ip_dscp : u8 {
   IP_API_DSCP_CS0 =  0,
   IP_API_DSCP_CS1 = 8,
diff --git a/src/vnet/ip/ip_types_api.c b/src/vnet/ip/ip_types_api.c
index 0343d20..ca26731 100644
--- a/src/vnet/ip/ip_types_api.c
+++ b/src/vnet/ip/ip_types_api.c
@@ -95,6 +95,18 @@
   return (clib_host_to_net_u32 (IP_API_PROTO_TCP));
 }
 
+ip_dscp_t
+ip_dscp_decode (u8 in)
+{
+  return ((ip_dscp_t) in);
+}
+
+u8
+ip_dscp_encode (ip_dscp_t dscp)
+{
+  return (dscp);
+}
+
 void
 ip6_address_encode (const ip6_address_t * in, vl_api_ip6_address_t out)
 {
diff --git a/src/vnet/ip/ip_types_api.h b/src/vnet/ip/ip_types_api.h
index 4c79bf1..fc7a416 100644
--- a/src/vnet/ip/ip_types_api.h
+++ b/src/vnet/ip/ip_types_api.h
@@ -41,6 +41,8 @@
 extern int ip_address_family_encode (ip_address_family_t af);
 extern int ip_proto_decode (int _af, ip_protocol_t * out);
 extern int ip_proto_encode (ip_protocol_t af);
+extern ip_dscp_t ip_dscp_decode (u8 _dscp);
+extern u8 ip_dscp_encode (ip_dscp_t dscp);
 
 /**
  * Decode/Encode for struct/union types