Commit 6fcf018a authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch

Jesse Gross says:

====================
Open vSwitch

A set of updates for net-next/3.13. Major changes are:
 * Restructure flow handling code to be more logically organized and
   easier to read.
 * Rehashing of the flow table is moved from a workqueue to flow
   installation time. Before, heavy load could block the workqueue for
   excessive periods of time.
 * Additional debugging information is provided to help diagnose megaflows.
 * It's now possible to match on TCP flags.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a6e55c4 8ddd0946
...@@ -63,15 +63,18 @@ enum ovs_datapath_cmd { ...@@ -63,15 +63,18 @@ enum ovs_datapath_cmd {
* not be sent. * not be sent.
* @OVS_DP_ATTR_STATS: Statistics about packets that have passed through the * @OVS_DP_ATTR_STATS: Statistics about packets that have passed through the
* datapath. Always present in notifications. * datapath. Always present in notifications.
* @OVS_DP_ATTR_MEGAFLOW_STATS: Statistics about mega flow masks usage for the
* datapath. Always present in notifications.
* *
* These attributes follow the &struct ovs_header within the Generic Netlink * These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_DP_* commands. * payload for %OVS_DP_* commands.
*/ */
enum ovs_datapath_attr { enum ovs_datapath_attr {
OVS_DP_ATTR_UNSPEC, OVS_DP_ATTR_UNSPEC,
OVS_DP_ATTR_NAME, /* name of dp_ifindex netdev */ OVS_DP_ATTR_NAME, /* name of dp_ifindex netdev */
OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */ OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */
OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */ OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */
OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */
__OVS_DP_ATTR_MAX __OVS_DP_ATTR_MAX
}; };
...@@ -84,6 +87,14 @@ struct ovs_dp_stats { ...@@ -84,6 +87,14 @@ struct ovs_dp_stats {
__u64 n_flows; /* Number of flows present */ __u64 n_flows; /* Number of flows present */
}; };
struct ovs_dp_megaflow_stats {
__u64 n_mask_hit; /* Number of masks used for flow lookups. */
__u32 n_masks; /* Number of masks for the datapath. */
__u32 pad0; /* Pad for future expension. */
__u64 pad1; /* Pad for future expension. */
__u64 pad2; /* Pad for future expension. */
};
struct ovs_vport_stats { struct ovs_vport_stats {
__u64 rx_packets; /* total packets received */ __u64 rx_packets; /* total packets received */
__u64 tx_packets; /* total packets transmitted */ __u64 tx_packets; /* total packets transmitted */
...@@ -260,6 +271,7 @@ enum ovs_key_attr { ...@@ -260,6 +271,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */ OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */
OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */ OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */
OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */ OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */
OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */
#ifdef __KERNEL__ #ifdef __KERNEL__
OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */ OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */
......
...@@ -9,6 +9,8 @@ openvswitch-y := \ ...@@ -9,6 +9,8 @@ openvswitch-y := \
datapath.o \ datapath.o \
dp_notify.o \ dp_notify.o \
flow.o \ flow.o \
flow_netlink.o \
flow_table.o \
vport.o \ vport.o \
vport-internal_dev.o \ vport-internal_dev.o \
vport-netdev.o vport-netdev.o
......
This diff is collapsed.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/u64_stats_sync.h> #include <linux/u64_stats_sync.h>
#include "flow.h" #include "flow.h"
#include "flow_table.h"
#include "vport.h" #include "vport.h"
#define DP_MAX_PORTS USHRT_MAX #define DP_MAX_PORTS USHRT_MAX
...@@ -45,11 +46,15 @@ ...@@ -45,11 +46,15 @@
* @n_lost: Number of received packets that had no matching flow in the flow * @n_lost: Number of received packets that had no matching flow in the flow
* table that could not be sent to userspace (normally due to an overflow in * table that could not be sent to userspace (normally due to an overflow in
* one of the datapath's queues). * one of the datapath's queues).
* @n_mask_hit: Number of masks looked up for flow match.
* @n_mask_hit / (@n_hit + @n_missed) will be the average masks looked
* up per packet.
*/ */
struct dp_stats_percpu { struct dp_stats_percpu {
u64 n_hit; u64 n_hit;
u64 n_missed; u64 n_missed;
u64 n_lost; u64 n_lost;
u64 n_mask_hit;
struct u64_stats_sync sync; struct u64_stats_sync sync;
}; };
...@@ -57,7 +62,7 @@ struct dp_stats_percpu { ...@@ -57,7 +62,7 @@ struct dp_stats_percpu {
* struct datapath - datapath for flow-based packet switching * struct datapath - datapath for flow-based packet switching
* @rcu: RCU callback head for deferred destruction. * @rcu: RCU callback head for deferred destruction.
* @list_node: Element in global 'dps' list. * @list_node: Element in global 'dps' list.
* @table: Current flow table. Protected by ovs_mutex and RCU. * @table: flow table.
* @ports: Hash table for ports. %OVSP_LOCAL port always exists. Protected by * @ports: Hash table for ports. %OVSP_LOCAL port always exists. Protected by
* ovs_mutex and RCU. * ovs_mutex and RCU.
* @stats_percpu: Per-CPU datapath statistics. * @stats_percpu: Per-CPU datapath statistics.
...@@ -71,7 +76,7 @@ struct datapath { ...@@ -71,7 +76,7 @@ struct datapath {
struct list_head list_node; struct list_head list_node;
/* Flow table. */ /* Flow table. */
struct flow_table __rcu *table; struct flow_table table;
/* Switch ports. */ /* Switch ports. */
struct hlist_head *ports; struct hlist_head *ports;
......
This diff is collapsed.
...@@ -33,14 +33,6 @@ ...@@ -33,14 +33,6 @@
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
struct sk_buff; 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. */ /* Used to memset ovs_key_ipv4_tunnel padding. */
#define OVS_TUNNEL_KEY_SIZE \ #define OVS_TUNNEL_KEY_SIZE \
...@@ -101,6 +93,7 @@ struct sw_flow_key { ...@@ -101,6 +93,7 @@ struct sw_flow_key {
struct { struct {
__be16 src; /* TCP/UDP/SCTP source port. */ __be16 src; /* TCP/UDP/SCTP source port. */
__be16 dst; /* TCP/UDP/SCTP destination port. */ __be16 dst; /* TCP/UDP/SCTP destination port. */
__be16 flags; /* TCP flags. */
} tp; } tp;
struct { struct {
u8 sha[ETH_ALEN]; /* ARP source hardware address. */ u8 sha[ETH_ALEN]; /* ARP source hardware address. */
...@@ -117,6 +110,7 @@ struct sw_flow_key { ...@@ -117,6 +110,7 @@ struct sw_flow_key {
struct { struct {
__be16 src; /* TCP/UDP/SCTP source port. */ __be16 src; /* TCP/UDP/SCTP source port. */
__be16 dst; /* TCP/UDP/SCTP destination port. */ __be16 dst; /* TCP/UDP/SCTP destination port. */
__be16 flags; /* TCP flags. */
} tp; } tp;
struct { struct {
struct in6_addr target; /* ND target address. */ struct in6_addr target; /* ND target address. */
...@@ -127,6 +121,31 @@ struct sw_flow_key { ...@@ -127,6 +121,31 @@ struct sw_flow_key {
}; };
} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */ } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
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 {
struct sw_flow_key *key;
struct sw_flow_key_range range;
struct sw_flow_mask *mask;
};
struct sw_flow_actions {
struct rcu_head rcu;
u32 actions_len;
struct nlattr actions[];
};
struct sw_flow { struct sw_flow {
struct rcu_head rcu; struct rcu_head rcu;
struct hlist_node hash_node[2]; struct hlist_node hash_node[2];
...@@ -141,23 +160,9 @@ struct sw_flow { ...@@ -141,23 +160,9 @@ struct sw_flow {
unsigned long used; /* Last used time (in jiffies). */ unsigned long used; /* Last used time (in jiffies). */
u64 packet_count; /* Number of packets matched. */ u64 packet_count; /* Number of packets matched. */
u64 byte_count; /* Number of bytes matched. */ u64 byte_count; /* Number of bytes matched. */
u8 tcp_flags; /* Union of seen TCP flags. */ __be16 tcp_flags; /* Union of seen TCP flags. */
};
struct sw_flow_key_range {
size_t start;
size_t end;
}; };
struct sw_flow_match {
struct sw_flow_key *key;
struct sw_flow_key_range range;
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 arp_eth_header { struct arp_eth_header {
__be16 ar_hrd; /* format of hardware address */ __be16 ar_hrd; /* format of hardware address */
__be16 ar_pro; /* format of protocol address */ __be16 ar_pro; /* format of protocol address */
...@@ -172,88 +177,9 @@ struct arp_eth_header { ...@@ -172,88 +177,9 @@ struct arp_eth_header {
unsigned char ar_tip[4]; /* target IP address */ unsigned char ar_tip[4]; /* target IP address */
} __packed; } __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_used(struct sw_flow *, struct sk_buff *);
u64 ovs_flow_used_time(unsigned long flow_jiffies); 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) int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
#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;
};
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 */ #endif /* flow.h */
This diff is collapsed.
/*
* Copyright (c) 2007-2013 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef FLOW_NETLINK_H
#define FLOW_NETLINK_H 1
#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/openvswitch.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/if_ether.h>
#include <linux/in6.h>
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/flex_array.h>
#include <net/inet_ecn.h>
#include <net/ip_tunnels.h>
#include "flow.h"
void ovs_match_init(struct sw_flow_match *match,
struct sw_flow_key *key, struct sw_flow_mask *mask);
int ovs_nla_put_flow(const struct sw_flow_key *,
const struct sw_flow_key *, struct sk_buff *);
int ovs_nla_get_flow_metadata(struct sw_flow *flow,
const struct nlattr *attr);
int ovs_nla_get_match(struct sw_flow_match *match,
const struct nlattr *,
const struct nlattr *);
int ovs_nla_copy_actions(const struct nlattr *attr,
const struct sw_flow_key *key, int depth,
struct sw_flow_actions **sfa);
int ovs_nla_put_actions(const struct nlattr *attr,
int len, struct sk_buff *skb);
struct sw_flow_actions *ovs_nla_alloc_flow_actions(int actions_len);
void ovs_nla_free_flow_actions(struct sw_flow_actions *);
#endif /* flow_netlink.h */
This diff is collapsed.
/*
* Copyright (c) 2007-2013 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
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef FLOW_TABLE_H
#define FLOW_TABLE_H 1
#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/openvswitch.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/if_ether.h>
#include <linux/in6.h>
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/flex_array.h>
#include <net/inet_ecn.h>
#include <net/ip_tunnels.h>
#include "flow.h"
struct table_instance {
struct flex_array *buckets;
unsigned int n_buckets;
struct rcu_head rcu;
int node_ver;
u32 hash_seed;
bool keep_flows;
};
struct flow_table {
struct table_instance __rcu *ti;
struct list_head mask_list;
unsigned long last_rehash;
unsigned int count;
};
int ovs_flow_init(void);
void ovs_flow_exit(void);
struct sw_flow *ovs_flow_alloc(void);
void ovs_flow_free(struct sw_flow *, bool deferred);
int ovs_flow_tbl_init(struct flow_table *);
int ovs_flow_tbl_count(struct flow_table *table);
void ovs_flow_tbl_destroy(struct flow_table *table);
int ovs_flow_tbl_flush(struct flow_table *flow_table);
int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
struct sw_flow_mask *mask);
void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow);
int ovs_flow_tbl_num_masks(const struct flow_table *table);
struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *table,
u32 *bucket, u32 *idx);
struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
const struct sw_flow_key *,
u32 *n_mask_hit);
bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
struct sw_flow_match *match);
void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
const struct sw_flow_mask *mask);
#endif /* flow_table.h */
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include <linux/if_tunnel.h> #include <linux/if_tunnel.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/in_route.h> #include <linux/in_route.h>
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
#include <linux/jhash.h> #include <linux/jhash.h>
......
...@@ -134,7 +134,7 @@ static void do_setup(struct net_device *netdev) ...@@ -134,7 +134,7 @@ static void do_setup(struct net_device *netdev)
netdev->tx_queue_len = 0; netdev->tx_queue_len = 0;
netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_TSO; NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
netdev->vlan_features = netdev->features; netdev->vlan_features = netdev->features;
netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/ip_tunnels.h> #include <net/ip_tunnels.h>
#include <net/udp.h>
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
#include <net/route.h> #include <net/route.h>
#include <net/dsfield.h> #include <net/dsfield.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment