mirror of
https://github.com/openvswitch/ovs
synced 2025-10-21 14:49:41 +00:00
odp-utils: Refactor slow_path_reason parse and format functions.
These functions are used in next patch. Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
This commit is contained in:
110
lib/odp-util.c
110
lib/odp-util.c
@@ -167,8 +167,10 @@ format_odp_sample_action(struct ds *ds, const struct nlattr *attr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
slow_path_reason_to_string(enum slow_path_reason bit)
|
slow_path_reason_to_string(uint32_t data)
|
||||||
{
|
{
|
||||||
|
enum slow_path_reason bit = (enum slow_path_reason) data;
|
||||||
|
|
||||||
switch (bit) {
|
switch (bit) {
|
||||||
case SLOW_CFM:
|
case SLOW_CFM:
|
||||||
return "cfm";
|
return "cfm";
|
||||||
@@ -188,28 +190,85 @@ slow_path_reason_to_string(enum slow_path_reason bit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
format_slow_path_reason(struct ds *ds, uint32_t slow)
|
format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
|
||||||
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
uint32_t bad = 0;
|
uint32_t bad = 0;
|
||||||
|
|
||||||
while (slow) {
|
ds_put_format(ds, "(");
|
||||||
uint32_t bit = rightmost_1bit(slow);
|
if (!flags) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
while (flags) {
|
||||||
|
uint32_t bit = rightmost_1bit(flags);
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
s = slow_path_reason_to_string(bit);
|
s = bit_to_string(bit);
|
||||||
if (s) {
|
if (s) {
|
||||||
ds_put_format(ds, "%s,", s);
|
ds_put_format(ds, "%s,", s);
|
||||||
} else {
|
} else {
|
||||||
bad |= bit;
|
bad |= bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
slow &= ~bit;
|
flags &= ~bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bad) {
|
if (bad) {
|
||||||
ds_put_format(ds, "0x%"PRIx32",", bad);
|
ds_put_format(ds, "0x%"PRIx32",", bad);
|
||||||
}
|
}
|
||||||
ds_chomp(ds, ',');
|
ds_chomp(ds, ',');
|
||||||
|
out:
|
||||||
|
ds_put_format(ds, ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_flags(const char *s, const char *(*bit_to_string)(uint32_t),
|
||||||
|
uint32_t *res)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (s[n] != '(') {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
|
||||||
|
while (s[n] != ')') {
|
||||||
|
unsigned long long int flags;
|
||||||
|
uint32_t bit;
|
||||||
|
int n0;
|
||||||
|
|
||||||
|
if (sscanf(&s[n], "%lli%n", &flags, &n0) > 0 && n0 > 0) {
|
||||||
|
n += n0 + (s[n + n0] == ',');
|
||||||
|
result |= flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bit = 1; bit; bit <<= 1) {
|
||||||
|
const char *name = bit_to_string(bit);
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(name);
|
||||||
|
if (!strncmp(s + n, name, len) &&
|
||||||
|
(s[n + len] == ',' || s[n + len] == ')')) {
|
||||||
|
result |= bit;
|
||||||
|
n += len + (s[n + len] == ',');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bit) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
|
||||||
|
*res = result;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -245,11 +304,8 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USER_ACTION_COOKIE_SLOW_PATH:
|
case USER_ACTION_COOKIE_SLOW_PATH:
|
||||||
ds_put_cstr(ds, ",slow_path(");
|
ds_put_cstr(ds, ",slow_path");
|
||||||
if (cookie.slow_path.reason) {
|
format_flags(ds, slow_path_reason_to_string, cookie.slow_path.reason);
|
||||||
format_slow_path_reason(ds, cookie.slow_path.reason);
|
|
||||||
}
|
|
||||||
ds_put_char(ds, ')');
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USER_ACTION_COOKIE_UNSPEC:
|
case USER_ACTION_COOKIE_UNSPEC:
|
||||||
@@ -415,39 +471,25 @@ parse_odp_action(const char *s, const struct simap *port_names,
|
|||||||
cookie.sflow.output = output;
|
cookie.sflow.output = output;
|
||||||
odp_put_userspace_action(pid, &cookie, actions);
|
odp_put_userspace_action(pid, &cookie, actions);
|
||||||
return n;
|
return n;
|
||||||
} else if (sscanf(s, "userspace(pid=%lli,slow_path(%n", &pid, &n) > 0
|
} else if (sscanf(s, "userspace(pid=%lli,slow_path%n", &pid, &n) > 0
|
||||||
&& n > 0) {
|
&& n > 0) {
|
||||||
union user_action_cookie cookie;
|
union user_action_cookie cookie;
|
||||||
|
int res;
|
||||||
|
|
||||||
cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
|
cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
|
||||||
cookie.slow_path.unused = 0;
|
cookie.slow_path.unused = 0;
|
||||||
cookie.slow_path.reason = 0;
|
cookie.slow_path.reason = 0;
|
||||||
|
|
||||||
while (s[n] != ')') {
|
res = parse_flags(&s[n], slow_path_reason_to_string,
|
||||||
uint32_t bit;
|
&cookie.slow_path.reason);
|
||||||
|
if (res < 0) {
|
||||||
for (bit = 1; bit; bit <<= 1) {
|
return res;
|
||||||
const char *reason = slow_path_reason_to_string(bit);
|
|
||||||
size_t len = strlen(reason);
|
|
||||||
|
|
||||||
if (reason
|
|
||||||
&& !strncmp(s + n, reason, len)
|
|
||||||
&& (s[n + len] == ',' || s[n + len] == ')'))
|
|
||||||
{
|
|
||||||
cookie.slow_path.reason |= bit;
|
|
||||||
n += len + (s[n + len] == ',');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bit) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (s[n + 1] != ')') {
|
n += res;
|
||||||
|
if (s[n] != ')') {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
n += 2;
|
n++;
|
||||||
|
|
||||||
odp_put_userspace_action(pid, &cookie, actions);
|
odp_put_userspace_action(pid, &cookie, actions);
|
||||||
return n;
|
return n;
|
||||||
|
Reference in New Issue
Block a user