mirror of
https://github.com/openvswitch/ovs
synced 2025-09-04 08:15:25 +00:00
dpctl: Add support for using UFID to add/del flows.
Parse "ufid:<foo>" at the beginning of a flow specification and use it for flow manipulation if present. Signed-off-by: Joe Stringer <joestringer@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
41
lib/dpctl.c
41
lib/dpctl.c
@@ -819,9 +819,11 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
|
|||||||
struct ofpbuf key;
|
struct ofpbuf key;
|
||||||
struct ofpbuf mask;
|
struct ofpbuf mask;
|
||||||
struct dpif *dpif;
|
struct dpif *dpif;
|
||||||
|
ovs_u128 ufid;
|
||||||
|
bool ufid_present;
|
||||||
char *dp_name;
|
char *dp_name;
|
||||||
struct simap port_names;
|
struct simap port_names;
|
||||||
int error;
|
int n, error;
|
||||||
|
|
||||||
dp_name = argc == 4 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
|
dp_name = argc == 4 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
|
||||||
if (!dp_name) {
|
if (!dp_name) {
|
||||||
@@ -834,6 +836,15 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ufid_present = false;
|
||||||
|
n = odp_ufid_from_string(key_s, &ufid);
|
||||||
|
if (n < 0) {
|
||||||
|
dpctl_error(dpctl_p, -n, "parsing flow ufid");
|
||||||
|
return -n;
|
||||||
|
} else if (n) {
|
||||||
|
key_s += n;
|
||||||
|
ufid_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
simap_init(&port_names);
|
simap_init(&port_names);
|
||||||
DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
|
DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
|
||||||
@@ -860,7 +871,8 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
|
|||||||
ofpbuf_size(&mask) == 0 ? NULL : ofpbuf_data(&mask),
|
ofpbuf_size(&mask) == 0 ? NULL : ofpbuf_data(&mask),
|
||||||
ofpbuf_size(&mask),
|
ofpbuf_size(&mask),
|
||||||
ofpbuf_data(&actions), ofpbuf_size(&actions),
|
ofpbuf_data(&actions), ofpbuf_size(&actions),
|
||||||
NULL, dpctl_p->print_statistics ? &stats : NULL);
|
ufid_present ? &ufid : NULL,
|
||||||
|
dpctl_p->print_statistics ? &stats : NULL);
|
||||||
if (error) {
|
if (error) {
|
||||||
dpctl_error(dpctl_p, error, "updating flow table");
|
dpctl_error(dpctl_p, error, "updating flow table");
|
||||||
goto out_freeactions;
|
goto out_freeactions;
|
||||||
@@ -916,9 +928,11 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
|
|||||||
struct ofpbuf key;
|
struct ofpbuf key;
|
||||||
struct ofpbuf mask; /* To be ignored. */
|
struct ofpbuf mask; /* To be ignored. */
|
||||||
struct dpif *dpif;
|
struct dpif *dpif;
|
||||||
|
ovs_u128 ufid;
|
||||||
|
bool ufid_present;
|
||||||
char *dp_name;
|
char *dp_name;
|
||||||
struct simap port_names;
|
struct simap port_names;
|
||||||
int error;
|
int n, error;
|
||||||
|
|
||||||
dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
|
dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
|
||||||
if (!dp_name) {
|
if (!dp_name) {
|
||||||
@@ -931,6 +945,16 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ufid_present = false;
|
||||||
|
n = odp_ufid_from_string(key_s, &ufid);
|
||||||
|
if (n < 0) {
|
||||||
|
dpctl_error(dpctl_p, -n, "parsing flow ufid");
|
||||||
|
return -n;
|
||||||
|
} else if (n) {
|
||||||
|
key_s += n;
|
||||||
|
ufid_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
simap_init(&port_names);
|
simap_init(&port_names);
|
||||||
DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
|
DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
|
||||||
simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
|
simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
|
||||||
@@ -946,10 +970,19 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
error = dpif_flow_del(dpif,
|
error = dpif_flow_del(dpif,
|
||||||
ofpbuf_data(&key), ofpbuf_size(&key), NULL,
|
ofpbuf_data(&key), ofpbuf_size(&key),
|
||||||
|
ufid_present ? &ufid : NULL,
|
||||||
dpctl_p->print_statistics ? &stats : NULL);
|
dpctl_p->print_statistics ? &stats : NULL);
|
||||||
if (error) {
|
if (error) {
|
||||||
dpctl_error(dpctl_p, error, "deleting flow");
|
dpctl_error(dpctl_p, error, "deleting flow");
|
||||||
|
if (error == ENOENT && !ufid_present) {
|
||||||
|
struct ds s;
|
||||||
|
|
||||||
|
ds_init(&s);
|
||||||
|
ds_put_format(&s, "Perhaps you need to specify a UFID?");
|
||||||
|
dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
|
||||||
|
ds_destroy(&s);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1999,6 +1999,41 @@ generate_all_wildcard_mask(struct ofpbuf *ofp, const struct nlattr *key)
|
|||||||
return ofpbuf_base(ofp);
|
return ofpbuf_base(ofp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
odp_ufid_from_string(const char *s_, ovs_u128 *ufid)
|
||||||
|
{
|
||||||
|
const char *s = s_;
|
||||||
|
|
||||||
|
if (ovs_scan(s, "ufid:")) {
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
s += 5;
|
||||||
|
if (ovs_scan(s, "0x")) {
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = strspn(s, "0123456789abcdefABCDEF");
|
||||||
|
if (n != 32) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ovs_scan(s, "%"SCNx64, &ufid->u64.hi)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
s += 16;
|
||||||
|
|
||||||
|
if (!ovs_scan(s, "%"SCNx64, &ufid->u64.lo)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
s += 16;
|
||||||
|
s += strspn(s, delimiters);
|
||||||
|
|
||||||
|
return s - s_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
odp_format_ufid(const ovs_u128 *ufid, struct ds *ds)
|
odp_format_ufid(const ovs_u128 *ufid, struct ds *ds)
|
||||||
{
|
{
|
||||||
|
@@ -145,6 +145,7 @@ struct odputil_keybuf {
|
|||||||
enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *,
|
enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *,
|
||||||
struct flow_tnl *);
|
struct flow_tnl *);
|
||||||
|
|
||||||
|
int odp_ufid_from_string(const char *s_, ovs_u128 *ufid);
|
||||||
void odp_format_ufid(const ovs_u128 *ufid, struct ds *);
|
void odp_format_ufid(const ovs_u128 *ufid, struct ds *);
|
||||||
void odp_flow_format(const struct nlattr *key, size_t key_len,
|
void odp_flow_format(const struct nlattr *key, size_t key_len,
|
||||||
const struct nlattr *mask, size_t mask_len,
|
const struct nlattr *mask, size_t mask_len,
|
||||||
|
Reference in New Issue
Block a user