X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fflow.h;h=36d453ae4a97d6cec2c96355eb17d001dc5f6485;hb=d4570fd8ba5f36f21b9b631628e812de0189fa20;hp=c834cb5540e60c1cc36d09287c68936bf2db0856;hpb=b7807e4f64c8c64bb6000767de72368306a95c90;p=sliver-openvswitch.git diff --git a/lib/flow.h b/lib/flow.h index c834cb554..36d453ae4 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -271,13 +271,6 @@ hash_odp_port(odp_port_t odp_port) { return hash_int(odp_to_u32(odp_port), 0); } - -uint32_t flow_hash_in_minimask(const struct flow *, const struct minimask *, - uint32_t basis); -uint32_t flow_hash_in_minimask_range(const struct flow *, - const struct minimask *, - uint8_t start, uint8_t end, - uint32_t *basis); /* Wildcards for a flow. * @@ -305,13 +298,6 @@ void flow_wildcards_or(struct flow_wildcards *dst, const struct flow_wildcards *src2); bool flow_wildcards_has_extra(const struct flow_wildcards *, const struct flow_wildcards *); - -void flow_wildcards_fold_minimask(struct flow_wildcards *, - const struct minimask *); -void flow_wildcards_fold_minimask_range(struct flow_wildcards *, - const struct minimask *, - uint8_t start, uint8_t end); - uint32_t flow_wildcards_hash(const struct flow_wildcards *, uint32_t basis); bool flow_wildcards_equal(const struct flow_wildcards *, const struct flow_wildcards *); @@ -402,18 +388,59 @@ void miniflow_destroy(struct miniflow *); void miniflow_expand(const struct miniflow *, struct flow *); -/* These accessors use byte offsets, which are assumed to be compile-time - * constants. */ -static inline uint8_t miniflow_get_u8(const struct miniflow *, - unsigned int ofs); -static inline uint16_t miniflow_get_u16(const struct miniflow *, - unsigned int ofs); -static inline ovs_be16 miniflow_get_be16(const struct miniflow *, - unsigned int ofs); -static inline uint32_t miniflow_get_u32(const struct miniflow *, - unsigned int ofs); -static inline ovs_be32 miniflow_get_be32(const struct miniflow *, - unsigned int ofs); +#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 *); @@ -426,12 +453,7 @@ bool miniflow_equal_in_minimask(const struct miniflow *a, bool miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow *b, const struct minimask *); -uint32_t miniflow_hash(const struct miniflow *, uint32_t basis); -uint32_t miniflow_hash_in_minimask(const struct miniflow *, - const struct minimask *, uint32_t basis); -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. */ @@ -461,60 +483,27 @@ 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); -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 *); - - -/* 'OFS' is a compile-time constant. */ -#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 - -static inline uint8_t -miniflow_get_u8(const struct miniflow *flow, unsigned int ofs) -{ - return MINIFLOW_GET_TYPE(flow, uint8_t, ofs); -} - -static inline uint16_t -miniflow_get_u16(const struct miniflow *flow, unsigned int ofs) -{ - return MINIFLOW_GET_TYPE(flow, uint16_t, ofs); -} - -/* Returns the ovs_be16 that would be at byte offset 'u8_ofs' if 'flow' were - * expanded into a "struct flow". */ -static inline ovs_be16 -miniflow_get_be16(const struct miniflow *flow, unsigned int ofs) -{ - return MINIFLOW_GET_TYPE(flow, ovs_be16, ofs); -} - -static inline uint32_t -miniflow_get_u32(const struct miniflow *flow, unsigned int ofs) -{ - return MINIFLOW_GET_TYPE(flow, uint32_t, ofs); -} -static inline ovs_be32 -miniflow_get_be32(const struct miniflow *flow, unsigned int ofs) +/* Returns true if 'mask' matches every packet, false if 'mask' fixes any bits + * or fields. */ +static inline bool +minimask_is_catchall(const struct minimask *mask) { - return MINIFLOW_GET_TYPE(flow, ovs_be32, ofs); + /* For every 1-bit in mask's map, the corresponding value is non-zero, + * so the only way the mask can not fix any bits or fields is for the + * map the be zero. */ + return mask->masks.map == 0; } -#undef MINIFLOW_GET_TYPE + /* 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, offsetof(struct flow, vlan_tci)); + ovs_be16 tci = MINIFLOW_GET_BE16(flow, vlan_tci); return vlan_tci_to_vid(tci); } @@ -530,19 +519,27 @@ minimask_get_vid_mask(const struct minimask *mask) static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *flow) { - return ntohs(miniflow_get_be16(flow, offsetof(struct flow, tcp_flags))); + 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 = miniflow_get_be32(flow, MD_OFS); - ovs_be32 lo = miniflow_get_be32(flow, MD_OFS + 4); + 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'. @@ -557,6 +554,20 @@ minimask_get_metadata_mask(const struct minimask *mask) return miniflow_get_metadata(&mask->masks); } +/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent + * fields in 'dst', storing the result in 'dst'. */ +static inline void +flow_union_with_miniflow(struct flow *dst, const struct miniflow *src) +{ + uint32_t *dst_u32 = (uint32_t *) dst; + const uint32_t *p = (uint32_t *)src->values; + uint64_t map; + + for (map = src->map; map; map = zero_rightmost_1bit(map)) { + dst_u32[raw_ctz(map)] |= *p++; + } +} + static inline struct pkt_metadata pkt_metadata_from_flow(const struct flow *flow) { @@ -589,4 +600,10 @@ static inline bool is_icmpv6(const struct flow *flow) && 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 */