Когда я хочу получить значение из карты bpf, тип входного ключа — const char*, он не может получить значение карты; Но когда тип ключа равен char name[192], он может получить правильное значение. В чем разница между двумя типами ключей выше? почему так произошло в этой ситуации?
Это код ebpf:
struct {
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
__uint(key_size, CLUSTER_NAME_MAX_LEN);
__uint(value_size, sizeof(__u32));
__uint(max_entries, MAP_SIZE_OF_CLUSTER);
__uint(map_flags, BPF_F_NO_PREALLOC);
__array(values, struct inner_of_maglev);
}outer_of_maglev SEC(".maps"); // CLUSTER_NAME_MAX_LEN equal 192
static inline void *loadbalance(struct cluster_endpoints *eps, const char* name,ctx_buff_t *ctx)
{
if (!eps || eps->ep_num == 0)
return NULL;
__u32 *res1;
__u32 *res2;
char c_name[192] = "outbound|5000||helloworld.default.svc.cluster.local";
res1 = (__u32 *)bpf_map_lookup_elem(&outer_of_maglev,name);
res2 = (__u32 *)bpf_map_lookup_elem(&outer_of_maglev,c_name);
if (res1) {
BPF_LOG(INFO, CLUSTER, "loadbalance_maglev test res %u\n",res);
}
return NULL;
}
Как и в приведенном выше утверждении, res1 имеет значение NULL, res2 не имеет значения NULL, что является правильным значением карты. Кроме того, содержимое имени переменной такое же, как и c_name;
@VladfromMoscow man7.org/linux/man-pages/man7/bpf-helpers.7.html здесь второй параметр const void *. Что ты конкретно имеешь ввиду?
@ariel marcovitch Я добавил определенную карту ebpf в приведенный выше блок кода.
@bfforever Немного сложно сказать, что происходит, не зная, откуда берутся аргументы для loadbalance(). Вероятно, происходит что-то вроде Ариэля, описанного ниже, но, вероятно, не с неинициализированным массивом, иначе вы не сможете загрузить свою программу.





Я думаю, проблема в том, что идет после вашей строки в памяти. Поскольку все ключи на карте должны иметь одинаковый размер (в вашем случае размер 192 байта), и для поиска используется весь ключ (а не только часть до нулевого терминатора)
В вашем аргументе char[192] остальная часть массива обнуляется.
В случае с аргументом char* это зависит от того, как вы его создали. Если вы не выделили его как обнуленный 192-байтовый массив и только затем скопировали строку, то для вашего ключа также будут использованы случайные байты из памяти, и вы не получите ожидаемого результата.
Это возможно, но кажется относительно маловероятным, учитывая контекст eBPF. Верификатор eBPF отклонит программу, пытающуюся получить доступ к неинициализированным данным (даже через такой помощник, как bpf_map_lookup_elem).
Это разумно. Нам, вероятно, понадобится OP, чтобы дать больше контекста для «имени».
Я решил эту проблему. Как описал Ариэль, передайте в функцию параметр типа char[192], используйте bpf_strncpy, скопируйте из char *name в char name[192].
Однако это не совсем объясняет, почему это не удалось :-/ И теперь у вас есть одна дополнительная, вероятно, ненужная копия.
Похоже, это связано с неопределенным поведением, поскольку второй параметр функции имеет тип void *, а не const void *. Попробуйте вывести c_name после вызова функции. Интересно, меняет ли функция массив.