diff options
Diffstat (limited to 'net/openvswitch/flow.h')
| -rw-r--r-- | net/openvswitch/flow.h | 185 | 
1 files changed, 59 insertions, 126 deletions
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 212fbf7510c..5e5aaed3a85 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2007-2013 Nicira, Inc. + * Copyright (c) 2007-2014 Nicira, Inc.   *   * This program is free software; you can redistribute it and/or   * modify it under the terms of version 2 of the GNU General Public @@ -19,6 +19,7 @@  #ifndef FLOW_H  #define FLOW_H 1 +#include <linux/cache.h>  #include <linux/kernel.h>  #include <linux/netlink.h>  #include <linux/openvswitch.h> @@ -33,14 +34,6 @@  #include <net/inet_ecn.h>  struct sk_buff; -struct sw_flow_mask; -struct flow_table; - -struct sw_flow_actions { -	struct rcu_head rcu; -	u32 actions_len; -	struct nlattr actions[]; -};  /* Used to memset ovs_key_ipv4_tunnel padding. */  #define OVS_TUNNEL_KEY_SIZE					\ @@ -54,7 +47,7 @@ struct ovs_key_ipv4_tunnel {  	__be16 tun_flags;  	u8   ipv4_tos;  	u8   ipv4_ttl; -}; +} __packed __aligned(4); /* Minimize padding. */  static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,  					 const struct iphdr *iph, __be64 tun_id, @@ -78,7 +71,7 @@ struct sw_flow_key {  		u32	priority;	/* Packet QoS priority. */  		u32	skb_mark;	/* SKB mark. */  		u16	in_port;	/* Input switch port (or DP_MAX_PORTS). */ -	} phy; +	} __packed phy; /* Safe when right after 'tun_key'. */  	struct {  		u8     src[ETH_ALEN];	/* Ethernet source address. */  		u8     dst[ETH_ALEN];	/* Ethernet destination address. */ @@ -91,22 +84,21 @@ struct sw_flow_key {  		u8     ttl;		/* IP TTL/hop limit. */  		u8     frag;		/* One of OVS_FRAG_TYPE_*. */  	} ip; +	struct { +		__be16 src;		/* TCP/UDP/SCTP source port. */ +		__be16 dst;		/* TCP/UDP/SCTP destination port. */ +		__be16 flags;		/* TCP flags. */ +	} tp;  	union {  		struct {  			struct {  				__be32 src;	/* IP source address. */  				__be32 dst;	/* IP destination address. */  			} addr; -			union { -				struct { -					__be16 src;		/* TCP/UDP/SCTP source port. */ -					__be16 dst;		/* TCP/UDP/SCTP destination port. */ -				} tp; -				struct { -					u8 sha[ETH_ALEN];	/* ARP source hardware address. */ -					u8 tha[ETH_ALEN];	/* ARP target hardware address. */ -				} arp; -			}; +			struct { +				u8 sha[ETH_ALEN];	/* ARP source hardware address. */ +				u8 tha[ETH_ALEN];	/* ARP target hardware address. */ +			} arp;  		} ipv4;  		struct {  			struct { @@ -115,10 +107,6 @@ struct sw_flow_key {  			} addr;  			__be32 label;			/* IPv6 flow label. */  			struct { -				__be16 src;		/* TCP/UDP/SCTP source port. */ -				__be16 dst;		/* TCP/UDP/SCTP destination port. */ -			} tp; -			struct {  				struct in6_addr target;	/* ND target address. */  				u8 sll[ETH_ALEN];	/* ND source link layer address. */  				u8 tll[ETH_ALEN];	/* ND target link layer address. */ @@ -127,26 +115,17 @@ struct sw_flow_key {  	};  } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */ -struct sw_flow { -	struct rcu_head rcu; -	struct hlist_node hash_node[2]; -	u32 hash; - -	struct sw_flow_key key; -	struct sw_flow_key unmasked_key; -	struct sw_flow_mask *mask; -	struct sw_flow_actions __rcu *sf_acts; - -	spinlock_t lock;	/* Lock for values below. */ -	unsigned long used;	/* Last used time (in jiffies). */ -	u64 packet_count;	/* Number of packets matched. */ -	u64 byte_count;		/* Number of bytes matched. */ -	u8 tcp_flags;		/* Union of seen TCP flags. */ +struct sw_flow_key_range { +	unsigned short int start; +	unsigned short int end;  }; -struct sw_flow_key_range { -	size_t start; -	size_t end; +struct sw_flow_mask { +	int ref_count; +	struct rcu_head rcu; +	struct list_head list; +	struct sw_flow_key_range range; +	struct sw_flow_key key;  };  struct sw_flow_match { @@ -155,8 +134,37 @@ struct sw_flow_match {  	struct sw_flow_mask *mask;  }; -void ovs_match_init(struct sw_flow_match *match, -		struct sw_flow_key *key, struct sw_flow_mask *mask); +struct sw_flow_actions { +	struct rcu_head rcu; +	u32 actions_len; +	struct nlattr actions[]; +}; + +struct flow_stats { +	u64 packet_count;		/* Number of packets matched. */ +	u64 byte_count;			/* Number of bytes matched. */ +	unsigned long used;		/* Last used time (in jiffies). */ +	spinlock_t lock;		/* Lock for atomic stats update. */ +	__be16 tcp_flags;		/* Union of seen TCP flags. */ +}; + +struct sw_flow { +	struct rcu_head rcu; +	struct hlist_node hash_node[2]; +	u32 hash; +	int stats_last_writer;		/* NUMA-node id of the last writer on +					 * 'stats[0]'. +					 */ +	struct sw_flow_key key; +	struct sw_flow_key unmasked_key; +	struct sw_flow_mask *mask; +	struct sw_flow_actions __rcu *sf_acts; +	struct flow_stats __rcu *stats[]; /* One for each NUMA node.  First one +					   * is allocated at flow creation time, +					   * the rest are allocated on demand +					   * while holding the 'stats[0].lock'. +					   */ +};  struct arp_eth_header {  	__be16      ar_hrd;	/* format of hardware address   */ @@ -172,88 +180,13 @@ struct arp_eth_header {  	unsigned char       ar_tip[4];		/* target IP address        */  } __packed; -int ovs_flow_init(void); -void ovs_flow_exit(void); - -struct sw_flow *ovs_flow_alloc(void); -void ovs_flow_deferred_free(struct sw_flow *); -void ovs_flow_free(struct sw_flow *, bool deferred); - -struct sw_flow_actions *ovs_flow_actions_alloc(int actions_len); -void ovs_flow_deferred_free_acts(struct sw_flow_actions *); - -int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *); -void ovs_flow_used(struct sw_flow *, struct sk_buff *); +void ovs_flow_stats_update(struct sw_flow *, __be16 tcp_flags, +			   struct sk_buff *); +void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *, +			unsigned long *used, __be16 *tcp_flags); +void ovs_flow_stats_clear(struct sw_flow *);  u64 ovs_flow_used_time(unsigned long flow_jiffies); -int ovs_flow_to_nlattrs(const struct sw_flow_key *, -		const struct sw_flow_key *, struct sk_buff *); -int ovs_match_from_nlattrs(struct sw_flow_match *match, -		      const struct nlattr *, -		      const struct nlattr *); -int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, -		const struct nlattr *attr); - -#define MAX_ACTIONS_BUFSIZE    (32 * 1024) -#define TBL_MIN_BUCKETS		1024 - -struct flow_table { -	struct flex_array *buckets; -	unsigned int count, n_buckets; -	struct rcu_head rcu; -	struct list_head *mask_list; -	int node_ver; -	u32 hash_seed; -	bool keep_flows; -}; - -static inline int ovs_flow_tbl_count(struct flow_table *table) -{ -	return table->count; -} - -static inline int ovs_flow_tbl_need_to_expand(struct flow_table *table) -{ -	return (table->count > table->n_buckets); -} - -struct sw_flow *ovs_flow_lookup(struct flow_table *, -				const struct sw_flow_key *); -struct sw_flow *ovs_flow_lookup_unmasked_key(struct flow_table *table, -				    struct sw_flow_match *match); - -void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred); -struct flow_table *ovs_flow_tbl_alloc(int new_size); -struct flow_table *ovs_flow_tbl_expand(struct flow_table *table); -struct flow_table *ovs_flow_tbl_rehash(struct flow_table *table); - -void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow); -void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow); - -struct sw_flow *ovs_flow_dump_next(struct flow_table *table, u32 *bucket, u32 *idx); -extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; -int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr, -			     struct sw_flow_match *match, bool is_mask); -int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb, -			   const struct ovs_key_ipv4_tunnel *tun_key, -			   const struct ovs_key_ipv4_tunnel *output); -bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow, -		const struct sw_flow_key *key, int key_end); - -struct sw_flow_mask { -	int ref_count; -	struct rcu_head rcu; -	struct list_head list; -	struct sw_flow_key_range range; -	struct sw_flow_key key; -}; +int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *); -struct sw_flow_mask *ovs_sw_flow_mask_alloc(void); -void ovs_sw_flow_mask_add_ref(struct sw_flow_mask *); -void ovs_sw_flow_mask_del_ref(struct sw_flow_mask *, bool deferred); -void ovs_sw_flow_mask_insert(struct flow_table *, struct sw_flow_mask *); -struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *, -		const struct sw_flow_mask *); -void ovs_flow_key_mask(struct sw_flow_key *dst, const struct sw_flow_key *src, -		       const struct sw_flow_mask *mask);  #endif /* flow.h */  | 
