miniflow_extract_from_flow() is faster than miniflow_init(), since it does not scan the fields not significant for the packet type. More importantly, it produces the same layout as miniflow_extract, which does not try to compress zero-valued packet header fields.
Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/flow.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/flow.h | 1 + 2 files changed, 89 insertions(+) diff --git a/lib/flow.c b/lib/flow.c index 14a3350..6fe4eae 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -638,6 +638,94 @@ miniflow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, dst->map = mf.map; } +/* This mirrors miniflow_extract(), but the input is from a struct flow. */ +void +miniflow_extract_from_flow(struct miniflow *dst, const struct flow *flow) +{ + uint32_t *values = miniflow_values(dst); + struct mf_ctx mf = { 0, values, values + FLOW_U32S }; + + /* Metadata. */ + if (flow->tunnel.ip_dst) { + miniflow_push_words(mf, tunnel, &flow->tunnel, + sizeof flow->tunnel / 4); + } + miniflow_push_uint32_check(mf, skb_priority, flow->skb_priority); + miniflow_push_uint32_check(mf, pkt_mark, flow->pkt_mark); + miniflow_push_uint32_check(mf, recirc_id, flow->recirc_id); + miniflow_push_uint32(mf, in_port, odp_to_u32(flow->in_port.odp_port)); + + /* Link layer. */ + miniflow_push_words(mf, dl_dst, &flow->dl_dst, ETH_ADDR_LEN * 2 / 4); + miniflow_push_be16(mf, dl_type, flow->dl_type); + miniflow_push_be16(mf, vlan_tci, flow->vlan_tci); + + if (OVS_UNLIKELY(eth_type_mpls(flow->dl_type))) { + int count; + + for (count = 0; count < FLOW_MAX_MPLS_LABELS; count++) { + if (mpls_lse_to_bos(flow->mpls_lse[count])) { + break; + } + } + count++; + miniflow_push_words(mf, mpls_lse, flow->mpls_lse, count); + goto out; + } else if (OVS_LIKELY(flow->dl_type == htons(ETH_TYPE_IP))) { + /* Push both source and destination address at once. */ + miniflow_push_words(mf, nw_src, &flow->nw_src, 2); + } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { + miniflow_push_words(mf, ipv6_src, &flow->ipv6_src, + sizeof flow->ipv6_src / 4); + miniflow_push_words(mf, ipv6_dst, &flow->ipv6_dst, + sizeof flow->ipv6_dst / 4); + + miniflow_push_be32(mf, ipv6_label, flow->ipv6_label); + } else { + if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { + + miniflow_push_words(mf, nw_src, &flow->nw_src, 1); + miniflow_push_words(mf, nw_dst, &flow->nw_dst, 1); + miniflow_push_be32(mf, nw_frag, htonl(flow->nw_proto)); + miniflow_push_words(mf, arp_sha, &flow->arp_sha, + ETH_ADDR_LEN * 2 / 4); + } + goto out; + } + + miniflow_push_uint32(mf, nw_frag, + BYTES_TO_BE32(flow->nw_frag, flow->nw_tos, + flow->nw_ttl, flow->nw_proto)); + + if (OVS_LIKELY(!(flow->nw_frag & FLOW_NW_FRAG_LATER))) { + if (OVS_LIKELY(flow->nw_proto == IPPROTO_TCP)) { + miniflow_push_words(mf, tcp_flags, &flow->tcp_flags, 1); + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + } else if (OVS_LIKELY(flow->nw_proto == IPPROTO_UDP)) { + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + } else if (OVS_LIKELY(flow->nw_proto == IPPROTO_SCTP)) { + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + } else if (OVS_LIKELY(flow->nw_proto == IPPROTO_ICMP)) { + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + } else if (OVS_LIKELY(flow->nw_proto == IPPROTO_IGMP)) { + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + miniflow_push_be32(mf, igmp_group_ip4, flow->igmp_group_ip4); + } else if (OVS_LIKELY(flow->nw_proto == IPPROTO_ICMPV6)) { + miniflow_push_words(mf, arp_sha, &flow->arp_sha, + ETH_ADDR_LEN * 2 / 4); + if (!ipv6_addr_equals(&flow->nd_target, &in6addr_any)) { + miniflow_push_words(mf, nd_target, &flow->nd_target, + sizeof flow->nd_target / 4); + } + miniflow_push_words(mf, tp_src, &flow->tp_src, 1); + } + } + miniflow_push_uint32_check(mf, dp_hash, flow->dp_hash); + out: + dst->map = mf.map; +} + /* For every bit of a field that is wildcarded in 'wildcards', sets the * corresponding bit in 'flow' to zero. */ void diff --git a/lib/flow.h b/lib/flow.h index b9c9f1b..9bb9a58 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -444,6 +444,7 @@ struct pkt_metadata; * indicate which fields were extracted. */ void miniflow_extract(struct ofpbuf *packet, const struct pkt_metadata *, struct miniflow *dst); +void miniflow_extract_from_flow(struct miniflow *dst, const struct flow *); void miniflow_init(struct miniflow *, const struct flow *); void miniflow_init_with_minimask(struct miniflow *, const struct flow *, const struct minimask *); -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev