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);
}
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
diff --git a/src/vnet/mpls/packet.h b/src/vnet/mpls/packet.h
index ca6ac40..8573bc3 100644
--- a/src/vnet/mpls/packet.h
+++ b/src/vnet/mpls/packet.h
@@ -1,6 +1,3 @@
-#ifndef included_vnet_mpls_packet_h
-#define included_vnet_mpls_packet_h
-
/*
* MPLS packet format
*
@@ -18,6 +15,11 @@
* limitations under the License.
*/
+#ifndef included_vnet_mpls_packet_h
+#define included_vnet_mpls_packet_h
+
+#include <vnet/ip/ip_packet.h>
+
/**
* A label value only, i.e. 20bits.
*/
@@ -55,7 +57,7 @@
/**
* When in uniform mode convert an IPv[46] DSCP value to an MPLS EXP value
*/
-static inline u8 ip_dscp_to_mpls_exp (u8 tos)
+static inline u8 ip_dscp_to_mpls_exp (ip_dscp_t tos)
{
return (tos >> 5);
}