[v1,1/3] librte_pipeline: add support for DSCP action

Message ID 20180211085722.59717-1-georgina.sheehan@intel.com
State Superseded, archived
Delegated to: Cristian Dumitrescu
Headers show
Series
  • [v1,1/3] librte_pipeline: add support for DSCP action
Related show

Checks

Context Check Description
ci/Performance-Testing fail build patch failure
ci/checkpatch success coding style OK

Commit Message

Sheehan,Georgina Feb. 11, 2018, 8:57 a.m.
From: Georgina Sheehan <georgina.sheehan@intel.com>

This allows the application to change the DSCP value of incoming packets

Signed-off-by: Georgina Sheehan <georgina.sheehan@intel.com>
---
 lib/librte_pipeline/rte_table_action.c | 133 +++++++++++++++++++++++++
 lib/librte_pipeline/rte_table_action.h |  20 ++++
 2 files changed, 153 insertions(+)

Patch

diff --git a/lib/librte_pipeline/rte_table_action.c b/lib/librte_pipeline/rte_table_action.c
index 8a2bb13dc..8f11a17e6 100644
--- a/lib/librte_pipeline/rte_table_action.c
+++ b/lib/librte_pipeline/rte_table_action.c
@@ -2119,6 +2119,87 @@  pkt4_work_decap(struct rte_mbuf *mbuf0,
 	mbuf3->pkt_len = pkt_len3 - n3;
 }
 
+/**
+ * RTE_TABLE_ACTION_DSCP
+ */
+
+struct dscp_data {
+	uint8_t dscp_val;
+} __attribute__((__packed__));
+
+static int
+dscp_apply(void *data,
+	struct rte_table_action_dscp_params *p)
+{
+	struct dscp_data *d = data;
+
+	d->dscp_val = (p->dscp_val & 0x3f) << 2;
+
+	return 0;
+}
+
+static __rte_always_inline uint16_t
+dscp_ipv4_checksum_update(uint16_t cksum0,
+	uint8_t dscp_old,
+	uint8_t dscp_new)
+{
+	int32_t cksum1;
+	cksum1 = cksum0;
+	cksum1 = ~cksum1 & 0xFFFF;
+
+	/* Subtract ip0 (one's complement logic) */
+	cksum1 -= ((uint16_t)dscp_old & 0xFFFF);
+	cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
+	cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
+
+	/* Add ip1 (one's complement logic) */
+	cksum1 += ((uint16_t)dscp_new & 0xFFFF);
+	cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
+	cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
+
+	return (uint16_t)(~cksum1);
+}
+
+static __rte_always_inline void
+pkt_ipv4_work_dscp(struct ipv4_hdr *ip, struct dscp_data *data)
+{
+	uint16_t ip_cksum;
+	uint8_t dscp;
+
+	ip->hdr_checksum = ntohs(ip->hdr_checksum);
+
+	dscp = ip->type_of_service & 0x3;
+	dscp = ip->type_of_service | data->dscp_val;
+
+	ip_cksum = dscp_ipv4_checksum_update(ip->hdr_checksum,
+		ip->type_of_service, dscp);
+
+	ip->type_of_service = dscp;
+
+	ip_cksum = ntohs(ip_cksum);
+
+	ip->hdr_checksum = ip_cksum;
+}
+
+static __rte_always_inline void
+pkt_ipv6_work_dscp(struct ipv6_hdr *ip, struct dscp_data *data)
+{
+	ip->vtc_flow = rte_ntohl(ip->vtc_flow);
+
+	uint32_t dscp = data->dscp_val;
+
+	dscp = dscp << 20;
+
+	uint32_t vtc_flow;
+
+	vtc_flow = ip->vtc_flow & 0xF03FFFFF;
+	vtc_flow = ip->vtc_flow | dscp;
+
+	vtc_flow = rte_htonl(vtc_flow);
+
+	ip->vtc_flow = vtc_flow;
+}
+
 /**
  * Action profile
  */
@@ -2138,6 +2219,7 @@  action_valid(enum rte_table_action_type action)
 	case RTE_TABLE_ACTION_SYM_CRYPTO:
 	case RTE_TABLE_ACTION_TAG:
 	case RTE_TABLE_ACTION_DECAP:
+	case RTE_TABLE_ACTION_DSCP:
 		return 1;
 	default:
 		return 0;
@@ -2158,6 +2240,7 @@  struct ap_config {
 	struct rte_table_action_ttl_config ttl;
 	struct rte_table_action_stats_config stats;
 	struct rte_table_action_sym_crypto_config sym_crypto;
+	struct rte_table_action_dscp_config dscp;
 };
 
 static size_t
@@ -2180,6 +2263,8 @@  action_cfg_size(enum rte_table_action_type action)
 		return sizeof(struct rte_table_action_stats_config);
 	case RTE_TABLE_ACTION_SYM_CRYPTO:
 		return sizeof(struct rte_table_action_sym_crypto_config);
+	case RTE_TABLE_ACTION_DSCP:
+		return sizeof(struct rte_table_action_dscp_config);
 	default:
 		return 0;
 	}
@@ -2213,6 +2298,9 @@  action_cfg_get(struct ap_config *ap_config,
 
 	case RTE_TABLE_ACTION_SYM_CRYPTO:
 		return &ap_config->sym_crypto;
+
+	case RTE_TABLE_ACTION_DSCP:
+		return &ap_config->dscp;
 	default:
 		return NULL;
 	}
@@ -2278,6 +2366,9 @@  action_data_size(enum rte_table_action_type action,
 	case RTE_TABLE_ACTION_DECAP:
 		return sizeof(struct decap_data);
 
+	case RTE_TABLE_ACTION_DSCP:
+		return sizeof(struct dscp_data);
+
 	default:
 		return 0;
 	}
@@ -2543,6 +2634,10 @@  rte_table_action_apply(struct rte_table_action *action,
 		return decap_apply(action_data,
 			action_params);
 
+	case RTE_TABLE_ACTION_DSCP:
+		return dscp_apply(action_data,
+			action_params);
+
 	default:
 		return -EINVAL;
 	}
@@ -2939,6 +3034,17 @@  pkt_work(struct rte_mbuf *mbuf,
 		pkt_work_tag(mbuf, data);
 	}
 
+	if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_DSCP)) {
+		void *data =
+			action_data_get(table_entry, action,
+				RTE_TABLE_ACTION_DSCP);
+
+		if (cfg->common.ip_version)
+			pkt_ipv4_work_dscp(ip, data);
+		else
+			pkt_ipv6_work_dscp(ip, data);
+	}
+
 	return drop_mask;
 }
 
@@ -3283,6 +3389,33 @@  pkt4_work(struct rte_mbuf **mbufs,
 			data0, data1, data2, data3);
 	}
 
+	if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_DSCP)) {
+		void *data0 =
+			action_data_get(table_entry0, action,
+				RTE_TABLE_ACTION_DSCP);
+		void *data1 =
+			action_data_get(table_entry1, action,
+				RTE_TABLE_ACTION_DSCP);
+		void *data2 =
+			action_data_get(table_entry2, action,
+				RTE_TABLE_ACTION_DSCP);
+		void *data3 =
+			action_data_get(table_entry3, action,
+				RTE_TABLE_ACTION_DSCP);
+
+		if (cfg->common.ip_version) {
+			pkt_ipv4_work_dscp(ip0, data0);
+			pkt_ipv4_work_dscp(ip1, data1);
+			pkt_ipv4_work_dscp(ip2, data2);
+			pkt_ipv4_work_dscp(ip3, data3);
+		} else {
+			pkt_ipv6_work_dscp(ip0, data0);
+			pkt_ipv6_work_dscp(ip1, data1);
+			pkt_ipv6_work_dscp(ip2, data2);
+			pkt_ipv6_work_dscp(ip3, data3);
+		}
+	}
+
 	return drop_mask0 |
 		(drop_mask1 << 1) |
 		(drop_mask2 << 2) |
diff --git a/lib/librte_pipeline/rte_table_action.h b/lib/librte_pipeline/rte_table_action.h
index c96061291..28db53303 100644
--- a/lib/librte_pipeline/rte_table_action.h
+++ b/lib/librte_pipeline/rte_table_action.h
@@ -102,6 +102,9 @@  enum rte_table_action_type {
 
 	/** Packet decapsulations. */
 	RTE_TABLE_ACTION_DECAP,
+
+	/** Differentiated Services Code Point (DSCP) **/
+	RTE_TABLE_ACTION_DSCP,
 };
 
 /** Common action configuration (per table action profile). */
@@ -794,6 +797,23 @@  struct rte_table_action_decap_params {
 	uint16_t n;
 };
 
+/**
+ * RTE_TABLE_ACTION_DSCP
+ */
+/** DSCP action configuration (per table action profile). */
+struct rte_table_action_dscp_config {
+	/** dscp length  */
+	uint8_t dscp_len;
+
+};
+
+/** DSCP action parameters (per table rule). */
+struct rte_table_action_dscp_params {
+	/** dscp value to be set */
+	uint8_t dscp_val;
+
+};
+
 /**
  * Table action profile.
  */