X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fflow.h;h=ad51496900e0c10812c1172bdfbb7df3fd8d7436;hb=2431be1b68d386bd616378d2c528242775c4d54a;hp=0fdf4ef971c94b55545c55928a83524efe96ba8a;hpb=0ad90c845b7e82090a846fbe9f927e8d1c84cfc9;p=sliver-openvswitch.git diff --git a/lib/flow.h b/lib/flow.h index 0fdf4ef97..ad5149690 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -21,6 +21,7 @@ #include #include #include +#include "byte-order.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" #include "hash.h" @@ -36,7 +37,7 @@ struct ofpbuf; /* This sequence number should be incremented whenever anything involving flows * or the wildcarding of flows changes. This will cause build assertion * failures in places which likely need to be updated. */ -#define FLOW_WC_SEQ 20 +#define FLOW_WC_SEQ 21 #define FLOW_N_REGS 8 BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS); @@ -68,14 +69,26 @@ struct flow_tnl { 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 { + ofp_port_t ofp_port; + odp_port_t odp_port; +}; + /* -* A flow in the network. -* -* The meaning of 'in_port' is context-dependent. In most cases, it is a -* 16-bit OpenFlow 1.0 port number. In the software datapath interface (dpif) -* layer and its implementations (e.g. dpif-linux, dpif-netdev), it is instead -* a 32-bit datapath port number. -*/ + * A flow in the network. + * + * Must be initialized to all zeros to make any compiler-induced padding + * zeroed. Helps also in keeping unused fields (such as mutually exclusive + * IPv4 and IPv6 addresses) zeroed out. + * + * The meaning of 'in_port' is context-dependent. In most cases, it is a + * 16-bit OpenFlow 1.0 port number. In the software datapath interface (dpif) + * layer and its implementations (e.g. dpif-linux, dpif-netdev), it is instead + * a 32-bit datapath port number. + */ struct flow { struct flow_tnl tunnel; /* Encapsulating tunnel parameters. */ ovs_be64 metadata; /* OpenFlow Metadata. */ @@ -87,16 +100,13 @@ struct flow { ovs_be32 nw_src; /* IPv4 source address. */ ovs_be32 nw_dst; /* IPv4 destination address. */ ovs_be32 ipv6_label; /* IPv6 flow label. */ - uint32_t in_port; /* Input port. OpenFlow port number - unless in DPIF code, in which case it - is the datapath port number. */ - uint32_t skb_mark; /* Packet mark. */ + union flow_in_port in_port; /* Input port.*/ + uint32_t pkt_mark; /* Packet mark. */ ovs_be32 mpls_lse; /* MPLS label stack entry. */ - uint16_t mpls_depth; /* Depth of MPLS stack. */ ovs_be16 vlan_tci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */ ovs_be16 dl_type; /* Ethernet frame type. */ - ovs_be16 tp_src; /* TCP/UDP source port. */ - ovs_be16 tp_dst; /* TCP/UDP destination port. */ + ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */ + ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port. */ uint8_t dl_src[6]; /* Ethernet source address. */ uint8_t dl_dst[6]; /* Ethernet destination address. */ uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */ @@ -104,16 +114,17 @@ struct flow { uint8_t arp_sha[6]; /* ARP/ND source hardware address. */ uint8_t arp_tha[6]; /* ARP/ND target hardware address. */ uint8_t nw_ttl; /* IP TTL/Hop Limit. */ - uint8_t nw_frag; /* FLOW_FRAG_* flags. */ - uint8_t zeros[6]; + uint8_t nw_frag; /* FLOW_FRAG_* flags. Keep last for the + BUILD_ASSERT_DECL below */ }; BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0); #define FLOW_U32S (sizeof(struct flow) / 4) /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ -BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_tnl) + 160 && - FLOW_WC_SEQ == 20); +BUILD_ASSERT_DECL(offsetof(struct flow, nw_frag) + 1 + == sizeof(struct flow_tnl) + 152 + && FLOW_WC_SEQ == 21); /* Represents the metadata fields of struct flow. */ struct flow_metadata { @@ -122,11 +133,13 @@ struct flow_metadata { ovs_be32 tun_dst; /* Tunnel outer IPv4 dst addr */ ovs_be64 metadata; /* OpenFlow 1.1+ metadata field. */ uint32_t regs[FLOW_N_REGS]; /* Registers. */ - uint16_t in_port; /* OpenFlow port or zero. */ + uint32_t pkt_mark; /* Packet mark. */ + ofp_port_t in_port; /* OpenFlow port or zero. */ }; void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark, - const struct flow_tnl *, uint16_t in_port, struct flow *); + const struct flow_tnl *, const union flow_in_port *in_port, + struct flow *); void flow_zero_wildcards(struct flow *, const struct flow_wildcards *); void flow_get_metadata(const struct flow *, struct flow_metadata *); @@ -170,6 +183,54 @@ flow_hash(const struct flow *flow, uint32_t basis) return hash_words((const uint32_t *) flow, sizeof *flow / 4, basis); } +static inline uint16_t +ofp_to_u16(ofp_port_t ofp_port) +{ + return (OVS_FORCE uint16_t) ofp_port; +} + +static inline uint32_t +odp_to_u32(odp_port_t odp_port) +{ + return (OVS_FORCE uint32_t) odp_port; +} + +static inline uint32_t +ofp11_to_u32(ofp11_port_t ofp11_port) +{ + return (OVS_FORCE uint32_t) ofp11_port; +} + +static inline ofp_port_t +u16_to_ofp(uint16_t port) +{ + return OFP_PORT_C(port); +} + +static inline odp_port_t +u32_to_odp(uint32_t port) +{ + return ODP_PORT_C(port); +} + +static inline ofp11_port_t +u32_to_ofp11(uint32_t port) +{ + return OFP11_PORT_C(port); +} + +static inline uint32_t +hash_ofp_port(ofp_port_t ofp_port) +{ + return hash_int(ofp_to_u16(ofp_port), 0); +} + +static inline uint32_t +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); @@ -183,29 +244,42 @@ struct flow_wildcards { }; void flow_wildcards_init_catchall(struct flow_wildcards *); -void flow_wildcards_init_exact(struct flow_wildcards *); bool flow_wildcards_is_catchall(const struct flow_wildcards *); void flow_wildcards_set_reg_mask(struct flow_wildcards *, int idx, uint32_t mask); -void flow_wildcards_combine(struct flow_wildcards *dst, - const struct flow_wildcards *src1, - const struct flow_wildcards *src2); +void flow_wildcards_and(struct flow_wildcards *dst, + const struct flow_wildcards *src1, + const struct flow_wildcards *src2); +void flow_wildcards_or(struct flow_wildcards *dst, + const struct flow_wildcards *src1, + 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 *); + uint32_t flow_wildcards_hash(const struct flow_wildcards *, uint32_t basis); bool flow_wildcards_equal(const struct flow_wildcards *, const struct flow_wildcards *); uint32_t flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis); +/* Initialize a flow with random fields that matter for nx_hash_fields. */ +void flow_random_hash_fields(struct flow *); +void flow_mask_hash_fields(const struct flow *, struct flow_wildcards *, + enum nx_hash_fields); uint32_t flow_hash_fields(const struct flow *, enum nx_hash_fields, uint16_t basis); const char *flow_hash_fields_to_str(enum nx_hash_fields); bool flow_hash_fields_valid(enum nx_hash_fields); +uint32_t flow_hash_in_wildcards(const struct flow *, + const struct flow_wildcards *, + uint32_t basis); + bool flow_equal_except(const struct flow *a, const struct flow *b, const struct flow_wildcards *); @@ -223,7 +297,7 @@ bool flow_equal_except(const struct flow *a, const struct flow *b, * * The 'map' member holds one bit for each uint32_t in a "struct flow". Each * 0-bit indicates that the corresponding uint32_t is zero, each 1-bit that it - * is nonzero. + * *may* be nonzero. * * 'values' points to the start of an array that has one element for each 1-bit * in 'map'. The least-numbered 1-bit is in values[0], the next 1-bit is in @@ -241,9 +315,9 @@ bool flow_equal_except(const struct flow *a, const struct flow *b, * that makes sense. So far that's only proved useful for * minimask_combine(), but the principle works elsewhere. * - * The implementation maintains and depends on the invariant that every element - * in 'values' is nonzero; that is, wherever a 1-bit appears in 'map', the - * corresponding element of 'values' must be nonzero. + * Elements in 'values' are allowed to be zero. This is useful for "struct + * minimatch", for which ensuring that the miniflow and minimask members have + * same 'map' allows optimization . */ struct miniflow { uint32_t *values; @@ -252,13 +326,17 @@ struct miniflow { }; void miniflow_init(struct miniflow *, const struct flow *); +void miniflow_init_with_minimask(struct miniflow *, const struct flow *, + const struct minimask *); void miniflow_clone(struct miniflow *, const struct miniflow *); +void miniflow_move(struct miniflow *dst, struct miniflow *); 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 ovs_be64 miniflow_get_metadata(const struct miniflow *); bool miniflow_equal(const struct miniflow *a, const struct miniflow *b); bool miniflow_equal_in_minimask(const struct miniflow *a, @@ -282,6 +360,7 @@ struct minimask { void minimask_init(struct minimask *, const struct flow_wildcards *); void minimask_clone(struct minimask *, const struct minimask *); +void minimask_move(struct minimask *dst, struct minimask *src); void minimask_combine(struct minimask *dst, const struct minimask *a, const struct minimask *b, uint32_t storage[FLOW_U32S]); @@ -291,11 +370,36 @@ 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 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 *); + +/* 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); + + return htonll(((uint64_t) ntohl(hi) << 32) | ntohl(lo)); +} + +/* Returns the mask for the OpenFlow 1.1+ "metadata" field in 'mask'. + * + * The return value is all-1-bits if 'mask' matches on the whole value of the + * metadata field, all-0-bits if 'mask' entirely wildcards the metadata field, + * or some other value if the metadata field is partially matched, partially + * wildcarded. */ +static inline ovs_be64 +minimask_get_metadata_mask(const struct minimask *mask) +{ + return miniflow_get_metadata(&mask->masks); +} #endif /* flow.h */