[qca-nss-clients] IPv6 Auto-rule insertion support.
Added support for inserting flow rules automatically to offload
IPsec-over-IPv6 flows.
Change-Id: Ibc3fdb1f5d8638c39ee063f219888ca49f4c12ba
Signed-off-by: mandrw <mandrw@codeaurora.org>
diff --git a/ipsecmgr/nss_ipsecmgr_flow.c b/ipsecmgr/nss_ipsecmgr_flow.c
index 7f1dc79..5ce24e2 100644
--- a/ipsecmgr/nss_ipsecmgr_flow.c
+++ b/ipsecmgr/nss_ipsecmgr_flow.c
@@ -92,6 +92,7 @@
struct nss_ipsecmgr_flow_entry *flow;
struct nss_ipsec_rule_sel local_sel;
struct nss_ipsec_rule_sel *flow_sel;
+ struct nss_ipsec_msg nss_nim;
flow = container_of(ref, struct nss_ipsecmgr_flow_entry, ref);
flow_sel = &flow->nim.msg.push.sel;
@@ -110,7 +111,12 @@
memcpy(flow_sel, &local_sel, sizeof(struct nss_ipsec_rule_sel));
}
- if (nss_ipsec_tx_msg(priv->nss_ctx, &flow->nim) != NSS_TX_SUCCESS) {
+ /*
+ * Convert the message to NSS format
+ */
+ nss_ipsecmgr_copy_nim(&flow->nim, &nss_nim);
+
+ if (nss_ipsec_tx_msg(priv->nss_ctx, &nss_nim) != NSS_TX_SUCCESS) {
/*
* XXX: Stop the TX queue and add this "entry"
* to pending queue
@@ -127,13 +133,19 @@
static void nss_ipsecmgr_flow_free(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_ref *ref)
{
struct nss_ipsecmgr_flow_entry *flow = container_of(ref, struct nss_ipsecmgr_flow_entry, ref);
+ struct nss_ipsec_msg nss_nim;
/*
* update the common message structure
*/
flow->nim.cm.type = NSS_IPSEC_MSG_TYPE_DEL_RULE;
- if (nss_ipsec_tx_msg(priv->nss_ctx, &flow->nim) != NSS_TX_SUCCESS) {
+ /*
+ * Convert the message to NSS format
+ */
+ nss_ipsecmgr_copy_nim(&flow->nim, &nss_nim);
+
+ if (nss_ipsec_tx_msg(priv->nss_ctx, &nss_nim) != NSS_TX_SUCCESS) {
/*
* XXX: add this "entry" to pending queue
*/
@@ -153,8 +165,6 @@
/*
* nss_ipsecmgr_flow_stats_resp()
* response for the flow message
- *
- * Note: we don't have anything to process for flow responses as of now
*/
static void nss_ipsecmgr_flow_stats_resp(void *app_data, struct nss_ipsec_msg *nim)
{
@@ -179,6 +189,14 @@
sel = &nim->msg.flow_stats.sel;
/*
+ * NSS uses a hybrid endian order for v6 addresses. Need to convert to host
+ */
+ if (sel->ip_ver == NSS_IPSEC_IPVER_6) {
+ nss_ipsecmgr_v6addr_swap(sel->dst_addr, sel->dst_addr);
+ nss_ipsecmgr_v6addr_swap(sel->src_addr, sel->src_addr);
+ }
+
+ /*
* prepare key from selector
*/
switch (interface) {
@@ -226,11 +244,12 @@
struct dentry *parent = dget_parent(fp->f_dentry);
uint32_t tunnel_id = (uint32_t)fp->private_data;
struct nss_ipsecmgr_flow_entry *flow;
- struct nss_ipsec_rule_sel *flow_sel;
+ struct nss_ipsec_rule_sel flow_sel;
struct nss_ipsecmgr_priv *priv;
struct nss_ipsecmgr_ref *ref;
struct nss_ipsecmgr_key key;
struct nss_ipsec_msg nim;
+ uint32_t pkts_processed;
struct net_device *dev;
uint16_t interface;
uint32_t addr[4];
@@ -279,6 +298,14 @@
read_unlock_bh(&priv->lock);
+ if (nim.msg.flow_stats.sel.ip_ver == NSS_IPSEC_IPVER_6) {
+ /*
+ * change the IPv6 address to NSS order before sending
+ */
+ nss_ipsecmgr_v6addr_swap(nim.msg.flow_stats.sel.src_addr, nim.msg.flow_stats.sel.src_addr);
+ nss_ipsecmgr_v6addr_swap(nim.msg.flow_stats.sel.dst_addr, nim.msg.flow_stats.sel.dst_addr);
+ }
+
/*
* send stats message to nss
*/
@@ -296,12 +323,6 @@
goto done;
}
- local = vzalloc(NSS_IPSECMGR_MAX_BUF_SZ);
- if (!local) {
- nss_ipsecmgr_error("unable to allocate local buffer for tunnel-id: %d\n", tunnel_id);
- goto done;
- }
-
/*
* After wait_for_completion, confirm if flow still exist
*/
@@ -309,13 +330,21 @@
ref = nss_ipsecmgr_flow_lookup(priv, &key);
if (!ref) {
read_unlock_bh(&priv->lock);
- vfree(local);
nss_ipsecmgr_error("flow not found tunnel-id: %d\n", tunnel_id);
goto done;
}
flow = container_of(ref, struct nss_ipsecmgr_flow_entry, ref);
- flow_sel = &flow->nim.msg.push.sel;
+ memcpy(&flow_sel, &flow->nim.msg.push.sel, sizeof(flow_sel));
+ pkts_processed = flow->pkts_processed;
+
+ read_unlock_bh(&priv->lock);
+
+ local = vzalloc(NSS_IPSECMGR_MAX_BUF_SZ);
+ if (!local) {
+ nss_ipsecmgr_error("unable to allocate local buffer for tunnel-id: %d\n", tunnel_id);
+ goto done;
+ }
/*
* IPv4 Generel info
@@ -335,27 +364,26 @@
len = 0;
len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "type:%s\n", type);
- switch (flow_sel->ip_ver) {
+ switch (flow_sel.ip_ver) {
case NSS_IPSEC_IPVER_4:
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI4h\n", &flow_sel->dst_addr[0]);
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI4h\n", &flow_sel->src_addr[0]);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI4h\n", flow_sel.dst_addr);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI4h\n", flow_sel.src_addr);
break;
case NSS_IPSEC_IPVER_6:
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntohl(flow_sel->dst_addr, addr));
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntohl(flow_sel->src_addr, addr));
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntoh(flow_sel.dst_addr, addr));
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntoh(flow_sel.src_addr, addr));
break;
}
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "proto: %d\n", flow_sel->proto_next_hdr);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "proto: %d\n", flow_sel.proto_next_hdr);
/*
* packet stats
*/
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "processed: %d\n", flow->pkts_processed);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "processed: %d\n", pkts_processed);
- read_unlock_bh(&priv->lock);
ret = simple_read_from_buffer(ubuf, sz, ppos, local, len + 1);
vfree(local);
@@ -774,7 +802,7 @@
/*
* copy nim data from subnet entry
*/
- nss_ipsecmgr_copy_v4_subnet(&nim, subnet_ref);
+ nss_ipsecmgr_copy_subnet(&nim, subnet_ref);
/*
* if, the same flow was added in between then flow alloc will return the
@@ -795,7 +823,6 @@
nss_ipsecmgr_ref_update(priv, flow_ref, &nim);
write_unlock(&priv->lock);
-
break;
case htons(ETH_P_IPV6):
@@ -814,10 +841,51 @@
/*
* if flow is found then proceed with the TX
*/
- if (!flow_ref) {
+ if (flow_ref) {
+ return true;
+ }
+
+ /*
+ * flow table miss results in lookup in the subnet table. If,
+ * a match is found then a rule is inserted in NSS for encapsulating
+ * this flow.
+ */
+ nss_ipsecmgr_v6_subnet_sel2key(sel, &subnet_key);
+
+ /*
+ * write lock as it can update the flow database
+ */
+ write_lock(&priv->lock);
+
+ subnet_ref = nss_ipsecmgr_v6_subnet_match(priv, &subnet_key);
+ if (!subnet_ref) {
+ write_unlock(&priv->lock);
return false;
}
+ /*
+ * copy nim data from subnet entry
+ */
+ nss_ipsecmgr_copy_subnet(&nim, subnet_ref);
+
+ /*
+ * if, the same flow was added in between then flow alloc will return the
+ * same flow. The only side affect of this will be NSS getting duplicate
+ * add requests and thus rejecting one of them
+ */
+ flow_ref = nss_ipsecmgr_flow_alloc(priv, &flow_key);
+ if (!flow_ref) {
+ write_unlock(&priv->lock);
+ return false;
+ }
+
+ /*
+ * add reference to subnet and trigger an update
+ */
+ nss_ipsecmgr_ref_add(flow_ref, subnet_ref);
+ nss_ipsecmgr_ref_update(priv, flow_ref, &nim);
+
+ write_unlock(&priv->lock);
break;
default:
diff --git a/ipsecmgr/nss_ipsecmgr_priv.h b/ipsecmgr/nss_ipsecmgr_priv.h
index b07ea43..6f0c503 100644
--- a/ipsecmgr/nss_ipsecmgr_priv.h
+++ b/ipsecmgr/nss_ipsecmgr_priv.h
@@ -76,7 +76,7 @@
#error "NSS_IPSECMGR_MAX_SUBNET is not a power of 2"
#endif
-#define NSS_IPSECMGR_MAX_NETMASK 32 /* Max ipv4 subnets */
+#define NSS_IPSECMGR_MAX_NETMASK 64 /* 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
@@ -104,6 +104,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_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
@@ -219,8 +220,8 @@
* IPsec netmask entry
*/
struct nss_ipsecmgr_netmask_entry {
+ uint64_t mask_bits; /* no. of bits in netmask */
uint32_t count; /* no. of subnets entries */
- uint32_t mask_bits; /* no. of bits in netmask */
struct list_head subnets[NSS_IPSECMGR_MAX_SUBNET]; /* subnet database */
};
@@ -601,7 +602,6 @@
*data = v;
*mask = NSS_IPSECMGR_GENMASK(31, 0);
}
-
/*
* nss_ipsecmgr_key_clear_32()
* clear 32-bit mask from the specified position
@@ -615,29 +615,51 @@
}
/*
- * nss_ipsecmgr_key_read()
- * read value from the specified position using mask
+ * nss_ipsecmgr_key_read_n()
+ * read n nnumber of values from the specified position using mask
*/
-static inline void nss_ipsecmgr_key_read(struct nss_ipsecmgr_key *key, uint32_t *v, uint32_t *m, enum nss_ipsecmgr_key_pos p)
+static inline void nss_ipsecmgr_key_read(struct nss_ipsecmgr_key *key, uint32_t *v, uint32_t *m, enum nss_ipsecmgr_key_pos p, uint32_t n)
{
+ uint32_t *k_data, *k_mask;
uint16_t idx;
+ int delta;
idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
- *v = key->data[idx];
- *m = key->mask[idx];
+ delta = NSS_IPSECMGR_MAX_KEY_WORDS - idx;
+
+ n = n > delta ? delta : n;
+
+ k_data = &key->data[idx];
+ k_mask = &key->mask[idx];
+
+ for (; n--;) {
+ *v++ = *k_data++;
+ *m++ = *k_mask++;
+ }
}
/*
* nss_ipsecmgr_key_write()
* write value from the specified position using mask
*/
-static inline void nss_ipsecmgr_key_write(struct nss_ipsecmgr_key *key, uint32_t v, uint32_t m, enum nss_ipsecmgr_key_pos p)
+static inline void nss_ipsecmgr_key_write(struct nss_ipsecmgr_key *key, uint32_t *v, uint32_t *m, enum nss_ipsecmgr_key_pos p, uint32_t n)
{
+ uint32_t *k_data, *k_mask;
uint16_t idx;
+ int delta;
idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
- key->data[idx] = v;
- key->mask[idx] = m;
+ delta = NSS_IPSECMGR_MAX_KEY_WORDS - idx;
+
+ n = n > delta ? delta : n;
+
+ k_data = &key->data[idx];
+ k_mask = &key->mask[idx];
+
+ for (; n--;) {
+ *k_data++ = *v++;
+ *k_mask++ = *m++;
+ }
}
/*
@@ -653,6 +675,35 @@
}
/*
+ * nss_ipsecmgr_read_key_mask32()
+ * read a 32 bit mask starting from position
+ */
+static inline uint32_t nss_ipsecmgr_key_read_mask32(struct nss_ipsecmgr_key *key, enum nss_ipsecmgr_key_pos p)
+{
+ uint16_t idx;
+
+ idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+
+ return key->mask[idx];
+}
+
+/*
+ * nss_ipsecmgr_read_key_mask64()
+ * read a 64 bit mask starting from position
+ */
+static inline uint64_t nss_ipsecmgr_key_read_mask64(struct nss_ipsecmgr_key *key, enum nss_ipsecmgr_key_pos p)
+{
+ uint64_t *mask;
+ uint16_t idx;
+
+ idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+
+ mask = (uint64_t *)&key->mask[idx];
+
+ return *mask;
+}
+
+/*
* nss_ipsecmgr_key_lshift_mask()
* left shift mask by an amount 's'
*/
@@ -665,6 +716,21 @@
}
/*
+ * nss_ipsecmgr_key_lshift_mask64()
+ * left shift mask by an amount 's'
+ */
+static inline void nss_ipsecmgr_key_lshift_mask64(struct nss_ipsecmgr_key *key, uint32_t s, enum nss_ipsecmgr_key_pos p)
+{
+ uint64_t *mask;
+ uint16_t idx;
+
+ idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+
+ mask = (uint64_t *)&key->mask[idx];
+ *mask <<= s;
+}
+
+/*
* nss_ipsecmgr_key_cmp_data()
* compare source key with destination key
*
@@ -787,7 +853,7 @@
char *tmp = str;
uint8_t *hash;
- nss_ipsecmgr_key_read(key, &data, &mask, pos);
+ nss_ipsecmgr_key_read(key, &data, &mask, pos, 1);
hash = (uint8_t *)&mask;
str = hex_byte_pack(str, hash[0]);
@@ -875,21 +941,81 @@
}
/*
- * nss_ipsecmgr_v6addr_ntohl()
- * convert the v6 address to
+ * nss_ipsecmgr_v6addr_swap()
+ * Swap the words in the array.
*/
-static inline uint32_t *nss_ipsecmgr_v6addr_ntohl(uint32_t src[], uint32_t dst[])
+static uint32_t *nss_ipsecmgr_v6addr_swap(uint32_t *src, uint32_t *dst)
{
- int i = 4;
+ uint32_t temp[4];
- while (i--) {
- dst[i] = ntohl(src[i]);
+ if (src == dst) {
+ memcpy(temp, src, sizeof(temp));
+ src = temp;
}
+ dst[3] = src[0];
+ dst[2] = src[1];
+ dst[1] = src[2];
+ dst[0] = src[3];
+
return dst;
}
/*
+ * nss_ipsecmgr_v6addr_ntoh()
+ * convert the v6 address form network to host order.
+ */
+static inline uint32_t *nss_ipsecmgr_v6addr_ntoh(uint32_t *src, uint32_t *dst)
+{
+ uint32_t *dst_addr = nss_ipsecmgr_v6addr_swap(src, dst);
+
+ dst_addr[0] = ntohl(dst_addr[0]);
+ dst_addr[1] = ntohl(dst_addr[1]);
+ dst_addr[2] = ntohl(dst_addr[2]);
+ dst_addr[3] = ntohl(dst_addr[3]);
+
+ return dst_addr;
+}
+
+/*
+ * nss_ipsecmgr_v6addr_hton()
+ * convert the v6 address to host to network order.
+ */
+static inline uint32_t *nss_ipsecmgr_v6addr_hton(uint32_t *src, uint32_t *dst)
+{
+ uint32_t *dst_addr = nss_ipsecmgr_v6addr_swap(src, dst);
+
+ dst_addr[0] = htonl(dst_addr[0]);
+ dst_addr[1] = htonl(dst_addr[1]);
+ dst_addr[2] = htonl(dst_addr[2]);
+ dst_addr[3] = htonl(dst_addr[3]);
+
+ return dst_addr;
+}
+
+/*
+ * nss_ipsecmgr_copy_nim()
+ * copy nim from source to destination, also swap the v6 addresses if any
+ */
+static inline void nss_ipsecmgr_copy_nim(struct nss_ipsec_msg *src_nim, struct nss_ipsec_msg *dst_nim)
+{
+ struct nss_ipsec_rule *src_push = &src_nim->msg.push;
+ struct nss_ipsec_rule *dst_push = &dst_nim->msg.push;
+
+ memcpy(dst_nim, src_nim, sizeof(struct nss_ipsec_msg));
+
+ if (src_push->sel.ip_ver == NSS_IPSEC_IPVER_6) {
+ nss_ipsecmgr_v6addr_swap(src_push->sel.dst_addr, dst_push->sel.dst_addr);
+ nss_ipsecmgr_v6addr_swap(src_push->sel.src_addr, dst_push->sel.src_addr);
+ }
+
+ if (src_push->oip.ip_ver == NSS_IPSEC_IPVER_6) {
+ nss_ipsecmgr_v6addr_swap(src_push->oip.dst_addr, dst_push->oip.dst_addr);
+ nss_ipsecmgr_v6addr_swap(src_push->oip.src_addr, dst_push->oip.src_addr);
+ }
+}
+
+/*
* nss_ipsecmgr_v6_hdr2sel()
* convert v6_hdr to message sel
*/
@@ -908,8 +1034,8 @@
nexthdr = frag->nexthdr;
}
- nss_ipsecmgr_v6addr_ntohl(iph->daddr.s6_addr32, sel->dst_addr);
- nss_ipsecmgr_v6addr_ntohl(iph->saddr.s6_addr32, sel->src_addr);
+ nss_ipsecmgr_v6addr_ntoh(iph->daddr.s6_addr32, sel->dst_addr);
+ nss_ipsecmgr_v6addr_ntoh(iph->saddr.s6_addr32, sel->src_addr);
sel->proto_next_hdr = nexthdr;
sel->ip_ver = NSS_IPSEC_IPVER_6;
@@ -968,9 +1094,11 @@
/*
* Subnet API(s)
*/
-void nss_ipsecmgr_copy_v4_subnet(struct nss_ipsec_msg *nim, struct nss_ipsecmgr_ref *subnet_ref);
+void nss_ipsecmgr_copy_subnet(struct nss_ipsec_msg *nim, struct nss_ipsecmgr_ref *subnet_ref);
void nss_ipsecmgr_v4_subnet2key(struct nss_ipsecmgr_encap_v4_subnet *subnet, struct nss_ipsecmgr_key *key);
+void nss_ipsecmgr_v6_subnet2key(struct nss_ipsecmgr_encap_v6_subnet *subnet, struct nss_ipsecmgr_key *key);
void nss_ipsecmgr_v4_subnet_sel2key(struct nss_ipsec_rule_sel *sel, struct nss_ipsecmgr_key *key);
+void nss_ipsecmgr_v6_subnet_sel2key(struct nss_ipsec_rule_sel *sel, struct nss_ipsecmgr_key *key);
/*
* Subnet alloc/lookup API(s)
@@ -978,6 +1106,7 @@
struct nss_ipsecmgr_ref *nss_ipsecmgr_subnet_alloc(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *key);
struct nss_ipsecmgr_ref *nss_ipsecmgr_subnet_lookup(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *key);
struct nss_ipsecmgr_ref *nss_ipsecmgr_v4_subnet_match(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *sel);
+struct nss_ipsecmgr_ref *nss_ipsecmgr_v6_subnet_match(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *sel);
/*
* SA API(s)
diff --git a/ipsecmgr/nss_ipsecmgr_sa.c b/ipsecmgr/nss_ipsecmgr_sa.c
index a7993c8..6d8d26a 100644
--- a/ipsecmgr/nss_ipsecmgr_sa.c
+++ b/ipsecmgr/nss_ipsecmgr_sa.c
@@ -144,8 +144,8 @@
break;
case NSS_IPSEC_IPVER_6:
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntohl(oip->dst_addr, addr));
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI6c\n", nss_ipsecmgr_v6addr_ntohl(oip->src_addr, addr));
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI6c\n", nss_ipsecmgr_v6addr_hton(oip->dst_addr, addr));
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "src_ip: %pI6c\n", nss_ipsecmgr_v6addr_hton(oip->src_addr, addr));
break;
}
@@ -513,6 +513,9 @@
nss_ipsecmgr_key_write_8(key, 6 /* v6 */, NSS_IPSECMGR_KEY_POS_IP_VER);
nss_ipsecmgr_key_write_8(key, IPPROTO_ESP, NSS_IPSECMGR_KEY_POS_IP_PROTO);
+ nss_ipsecmgr_v6addr_swap(sel->dst_addr, sel->dst_addr);
+ nss_ipsecmgr_v6addr_swap(sel->src_addr, sel->src_addr);
+
for (i = 0; i < 4; i++) {
nss_ipsecmgr_key_write_32(key, sel->dst_addr[i], NSS_IPSECMGR_KEY_POS_IPV6_DST + (i * 32));
nss_ipsecmgr_key_write_32(key, sel->src_addr[i], NSS_IPSECMGR_KEY_POS_IPV6_SRC + (i * 32));
@@ -732,6 +735,7 @@
info.child_alloc = nss_ipsecmgr_subnet_alloc;
info.child_lookup = nss_ipsecmgr_subnet_lookup;
break;
+
case NSS_IPSECMGR_FLOW_TYPE_V6_TUPLE:
nss_ipsecmgr_copy_encap_v6_flow(&info.nim, &flow->data.v6_tuple);
@@ -745,6 +749,17 @@
info.child_lookup = nss_ipsecmgr_flow_lookup;
break;
+ case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
+
+ nss_ipsecmgr_copy_v6_sa(&info.nim, &sa->data.v6);
+ nss_ipsecmgr_copy_sa_data(&info.nim, data);
+
+ nss_ipsecmgr_v6_subnet2key(&flow->data.v6_subnet, &info.child_key);
+ nss_ipsecmgr_v6_sa2key(&sa->data.v6, &info.sa_key);
+
+ info.child_alloc = nss_ipsecmgr_subnet_alloc;
+ info.child_lookup = nss_ipsecmgr_subnet_lookup;
+ break;
default:
nss_ipsecmgr_warn("%p:unknown flow type(%d)\n", tun, flow->type);
@@ -814,6 +829,17 @@
info.child_lookup = nss_ipsecmgr_flow_lookup;
break;
+ case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
+
+ nss_ipsecmgr_copy_v6_sa(&info.nim, &sa->data.v6);
+
+ nss_ipsecmgr_v6_subnet2key(&flow->data.v6_subnet, &info.child_key);
+ nss_ipsecmgr_v6_sa2key(&sa->data.v6, &info.sa_key);
+
+ info.child_alloc = nss_ipsecmgr_subnet_alloc;
+ info.child_lookup = nss_ipsecmgr_subnet_lookup;
+ break;
+
default:
nss_ipsecmgr_warn("%p:unknown flow type(%d)\n", tun, flow->type);
return false;
diff --git a/ipsecmgr/nss_ipsecmgr_subnet.c b/ipsecmgr/nss_ipsecmgr_subnet.c
index a94ba7c..5479cf1 100644
--- a/ipsecmgr/nss_ipsecmgr_subnet.c
+++ b/ipsecmgr/nss_ipsecmgr_subnet.c
@@ -60,10 +60,14 @@
*/
static inline bool nss_ipsecmgr_netmask_is_default(struct nss_ipsecmgr_key *key)
{
- uint32_t data, mask;
+ uint8_t ip_ver;
- nss_ipsecmgr_key_read(key, &data, &mask, NSS_IPSECMGR_KEY_POS_IPV4_DST);
- return !mask;
+ 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);
}
/*
@@ -124,17 +128,26 @@
return NULL;
}
-
+/*
+ * nss_ipsecmgr_netmask2idx()
+ * Get the index of the netmask array from key.
+ */
static inline uint32_t nss_ipsecmgr_netmask2idx(struct nss_ipsecmgr_key *key)
{
- uint32_t mask, data;
+ uint32_t mask32;
+ uint64_t mask64;
+ uint8_t ip_ver;
- nss_ipsecmgr_key_read(key, &data, &mask, NSS_IPSECMGR_KEY_POS_IPV4_DST);
+ ip_ver = nss_ipsecmgr_key_read_8(key, NSS_IPSECMGR_KEY_POS_IP_VER);
+ if (likely(ip_ver == 4)) {
+ mask32 = nss_ipsecmgr_key_read_mask32(key, NSS_IPSECMGR_KEY_POS_IPV4_DST);
+ return ffs(mask32) - 1;
+ }
- /*
- * for zero mask this will return 0xFFFF_FFFF
- */
- return ffs(mask) - 1;
+ 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;
}
/*
@@ -189,12 +202,13 @@
static ssize_t nss_ipsecmgr_subnet_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
{
struct dentry *parent = dget_parent(fp->f_dentry);
- struct nss_ipsecmgr_subnet_entry *subnet;
+ struct nss_ipsecmgr_subnet_entry *subnet_entry;
struct nss_ipsecmgr_priv *priv;
struct nss_ipsecmgr_ref *ref;
+ uint32_t subnet[4], mask[4];
struct net_device *dev;
- uint32_t dst, m_dst;
ssize_t ret = 0;
+ uint8_t ip_ver;
uint8_t proto;
char *local;
int len;
@@ -205,6 +219,9 @@
}
priv = netdev_priv(dev);
+ /*
+ * Take the read lock.
+ */
read_lock(&priv->lock);
ref = nss_ipsecmgr_subnet_name_lookup(priv, parent->d_name.name);
@@ -214,15 +231,28 @@
goto done;
}
- subnet = container_of(ref, struct nss_ipsecmgr_subnet_entry, ref);
+ subnet_entry = container_of(ref, struct nss_ipsecmgr_subnet_entry, ref);
- /*
- * Extract info from key.
- * NOTE: for IPv6 respective positions for dst_ip and netmask should be used.
- */
- nss_ipsecmgr_key_read(&subnet->key, &dst, &m_dst, NSS_IPSECMGR_KEY_POS_IPV4_DST);
- proto = nss_ipsecmgr_key_read_8(&subnet->key, NSS_IPSECMGR_KEY_POS_IP_PROTO);
+ proto = nss_ipsecmgr_key_read_8(&subnet_entry->key, NSS_IPSECMGR_KEY_POS_IP_PROTO);
+ ip_ver = nss_ipsecmgr_key_read_8(&subnet_entry->key, NSS_IPSECMGR_KEY_POS_IP_VER);
+ switch (ip_ver) {
+ case 4:
+ nss_ipsecmgr_key_read(&subnet_entry->key, subnet, mask, NSS_IPSECMGR_KEY_POS_IPV4_DST, 1);
+ break;
+
+ case 6:
+ /*
+ * 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_v6addr_hton(subnet, subnet);
+ nss_ipsecmgr_v6addr_hton(mask, mask);
+ break;
+
+ }
read_unlock(&priv->lock);
local = vzalloc(NSS_IPSECMGR_MAX_BUF_SZ);
@@ -231,12 +261,20 @@
goto done;
}
- /*
- * IPv4 Generel info
- */
+
len = 0;
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI4h\n", &dst);
- len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_mask: %pI4h\n", &m_dst);
+ switch (ip_ver) {
+ case 4:
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI4h\n", subnet);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_mask: %pI4h\n", mask);
+ break;
+
+ case 6:
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_ip: %pI6c\n", subnet);
+ len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "dst_mask: %pI6c\n", mask);
+ break;
+ }
+
len += snprintf(local + len, NSS_IPSECMGR_MAX_BUF_SZ - len, "proto: %d\n", proto);
ret = simple_read_from_buffer(ubuf, sz, ppos, local, len + 1);
@@ -346,10 +384,10 @@
/*
- * nss_ipsecmgr_copy_v4_subnet()
- * copy v4_subnet nim
+ * nss_ipsecmgr_copy_subnet()
+ * copy subnet nim
*/
-void nss_ipsecmgr_copy_v4_subnet(struct nss_ipsec_msg *nim, struct nss_ipsecmgr_ref *ref)
+void nss_ipsecmgr_copy_subnet(struct nss_ipsec_msg *nim, struct nss_ipsecmgr_ref *ref)
{
struct nss_ipsecmgr_subnet_entry *entry;
struct nss_ipsec_rule_data *data;
@@ -380,6 +418,28 @@
}
/*
+ * nss_ipsecmgr_v6_subnet_sel2key()
+ * convert subnet selector to key
+ */
+void nss_ipsecmgr_v6_subnet_sel2key(struct nss_ipsec_rule_sel *sel, struct nss_ipsecmgr_key *key)
+{
+ 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);
+
+ key->len = NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET;
+}
+
+
+/*
* nss_ipsecmgr_v4_subnet2key()
* convert an v4 subnet into a key
*/
@@ -389,7 +449,7 @@
nss_ipsecmgr_key_write_8(key, 4 /* ipv4 */, NSS_IPSECMGR_KEY_POS_IP_VER);
nss_ipsecmgr_key_write_8(key, (uint8_t)net->protocol, NSS_IPSECMGR_KEY_POS_IP_PROTO);
- nss_ipsecmgr_key_write(key, net->dst_subnet, net->dst_mask, NSS_IPSECMGR_KEY_POS_IPV4_DST);
+ nss_ipsecmgr_key_write(key, &net->dst_subnet, &net->dst_mask, NSS_IPSECMGR_KEY_POS_IPV4_DST, 1);
/*
* clear mask if caller specify protocol as any (0xff).
@@ -403,6 +463,22 @@
}
/*
+ * nss_ipsecmgr_v6_subnet2key()
+ * convert an v6 subnet into a key
+ */
+void nss_ipsecmgr_v6_subnet2key(struct nss_ipsecmgr_encap_v6_subnet *net, struct nss_ipsecmgr_key *key)
+{
+ 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, (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);
+
+ key->len = NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET;
+}
+
+
+/*
* nss_ipsecmgr_v4_subnet_match()
* peform a v4 subnet based match in netmask database
*/
@@ -418,7 +494,7 @@
/*
* cycle through the bitmap for each subnet
*/
- for_each_set_bit(i, db->bitmap, NSS_IPSECMGR_MAX_NETMASK) {
+ for_each_set_bit(i, db->bitmap, 32) {
BUG_ON(db->entries[i] == NULL);
BUG_ON(db->entries[i]->count == 0);
@@ -450,6 +526,38 @@
}
/*
+ * nss_ipsecmgr_v6_subnet_match()
+ * peform a v6 subnet based match in netmask database
+ */
+struct nss_ipsecmgr_ref *nss_ipsecmgr_v6_subnet_match(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *key)
+{
+ struct nss_ipsecmgr_netmask_db *db = &priv->net_db;
+ struct nss_ipsecmgr_key tmp_key;
+ struct nss_ipsecmgr_ref *ref;
+ int i;
+
+ memcpy(&tmp_key, key, sizeof(struct nss_ipsecmgr_key));
+
+ /*
+ * cycle through the bitmap for each subnet
+ */
+ for_each_set_bit(i, db->bitmap, NSS_IPSECMGR_MAX_NETMASK) {
+
+ BUG_ON(db->entries[i] == NULL);
+ BUG_ON(db->entries[i]->count == 0);
+
+ nss_ipsecmgr_key_lshift_mask64(&tmp_key, i, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+
+ ref = nss_ipsecmgr_subnet_lookup(priv, &tmp_key);
+ if (ref) {
+ return ref;
+ }
+ }
+
+ return NULL;
+}
+
+/*
* nss_ipsecmgr_subnet_lookup()
* lookup a subnet entry
*/
diff --git a/netlink/include/nss_nlipv6_if.h b/netlink/include/nss_nlipv6_if.h
index a26c816..6a110a0 100644
--- a/netlink/include/nss_nlipv6_if.h
+++ b/netlink/include/nss_nlipv6_if.h
@@ -26,7 +26,8 @@
*/
#define NSS_NLIPV6_FAMILY "nss_nlipv6"
-#define NSS_NLIPV6_ADDR_BITS (sizeof(uint32_t) * 4)
+#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 */
/**
* @brief IPv6 rule
@@ -52,4 +53,24 @@
nss_nlcmn_init_cmd(&rule->cm, sizeof(struct nss_nlipv6_rule), type);
}
+/**
+ * @brief convert ipv6 address to NSS format
+ *
+ * @param rule[IN] IPv6 address
+ */
+static inline void nss_nlipv6_swap_addr(uint32_t *src, uint32_t *dst)
+{
+ uint32_t temp[4];
+
+ if (src == dst) {
+ memcpy(temp, src, sizeof(temp));
+ src = temp;
+ }
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+
+}
#endif /* __NSS_NLIPV6_IF_H */
diff --git a/netlink/nss_nlipsec.c b/netlink/nss_nlipsec.c
index 0dc439f..dadfc5f 100644
--- a/netlink/nss_nlipsec.c
+++ b/netlink/nss_nlipsec.c
@@ -192,6 +192,7 @@
{
struct nss_ipsecmgr_encap_v4_tuple *v4_tuple;
struct nss_ipsecmgr_encap_v4_subnet *v4_subnet;
+ struct nss_ipsecmgr_encap_v6_subnet *v6_subnet;
struct nss_ipsecmgr_encap_v6_tuple *v6_tuple;
struct nss_ipsecmgr_sa_v4 *v4;
struct nss_ipsecmgr_sa_v6 *v6;
@@ -221,12 +222,12 @@
case NSS_IPSECMGR_FLOW_TYPE_V6_TUPLE:
v6_tuple = &encap_flow->data.v6_tuple;
- if (!bitmap_empty((unsigned long *)v6_tuple->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6_tuple->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid v6 src_ip\n");
return -1;
}
- if (!bitmap_empty((unsigned long *)v6_tuple->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6_tuple->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid v6 dst_ip\n");
return -1;
}
@@ -238,6 +239,15 @@
break;
case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
+ v6_subnet = &encap_flow->data.v6_subnet;
+
+ if (bitmap_empty((unsigned long *)v6_subnet->dst_subnet, NSS_NLIPV6_SUBNET_BITS) &&
+ !bitmap_empty((unsigned long *)v6_subnet->dst_mask, NSS_NLIPV6_SUBNET_BITS)) {
+ nss_nl_error("Invalid v6 dst_subnet\n");
+ return -1;
+ }
+ break;
+
default:
nss_nl_error("Invalid flow type\n");
return -1;
@@ -259,12 +269,12 @@
case NSS_IPSECMGR_SA_TYPE_V6:
v6 = &encap_sa->data.v6;
- if (!bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 src_ip\n");
return -2;
}
- if (!bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 dst_ip\n");
return -2;
}
@@ -320,12 +330,12 @@
case NSS_IPSECMGR_SA_TYPE_V6:
v6 = &decap_sa->data.v6;
- if (!bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 src_ip\n");
return -2;
}
- if (!bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 dst_ip\n");
return -2;
}
@@ -360,6 +370,7 @@
{
struct nss_ipsecmgr_encap_v4_tuple *v4_tuple;
struct nss_ipsecmgr_encap_v4_subnet *v4_subnet;
+ struct nss_ipsecmgr_encap_v6_subnet *v6_subnet;
struct nss_ipsecmgr_encap_v6_tuple *v6_tuple;
struct nss_ipsecmgr_sa_v4 *v4;
struct nss_ipsecmgr_sa_v6 *v6;
@@ -389,12 +400,12 @@
case NSS_IPSECMGR_FLOW_TYPE_V6_TUPLE:
v6_tuple = &encap_flow->data.v6_tuple;
- if (!bitmap_empty((unsigned long *)v6_tuple->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6_tuple->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid v6 src_ip\n");
return -1;
}
- if (!bitmap_empty((unsigned long *)v6_tuple->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6_tuple->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid v6 dest_ip\n");
return -1;
}
@@ -406,6 +417,14 @@
break;
case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
+ v6_subnet = &encap_flow->data.v6_subnet;
+ if (bitmap_empty((unsigned long *)v6_subnet->dst_subnet, NSS_NLIPV6_SUBNET_BITS) &&
+ !bitmap_empty((unsigned long *)v6_subnet->dst_mask, NSS_NLIPV6_SUBNET_BITS)) {
+ nss_nl_error("Invalid v6 dst_subnet\n");
+ return -1;
+ }
+ break;
+
default:
nss_nl_error("Invalid flow type\n");
return -1;
@@ -426,12 +445,12 @@
case NSS_IPSECMGR_SA_TYPE_V6:
v6 = &encap_sa->data.v6;
- if (!bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 src_ip\n");
return -2;
}
- if (!bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 dst_ip\n");
return -2;
}
@@ -472,12 +491,12 @@
case NSS_IPSECMGR_SA_TYPE_V6:
v6 = &encap_sa->data.v6;
- if (!bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 src_ip\n");
return -2;
}
- if (!bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 dst_ip\n");
return -2;
}
@@ -518,12 +537,12 @@
case NSS_IPSECMGR_SA_TYPE_V6:
v6 = &decap_sa->data.v6;
- if (!bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->src_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 src_ip\n");
return -2;
}
- if (!bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)v6->dst_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_error("Invalid V6 dst_ip\n");
return -2;
}
diff --git a/netlink/nss_nlipv6.c b/netlink/nss_nlipv6.c
index a258af9..ece3145 100644
--- a/netlink/nss_nlipv6.c
+++ b/netlink/nss_nlipv6.c
@@ -141,16 +141,17 @@
}
/*
- * nss_nlipv6_get_addr_htonl()
+ * nss_nlipv6_get_addr_hton()
* Convert the ipv6 address from host order to network order.
*/
-static inline void nss_nlipv6_get_addr_htonl(uint32_t src[4], uint32_t dst[4])
+static inline void nss_nlipv6_get_addr_hton(uint32_t src[4], uint32_t dst[4])
{
- int32_t i;
+ nss_nlipv6_swap_addr(src, dst);
- for (i = 0; i < 4; i++) {
- dst[i] = htonl(src[i]);
- }
+ dst[0] = htonl(dst[0]);
+ dst[1] = htonl(dst[1]);
+ dst[2] = htonl(dst[2]);
+ dst[3] = htonl(dst[3]);
}
/*
@@ -167,7 +168,7 @@
struct neighbour *neigh;
struct in6_addr addr;
- nss_nlipv6_get_addr_htonl(ip_addr, addr.s6_addr32);
+ nss_nlipv6_get_addr_hton(ip_addr, addr.s6_addr32);
if (ipv6_addr_is_multicast(&addr)) {
/*
@@ -239,12 +240,12 @@
return -EINVAL;
}
- if (!bitmap_empty((unsigned long *)tuple->flow_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)tuple->flow_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_info("Empty flow IP\n");
return -EINVAL;
}
- if (!bitmap_empty((unsigned long *)tuple->return_ip, NSS_NLIPV6_ADDR_BITS)) {
+ if (bitmap_empty((unsigned long *)tuple->return_ip, NSS_NLIPV6_ADDR_BITS)) {
nss_nl_info("Empty return IP\n");
return -EINVAL;
}
@@ -643,6 +644,12 @@
(void *)resp); /* app context */
/*
+ * Conver the IP addresses to NSS format
+ */
+ nss_nlipv6_swap_addr(nim->msg.rule_create.tuple.flow_ip, nim->msg.rule_create.tuple.flow_ip);
+ nss_nlipv6_swap_addr(nim->msg.rule_create.tuple.return_ip, nim->msg.rule_create.tuple.return_ip);
+
+ /*
* Push Rule to NSS
*/
tx_status = nss_ipv6_tx(gbl_ctx.nss, nim);
@@ -717,6 +724,12 @@
sizeof(struct nss_ipv6_rule_destroy_msg), /* message size */
nss_nlipv6_process_resp, /* response callback */
(void *)resp); /* app context */
+ /*
+ * Conver the IP addresses to NSS format
+ */
+ nss_nlipv6_swap_addr(nim->msg.rule_destroy.tuple.flow_ip, nim->msg.rule_destroy.tuple.flow_ip);
+ nss_nlipv6_swap_addr(nim->msg.rule_destroy.tuple.return_ip, nim->msg.rule_destroy.tuple.return_ip);
+
/*
* Push rule to NSS