X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fflow.h;h=e63e4e2b285018bdb96f5cf266d0317b8e6ade27;hb=28c5588e8e1a8d091c5d2275232c35f2968a97fa;hp=4f42f0cab52289757aac1a582b592a161d383077;hpb=419681daf125576d25839eaefbb179b65e19c091;p=sliver-openvswitch.git diff --git a/lib/flow.h b/lib/flow.h index 4f42f0cab..e63e4e2b2 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,9 +402,49 @@ 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 *); +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_)) + +/* 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); + +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 *); +static inline uint8_t miniflow_get_u8(const struct miniflow *, unsigned int ofs); bool miniflow_equal(const struct miniflow *a, const struct miniflow *b); bool miniflow_equal_in_minimask(const struct miniflow *a, @@ -435,6 +459,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 +485,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,14 +494,81 @@ 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) +{ + return MINIFLOW_GET_TYPE(flow, ovs_be32, ofs); +} + +#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)); + 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, offsetof(struct 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) { 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); + ovs_be32 hi = miniflow_get_be32(flow, MD_OFS); + ovs_be32 lo = miniflow_get_be32(flow, MD_OFS + 4); return htonll(((uint64_t) ntohl(hi) << 32) | ntohl(lo)); } @@ -493,4 +585,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 */