X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fipsec-secgw%2Fsad.h;h=55712bad6976477e0e7979469fcf12e27b142bfd;hb=dc38ae8d08269f1a7023f9f26045408f3d0e0e25;hp=29ed0f873dd3dd8e9446585404f9f71adbdd5374;hpb=8e499dff73fdf18281bf8ff4112712bdfc1da76d;p=dpdk.git diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h index 29ed0f873d..55712bad69 100644 --- a/examples/ipsec-secgw/sad.h +++ b/examples/ipsec-secgw/sad.h @@ -7,6 +7,17 @@ #include +#define SA_CACHE_SZ 128 +#define SPI2IDX(spi, mask) ((spi) & (mask)) + +struct ipsec_sad_cache { + struct ipsec_sa **v4; + struct ipsec_sa **v6; + uint32_t mask; +}; + +RTE_DECLARE_PER_LCORE(struct ipsec_sad_cache, sad_cache); + struct ipsec_sad { struct rte_ipsec_sad *sad_v4; struct rte_ipsec_sad *sad_v6; @@ -17,8 +28,42 @@ int ipsec_sad_create(const char *name, struct ipsec_sad *sad, int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa); +int ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent); + +static inline int +cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4, + struct rte_ipv6_hdr *ipv6) +{ + int sa_type = WITHOUT_TRANSPORT_VERSION(sa->flags); + if ((sa_type == TRANSPORT) || + /* IPv4 check */ + (is_v4 && (sa_type == IP4_TUNNEL) && + (sa->src.ip.ip4 == ipv4->src_addr) && + (sa->dst.ip.ip4 == ipv4->dst_addr)) || + /* IPv6 check */ + (!is_v4 && (sa_type == IP6_TUNNEL) && + (!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) && + (!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16)))) + return 1; + + return 0; +} + static inline void -sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[], +sa_cache_update(struct ipsec_sa **sa_cache, struct ipsec_sa *sa, uint32_t mask) +{ + uint32_t cache_idx; + + /* SAD cache is disabled */ + if (mask == 0) + return; + + cache_idx = SPI2IDX(sa->spi, mask); + sa_cache[cache_idx] = sa; +} + +static inline void +sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[], void *sa[], uint16_t nb_pkts) { uint32_t i; @@ -34,13 +79,39 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[], const union rte_ipsec_sad_key *keys_v6[nb_pkts]; void *v4_res[nb_pkts]; void *v6_res[nb_pkts]; + uint32_t spi, cache_idx; + struct ipsec_sad_cache *cache; + struct ipsec_sa *cached_sa; + int is_ipv4; + + cache = &RTE_PER_LCORE(sad_cache); /* split received packets by address family into two arrays */ for (i = 0; i < nb_pkts; i++) { ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *); + ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *); esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *, pkts[i]->l3_len); - if ((ipv4->version_ihl >> 4) == IPVERSION) { + + is_ipv4 = pkts[i]->packet_type & RTE_PTYPE_L3_IPV4; + spi = rte_be_to_cpu_32(esp->spi); + cache_idx = SPI2IDX(spi, cache->mask); + + if (is_ipv4) { + cached_sa = (cache->mask != 0) ? + cache->v4[cache_idx] : NULL; + /* check SAD cache entry */ + if ((cached_sa != NULL) && (cached_sa->spi == spi)) { + if (cmp_sa_key(cached_sa, 1, ipv4, ipv6)) { + /* cache hit */ + sa[i] = cached_sa; + continue; + } + } + /* + * cache miss + * preparing sad key to proceed with sad lookup + */ v4[nb_v4].spi = esp->spi; v4[nb_v4].dip = ipv4->dst_addr; v4[nb_v4].sip = ipv4->src_addr; @@ -48,7 +119,14 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[], &v4[nb_v4]; v4_idxes[nb_v4++] = i; } else { - ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *); + cached_sa = (cache->mask != 0) ? + cache->v6[cache_idx] : NULL; + if ((cached_sa != NULL) && (cached_sa->spi == spi)) { + if (cmp_sa_key(cached_sa, 0, ipv4, ipv6)) { + sa[i] = cached_sa; + continue; + } + } v6[nb_v6].spi = esp->spi; memcpy(v6[nb_v6].dip, ipv6->dst_addr, sizeof(ipv6->dst_addr)); @@ -65,11 +143,28 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[], if (nb_v6 != 0) rte_ipsec_sad_lookup(sad->sad_v6, keys_v6, v6_res, nb_v6); - for (i = 0; i < nb_v4; i++) - sa[v4_idxes[i]] = v4_res[i]; - - for (i = 0; i < nb_v6; i++) - sa[v6_idxes[i]] = v6_res[i]; + for (i = 0; i < nb_v4; i++) { + ipv4 = rte_pktmbuf_mtod(pkts[v4_idxes[i]], + struct rte_ipv4_hdr *); + if ((v4_res[i] != NULL) && + (cmp_sa_key(v4_res[i], 1, ipv4, NULL))) { + sa[v4_idxes[i]] = v4_res[i]; + sa_cache_update(cache->v4, (struct ipsec_sa *)v4_res[i], + cache->mask); + } else + sa[v4_idxes[i]] = NULL; + } + for (i = 0; i < nb_v6; i++) { + ipv6 = rte_pktmbuf_mtod(pkts[v6_idxes[i]], + struct rte_ipv6_hdr *); + if ((v6_res[i] != NULL) && + (cmp_sa_key(v6_res[i], 0, NULL, ipv6))) { + sa[v6_idxes[i]] = v6_res[i]; + sa_cache_update(cache->v6, (struct ipsec_sa *)v6_res[i], + cache->mask); + } else + sa[v6_idxes[i]] = NULL; + } } #endif /* __SAD_H__ */