Parse "ufid:<foo>" at the beginning of a flow specification and use it for flow manipulation if present.
Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- v3: Fix build on windows. v2: Rebase. --- lib/dpctl.c | 41 +++++++++++++++++++++++++++++++++++++---- lib/odp-util.c | 35 +++++++++++++++++++++++++++++++++++ lib/odp-util.h | 1 + 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/lib/dpctl.c b/lib/dpctl.c index 4e41fe4..7dc4714 100644 --- a/lib/dpctl.c +++ b/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 mask; struct dpif *dpif; + ovs_u128 ufid; + bool ufid_present; char *dp_name; struct simap port_names; - int error; + int n, error; dp_name = argc == 4 ? xstrdup(argv[1]) : get_one_dp(dpctl_p); if (!dp_name) { @@ -834,6 +836,15 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags, return error; } + ufid_present = false; + n = odp_ufid_from_string(key_s, &ufid); + if (n < 0) { + dpctl_error(dpctl_p, error, "parsing flow ufid"); + return -n; + } else if (n) { + key_s += n; + ufid_present = true; + } simap_init(&port_names); 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), 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) { dpctl_error(dpctl_p, error, "updating flow table"); 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 mask; /* To be ignored. */ struct dpif *dpif; + ovs_u128 ufid; + bool ufid_present; char *dp_name; struct simap port_names; - int error; + int n, error; dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp(dpctl_p); if (!dp_name) { @@ -931,6 +945,16 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p) return error; } + ufid_present = false; + n = odp_ufid_from_string(key_s, &ufid); + if (n < 0) { + dpctl_error(dpctl_p, error, "parsing flow ufid"); + return -n; + } else if (n) { + key_s += n; + ufid_present = true; + } + simap_init(&port_names); DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) { 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, - ofpbuf_data(&key), ofpbuf_size(&key), NULL, + ofpbuf_data(&key), ofpbuf_size(&key), + ufid_present ? &ufid : NULL, dpctl_p->print_statistics ? &stats : NULL); if (error) { 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; } diff --git a/lib/odp-util.c b/lib/odp-util.c index a89d5f8..54cdf1d 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1999,6 +1999,41 @@ generate_all_wildcard_mask(struct ofpbuf *ofp, const struct nlattr *key) return ofpbuf_base(ofp); } +int +odp_ufid_from_string(const char *s_, ovs_u128 *ufid) +{ + const char *s = s_; + + if (!strncmp(s, "ufid:", 5)) { + const char *upper; + size_t n; + + s += 5; + n = strspn(s, "0123456789abcdefABCDEF"); + if (!n || n > 32) { + return -EINVAL; + } + + upper = s; + if (n > 16) { + char lower[17]; + + ovs_strlcpy(lower, s, n - 16 + 1); + ufid->u64.lo = strtoull(lower, NULL, 16); + upper += (n - 16); + } else { + ufid->u64.lo = 0; + } + ufid->u64.hi = strtoull(upper, NULL, 16); + s += n; + s += strspn(s, delimiters); + + return s - s_; + } + + return 0; +} + void odp_format_ufid(const ovs_u128 *ufid, struct ds *ds) { diff --git a/lib/odp-util.h b/lib/odp-util.h index 27a5ca7..9c990cd 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -145,6 +145,7 @@ struct odputil_keybuf { enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *, 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_flow_format(const struct nlattr *key, size_t key_len, const struct nlattr *mask, size_t mask_len, -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev