netfilter: ipset: list:set timeout variant fixes

- the timeout value was actually not set
- the garbage collector was broken

The variant is fixed, the tests to the ipset testsuite are added.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by Jozsef Kadlecsik and committed by Patrick McHardy 49a341f2 961ed183

+24 -29
+24 -29
net/netfilter/ipset/ip_set_list_set.c
··· 43 static inline struct set_elem * 44 list_set_elem(const struct list_set *map, u32 id) 45 { 46 - return (struct set_elem *)((char *)map->members + id * map->dsize); 47 } 48 49 static inline bool 50 list_set_timeout(const struct list_set *map, u32 id) 51 { 52 - const struct set_telem *elem = 53 - (const struct set_telem *) list_set_elem(map, id); 54 55 return ip_set_timeout_test(elem->timeout); 56 } ··· 63 static inline bool 64 list_set_expired(const struct list_set *map, u32 id) 65 { 66 - const struct set_telem *elem = 67 - (const struct set_telem *) list_set_elem(map, id); 68 69 return ip_set_timeout_expired(elem->timeout); 70 - } 71 - 72 - static inline int 73 - list_set_exist(const struct set_telem *elem) 74 - { 75 - return elem->id != IPSET_INVALID_ID && 76 - !ip_set_timeout_expired(elem->timeout); 77 } 78 79 /* Set list without and with timeout */ ··· 143 struct set_telem *e; 144 145 for (; i < map->size; i++) { 146 - e = (struct set_telem *)list_set_elem(map, i); 147 swap(e->id, id); 148 if (e->id == IPSET_INVALID_ID) 149 break; 150 - swap(e->timeout, timeout); 151 } 152 } 153 ··· 161 /* Last element replaced: e.g. add new,before,last */ 162 ip_set_put_byindex(e->id); 163 if (with_timeout(map->timeout)) 164 - list_elem_tadd(map, i, id, timeout); 165 else 166 list_elem_add(map, i, id); 167 ··· 169 } 170 171 static int 172 - list_set_del(struct list_set *map, ip_set_id_t id, u32 i) 173 { 174 struct set_elem *a = list_set_elem(map, i), *b; 175 176 - ip_set_put_byindex(id); 177 178 for (; i < map->size - 1; i++) { 179 b = list_set_elem(map, i + 1); ··· 305 (before == 0 || 306 (before > 0 && 307 next_id_eq(map, i, refid)))) 308 - ret = list_set_del(map, id, i); 309 else if (before < 0 && 310 elem->id == refid && 311 next_id_eq(map, i, id)) 312 - ret = list_set_del(map, id, i + 1); 313 } 314 break; 315 default: ··· 457 struct list_set *map = set->data; 458 struct set_telem *e; 459 u32 i; 460 - 461 - /* We run parallel with other readers (test element) 462 - * but adding/deleting new entries is locked out */ 463 - read_lock_bh(&set->lock); 464 - for (i = map->size - 1; i >= 0; i--) { 465 - e = (struct set_telem *) list_set_elem(map, i); 466 - if (e->id != IPSET_INVALID_ID && 467 - list_set_expired(map, i)) 468 - list_set_del(map, e->id, i); 469 } 470 - read_unlock_bh(&set->lock); 471 472 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 473 add_timer(&map->gc);
··· 43 static inline struct set_elem * 44 list_set_elem(const struct list_set *map, u32 id) 45 { 46 + return (struct set_elem *)((void *)map->members + id * map->dsize); 47 + } 48 + 49 + static inline struct set_telem * 50 + list_set_telem(const struct list_set *map, u32 id) 51 + { 52 + return (struct set_telem *)((void *)map->members + id * map->dsize); 53 } 54 55 static inline bool 56 list_set_timeout(const struct list_set *map, u32 id) 57 { 58 + const struct set_telem *elem = list_set_telem(map, id); 59 60 return ip_set_timeout_test(elem->timeout); 61 } ··· 58 static inline bool 59 list_set_expired(const struct list_set *map, u32 id) 60 { 61 + const struct set_telem *elem = list_set_telem(map, id); 62 63 return ip_set_timeout_expired(elem->timeout); 64 } 65 66 /* Set list without and with timeout */ ··· 146 struct set_telem *e; 147 148 for (; i < map->size; i++) { 149 + e = list_set_telem(map, i); 150 swap(e->id, id); 151 + swap(e->timeout, timeout); 152 if (e->id == IPSET_INVALID_ID) 153 break; 154 } 155 } 156 ··· 164 /* Last element replaced: e.g. add new,before,last */ 165 ip_set_put_byindex(e->id); 166 if (with_timeout(map->timeout)) 167 + list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); 168 else 169 list_elem_add(map, i, id); 170 ··· 172 } 173 174 static int 175 + list_set_del(struct list_set *map, u32 i) 176 { 177 struct set_elem *a = list_set_elem(map, i), *b; 178 179 + ip_set_put_byindex(a->id); 180 181 for (; i < map->size - 1; i++) { 182 b = list_set_elem(map, i + 1); ··· 308 (before == 0 || 309 (before > 0 && 310 next_id_eq(map, i, refid)))) 311 + ret = list_set_del(map, i); 312 else if (before < 0 && 313 elem->id == refid && 314 next_id_eq(map, i, id)) 315 + ret = list_set_del(map, i + 1); 316 } 317 break; 318 default: ··· 460 struct list_set *map = set->data; 461 struct set_telem *e; 462 u32 i; 463 + 464 + /* nfnl_lock should be called */ 465 + write_lock_bh(&set->lock); 466 + for (i = 0; i < map->size; i++) { 467 + e = list_set_telem(map, i); 468 + if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) 469 + list_set_del(map, i); 470 } 471 + write_unlock_bh(&set->lock); 472 473 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 474 add_timer(&map->gc);