From 038e1dfbdfd0bd785852c364011da0a1d828093e Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 19 Jul 2019 14:01:02 +0000 Subject: 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 --- src/vnet/dhcp/client.c | 21 ++++++++++++++++++++- src/vnet/dhcp/client.h | 6 +++++- src/vnet/dhcp/dhcp.api | 4 ++++ src/vnet/dhcp/dhcp_api.c | 15 ++++++++------- src/vnet/ip/ip.c | 17 +++++++++++++++++ src/vnet/ip/ip4_packet.h | 2 +- src/vnet/ip/ip6_packet.h | 6 +++--- src/vnet/ip/ip_packet.h | 38 ++++++++++++++++++++++++++++++++++++++ src/vnet/ip/ip_types.api | 2 +- src/vnet/ip/ip_types_api.c | 12 ++++++++++++ src/vnet/ip/ip_types_api.h | 2 ++ src/vnet/mpls/packet.h | 10 ++++++---- 12 files changed, 117 insertions(+), 18 deletions(-) (limited to 'src/vnet') diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c index 472de5253ef..aaeda96327d 100644 --- a/src/vnet/dhcp/client.c +++ b/src/vnet/dhcp/client.c @@ -17,6 +17,7 @@ #include #include #include +#include dhcp_client_main_t dhcp_client_main; static u8 *format_dhcp_client_state (u8 * s, va_list * va); @@ -434,6 +435,19 @@ send_dhcp_pkt (dhcp_client_main_t * dcm, dhcp_client_t * c, 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_dhcp_client (u8 * s, va_list * va) 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 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a) 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 @@ dhcp_client_config (u32 is_add, 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 @@ dhcp_client_config (u32 is_add, 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 a79d6e59715..5191fcf0fa8 100644 --- a/src/vnet/dhcp/client.h +++ b/src/vnet/dhcp/client.h @@ -89,6 +89,8 @@ typedef struct dhcp_client_t_ 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 @@ typedef struct /* 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 @@ extern int dhcp_client_config (u32 is_add, 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 033c7a34fed..6db9033a7f4 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 @@ autoreply define dhcp_proxy_set_vss 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 @@ typeonly define dhcp_client 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 7eb2bf46a06..7935ad8ba01 100644 --- a/src/vnet/dhcp/dhcp_api.c +++ b/src/vnet/dhcp/dhcp_api.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -263,6 +264,7 @@ dhcp_client_data_encode (vl_api_dhcp_client_t * vclient, 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 @@ static void vl_api_dhcp_client_config_t_handler 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 @@ static void vl_api_dhcp_client_config_t_handler (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 6e8ac7c437d..133767bd06c 100644 --- a/src/vnet/ip/ip.c +++ b/src/vnet/ip/ip.c @@ -294,6 +294,23 @@ format_ip_address_family (u8 * s, va_list * args) 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 2ce6763f8d7..c1852fc3ff2 100644 --- a/src/vnet/ip/ip4_packet.h +++ b/src/vnet/ip/ip4_packet.h @@ -138,7 +138,7 @@ typedef union 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 c8bc4c817e8..c1bd2aa3bf7 100644 --- a/src/vnet/ip/ip6_packet.h +++ b/src/vnet/ip/ip6_packet.h @@ -383,13 +383,13 @@ typedef struct 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 @@ ip6_traffic_class_network_order (const ip6_header_t * ip6) } 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 c4990976188..97b3c96b2ce 100644 --- a/src/vnet/ip/ip_packet.h +++ b/src/vnet/ip/ip_packet.h @@ -84,6 +84,44 @@ typedef enum #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 8b46a1d44fe..13c6a4aab28 100644 --- a/src/vnet/ip/ip_types.api +++ b/src/vnet/ip/ip_types.api @@ -34,8 +34,8 @@ enum ip_ecn : u8 { /* 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 0343d2001ad..ca26731a30a 100644 --- a/src/vnet/ip/ip_types_api.c +++ b/src/vnet/ip/ip_types_api.c @@ -95,6 +95,18 @@ ip_proto_encode (ip_protocol_t ipp) 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 4c79bf138e3..fc7a416a06d 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_decode (int _af, ip_address_family_t * out); 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 ca6ac407686..8573bc3bef5 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 + /** * A label value only, i.e. 20bits. */ @@ -55,7 +57,7 @@ typedef enum mpls_eos_bit_t_ /** * 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); } -- cgit 1.2.3-korg