[ovs-dev] [PATCH 4/7] lib/flow: Add miniflow_extract_from_flow
Jarno Rajahalme
jrajahalme at nicira.com
Wed Oct 1 23:02:34 UTC 2014
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 <jrajahalme at 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
More information about the dev
mailing list