diff mbox series

[1/2] linux-generic: classification: implement ipv6 packet matching rule

Message ID 1485781010-11166-1-git-send-email-bala.manoharan@linaro.org
State Superseded
Headers show
Series [1/2] linux-generic: classification: implement ipv6 packet matching rule | expand

Commit Message

Balasubramanian Manoharan Jan. 30, 2017, 12:56 p.m. UTC
Implements IPV6 src and dst address packet matching rule

Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>

---
 .../include/odp_classification_datamodel.h         | 11 +++++-
 .../include/odp_classification_inlines.h           | 44 ++++++++++++++++++----
 .../linux-generic/include/odp_packet_internal.h    |  5 +++
 platform/linux-generic/odp_classification.c        | 26 +++++++++++++
 4 files changed, 77 insertions(+), 9 deletions(-)

-- 
1.9.1
diff mbox series

Patch

diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h
index f6393ee..5b1cde3 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -25,6 +25,7 @@  extern "C" {
 #include <odp_packet_internal.h>
 #include <odp_packet_io_internal.h>
 #include <odp_queue_internal.h>
+#include <protocols/ip.h>
 
 /* Maximum Class Of Service Entry */
 #define ODP_COS_MAX_ENTRY		64
@@ -43,7 +44,7 @@  extern "C" {
 /* Max L3 QoS Value */
 #define ODP_COS_MAX_L3_QOS		(1 << ODP_COS_L3_QOS_BITS)
 /* Max PMR Term bits */
-#define ODP_PMR_TERM_BYTES_MAX		8
+#define ODP_PMR_TERM_BYTES_MAX		16
 
 /**
 Packet Matching Rule Term Value
@@ -67,6 +68,14 @@  typedef struct pmr_term_value {
 			/** End value of the range */
 			uint64_t	val_end;
 		} range;
+		struct {
+			uint8_t value[_ODP_IPV6ADDR_LEN];
+			uint8_t mask[_ODP_IPV6ADDR_LEN];
+		} match_ipv6;
+		struct {
+			uint8_t val_start[_ODP_IPV6ADDR_LEN];
+			uint8_t val_end[_ODP_IPV6ADDR_LEN];
+		} range_ipv6;
 	};
 	uint32_t	offset;	/**< Offset if term == ODP_PMR_CUSTOM_FRAME */
 	uint32_t	val_sz;	/**< Size of the value to be matched */
diff --git a/platform/linux-generic/include/odp_classification_inlines.h b/platform/linux-generic/include/odp_classification_inlines.h
index b839197..4d85cf2 100644
--- a/platform/linux-generic/include/odp_classification_inlines.h
+++ b/platform/linux-generic/include/odp_classification_inlines.h
@@ -179,19 +179,47 @@  static inline int verify_pmr_dmac(const uint8_t *pkt_addr,
 	return 0;
 }
 
-static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED,
-					odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-					pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr,
+					odp_packet_hdr_t *pkt_hdr,
+					pmr_term_value_t *term_value)
 {
-	ODP_UNIMPLEMENTED();
+	const _odp_ipv6hdr_t *ipv6;
+	uint8_t		src_addr[_ODP_IPV6ADDR_LEN];
+	uint8_t i;
+
+	if (!packet_hdr_has_ipv6(pkt_hdr))
+		return 0;
+
+	ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+	memcpy(src_addr, ipv6->src_addr, _ODP_IPV6ADDR_LEN);
+	for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+		src_addr[i] = src_addr[i] & term_value->match_ipv6.mask[i];
+
+	if (!memcmp(term_value->match_ipv6.value, src_addr, _ODP_IPV6ADDR_LEN))
+		return 1;
+
 	return 0;
 }
 
-static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED,
-					odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-					pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr,
+					odp_packet_hdr_t *pkt_hdr,
+					pmr_term_value_t *term_value)
 {
-	ODP_UNIMPLEMENTED();
+	const _odp_ipv6hdr_t *ipv6;
+	uint8_t		dst_addr[_ODP_IPV6ADDR_LEN];
+	uint8_t i;
+
+	if (!packet_hdr_has_ipv6(pkt_hdr))
+		return 0;
+
+	ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+	memcpy(dst_addr, ipv6->dst_addr, _ODP_IPV6ADDR_LEN);
+	for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+		dst_addr[i] = dst_addr[i] & term_value->match_ipv6.mask[i];
+
+	if (!memcmp(term_value->match_ipv6.value, dst_addr, _ODP_IPV6ADDR_LEN))
+		return 1;
+
 	return 0;
 }
 
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index e6e9d74..e3ada5c 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -294,6 +294,11 @@  static inline int packet_hdr_has_eth(odp_packet_hdr_t *pkt_hdr)
 	return pkt_hdr->p.input_flags.eth;
 }
 
+static inline int packet_hdr_has_ipv6(odp_packet_hdr_t *pkt_hdr)
+{
+	return pkt_hdr->p.input_flags.ipv6;
+}
+
 static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts)
 {
 	if (ts != NULL) {
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 50a7e54..d8c0479 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -447,6 +447,31 @@  static int odp_pmr_create_term(pmr_term_value_t *value,
 {
 	value->term = param->term;
 	value->range_term = param->range_term;
+	uint8_t i;
+
+	switch (value->term) {
+	case ODP_PMR_SIP6_ADDR:
+	case ODP_PMR_DIP6_ADDR:
+	if (!value->range_term) {
+		memset(value->match_ipv6.value, 0, 16);
+		memset(value->match_ipv6.mask, 0, 16);
+		memcpy(&value->match_ipv6.value, param->match.value,
+		       param->val_sz);
+		memcpy(&value->match_ipv6.mask, param->match.mask,
+		       param->val_sz);
+		for (i = 0; i < 16; i++)
+			value->match_ipv6.value[i] &= value->match_ipv6.mask[i];
+	} else {
+		memset(value->range_ipv6.val_start, 0, 16);
+		memset(value->range_ipv6.val_end, 0, 16);
+		memcpy(&value->range_ipv6.val_start, param->range.val_start,
+		       param->val_sz);
+		memcpy(&value->range_ipv6.val_end, param->range.val_end,
+		       param->val_sz);
+	}
+
+	break;
+	default:
 	if (!value->range_term) {
 		value->match.value = 0;
 		value->match.mask = 0;
@@ -461,6 +486,7 @@  static int odp_pmr_create_term(pmr_term_value_t *value,
 		memcpy(&value->range.val_end, param->range.val_end,
 		       param->val_sz);
 	}
+	}
 	value->offset = param->offset;
 	value->val_sz = param->val_sz;
 	return 0;