[qca-nss-clients] IPv6 IPsec: Support for 128 subnet

Expanded the ipsecmgr netmask array to 128 bits wide.
And made necessary change to support the 128 subnet.

Change-Id: I40ce1824829c86f96865956a0405878e4a5e0b01
Signed-off-by: mandrw <mandrw@codeaurora.org>
diff --git a/ipsecmgr/nss_ipsecmgr_priv.h b/ipsecmgr/nss_ipsecmgr_priv.h
index fbf8f0c..ddcbc7e 100644
--- a/ipsecmgr/nss_ipsecmgr_priv.h
+++ b/ipsecmgr/nss_ipsecmgr_priv.h
@@ -85,7 +85,7 @@
 #error "NSS_IPSECMGR_MAX_SUBNET is not a power of 2"
 #endif
 
-#define NSS_IPSECMGR_MAX_NETMASK 64 /* Max subnets */
+#define NSS_IPSECMGR_MAX_NETMASK 128 /* Max subnets */
 #if (~(NSS_IPSECMGR_MAX_NETMASK - 1) & (NSS_IPSECMGR_MAX_NETMASK >> 1))
 #error "NSS_IPSECMGR_MAX_NETMASK is not a power of 2"
 #endif
@@ -118,7 +118,7 @@
 	NSS_IPSECMGR_KEY_LEN_IPV4_ENCAP_FLOW = 3,	/* 12 bytes */
 	NSS_IPSECMGR_KEY_LEN_IPV4_DECAP_FLOW = 4,	/* 16 bytes */
 	NSS_IPSECMGR_KEY_LEN_IPV6_SA = 10,		/* 40 bytes */
-	NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET = 3,		/* 12 bytes */
+	NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET = 5,		/* 20 bytes */
 	NSS_IPSECMGR_KEY_LEN_IPV6_ENCAP_FLOW = 9,	/* 36 bytes */
 	NSS_IPSECMGR_KEY_LEN_IPV6_DECAP_FLOW = 10,	/* 40 bytes */
 	NSS_IPSECMGR_KEY_LEN_MAX = NSS_IPSECMGR_MAX_KEY_WORDS
@@ -234,7 +234,7 @@
  * IPsec netmask entry
  */
 struct nss_ipsecmgr_netmask_entry {
-	uint64_t mask_bits;					/* no. of bits in netmask */
+	uint32_t mask_bits;					/* no. of bits in netmask */
 	uint32_t count;						/* no. of subnets entries */
 	struct list_head subnets[NSS_IPSECMGR_MAX_SUBNET];	/* subnet database */
 };
@@ -631,7 +631,7 @@
 
 /*
  * nss_ipsecmgr_key_clear_64()
- * 	clear 32-bit mask from the specified position
+ * 	clear 64-bit mask from the specified position
  */
 static inline void nss_ipsecmgr_key_clear_64(struct nss_ipsecmgr_key *key, enum nss_ipsecmgr_key_pos p)
 {
@@ -643,6 +643,19 @@
 }
 
 /*
+ * nss_ipsecmgr_key_clear_128()
+ * 	clear 128-bit mask from the specified position
+ */
+static inline void nss_ipsecmgr_key_clear_128(struct nss_ipsecmgr_key *key, enum nss_ipsecmgr_key_pos p)
+{
+	uint16_t idx;
+
+	idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+
+	memset(&key->mask[idx], 0, sizeof(uint32_t) * 4);
+}
+
+/*
  * nss_ipsecmgr_key_read_n()
  * 	read n nnumber of values from the specified position using mask
  */
@@ -759,6 +772,22 @@
 }
 
 /*
+ * nss_ipsecmgr_key_lshift_mask128()
+ * 	left shift mask by an amount 's'
+ */
+static inline void nss_ipsecmgr_key_lshift_mask128(struct nss_ipsecmgr_key *key, uint32_t s, enum nss_ipsecmgr_key_pos p)
+{
+	uint16_t idx;
+	uint32_t mask[4];
+
+	idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+
+	memcpy(mask, &key->mask[idx], sizeof(uint32_t) * 4);
+
+	bitmap_shift_left((unsigned long *)&key->mask[idx], (unsigned long *)mask, s, 128);
+}
+
+/*
  * nss_ipsecmgr_key_cmp_data()
  * 	compare source key with destination key
  *
diff --git a/ipsecmgr/nss_ipsecmgr_subnet.c b/ipsecmgr/nss_ipsecmgr_subnet.c
index de24319..598e874 100644
--- a/ipsecmgr/nss_ipsecmgr_subnet.c
+++ b/ipsecmgr/nss_ipsecmgr_subnet.c
@@ -61,13 +61,18 @@
 static inline bool nss_ipsecmgr_netmask_is_default(struct nss_ipsecmgr_key *key)
 {
 	uint8_t ip_ver;
+	uint64_t mask64_low;
+	uint64_t mask64_high;
 
 	ip_ver = nss_ipsecmgr_key_read_8(key, NSS_IPSECMGR_KEY_POS_IP_VER);
 	if (likely(ip_ver == 4)) {
 		return !nss_ipsecmgr_key_read_mask32(key, NSS_IPSECMGR_KEY_POS_IPV4_DST);
 	}
 
-	return !nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+	mask64_low = nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+	mask64_high = nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST + 2);
+
+	return !(mask64_low || mask64_high);
 }
 
 /*
@@ -135,7 +140,8 @@
 static inline uint32_t nss_ipsecmgr_netmask2idx(struct nss_ipsecmgr_key *key)
 {
 	uint32_t mask32;
-	uint64_t mask64;
+	uint64_t mask64_low;
+	uint64_t mask64_high;
 	uint8_t ip_ver;
 
 	ip_ver = nss_ipsecmgr_key_read_8(key, NSS_IPSECMGR_KEY_POS_IP_VER);
@@ -146,8 +152,17 @@
 
 	BUG_ON(ip_ver != 6);
 
-	mask64 = nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
-	return mask64 ? __ffs64(mask64) : NSS_IPSECMGR_MAX_NETMASK;
+	mask64_low = nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+	if (mask64_low) {
+		return __ffs64(mask64_low);
+	}
+
+	mask64_high = nss_ipsecmgr_key_read_mask64(key, NSS_IPSECMGR_KEY_POS_IPV6_DST + 2);
+	if (mask64_high) {
+		return __ffs64(mask64_high) + 64;
+	}
+
+	return NSS_IPSECMGR_MAX_NETMASK;
 }
 
 /*
@@ -246,7 +261,7 @@
 		 * The subnet and mask bits from the key are read to the upper words of the array
 		 * later converted to network order for display.
 		 */
-		nss_ipsecmgr_key_read(&subnet_entry->key, &subnet[2], &mask[2], NSS_IPSECMGR_KEY_POS_IPV6_DST, 2);
+		nss_ipsecmgr_key_read(&subnet_entry->key, subnet, mask, NSS_IPSECMGR_KEY_POS_IPV6_DST, 4);
 
 		nss_ipsecmgr_v6addr_hton(subnet, subnet);
 		nss_ipsecmgr_v6addr_hton(mask, mask);
@@ -423,17 +438,16 @@
  */
 void nss_ipsecmgr_v6_subnet_sel2key(struct nss_ipsec_rule_sel *sel, struct nss_ipsecmgr_key *key)
 {
+	uint32_t i;
+
 	nss_ipsecmgr_key_reset(key);
 
 	nss_ipsecmgr_key_write_8(key, 6 /* ipv6 */, NSS_IPSECMGR_KEY_POS_IP_VER);
 	nss_ipsecmgr_key_write_8(key, sel->proto_next_hdr, NSS_IPSECMGR_KEY_POS_IP_PROTO);
 
-	/*
-	 * IPv6 subnetting uses 64 most significant bits as subnet prefix.
-	 * So we store only 2 most significant worlds to the key.
-	 */
-	nss_ipsecmgr_key_write_32(key, sel->dst_addr[2], NSS_IPSECMGR_KEY_POS_IPV6_DST);
-	nss_ipsecmgr_key_write_32(key, sel->dst_addr[3], NSS_IPSECMGR_KEY_POS_IPV6_DST + 32);
+	for (i = 0; i < 4; i++) {
+		nss_ipsecmgr_key_write_32(key, sel->dst_addr[i], NSS_IPSECMGR_KEY_POS_IPV6_DST + (i * BITS_PER_LONG));
+	}
 
 	key->len = NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET;
 }
@@ -472,7 +486,7 @@
 
 	nss_ipsecmgr_key_write_8(key, 6 /* ipv6 */, NSS_IPSECMGR_KEY_POS_IP_VER);
 	nss_ipsecmgr_key_write_8(key, (uint8_t)net->next_hdr, NSS_IPSECMGR_KEY_POS_IP_PROTO);
-	nss_ipsecmgr_key_write(key, net->dst_subnet, net->dst_mask, NSS_IPSECMGR_KEY_POS_IPV6_DST, 2);
+	nss_ipsecmgr_key_write(key, net->dst_subnet, net->dst_mask, NSS_IPSECMGR_KEY_POS_IPV6_DST, 4);
 
 	/*
 	 * clear mask if caller specify protocol as any (0xff).
@@ -520,7 +534,6 @@
 	}
 
 	memcpy(&tmp_key, key, sizeof(struct nss_ipsecmgr_key));
-
 	/*
 	 * normal lookup failed; check default subnet entry
 	 * - clear the destination netmask before lookup
@@ -553,10 +566,9 @@
 
 		BUG_ON(db->entries[i] == NULL);
 		BUG_ON(db->entries[i]->count == 0);
-
 		memcpy(&tmp_key, key, sizeof(struct nss_ipsecmgr_key));
 
-		nss_ipsecmgr_key_lshift_mask64(&tmp_key, i, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+		nss_ipsecmgr_key_lshift_mask128(&tmp_key, i, NSS_IPSECMGR_KEY_POS_IPV6_DST);
 
 		ref = nss_ipsecmgr_subnet_lookup(priv, &tmp_key);
 		if (ref) {
@@ -570,7 +582,7 @@
 	 * normal lookup failed; check default subnet entry
 	 * - clear the destination netmask before lookup
 	 */
-	nss_ipsecmgr_key_clear_64(&tmp_key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+	nss_ipsecmgr_key_clear_128(&tmp_key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
 
 	ref = nss_ipsecmgr_subnet_lookup(priv, &tmp_key);
 	if (ref) {
@@ -605,7 +617,6 @@
 			return &entry->ref;
 		}
 	}
-
 	return NULL;
 }
 
diff --git a/netlink/include/nss_nlipv6_if.h b/netlink/include/nss_nlipv6_if.h
index 6a110a0..d6edac0 100644
--- a/netlink/include/nss_nlipv6_if.h
+++ b/netlink/include/nss_nlipv6_if.h
@@ -27,7 +27,7 @@
 #define NSS_NLIPV6_FAMILY "nss_nlipv6"
 
 #define NSS_NLIPV6_ADDR_BITS (sizeof(uint32_t) * 4 * BITS_PER_BYTE)	/* 128 bits */
-#define NSS_NLIPV6_SUBNET_BITS (sizeof(uint32_t) * 2 * BITS_PER_BYTE)	/* 64 bits */
+#define NSS_NLIPV6_SUBNET_BITS (sizeof(uint32_t) * 4 * BITS_PER_BYTE)	/* 128 bits */
 
 /**
  * @brief IPv6 rule