X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fodp-util.c;h=7caab09c5c3694ae4667ddd57ac29e011b9b1dac;hb=4b9f923273fb79079fcfa15350299b71a0062969;hp=7bfbadeb6a64a06783b2feb3d6244505ab76caa4;hpb=1673e0e4005a83ed9080e0c812089e747c7f71b1;p=openvswitch diff --git a/lib/odp-util.c b/lib/odp-util.c index 7bfbadeb..7caab09c 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -14,8 +14,8 @@ * limitations under the License. */ -#include #include +#include #include "odp-util.h" #include #include @@ -30,9 +30,8 @@ #include "flow.h" #include "netlink.h" #include "ofpbuf.h" -#include "openvswitch/tunnel.h" #include "packets.h" -#include "shash.h" +#include "simap.h" #include "timeval.h" #include "util.h" #include "vlog.h" @@ -49,7 +48,7 @@ VLOG_DEFINE_THIS_MODULE(odp_util); * from another. */ static const char *delimiters = ", \t\r\n"; -static int parse_odp_key_attr(const char *, const struct shash *port_names, +static int parse_odp_key_attr(const char *, const struct simap *port_names, struct ofpbuf *); static void format_odp_key_attr(const struct nlattr *a, struct ds *ds); @@ -166,6 +165,52 @@ format_odp_sample_action(struct ds *ds, const struct nlattr *attr) ds_put_format(ds, "))"); } +static const char * +slow_path_reason_to_string(enum slow_path_reason bit) +{ + switch (bit) { + case SLOW_CFM: + return "cfm"; + case SLOW_LACP: + return "lacp"; + case SLOW_STP: + return "stp"; + case SLOW_IN_BAND: + return "in_band"; + case SLOW_CONTROLLER: + return "controller"; + case SLOW_MATCH: + return "match"; + default: + return NULL; + } +} + +static void +format_slow_path_reason(struct ds *ds, uint32_t slow) +{ + uint32_t bad = 0; + + while (slow) { + uint32_t bit = rightmost_1bit(slow); + const char *s; + + s = slow_path_reason_to_string(bit); + if (s) { + ds_put_format(ds, "%s,", s); + } else { + bad |= bit; + } + + slow &= ~bit; + } + + if (bad) { + ds_put_format(ds, "0x%"PRIx32",", bad); + } + ds_chomp(ds, ','); +} + static void format_odp_userspace_action(struct ds *ds, const struct nlattr *attr) { @@ -191,13 +236,21 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr) switch (cookie.type) { case USER_ACTION_COOKIE_SFLOW: - ds_put_format(ds, ",sFlow," - "vid=%"PRIu16",pcp=%"PRIu8",output=%"PRIu32, + ds_put_format(ds, ",sFlow(" + "vid=%"PRIu16",pcp=%"PRIu8",output=%"PRIu32")", vlan_tci_to_vid(cookie.sflow.vlan_tci), vlan_tci_to_pcp(cookie.sflow.vlan_tci), cookie.sflow.output); break; + case USER_ACTION_COOKIE_SLOW_PATH: + ds_put_cstr(ds, ",slow_path("); + if (cookie.slow_path.reason) { + format_slow_path_reason(ds, cookie.slow_path.reason); + } + ds_put_char(ds, ')'); + break; + case USER_ACTION_COOKIE_UNSPEC: default: ds_put_format(ds, ",userdata=0x%"PRIx64, userdata); @@ -301,7 +354,7 @@ format_odp_actions(struct ds *ds, const struct nlattr *actions, } static int -parse_odp_action(const char *s, const struct shash *port_names, +parse_odp_action(const char *s, const struct simap *port_names, struct ofpbuf *actions) { /* Many of the sscanf calls in this function use oversized destination @@ -326,12 +379,11 @@ parse_odp_action(const char *s, const struct shash *port_names, if (port_names) { int len = strcspn(s, delimiters); - struct shash_node *node; + struct simap_node *node; - node = shash_find_len(port_names, s, len); + node = simap_find_len(port_names, s, len); if (node) { - nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, - (uintptr_t) node->data); + nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, node->data); return len; } } @@ -346,8 +398,8 @@ parse_odp_action(const char *s, const struct shash *port_names, if (sscanf(s, "userspace(pid=%lli)%n", &pid, &n) > 0 && n > 0) { odp_put_userspace_action(pid, NULL, actions); return n; - } else if (sscanf(s, "userspace(pid=%lli,sFlow,vid=%i," - "pcp=%i,output=%lli)%n", + } else if (sscanf(s, "userspace(pid=%lli,sFlow(vid=%i," + "pcp=%i,output=%lli))%n", &pid, &vid, &pcp, &output, &n) > 0 && n > 0) { union user_action_cookie cookie; uint16_t tci; @@ -360,6 +412,42 @@ parse_odp_action(const char *s, const struct shash *port_names, cookie.type = USER_ACTION_COOKIE_SFLOW; cookie.sflow.vlan_tci = htons(tci); cookie.sflow.output = output; + odp_put_userspace_action(pid, &cookie, actions); + return n; + } else if (sscanf(s, "userspace(pid=%lli,slow_path(%n", &pid, &n) > 0 + && n > 0) { + union user_action_cookie cookie; + + cookie.type = USER_ACTION_COOKIE_SLOW_PATH; + cookie.slow_path.unused = 0; + cookie.slow_path.reason = 0; + + while (s[n] != ')') { + uint32_t bit; + + for (bit = 1; bit; bit <<= 1) { + 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] != ')') { + return -EINVAL; + } + n += 2; + odp_put_userspace_action(pid, &cookie, actions); return n; } else if (sscanf(s, "userspace(pid=%lli,userdata=" @@ -444,7 +532,7 @@ parse_odp_action(const char *s, const struct shash *port_names, for (;;) { int retval; - s += strspn(s, delimiters); + n += strspn(s + n, delimiters); if (s[n] == ')') { break; } @@ -454,7 +542,6 @@ parse_odp_action(const char *s, const struct shash *port_names, return retval; } n += retval; - } nl_msg_end_nested(actions, actions_ofs); nl_msg_end_nested(actions, sample_ofs); @@ -472,7 +559,7 @@ parse_odp_action(const char *s, const struct shash *port_names, * Netlink attributes. On failure, no data is appended to 'actions'. Either * way, 'actions''s data might be reallocated. */ int -odp_actions_from_string(const char *s, const struct shash *port_names, +odp_actions_from_string(const char *s, const struct simap *port_names, struct ofpbuf *actions) { size_t old_size; @@ -789,7 +876,7 @@ ovs_frag_type_from_string(const char *s, enum ovs_frag_type *type) } static int -parse_odp_key_attr(const char *s, const struct shash *port_names, +parse_odp_key_attr(const char *s, const struct simap *port_names, struct ofpbuf *key) { /* Many of the sscanf calls in this function use oversized destination @@ -836,14 +923,14 @@ parse_odp_key_attr(const char *s, const struct shash *port_names, if (port_names && !strncmp(s, "in_port(", 8)) { const char *name; - const struct shash_node *node; + const struct simap_node *node; int name_len; name = s + 8; name_len = strcspn(s, ")"); - node = shash_find_len(port_names, name, name_len); + node = simap_find_len(port_names, name, name_len); if (node) { - nl_msg_put_u32(key, OVS_KEY_ATTR_IN_PORT, (uintptr_t) node->data); + nl_msg_put_u32(key, OVS_KEY_ATTR_IN_PORT, node->data); return 8 + name_len + 1; } } @@ -1120,15 +1207,15 @@ parse_odp_key_attr(const char *s, const struct shash *port_names, * data is appended to 'key'. Either way, 'key''s data might be * reallocated. * - * If 'port_names' is nonnull, it points to an shash that maps from a port name - * to a port number cast to void *. (Port names may be used instead of port - * numbers in in_port.) + * If 'port_names' is nonnull, it points to an simap that maps from a port name + * to a port number. (Port names may be used instead of port numbers in + * in_port.) * * On success, the attributes appended to 'key' are individually syntactically * valid, but they may not be valid as a sequence. 'key' might, for example, * have duplicated keys. odp_flow_key_to_flow() will detect those errors. */ int -odp_flow_key_from_string(const char *s, const struct shash *port_names, +odp_flow_key_from_string(const char *s, const struct simap *port_names, struct ofpbuf *key) { const size_t old_size = key->size; @@ -1159,7 +1246,10 @@ ovs_to_odp_frag(uint8_t nw_frag) : OVS_FRAG_TYPE_LATER); } -/* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'. */ +/* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'. + * + * 'buf' must have at least ODPUTIL_FLOW_KEY_BYTES bytes of space, or be + * capable of being expanded to allow for that much space. */ void odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) {