X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fodp-util.c;h=873e05aea57b1b6cf50c35fe01a39a387c80157d;hb=1e827902be9194d71ea851c9ce2676f65eeed33a;hp=62cc6380a0dc02c49102d5b05e6ac4174372fad0;hpb=99ab7312c17cd4ab603eb6194c50b9f1ef3ca1c9;p=sliver-openvswitch.git diff --git a/lib/odp-util.c b/lib/odp-util.c index 62cc6380a..873e05aea 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -26,6 +26,7 @@ #include #include "byte-order.h" #include "coverage.h" +#include "dpif.h" #include "dynamic-string.h" #include "flow.h" #include "netlink.h" @@ -378,7 +379,7 @@ format_odp_action(struct ds *ds, const struct nlattr *a) expected_len = odp_action_len(nl_attr_type(a)); if (expected_len != -2 && nl_attr_get_size(a) != expected_len) { - ds_put_format(ds, "bad length %zu, expected %d for: ", + ds_put_format(ds, "bad length %"PRIuSIZE", expected %d for: ", nl_attr_get_size(a), expected_len); format_generic_odp_action(ds, a); return; @@ -845,7 +846,7 @@ odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun) return ODP_FIT_ERROR; } if (unknown) { - return ODP_FIT_TOO_MUCH; + return ODP_FIT_TOO_MUCH; } return ODP_FIT_PERFECT; } @@ -977,14 +978,14 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, if (bad_key_len || bad_mask_len) { if (bad_key_len) { - ds_put_format(ds, "(bad key length %zu, expected %d)(", + ds_put_format(ds, "(bad key length %"PRIuSIZE", expected %d)(", nl_attr_get_size(a), odp_flow_key_attr_len(nl_attr_type(a))); } format_generic_odp_key(a, ds); if (bad_mask_len) { ds_put_char(ds, '/'); - ds_put_format(ds, "(bad mask length %zu, expected %d)(", + ds_put_format(ds, "(bad mask length %"PRIuSIZE", expected %d)(", nl_attr_get_size(ma), odp_flow_key_attr_len(nl_attr_type(ma))); } @@ -2596,6 +2597,74 @@ odp_flow_key_from_mask(struct ofpbuf *buf, const struct flow *mask, odp_flow_key_from_flow__(buf, mask, flow, u32_to_odp(odp_in_port_mask)); } +/* Generate ODP flow key from the given packet metadata */ +void +odp_key_from_pkt_metadata(struct ofpbuf *buf, const struct pkt_metadata *md) +{ + nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority); + + if (md->tunnel.ip_dst) { + tun_key_to_attr(buf, &md->tunnel); + } + + nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, md->pkt_mark); + + /* Add an ingress port attribute if 'odp_in_port' is not the magical + * value "ODPP_NONE". */ + if (md->in_port != ODPP_NONE) { + nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port); + } +} + +/* Generate packet metadata from the given ODP flow key. */ +void +odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len, + struct pkt_metadata *md) +{ + const struct nlattr *nla; + size_t left; + uint32_t wanted_attrs = 1u << OVS_KEY_ATTR_PRIORITY | + 1u << OVS_KEY_ATTR_SKB_MARK | 1u << OVS_KEY_ATTR_TUNNEL | + 1u << OVS_KEY_ATTR_IN_PORT; + + memset(md, 0, sizeof *md); + md->in_port = ODPP_NONE; + + NL_ATTR_FOR_EACH (nla, left, key, key_len) { + uint16_t type = nl_attr_type(nla); + size_t len = nl_attr_get_size(nla); + int expected_len = odp_flow_key_attr_len(type); + + if (len != expected_len && expected_len >= 0) { + continue; + } + + if (type == OVS_KEY_ATTR_PRIORITY) { + md->skb_priority = nl_attr_get_u32(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_PRIORITY); + } else if (type == OVS_KEY_ATTR_SKB_MARK) { + md->pkt_mark = nl_attr_get_u32(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_SKB_MARK); + } else if (type == OVS_KEY_ATTR_TUNNEL) { + enum odp_key_fitness res; + + res = odp_tun_key_from_attr(nla, &md->tunnel); + if (res == ODP_FIT_ERROR) { + memset(&md->tunnel, 0, sizeof md->tunnel); + } else if (res == ODP_FIT_PERFECT) { + wanted_attrs &= ~(1u << OVS_KEY_ATTR_TUNNEL); + } + } else if (type == OVS_KEY_ATTR_IN_PORT) { + md->in_port = nl_attr_get_odp_port(nla); + wanted_attrs &= ~(1u << OVS_KEY_ATTR_IN_PORT); + } + + if (!wanted_attrs) { + return; /* Have everything. */ + } + } +} + uint32_t odp_flow_key_hash(const struct nlattr *key, size_t key_len) { @@ -2676,7 +2745,7 @@ parse_flow_nlattrs(const struct nlattr *key, size_t key_len, if (len != expected_len && expected_len >= 0) { char namebuf[OVS_KEY_ATTR_BUFSIZE]; - VLOG_ERR_RL(&rl, "attribute %s has length %zu but should have " + VLOG_ERR_RL(&rl, "attribute %s has length %"PRIuSIZE" but should have " "length %d", ovs_key_attr_to_string(type, namebuf, sizeof namebuf), len, expected_len); @@ -2871,7 +2940,7 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], } else { goto done; } - if (is_mask) { + if (check_len > 0) { /* Happens only when 'is_mask'. */ if (!is_all_zeros(check_start, check_len) && flow->dl_type != htons(0xffff)) { return ODP_FIT_ERROR; @@ -3035,7 +3104,9 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], if (!is_mask && !(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) { return ODP_FIT_TOO_LITTLE; } else { - tci = nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]); + tci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN) + ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]) + : htons(0)); if (!is_mask) { if (tci == htons(0)) { /* Corner case for a truncated 802.1Q header. */ @@ -3146,8 +3217,9 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len, return ODP_FIT_ERROR; } - if ((is_mask && (src_flow->vlan_tci & htons(VLAN_CFI))) || - (!is_mask && src_flow->dl_type == htons(ETH_TYPE_VLAN))) { + if (is_mask + ? (src_flow->vlan_tci & htons(VLAN_CFI)) != 0 + : src_flow->dl_type == htons(ETH_TYPE_VLAN)) { return parse_8021q_onward(attrs, present_attrs, out_of_range_attr, expected_attrs, flow, key, key_len, src_flow); } @@ -3383,7 +3455,7 @@ commit_mpls_action(const struct flow *flow, struct flow *base, break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } base->dl_type = flow->dl_type;