X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fodp-util.c;h=78d5a1b4445543033d0544aea21d13c07b086567;hb=4b570f12766f3c4eeb527de69d8eedfd59c34b86;hp=3c3063df7e69ddd3cc231ed412fffe5016fb8984;hpb=db5a101931c5393d5f9df600559882418d536878;p=sliver-openvswitch.git diff --git a/lib/odp-util.c b/lib/odp-util.c index 3c3063df7..78d5a1b44 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -51,7 +51,8 @@ static const char *delimiters = ", \t\r\n"; static int parse_odp_key_mask_attr(const char *, const struct simap *port_names, struct ofpbuf *, struct ofpbuf *); static void format_odp_key_attr(const struct nlattr *a, - const struct nlattr *ma, struct ds *ds); + const struct nlattr *ma, struct ds *ds, + bool verbose); /* Returns one the following for the action with the given OVS_ACTION_ATTR_* * 'type': @@ -399,7 +400,7 @@ format_odp_action(struct ds *ds, const struct nlattr *a) break; case OVS_ACTION_ATTR_SET: ds_put_cstr(ds, "set("); - format_odp_key_attr(nl_attr_get(a), NULL, ds); + format_odp_key_attr(nl_attr_get(a), NULL, ds, true); ds_put_cstr(ds, ")"); break; case OVS_ACTION_ATTR_PUSH_VLAN: @@ -897,6 +898,12 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key) nl_msg_end_nested(a, tun_key_ofs); } +static bool +odp_mask_attr_is_wildcard(const struct nlattr *ma) +{ + return is_all_zeros(nl_attr_get(ma), nl_attr_get_size(ma)); +} + static bool odp_mask_attr_is_exact(const struct nlattr *ma) { @@ -929,7 +936,7 @@ odp_mask_attr_is_exact(const struct nlattr *ma) static void format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, - struct ds *ds) + struct ds *ds, bool verbose) { struct flow_tnl tun_key; enum ovs_key_attr attr = nl_attr_type(a); @@ -972,9 +979,10 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, case OVS_KEY_ATTR_ENCAP: if (ma && nl_attr_get_size(ma) && nl_attr_get_size(a)) { odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), - nl_attr_get(ma), nl_attr_get_size(ma), ds); + nl_attr_get(ma), nl_attr_get_size(ma), ds, verbose); } else if (nl_attr_get_size(a)) { - odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), NULL, 0, ds); + odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), NULL, 0, ds, + verbose); } break; @@ -1337,7 +1345,7 @@ generate_all_wildcard_mask(struct ofpbuf *ofp, const struct nlattr *key) void odp_flow_format(const struct nlattr *key, size_t key_len, const struct nlattr *mask, size_t mask_len, - struct ds *ds) + struct ds *ds, bool verbose) { if (key_len) { const struct nlattr *a; @@ -1345,22 +1353,35 @@ odp_flow_format(const struct nlattr *key, size_t key_len, bool has_ethtype_key = false; const struct nlattr *ma = NULL; struct ofpbuf ofp; + bool first_field = true; ofpbuf_init(&ofp, 100); NL_ATTR_FOR_EACH (a, left, key, key_len) { - if (a != key) { - ds_put_char(ds, ','); - } - if (nl_attr_type(a) == OVS_KEY_ATTR_ETHERTYPE) { + bool is_nested_attr; + bool is_wildcard = false; + int attr_type = nl_attr_type(a); + + if (attr_type == OVS_KEY_ATTR_ETHERTYPE) { has_ethtype_key = true; } + + is_nested_attr = (odp_flow_key_attr_len(attr_type) == -2); + if (mask && mask_len) { ma = nl_attr_find__(mask, mask_len, nl_attr_type(a)); - if (!ma) { + is_wildcard = ma ? odp_mask_attr_is_wildcard(ma) : true; + } + + if (verbose || !is_wildcard || is_nested_attr) { + if (is_wildcard && !ma) { ma = generate_all_wildcard_mask(&ofp, a); } + if (!first_field) { + ds_put_char(ds, ','); + } + format_odp_key_attr(a, ma, ds, verbose); + first_field = false; } - format_odp_key_attr(a, ma, ds); ofpbuf_clear(&ofp); } ofpbuf_uninit(&ofp); @@ -1395,7 +1416,7 @@ void odp_flow_key_format(const struct nlattr *key, size_t key_len, struct ds *ds) { - odp_flow_format(key, key_len, NULL, 0, ds); + odp_flow_format(key, key_len, NULL, 0, ds, true); } static void @@ -2311,6 +2332,17 @@ ovs_to_odp_frag(uint8_t nw_frag) : OVS_FRAG_TYPE_LATER); } +static uint8_t +ovs_to_odp_frag_mask(uint8_t nw_frag_mask) +{ + uint8_t frag_mask = ~(OVS_FRAG_TYPE_FIRST | OVS_FRAG_TYPE_LATER); + + frag_mask |= (nw_frag_mask & FLOW_NW_FRAG_ANY) ? OVS_FRAG_TYPE_FIRST : 0; + frag_mask |= (nw_frag_mask & FLOW_NW_FRAG_LATER) ? OVS_FRAG_TYPE_LATER : 0; + + return frag_mask; +} + static void odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data, const struct flow *flow, odp_port_t odp_in_port) @@ -2323,17 +2355,13 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data, * treat 'data' as a mask. */ is_mask = (data != flow); - if (flow->skb_priority) { - nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority); - } + nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority); - if (flow->tunnel.ip_dst) { + if (flow->tunnel.ip_dst || is_mask) { tun_key_to_attr(buf, &data->tunnel); } - if (flow->skb_mark) { - nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->skb_mark); - } + nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->skb_mark); /* Add an ingress port attribute if this is a mask or 'odp_in_port' * is not the magical value "ODPP_NONE". */ @@ -2391,7 +2419,8 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data, ipv4_key->ipv4_proto = data->nw_proto; ipv4_key->ipv4_tos = data->nw_tos; ipv4_key->ipv4_ttl = data->nw_ttl; - ipv4_key->ipv4_frag = ovs_to_odp_frag(data->nw_frag); + ipv4_key->ipv4_frag = is_mask ? ovs_to_odp_frag_mask(data->nw_frag) + : ovs_to_odp_frag(data->nw_frag); } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { struct ovs_key_ipv6 *ipv6_key; @@ -2403,7 +2432,8 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data, ipv6_key->ipv6_proto = data->nw_proto; ipv6_key->ipv6_tclass = data->nw_tos; ipv6_key->ipv6_hlimit = data->nw_ttl; - ipv6_key->ipv6_frag = ovs_to_odp_frag(flow->nw_frag); + ipv6_key->ipv6_frag = is_mask ? ovs_to_odp_frag_mask(data->nw_frag) + : ovs_to_odp_frag(data->nw_frag); } else if (flow->dl_type == htons(ETH_TYPE_ARP) || flow->dl_type == htons(ETH_TYPE_RARP)) { struct ovs_key_arp *arp_key;