X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fflow.h;h=02a5e187db0ec5006d8306b6bc5b6a75f414b024;hb=28a560d97a8b6882e7dfd4df2e52806dba4fd0e5;hp=4f42f0cab52289757aac1a582b592a161d383077;hpb=419681daf125576d25839eaefbb179b65e19c091;p=sliver-openvswitch.git diff --git a/lib/flow.h b/lib/flow.h index 4f42f0cab..02a5e187d 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -24,6 +24,7 @@ #include "byte-order.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" +#include "packets.h" #include "hash.h" #include "util.h" @@ -60,23 +61,6 @@ BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER); const char *flow_tun_flag_to_string(uint32_t flags); -struct flow_tnl { - ovs_be64 tun_id; - ovs_be32 ip_src; - ovs_be32 ip_dst; - uint16_t flags; - uint8_t ip_tos; - uint8_t ip_ttl; -}; - -/* Unfortunately, a "struct flow" sometimes has to handle OpenFlow port - * numbers and other times datapath (dpif) port numbers. This union allows - * access to both. */ -union flow_in_port { - odp_port_t odp_port; - ofp_port_t ofp_port; -}; - /* Maximum number of supported MPLS labels. */ #define FLOW_MAX_MPLS_LABELS 3 @@ -418,8 +402,62 @@ void miniflow_destroy(struct miniflow *); void miniflow_expand(const struct miniflow *, struct flow *); -uint32_t miniflow_get(const struct miniflow *, unsigned int u32_ofs); -uint16_t miniflow_get_vid(const struct miniflow *); +#define FLOW_U32_SIZE(FIELD) \ + DIV_ROUND_UP(sizeof(((struct flow *)0)->FIELD), sizeof(uint32_t)) + +#define MINIFLOW_MAP(FIELD) \ + (((UINT64_C(1) << FLOW_U32_SIZE(FIELD)) - 1) \ + << (offsetof(struct flow, FIELD) / 4)) + +static inline uint32_t +mf_get_next_in_map(uint64_t *fmap, uint64_t rm1bit, const uint32_t **fp, + uint32_t *value) +{ + *value = 0; + if (*fmap & rm1bit) { + uint64_t trash = *fmap & (rm1bit - 1); + + if (trash) { + *fmap -= trash; + *fp += count_1bits(trash); + } + *value = **fp; + } + return rm1bit != 0; +} + +/* Iterate through all miniflow u32 values specified by the 'MAP'. + * This works as the first statement in a block.*/ +#define MINIFLOW_FOR_EACH_IN_MAP(VALUE, FLOW, MAP) \ + const uint32_t *fp_ = (FLOW)->values; \ + uint64_t rm1bit_, fmap_, map_; \ + for (fmap_ = (FLOW)->map, map_ = (MAP), rm1bit_ = rightmost_1bit(map_); \ + mf_get_next_in_map(&fmap_, rm1bit_, &fp_, &(VALUE)); \ + map_ -= rm1bit_, rm1bit_ = rightmost_1bit(map_)) + +/* Get the value of 'FIELD' of an up to 4 byte wide integer type 'TYPE' of + * a miniflow. */ +#define MINIFLOW_GET_TYPE(MF, TYPE, OFS) \ + (((MF)->map & (UINT64_C(1) << (OFS) / 4)) \ + ? ((OVS_FORCE const TYPE *) \ + ((MF)->values \ + + count_1bits((MF)->map & ((UINT64_C(1) << (OFS) / 4) - 1)))) \ + [(OFS) % 4 / sizeof(TYPE)] \ + : 0) \ + +#define MINIFLOW_GET_U8(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint8_t, offsetof(struct flow, FIELD)) +#define MINIFLOW_GET_U16(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint16_t, offsetof(struct flow, FIELD)) +#define MINIFLOW_GET_BE16(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, ovs_be16, offsetof(struct flow, FIELD)) +#define MINIFLOW_GET_U32(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint32_t, offsetof(struct flow, FIELD)) +#define MINIFLOW_GET_BE32(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, ovs_be32, offsetof(struct flow, FIELD)) + +static inline uint16_t miniflow_get_vid(const struct miniflow *); +static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *); static inline ovs_be64 miniflow_get_metadata(const struct miniflow *); bool miniflow_equal(const struct miniflow *a, const struct miniflow *b); @@ -435,6 +473,7 @@ uint32_t miniflow_hash_in_minimask(const struct miniflow *, uint64_t miniflow_get_map_in_range(const struct miniflow *miniflow, uint8_t start, uint8_t end, unsigned int *offset); +uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis); /* Compressed flow wildcards. */ @@ -460,7 +499,7 @@ void minimask_destroy(struct minimask *); void minimask_expand(const struct minimask *, struct flow_wildcards *); uint32_t minimask_get(const struct minimask *, unsigned int u32_ofs); -uint16_t minimask_get_vid_mask(const struct minimask *); +static inline uint16_t minimask_get_vid_mask(const struct minimask *); static inline ovs_be64 minimask_get_metadata_mask(const struct minimask *); bool minimask_equal(const struct minimask *a, const struct minimask *b); @@ -469,16 +508,49 @@ uint32_t minimask_hash(const struct minimask *, uint32_t basis); bool minimask_has_extra(const struct minimask *, const struct minimask *); bool minimask_is_catchall(const struct minimask *); + +/* Returns the VID within the vlan_tci member of the "struct flow" represented + * by 'flow'. */ +static inline uint16_t +miniflow_get_vid(const struct miniflow *flow) +{ + ovs_be16 tci = MINIFLOW_GET_BE16(flow, vlan_tci); + return vlan_tci_to_vid(tci); +} + +/* Returns the VID mask within the vlan_tci member of the "struct + * flow_wildcards" represented by 'mask'. */ +static inline uint16_t +minimask_get_vid_mask(const struct minimask *mask) +{ + return miniflow_get_vid(&mask->masks); +} + +/* Returns the value of the "tcp_flags" field in 'flow'. */ +static inline uint16_t +miniflow_get_tcp_flags(const struct miniflow *flow) +{ + return ntohs(MINIFLOW_GET_BE16(flow, tcp_flags)); +} + /* Returns the value of the OpenFlow 1.1+ "metadata" field in 'flow'. */ static inline ovs_be64 miniflow_get_metadata(const struct miniflow *flow) { + union { + ovs_be64 be64; + struct { + ovs_be32 hi; + ovs_be32 lo; + }; + } value; + enum { MD_OFS = offsetof(struct flow, metadata) }; BUILD_ASSERT_DECL(MD_OFS % sizeof(uint32_t) == 0); - ovs_be32 hi = (OVS_FORCE ovs_be32) miniflow_get(flow, MD_OFS / 4); - ovs_be32 lo = (OVS_FORCE ovs_be32) miniflow_get(flow, MD_OFS / 4 + 1); + value.hi = MINIFLOW_GET_TYPE(flow, ovs_be32, MD_OFS); + value.lo = MINIFLOW_GET_TYPE(flow, ovs_be32, MD_OFS + 4); - return htonll(((uint64_t) ntohl(hi) << 32) | ntohl(lo)); + return value.be64; } /* Returns the mask for the OpenFlow 1.1+ "metadata" field in 'mask'. @@ -493,4 +565,42 @@ minimask_get_metadata_mask(const struct minimask *mask) return miniflow_get_metadata(&mask->masks); } +static inline struct pkt_metadata +pkt_metadata_from_flow(const struct flow *flow) +{ + struct pkt_metadata md; + + md.recirc_id = flow->recirc_id; + md.dp_hash = flow->dp_hash; + md.tunnel = flow->tunnel; + md.skb_priority = flow->skb_priority; + md.pkt_mark = flow->pkt_mark; + md.in_port = flow->in_port; + + return md; +} + +static inline bool is_ip_any(const struct flow *flow) +{ + return dl_type_is_ip_any(flow->dl_type); +} + +static inline bool is_icmpv4(const struct flow *flow) +{ + return (flow->dl_type == htons(ETH_TYPE_IP) + && flow->nw_proto == IPPROTO_ICMP); +} + +static inline bool is_icmpv6(const struct flow *flow) +{ + return (flow->dl_type == htons(ETH_TYPE_IPV6) + && flow->nw_proto == IPPROTO_ICMPV6); +} + +static inline bool is_stp(const struct flow *flow) +{ + return (eth_addr_equals(flow->dl_dst, eth_addr_stp) + && flow->dl_type == htons(FLOW_DL_TYPE_NONE)); +} + #endif /* flow.h */