Skip to content

Commit be898cb

Browse files
mykyta5anakryiko
authored andcommitted
selftests/bpf: Separate var preset parsing in veristat
Refactor var preset parsing in veristat to simplify implementation. Prepare parsed variable beforehand so that parsing logic is separated from functionality of calculating offsets and searching fields. Introduce rvalue struct, storing either int or enum (string value), will be reused in the next patch, extract parsing rvalue into a separate function. Signed-off-by: Mykyta Yatsenko <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 886178a commit be898cb

File tree

1 file changed

+99
-53
lines changed

1 file changed

+99
-53
lines changed

tools/testing/selftests/bpf/veristat.c

Lines changed: 99 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,23 @@ struct filter {
156156
bool abs;
157157
};
158158

159-
struct var_preset {
160-
char *name;
159+
struct rvalue {
161160
enum { INTEGRAL, ENUMERATOR } type;
162161
union {
163162
long long ivalue;
164163
char *svalue;
165164
};
165+
};
166+
167+
struct field_access {
168+
char *name;
169+
};
170+
171+
struct var_preset {
172+
struct field_access *atoms;
173+
int atom_count;
174+
char *full_name;
175+
struct rvalue value;
166176
bool applied;
167177
};
168178

@@ -1498,6 +1508,35 @@ static int reset_stat_cgroup(void)
14981508
return 0;
14991509
}
15001510

1511+
static int parse_rvalue(const char *val, struct rvalue *rvalue)
1512+
{
1513+
long long value;
1514+
char *val_end;
1515+
1516+
if (val[0] == '-' || isdigit(val[0])) {
1517+
/* must be a number */
1518+
errno = 0;
1519+
value = strtoll(val, &val_end, 0);
1520+
if (errno == ERANGE) {
1521+
errno = 0;
1522+
value = strtoull(val, &val_end, 0);
1523+
}
1524+
if (errno || *val_end != '\0') {
1525+
fprintf(stderr, "Failed to parse value '%s'\n", val);
1526+
return -EINVAL;
1527+
}
1528+
rvalue->ivalue = value;
1529+
rvalue->type = INTEGRAL;
1530+
} else {
1531+
/* if not a number, consider it enum value */
1532+
rvalue->svalue = strdup(val);
1533+
if (!rvalue->svalue)
1534+
return -ENOMEM;
1535+
rvalue->type = ENUMERATOR;
1536+
}
1537+
return 0;
1538+
}
1539+
15011540
static int process_prog(const char *filename, struct bpf_object *obj, struct bpf_program *prog)
15021541
{
15031542
const char *base_filename = basename(strdupa(filename));
@@ -1593,13 +1632,36 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
15931632
return 0;
15941633
};
15951634

1635+
static int parse_var_atoms(const char *full_var, struct var_preset *preset)
1636+
{
1637+
char expr[256], *name, *saveptr;
1638+
1639+
snprintf(expr, sizeof(expr), "%s", full_var);
1640+
preset->atom_count = 0;
1641+
while ((name = strtok_r(preset->atom_count ? NULL : expr, ".", &saveptr))) {
1642+
struct field_access *tmp;
1643+
int i = preset->atom_count;
1644+
1645+
tmp = reallocarray(preset->atoms, i + 1, sizeof(*preset->atoms));
1646+
if (!tmp)
1647+
return -ENOMEM;
1648+
1649+
preset->atoms = tmp;
1650+
preset->atom_count++;
1651+
1652+
preset->atoms[i].name = strdup(name);
1653+
if (!preset->atoms[i].name)
1654+
return -ENOMEM;
1655+
}
1656+
return 0;
1657+
}
1658+
15961659
static int append_var_preset(struct var_preset **presets, int *cnt, const char *expr)
15971660
{
15981661
void *tmp;
15991662
struct var_preset *cur;
1600-
char var[256], val[256], *val_end;
1601-
long long value;
1602-
int n;
1663+
char var[256], val[256];
1664+
int n, err;
16031665

16041666
tmp = realloc(*presets, (*cnt + 1) * sizeof(**presets));
16051667
if (!tmp)
@@ -1614,32 +1676,18 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
16141676
return -EINVAL;
16151677
}
16161678

1617-
if (val[0] == '-' || isdigit(val[0])) {
1618-
/* must be a number */
1619-
errno = 0;
1620-
value = strtoll(val, &val_end, 0);
1621-
if (errno == ERANGE) {
1622-
errno = 0;
1623-
value = strtoull(val, &val_end, 0);
1624-
}
1625-
if (errno || *val_end != '\0') {
1626-
fprintf(stderr, "Failed to parse value '%s'\n", val);
1627-
return -EINVAL;
1628-
}
1629-
cur->ivalue = value;
1630-
cur->type = INTEGRAL;
1631-
} else {
1632-
/* if not a number, consider it enum value */
1633-
cur->svalue = strdup(val);
1634-
if (!cur->svalue)
1635-
return -ENOMEM;
1636-
cur->type = ENUMERATOR;
1637-
}
1679+
err = parse_rvalue(val, &cur->value);
1680+
if (err)
1681+
return err;
16381682

1639-
cur->name = strdup(var);
1640-
if (!cur->name)
1683+
cur->full_name = strdup(var);
1684+
if (!cur->full_name)
16411685
return -ENOMEM;
16421686

1687+
err = parse_var_atoms(var, cur);
1688+
if (err)
1689+
return err;
1690+
16431691
return 0;
16441692
}
16451693

@@ -1766,22 +1814,20 @@ const int btf_find_member(const struct btf *btf,
17661814
}
17671815

17681816
static int adjust_var_secinfo(struct btf *btf, const struct btf_type *t,
1769-
struct btf_var_secinfo *sinfo, const char *var)
1817+
struct btf_var_secinfo *sinfo, struct var_preset *preset)
17701818
{
1771-
char expr[256], *saveptr;
17721819
const struct btf_type *base_type, *member_type;
1773-
int err, member_tid;
1774-
char *name;
1820+
int err, member_tid, i;
17751821
__u32 member_offset = 0;
17761822

17771823
base_type = btf__type_by_id(btf, btf__resolve_type(btf, t->type));
1778-
snprintf(expr, sizeof(expr), "%s", var);
1779-
strtok_r(expr, ".", &saveptr);
17801824

1781-
while ((name = strtok_r(NULL, ".", &saveptr))) {
1782-
err = btf_find_member(btf, base_type, 0, name, &member_tid, &member_offset);
1825+
for (i = 1; i < preset->atom_count; ++i) {
1826+
err = btf_find_member(btf, base_type, 0, preset->atoms[i].name,
1827+
&member_tid, &member_offset);
17831828
if (err) {
1784-
fprintf(stderr, "Could not find member %s for variable %s\n", name, var);
1829+
fprintf(stderr, "Could not find member %s for variable %s\n",
1830+
preset->atoms[i].name, preset->atoms[i - 1].name);
17851831
return err;
17861832
}
17871833
member_type = btf__type_by_id(btf, member_tid);
@@ -1799,7 +1845,7 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
17991845
{
18001846
const struct btf_type *base_type;
18011847
void *ptr;
1802-
long long value = preset->ivalue;
1848+
long long value = preset->value.ivalue;
18031849
size_t size;
18041850

18051851
base_type = btf__type_by_id(btf, btf__resolve_type(btf, sinfo->type));
@@ -1813,17 +1859,18 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
18131859
return -EINVAL;
18141860
}
18151861

1816-
if (preset->type == ENUMERATOR) {
1862+
if (preset->value.type == ENUMERATOR) {
18171863
if (btf_is_any_enum(base_type)) {
1818-
if (enum_value_from_name(btf, base_type, preset->svalue, &value)) {
1864+
if (enum_value_from_name(btf, base_type, preset->value.svalue, &value)) {
18191865
fprintf(stderr,
18201866
"Failed to find integer value for enum element %s\n",
1821-
preset->svalue);
1867+
preset->value.svalue);
18221868
return -EINVAL;
18231869
}
18241870
} else {
18251871
fprintf(stderr, "Value %s is not supported for type %s\n",
1826-
preset->svalue, btf__name_by_offset(btf, base_type->name_off));
1872+
preset->value.svalue,
1873+
btf__name_by_offset(btf, base_type->name_off));
18271874
return -EINVAL;
18281875
}
18291876
}
@@ -1890,20 +1937,16 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
18901937
for (j = 0; j < n; ++j, ++sinfo) {
18911938
const struct btf_type *var_type = btf__type_by_id(btf, sinfo->type);
18921939
const char *var_name;
1893-
int var_len;
18941940

18951941
if (!btf_is_var(var_type))
18961942
continue;
18971943

18981944
var_name = btf__name_by_offset(btf, var_type->name_off);
1899-
var_len = strlen(var_name);
19001945

19011946
for (k = 0; k < npresets; ++k) {
19021947
struct btf_var_secinfo tmp_sinfo;
19031948

1904-
if (strncmp(var_name, presets[k].name, var_len) != 0 ||
1905-
(presets[k].name[var_len] != '\0' &&
1906-
presets[k].name[var_len] != '.'))
1949+
if (strcmp(var_name, presets[k].atoms[0].name) != 0)
19071950
continue;
19081951

19091952
if (presets[k].applied) {
@@ -1913,7 +1956,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
19131956
}
19141957
tmp_sinfo = *sinfo;
19151958
err = adjust_var_secinfo(btf, var_type,
1916-
&tmp_sinfo, presets[k].name);
1959+
&tmp_sinfo, presets + k);
19171960
if (err)
19181961
return err;
19191962

@@ -1928,7 +1971,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
19281971
for (i = 0; i < npresets; ++i) {
19291972
if (!presets[i].applied) {
19301973
fprintf(stderr, "Global variable preset %s has not been applied\n",
1931-
presets[i].name);
1974+
presets[i].full_name);
19321975
}
19331976
presets[i].applied = false;
19341977
}
@@ -3062,7 +3105,7 @@ static int handle_replay_mode(void)
30623105

30633106
int main(int argc, char **argv)
30643107
{
3065-
int err = 0, i;
3108+
int err = 0, i, j;
30663109

30673110
if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
30683111
return 1;
@@ -3121,9 +3164,12 @@ int main(int argc, char **argv)
31213164
}
31223165
free(env.deny_filters);
31233166
for (i = 0; i < env.npresets; ++i) {
3124-
free(env.presets[i].name);
3125-
if (env.presets[i].type == ENUMERATOR)
3126-
free(env.presets[i].svalue);
3167+
free(env.presets[i].full_name);
3168+
for (j = 0; j < env.presets[i].atom_count; ++j)
3169+
free(env.presets[i].atoms[j].name);
3170+
free(env.presets[i].atoms);
3171+
if (env.presets[i].value.type == ENUMERATOR)
3172+
free(env.presets[i].value.svalue);
31273173
}
31283174
free(env.presets);
31293175
return -err;

0 commit comments

Comments
 (0)