/* callback for array and lru timers */ staticint timer_cb1(void *map, int *key, struct bpf_timer *timer)
{ /* increment bss variable twice. *Onceviaarraytimercallbackandoncevialrutimercallback
*/
bss_data += 5;
/* *key == 0 - the callback was called for array timer. **key==4-thecallbackwascalledfromlrutimer.
*/ if (*key == ARRAY) { struct bpf_timer *lru_timer; int lru_key = LRU;
/* rearm array timer to be called again in ~35 seconds */ if (bpf_timer_start(timer, 1ull << 35, 0) != 0)
err |= 1;
lru_timer = bpf_map_lookup_elem(&lru, &lru_key); if (!lru_timer) return0;
bpf_timer_set_callback(lru_timer, timer_cb1); if (bpf_timer_start(lru_timer, 0, 0) != 0)
err |= 2;
} elseif (*key == LRU) { int lru_key, i;
for (i = LRU + 1;
i <= 100/* for current LRU eviction algorithm this number *shouldbelargerthan~lru->max_entries*2
*/;
i++) { struct elem init = {};
/* lru_key cannot be used as loop induction variable *otherwisetheloopwillbeunbounded.
*/
lru_key = i;
/* add more elements into lru map to push out current *elementandforcedeletionofthistimer
*/
bpf_map_update_elem(map, &lru_key, &init, 0); /* look it up to bump it into active list */
bpf_map_lookup_elem(map, &lru_key);
/* keep adding until *key changes underneath, *whichmeansthatkey/timermemorywasreused
*/ if (*key != LRU) break;
}
/* check that the timer was removed */ if (bpf_timer_cancel(timer) != -EINVAL)
err |= 4;
ok |= 1;
} return0;
}
SEC("fentry/bpf_fentry_test1") int BPF_PROG2(test1, int, a)
{ struct bpf_timer *arr_timer, *lru_timer; struct elem init = {}; int lru_key = LRU; int array_key = ARRAY;
arr_timer = bpf_map_lookup_elem(&array, &array_key); if (!arr_timer) return0;
bpf_timer_init(arr_timer, &array, CLOCK_MONOTONIC);
/* init more timers to check that array destruction *doesn'tleaktimermemory.
*/
array_key = 0;
arr_timer = bpf_map_lookup_elem(&array, &array_key); if (!arr_timer) return0;
bpf_timer_init(arr_timer, &array, CLOCK_MONOTONIC); return0;
}
/* callback for prealloc and non-prealloca hashtab timers */ staticint timer_cb2(void *map, int *key, struct hmap_elem *val)
{ if (*key == HTAB)
callback_check--; else
callback2_check--; if (val->counter > 0 && --val->counter) { /* re-arm the timer again to execute after 1 usec */
bpf_timer_start(&val->timer, 1000, 0);
} elseif (*key == HTAB) { struct bpf_timer *arr_timer; int array_key = ARRAY;
/* cancel arr_timer otherwise bpf_fentry_test1 prog *willstayaliveforever.
*/
arr_timer = bpf_map_lookup_elem(&array, &array_key); if (!arr_timer) return0; if (bpf_timer_cancel(arr_timer) != 1) /* bpf_timer_cancel should return 1 to indicate *thatarr_timerwasactiveatthistime
*/
err |= 8;
/* try to cancel ourself. It shouldn't deadlock. */ if (bpf_timer_cancel(&val->timer) != -EDEADLK)
err |= 16;
/* delete this key and this timer anyway. *Itshouldn'tdeadlockeither.
*/
bpf_map_delete_elem(map, key);
/* in preallocated hashmap both 'key' and 'val' could have been *reusedtostoreanothermapelement(likeinLRUabove), *butincontrolledtestenvironmentthebelowtestworks. *It'snotause-after-free.Thememoryisownedbythemap.
*/ if (bpf_timer_start(&val->timer, 1000, 0) != -EINVAL)
err |= 32;
ok |= 2;
} else { if (*key != HTAB_MALLOC)
err |= 64;
/* try to cancel ourself. It shouldn't deadlock. */ if (bpf_timer_cancel(&val->timer) != -EDEADLK)
err |= 128;
/* delete this key and this timer anyway. *Itshouldn'tdeadlockeither.
*/
bpf_map_delete_elem(map, key);
ok |= 4;
} return0;
}
int bpf_timer_test(void)
{ struct hmap_elem *val; int key = HTAB, key_malloc = HTAB_MALLOC;
val = bpf_map_lookup_elem(&hmap, &key); if (val) { if (bpf_timer_init(&val->timer, &hmap, CLOCK_BOOTTIME) != 0)
err |= 512;
bpf_timer_set_callback(&val->timer, timer_cb2);
bpf_timer_start(&val->timer, 1000, 0);
}
val = bpf_map_lookup_elem(&hmap_malloc, &key_malloc); if (val) { if (bpf_timer_init(&val->timer, &hmap_malloc, CLOCK_BOOTTIME) != 0)
err |= 1024;
bpf_timer_set_callback(&val->timer, timer_cb2);
bpf_timer_start(&val->timer, 1000, 0);
} return0;
}
SEC("fentry/bpf_fentry_test2") int BPF_PROG2(test2, int, a, int, b)
{ struct hmap_elem init = {}, *val; int key = HTAB, key_malloc = HTAB_MALLOC;
init.counter = 10; /* number of times to trigger timer_cb2 */
bpf_map_update_elem(&hmap, &key, &init, 0);
val = bpf_map_lookup_elem(&hmap, &key); if (val)
bpf_timer_init(&val->timer, &hmap, CLOCK_BOOTTIME); /* update the same key to free the timer */
bpf_map_update_elem(&hmap, &key, &init, 0);
bpf_map_update_elem(&hmap_malloc, &key_malloc, &init, 0);
val = bpf_map_lookup_elem(&hmap_malloc, &key_malloc); if (val)
bpf_timer_init(&val->timer, &hmap_malloc, CLOCK_BOOTTIME); /* update the same key to free the timer */
bpf_map_update_elem(&hmap_malloc, &key_malloc, &init, 0);
/* init more timers to check that htab operations *don'tleaktimermemory.
*/
key = 0;
bpf_map_update_elem(&hmap, &key, &init, 0);
val = bpf_map_lookup_elem(&hmap, &key); if (val)
bpf_timer_init(&val->timer, &hmap, CLOCK_BOOTTIME);
bpf_map_delete_elem(&hmap, &key);
bpf_map_update_elem(&hmap, &key, &init, 0);
val = bpf_map_lookup_elem(&hmap, &key); if (val)
bpf_timer_init(&val->timer, &hmap, CLOCK_BOOTTIME);
/* and with non-prealloc htab */
key_malloc = 0;
bpf_map_update_elem(&hmap_malloc, &key_malloc, &init, 0);
val = bpf_map_lookup_elem(&hmap_malloc, &key_malloc); if (val)
bpf_timer_init(&val->timer, &hmap_malloc, CLOCK_BOOTTIME);
bpf_map_delete_elem(&hmap_malloc, &key_malloc);
bpf_map_update_elem(&hmap_malloc, &key_malloc, &init, 0);
val = bpf_map_lookup_elem(&hmap_malloc, &key_malloc); if (val)
bpf_timer_init(&val->timer, &hmap_malloc, CLOCK_BOOTTIME);
return bpf_timer_test();
}
/* callback for absolute timer */ staticint timer_cb3(void *map, int *key, struct bpf_timer *timer)
{
abs_data += 6;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.