X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fodp-util.c;h=d97d30c038dca63c6c1c311a4235e63f125f6485;hb=be07be4dcba9faa181b195cdda0d8ab3761e738d;hp=2830fe8999dfb0d4dad476ff8e226808d2937ffd;hpb=df2c07f4338faac04f4969f243fe4e8083b309ac;p=openvswitch diff --git a/lib/odp-util.c b/lib/odp-util.c index 2830fe89..d97d30c0 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -49,8 +49,8 @@ odp_action_len(uint16_t type) switch ((enum ovs_action_type) type) { case OVS_ACTION_ATTR_OUTPUT: return 4; case OVS_ACTION_ATTR_USERSPACE: return 8; - case OVS_ACTION_ATTR_SET_DL_TCI: return 2; - case OVS_ACTION_ATTR_STRIP_VLAN: return 0; + case OVS_ACTION_ATTR_PUSH_VLAN: return 2; + case OVS_ACTION_ATTR_POP_VLAN: return 0; case OVS_ACTION_ATTR_SET_DL_SRC: return ETH_ADDR_LEN; case OVS_ACTION_ATTR_SET_DL_DST: return ETH_ADDR_LEN; case OVS_ACTION_ATTR_SET_NW_SRC: return 4; @@ -62,6 +62,7 @@ odp_action_len(uint16_t type) case OVS_ACTION_ATTR_SET_PRIORITY: return 4; case OVS_ACTION_ATTR_POP_PRIORITY: return 0; + case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: return -1; @@ -89,13 +90,50 @@ format_generic_odp_action(struct ds *ds, const struct nlattr *a) } } +static void +format_odp_sample_action(struct ds *ds, const struct nlattr *attr) +{ + static const struct nl_policy ovs_sample_policy[] = { + [OVS_SAMPLE_ATTR_PROBABILITY] = { .type = NL_A_U32 }, + [OVS_SAMPLE_ATTR_ACTIONS] = { .type = NL_A_NESTED } + }; + struct nlattr *a[ARRAY_SIZE(ovs_sample_policy)]; + struct ofpbuf buf; + double percentage; + const struct nlattr *nla_acts; + int len; + + ds_put_cstr(ds, "sample"); + + ofpbuf_use_const(&buf, nl_attr_get(attr), nl_attr_get_size(attr)); + if (!nl_policy_parse(&buf, 0, ovs_sample_policy, a, + ARRAY_SIZE(ovs_sample_policy))) { + ds_put_cstr(ds, "(error)"); + return; + } + + percentage = (100.0 * nl_attr_get_u32(a[OVS_SAMPLE_ATTR_PROBABILITY])) / + UINT32_MAX; + + ds_put_format(ds, "(sample=%.1f%%,", percentage); + + ds_put_cstr(ds, "actions("); + nla_acts = nl_attr_get(a[OVS_SAMPLE_ATTR_ACTIONS]); + len = nl_attr_get_size(a[OVS_SAMPLE_ATTR_ACTIONS]); + format_odp_actions(ds, nla_acts, len); + ds_put_format(ds, "))"); +} + void format_odp_action(struct ds *ds, const struct nlattr *a) { const uint8_t *eth; ovs_be32 ip; + struct user_action_cookie cookie; + uint64_t data; - if (nl_attr_get_size(a) != odp_action_len(nl_attr_type(a))) { + if (nl_attr_get_size(a) != odp_action_len(nl_attr_type(a)) && + nl_attr_type(a) != OVS_ACTION_ATTR_SAMPLE) { ds_put_format(ds, "bad length %zu, expected %d for: ", nl_attr_get_size(a), odp_action_len(nl_attr_type(a))); format_generic_odp_action(ds, a); @@ -107,19 +145,33 @@ format_odp_action(struct ds *ds, const struct nlattr *a) ds_put_format(ds, "%"PRIu16, nl_attr_get_u32(a)); break; case OVS_ACTION_ATTR_USERSPACE: - ds_put_format(ds, "userspace(%"PRIu64")", nl_attr_get_u64(a)); + data = nl_attr_get_u64(a); + memcpy(&cookie, &data, sizeof(cookie)); + + if (cookie.type == USER_ACTION_COOKIE_CONTROLLER) { + ds_put_format(ds, "userspace(controller,length=%"PRIu32")", + cookie.data); + } else if (cookie.type == USER_ACTION_COOKIE_SFLOW) { + ds_put_format(ds, "userspace(sFlow,n_output=%"PRIu8"," + "vid=%"PRIu16",pcp=%"PRIu8",ifindex=%"PRIu32")", + cookie.n_output, vlan_tci_to_vid(cookie.vlan_tci), + vlan_tci_to_pcp(cookie.vlan_tci), cookie.data); + } else { + ds_put_format(ds, "userspace(unknown,data=0x%"PRIx64")", + nl_attr_get_u64(a)); + } break; case OVS_ACTION_ATTR_SET_TUNNEL: ds_put_format(ds, "set_tunnel(%#"PRIx64")", ntohll(nl_attr_get_be64(a))); break; - case OVS_ACTION_ATTR_SET_DL_TCI: - ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)", + case OVS_ACTION_ATTR_PUSH_VLAN: + ds_put_format(ds, "push_vlan(vid=%"PRIu16",pcp=%d)", vlan_tci_to_vid(nl_attr_get_be16(a)), vlan_tci_to_pcp(nl_attr_get_be16(a))); break; - case OVS_ACTION_ATTR_STRIP_VLAN: - ds_put_format(ds, "strip_vlan"); + case OVS_ACTION_ATTR_POP_VLAN: + ds_put_format(ds, "pop_vlan"); break; case OVS_ACTION_ATTR_SET_DL_SRC: eth = nl_attr_get_unspec(a, ETH_ADDR_LEN); @@ -152,6 +204,9 @@ format_odp_action(struct ds *ds, const struct nlattr *a) case OVS_ACTION_ATTR_POP_PRIORITY: ds_put_cstr(ds, "pop_priority"); break; + case OVS_ACTION_ATTR_SAMPLE: + format_odp_sample_action(ds, a); + break; default: format_generic_odp_action(ds, a); break; @@ -713,8 +768,10 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) nl_msg_put_be64(buf, OVS_KEY_ATTR_TUN_ID, flow->tun_id); } - nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT, - ofp_port_to_odp_port(flow->in_port)); + if (flow->in_port != OFPP_NONE) { + nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT, + ofp_port_to_odp_port(flow->in_port)); + } eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET, sizeof *eth_key); @@ -830,6 +887,7 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, memset(flow, 0, sizeof *flow); flow->dl_type = htons(FLOW_DL_TYPE_NONE); + flow->in_port = OFPP_NONE; prev_type = OVS_KEY_ATTR_UNSPEC; NL_ATTR_FOR_EACH (nla, left, key, key_len) { @@ -865,6 +923,8 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, flow->in_port = odp_port_to_ofp_port(nl_attr_get_u32(nla)); break; + case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_ETHERNET): + case TRANSITION(OVS_KEY_ATTR_TUN_ID, OVS_KEY_ATTR_ETHERNET): case TRANSITION(OVS_KEY_ATTR_IN_PORT, OVS_KEY_ATTR_ETHERNET): eth_key = nl_attr_get(nla); memcpy(flow->dl_src, eth_key->eth_src, ETH_ADDR_LEN); @@ -984,10 +1044,6 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, break; default: - if (type == OVS_KEY_ATTR_UNSPEC - || prev_type == OVS_KEY_ATTR_UNSPEC) { - return EINVAL; - } return EINVAL; }