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/dhcp/client.c b/src/vnet/dhcp/client.c
index 472de52..aaeda96 100644
--- a/src/vnet/dhcp/client.c
+++ b/src/vnet/dhcp/client.c
@@ -17,6 +17,7 @@
 #include <vnet/dhcp/client.h>
 #include <vnet/dhcp/dhcp_proxy.h>
 #include <vnet/fib/fib_table.h>
+#include <vnet/qos/qos_types.h>
 
 dhcp_client_main_t dhcp_client_main;
 static u8 *format_dhcp_client_state (u8 * s, va_list * va);
@@ -434,6 +435,19 @@
   ip->ttl = 128;
   ip->protocol = IP_PROTOCOL_UDP;
 
+  ip->tos = c->dscp;
+
+  if (ip->tos)
+    {
+      /*
+       * Setup the buffer's QoS settings so any QoS marker on the egress
+       * interface, that might set VLAN CoS bits, based on this DSCP setting
+       */
+      vnet_buffer2 (b)->qos.source = QOS_SOURCE_IP;
+      vnet_buffer2 (b)->qos.bits = ip->tos;
+      b->flags |= VNET_BUFFER_F_QOS_DATA_VALID;
+    }
+
   if (is_broadcast)
     {
       /* src = 0.0.0.0, dst = 255.255.255.255 */
@@ -825,6 +839,9 @@
 	      format_vnet_sw_if_index_name, dcm->vnet_main, c->sw_if_index,
 	      format_dhcp_client_state, c->state);
 
+  if (0 != c->dscp)
+    s = format (s, "dscp %d ", c->dscp);
+
   if (c->leased_address.as_u32)
     {
       s = format (s, "addr %U/%d gw %U",
@@ -942,6 +959,7 @@
       c->hostname = a->hostname;
       c->client_identifier = a->client_identifier;
       c->set_broadcast_flag = a->set_broadcast_flag;
+      c->dscp = a->dscp;
       c->ai_ucast = ADJ_INDEX_INVALID;
       c->ai_bcast = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4,
 					 VNET_LINK_IP4,
@@ -1011,7 +1029,7 @@
 		    u8 * hostname,
 		    u8 * client_id,
 		    dhcp_event_cb_t event_callback,
-		    u8 set_broadcast_flag, u32 pid)
+		    u8 set_broadcast_flag, ip_dscp_t dscp, u32 pid)
 {
   dhcp_client_add_del_args_t _a, *a = &_a;
   int rv;
@@ -1023,6 +1041,7 @@
   a->pid = pid;
   a->event_callback = event_callback;
   a->set_broadcast_flag = set_broadcast_flag;
+  a->dscp = dscp;
   vec_validate (a->hostname, strlen ((char *) hostname) - 1);
   strncpy ((char *) a->hostname, (char *) hostname, vec_len (a->hostname));
   vec_validate (a->client_identifier, strlen ((char *) client_id) - 1);
diff --git a/src/vnet/dhcp/client.h b/src/vnet/dhcp/client.h
index a79d6e5..5191fcf 100644
--- a/src/vnet/dhcp/client.h
+++ b/src/vnet/dhcp/client.h
@@ -89,6 +89,8 @@
   adj_index_t ai_ucast;
   /* the broadcast adjacency on the link */
   adj_index_t ai_bcast;
+  /* IP DSCP to set in sent packets */
+  ip_dscp_t dscp;
 
   dhcp_event_cb_t event_callback;
 } dhcp_client_t;
@@ -121,6 +123,7 @@
   /* Information used for event callback */
   u32 client_index;
   u32 pid;
+  ip_dscp_t dscp;
   dhcp_event_cb_t event_callback;
 } dhcp_client_add_del_args_t;
 
@@ -143,7 +146,8 @@
 			       u8 * hostname,
 			       u8 * client_id,
 			       dhcp_event_cb_t event_callback,
-			       u8 set_broadcast_flag, u32 pid);
+			       u8 set_broadcast_flag,
+			       ip_dscp_t dscp, u32 pid);
 
 /**
  * callback function for clients walking the DHCP client configurations
diff --git a/src/vnet/dhcp/dhcp.api b/src/vnet/dhcp/dhcp.api
index 033c7a3..6db9033 100644
--- a/src/vnet/dhcp/dhcp.api
+++ b/src/vnet/dhcp/dhcp.api
@@ -15,6 +15,8 @@
 
 option version = "2.0.1";
 
+import "vnet/ip/ip_types.api";
+
 /** \brief DHCP Proxy config add / del request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -70,6 +72,7 @@
            via dhcp_compl_event API message if non-zero
     @param set_broadcast_flag - in the DHCP Discover to control
                                 how the resulting OFFER is addressed.
+    @param dscp - DSCP value set in IP packets sent by the client
     @param pid - sender's pid
 */
 typeonly define dhcp_client
@@ -79,6 +82,7 @@
   u8 id[64];
   u8 want_dhcp_event;
   u8 set_broadcast_flag;
+  vl_api_ip_dscp_t dscp;
   u32 pid;
 };
 
diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c
index 7eb2bf4..7935ad8 100644
--- a/src/vnet/dhcp/dhcp_api.c
+++ b/src/vnet/dhcp/dhcp_api.c
@@ -28,6 +28,7 @@
 #include <vnet/dhcp/dhcp6_ia_na_client_dp.h>
 #include <vnet/dhcp/dhcp6_client_common_dp.h>
 #include <vnet/fib/fib_table.h>
+#include <vnet/ip/ip_types_api.h>
 
 #include <vnet/vnet_msg_enum.h>
 
@@ -263,6 +264,7 @@
   else
     vclient->want_dhcp_event = 0;
   vclient->set_broadcast_flag = client->set_broadcast_flag;
+  vclient->dscp = ip_dscp_encode (client->dscp);
   vclient->pid = client->pid;
 }
 
@@ -292,14 +294,13 @@
   vlib_main_t *vm = vlib_get_main ();
   vl_api_dhcp_client_config_reply_t *rmp;
   u32 sw_if_index;
+  ip_dscp_t dscp;
   int rv = 0;
 
+  VALIDATE_SW_IF_INDEX (&(mp->client));
+
   sw_if_index = ntohl (mp->client.sw_if_index);
-  if (!vnet_sw_if_index_is_api_valid (sw_if_index))
-    {
-      rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
-      goto bad_sw_if_index;
-    }
+  dscp = ip_dscp_decode (mp->client.dscp);
 
   rv = dhcp_client_config (mp->is_add,
 			   mp->client_index,
@@ -310,10 +311,10 @@
 			   (mp->client.want_dhcp_event ?
 			    dhcp_compl_event_callback :
 			    NULL),
-			   mp->client.set_broadcast_flag, mp->client.pid);
+			   mp->client.set_broadcast_flag,
+			   dscp, mp->client.pid);
 
   BAD_SW_IF_INDEX_LABEL;
-
   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
 }