[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