Hi > > Function rte_ip_frag_sweep_table() enables callers to > incrementally sweep IP frament tables for incomplete, expired fragments. > > rte_ip_frag_sweep_table() is needed to identify > never-to-be-completed fragments during DDoS attacks.
There is a patch from Alex Kiselev: http://patches.dpdk.org/patch/40601/ doing the same thing, and I think in a better way (as it goes through LRU list, not entire table). So I'd suggest we go ahead with Alex one. Thanks Konstantin > > Signed-off-by: Qiaobin Fu <qiaob...@bu.edu> > Reviewed-by: Cody Doucette <douce...@bu.edu> > Reviewed-by: Michel Machado <mic...@digirati.com.br> > --- > lib/librte_ip_frag/ip_frag_common.h | 18 +++++++++++++++++ > lib/librte_ip_frag/ip_frag_internal.c | 18 ----------------- > lib/librte_ip_frag/rte_ip_frag.h | 17 ++++++++++++++++ > lib/librte_ip_frag/rte_ip_frag_common.c | 26 +++++++++++++++++++++++++ > 4 files changed, 61 insertions(+), 18 deletions(-) > > diff --git a/lib/librte_ip_frag/ip_frag_common.h > b/lib/librte_ip_frag/ip_frag_common.h > index 197acf8d8..ef869182d 100644 > --- a/lib/librte_ip_frag/ip_frag_common.h > +++ b/lib/librte_ip_frag/ip_frag_common.h > @@ -25,6 +25,12 @@ > #define IPv6_KEY_BYTES_FMT \ > "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 > > +#ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT > +#define IP_FRAG_TBL_STAT_UPDATE(s, f, v) ((s)->f += (v)) > +#else > +#define IP_FRAG_TBL_STAT_UPDATE(s, f, v) do {} while (0) > +#endif /* IP_FRAG_TBL_STAT */ > + > /* internal functions declarations */ > struct rte_mbuf * ip_frag_process(struct ip_frag_pkt *fp, > struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, > @@ -149,4 +155,16 @@ ip_frag_reset(struct ip_frag_pkt *fp, uint64_t tms) > fp->frags[IP_FIRST_FRAG_IDX] = zero_frag; > } > > +/* frag table helper functions */ > +static inline void > +ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row > *dr, > + struct ip_frag_pkt *fp) > +{ > + ip_frag_free(fp, dr); > + ip_frag_key_invalidate(&fp->key); > + TAILQ_REMOVE(&tbl->lru, fp, lru); > + tbl->use_entries--; > + IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1); > +} > + > #endif /* _IP_FRAG_COMMON_H_ */ > diff --git a/lib/librte_ip_frag/ip_frag_internal.c > b/lib/librte_ip_frag/ip_frag_internal.c > index 2560c7713..97470a872 100644 > --- a/lib/librte_ip_frag/ip_frag_internal.c > +++ b/lib/librte_ip_frag/ip_frag_internal.c > @@ -14,24 +14,6 @@ > #define IP_FRAG_TBL_POS(tbl, sig) \ > ((tbl)->pkt + ((sig) & (tbl)->entry_mask)) > > -#ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT > -#define IP_FRAG_TBL_STAT_UPDATE(s, f, v) ((s)->f += (v)) > -#else > -#define IP_FRAG_TBL_STAT_UPDATE(s, f, v) do {} while (0) > -#endif /* IP_FRAG_TBL_STAT */ > - > -/* local frag table helper functions */ > -static inline void > -ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row > *dr, > - struct ip_frag_pkt *fp) > -{ > - ip_frag_free(fp, dr); > - ip_frag_key_invalidate(&fp->key); > - TAILQ_REMOVE(&tbl->lru, fp, lru); > - tbl->use_entries--; > - IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1); > -} > - > static inline void > ip_frag_tbl_add(struct rte_ip_frag_tbl *tbl, struct ip_frag_pkt *fp, > const struct ip_frag_key *key, uint64_t tms) > diff --git a/lib/librte_ip_frag/rte_ip_frag.h > b/lib/librte_ip_frag/rte_ip_frag.h > index b3f3f78df..79443096c 100644 > --- a/lib/librte_ip_frag/rte_ip_frag.h > +++ b/lib/librte_ip_frag/rte_ip_frag.h > @@ -146,6 +146,23 @@ struct rte_ip_frag_tbl * > rte_ip_frag_table_create(uint32_t bucket_num, > uint32_t bucket_entries, uint32_t max_entries, > uint64_t max_cycles, int socket_id); > > +/** > + * Sweep the IP fragmentation table for expired segments. > + * > + * @param tbl > + * Fragmentation table to sweep. > + * @param dr > + * Death row to free buffers to > + * @param next > + * Pointer to the bucket iterator. > + * Should be 0 to start sweeping the fragmentation table. > + * Bucket iterator is incremented after each call of this function. > + * @return > + * 0 if successful. -EINVAL if the parameters are invalid. > + */ > +int rte_ip_frag_sweep_table(struct rte_ip_frag_tbl *tbl, > + struct rte_ip_frag_death_row *dr, uint32_t *next); > + > /** > * Free allocated IP fragmentation table. > * > diff --git a/lib/librte_ip_frag/rte_ip_frag_common.c > b/lib/librte_ip_frag/rte_ip_frag_common.c > index 659a17951..53325ddae 100644 > --- a/lib/librte_ip_frag/rte_ip_frag_common.c > +++ b/lib/librte_ip_frag/rte_ip_frag_common.c > @@ -7,6 +7,7 @@ > > #include <rte_memory.h> > #include <rte_log.h> > +#include <rte_cycles.h> > > #include "ip_frag_common.h" > > @@ -93,6 +94,31 @@ rte_ip_frag_table_destroy(struct rte_ip_frag_tbl *tbl) > rte_free(tbl); > } > > +/* Sweep the IP fragmentation table. */ > +int > +rte_ip_frag_sweep_table(struct rte_ip_frag_tbl *tbl, > + struct rte_ip_frag_death_row *dr, uint32_t *next) > +{ > + uint32_t i; > + uint64_t cur_tsc = rte_rdtsc(); > + struct ip_frag_pkt *pkt; > + > + if (tbl == NULL || dr == NULL || next == NULL || > + (*next * tbl->bucket_entries >= tbl->nb_entries)) > + return -EINVAL; > + > + pkt = tbl->pkt + *next * tbl->bucket_entries; > + for (i = 0; i < tbl->bucket_entries; i++) { > + if (tbl->max_cycles + pkt[i].start < cur_tsc) > + ip_frag_tbl_del(tbl, dr, pkt + i); > + } > + > + *next = (*next + 1) * tbl->bucket_entries >= tbl->nb_entries ? > + 0 : *next + 1; > + > + return 0; > +} > + > /* dump frag table statistics to file */ > void > rte_ip_frag_table_statistics_dump(FILE *f, const struct rte_ip_frag_tbl *tbl) > -- > 2.17.1