You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Jesse Gross says: ==================== [GIT net-next] Open vSwitch Open vSwitch changes for net-next/3.14. Highlights are: * Performance improvements in the mechanism to get packets to userspace using memory mapped netlink and skb zero copy where appropriate. * Per-cpu flow stats in situations where flows are likely to be shared across CPUs. Standard flow stats are used in other situations to save memory and allocation time. * A handful of code cleanups and rationalization. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
+128
-103
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,8 @@ struct datapath {
|
||||
/* Network namespace ref. */
|
||||
struct net *net;
|
||||
#endif
|
||||
|
||||
u32 user_features;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -145,6 +147,8 @@ int lockdep_ovsl_is_held(void);
|
||||
#define ASSERT_OVSL() WARN_ON(unlikely(!lockdep_ovsl_is_held()))
|
||||
#define ovsl_dereference(p) \
|
||||
rcu_dereference_protected(p, lockdep_ovsl_is_held())
|
||||
#define rcu_dereference_ovsl(p) \
|
||||
rcu_dereference_check(p, lockdep_ovsl_is_held())
|
||||
|
||||
static inline struct net *ovs_dp_get_net(struct datapath *dp)
|
||||
{
|
||||
@@ -178,14 +182,12 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
|
||||
|
||||
extern struct notifier_block ovs_dp_device_notifier;
|
||||
extern struct genl_family dp_vport_genl_family;
|
||||
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
|
||||
|
||||
void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
|
||||
void ovs_dp_detach_port(struct vport *);
|
||||
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
|
||||
const struct dp_upcall_info *);
|
||||
|
||||
const char *ovs_dp_name(const struct datapath *dp);
|
||||
struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
|
||||
u8 cmd);
|
||||
|
||||
|
||||
+89
-7
@@ -35,6 +35,7 @@
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/icmp.h>
|
||||
@@ -60,10 +61,16 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
|
||||
|
||||
#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
|
||||
|
||||
void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb)
|
||||
void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
|
||||
{
|
||||
struct flow_stats *stats;
|
||||
__be16 tcp_flags = 0;
|
||||
|
||||
if (!flow->stats.is_percpu)
|
||||
stats = flow->stats.stat;
|
||||
else
|
||||
stats = this_cpu_ptr(flow->stats.cpu_stats);
|
||||
|
||||
if ((flow->key.eth.type == htons(ETH_P_IP) ||
|
||||
flow->key.eth.type == htons(ETH_P_IPV6)) &&
|
||||
flow->key.ip.proto == IPPROTO_TCP &&
|
||||
@@ -71,12 +78,87 @@ void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb)
|
||||
tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
|
||||
}
|
||||
|
||||
spin_lock(&flow->lock);
|
||||
flow->used = jiffies;
|
||||
flow->packet_count++;
|
||||
flow->byte_count += skb->len;
|
||||
flow->tcp_flags |= tcp_flags;
|
||||
spin_unlock(&flow->lock);
|
||||
spin_lock(&stats->lock);
|
||||
stats->used = jiffies;
|
||||
stats->packet_count++;
|
||||
stats->byte_count += skb->len;
|
||||
stats->tcp_flags |= tcp_flags;
|
||||
spin_unlock(&stats->lock);
|
||||
}
|
||||
|
||||
static void stats_read(struct flow_stats *stats,
|
||||
struct ovs_flow_stats *ovs_stats,
|
||||
unsigned long *used, __be16 *tcp_flags)
|
||||
{
|
||||
spin_lock(&stats->lock);
|
||||
if (time_after(stats->used, *used))
|
||||
*used = stats->used;
|
||||
*tcp_flags |= stats->tcp_flags;
|
||||
ovs_stats->n_packets += stats->packet_count;
|
||||
ovs_stats->n_bytes += stats->byte_count;
|
||||
spin_unlock(&stats->lock);
|
||||
}
|
||||
|
||||
void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
|
||||
unsigned long *used, __be16 *tcp_flags)
|
||||
{
|
||||
int cpu, cur_cpu;
|
||||
|
||||
*used = 0;
|
||||
*tcp_flags = 0;
|
||||
memset(ovs_stats, 0, sizeof(*ovs_stats));
|
||||
|
||||
if (!flow->stats.is_percpu) {
|
||||
stats_read(flow->stats.stat, ovs_stats, used, tcp_flags);
|
||||
} else {
|
||||
cur_cpu = get_cpu();
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct flow_stats *stats;
|
||||
|
||||
if (cpu == cur_cpu)
|
||||
local_bh_disable();
|
||||
|
||||
stats = per_cpu_ptr(flow->stats.cpu_stats, cpu);
|
||||
stats_read(stats, ovs_stats, used, tcp_flags);
|
||||
|
||||
if (cpu == cur_cpu)
|
||||
local_bh_enable();
|
||||
}
|
||||
put_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
static void stats_reset(struct flow_stats *stats)
|
||||
{
|
||||
spin_lock(&stats->lock);
|
||||
stats->used = 0;
|
||||
stats->packet_count = 0;
|
||||
stats->byte_count = 0;
|
||||
stats->tcp_flags = 0;
|
||||
spin_unlock(&stats->lock);
|
||||
}
|
||||
|
||||
void ovs_flow_stats_clear(struct sw_flow *flow)
|
||||
{
|
||||
int cpu, cur_cpu;
|
||||
|
||||
if (!flow->stats.is_percpu) {
|
||||
stats_reset(flow->stats.stat);
|
||||
} else {
|
||||
cur_cpu = get_cpu();
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
||||
if (cpu == cur_cpu)
|
||||
local_bh_disable();
|
||||
|
||||
stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu));
|
||||
|
||||
if (cpu == cur_cpu)
|
||||
local_bh_enable();
|
||||
}
|
||||
put_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
static int check_header(struct sk_buff *skb, int len)
|
||||
|
||||
+24
-9
@@ -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>
|
||||
@@ -122,8 +123,8 @@ struct sw_flow_key {
|
||||
} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
|
||||
|
||||
struct sw_flow_key_range {
|
||||
size_t start;
|
||||
size_t end;
|
||||
unsigned short int start;
|
||||
unsigned short int end;
|
||||
};
|
||||
|
||||
struct sw_flow_mask {
|
||||
@@ -146,6 +147,22 @@ struct sw_flow_actions {
|
||||
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_stats {
|
||||
bool is_percpu;
|
||||
union {
|
||||
struct flow_stats *stat;
|
||||
struct flow_stats __percpu *cpu_stats;
|
||||
};
|
||||
};
|
||||
|
||||
struct sw_flow {
|
||||
struct rcu_head rcu;
|
||||
struct hlist_node hash_node[2];
|
||||
@@ -155,12 +172,7 @@ struct sw_flow {
|
||||
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. */
|
||||
__be16 tcp_flags; /* Union of seen TCP flags. */
|
||||
struct sw_flow_stats stats;
|
||||
};
|
||||
|
||||
struct arp_eth_header {
|
||||
@@ -177,7 +189,10 @@ struct arp_eth_header {
|
||||
unsigned char ar_tip[4]; /* target IP address */
|
||||
} __packed;
|
||||
|
||||
void ovs_flow_used(struct sw_flow *, struct sk_buff *);
|
||||
void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
|
||||
void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
|
||||
unsigned long *used, __be16 *tcp_flags);
|
||||
void ovs_flow_stats_clear(struct sw_flow *flow);
|
||||
u64 ovs_flow_used_time(unsigned long flow_jiffies);
|
||||
|
||||
int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
|
||||
|
||||
@@ -266,6 +266,20 @@ static bool is_all_zero(const u8 *fp, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_all_set(const u8 *fp, size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (fp[i] != 0xff)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __parse_flow_nlattrs(const struct nlattr *attr,
|
||||
const struct nlattr *a[],
|
||||
u64 *attrsp, bool nz)
|
||||
@@ -487,8 +501,9 @@ static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
const struct nlattr **a, bool is_mask)
|
||||
static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple,
|
||||
u64 attrs, const struct nlattr **a,
|
||||
bool is_mask)
|
||||
{
|
||||
int err;
|
||||
u64 orig_attrs = attrs;
|
||||
@@ -545,6 +560,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
|
||||
}
|
||||
|
||||
if (is_mask && exact_5tuple) {
|
||||
if (match->mask->key.eth.type != htons(0xffff))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
|
||||
const struct ovs_key_ipv4 *ipv4_key;
|
||||
|
||||
@@ -567,6 +587,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
|
||||
ipv4_key->ipv4_dst, is_mask);
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple) {
|
||||
if (ipv4_key->ipv4_proto != 0xff ||
|
||||
ipv4_key->ipv4_src != htonl(0xffffffff) ||
|
||||
ipv4_key->ipv4_dst != htonl(0xffffffff))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
|
||||
@@ -598,6 +625,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
is_mask);
|
||||
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple) {
|
||||
if (ipv6_key->ipv6_proto != 0xff ||
|
||||
!is_all_set((u8 *)ipv6_key->ipv6_src, sizeof(match->key->ipv6.addr.src)) ||
|
||||
!is_all_set((u8 *)ipv6_key->ipv6_dst, sizeof(match->key->ipv6.addr.dst)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
|
||||
@@ -640,6 +674,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
tcp_key->tcp_dst, is_mask);
|
||||
}
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_TCP);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple &&
|
||||
(tcp_key->tcp_src != htons(0xffff) ||
|
||||
tcp_key->tcp_dst != htons(0xffff)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
|
||||
@@ -671,6 +710,11 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
|
||||
udp_key->udp_dst, is_mask);
|
||||
}
|
||||
attrs &= ~(1 << OVS_KEY_ATTR_UDP);
|
||||
|
||||
if (is_mask && exact_5tuple && *exact_5tuple &&
|
||||
(udp_key->udp_src != htons(0xffff) ||
|
||||
udp_key->udp_dst != htons(0xffff)))
|
||||
*exact_5tuple = false;
|
||||
}
|
||||
|
||||
if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
|
||||
@@ -756,6 +800,7 @@ static void sw_flow_mask_set(struct sw_flow_mask *mask,
|
||||
* attribute specifies the mask field of the wildcarded flow.
|
||||
*/
|
||||
int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
bool *exact_5tuple,
|
||||
const struct nlattr *key,
|
||||
const struct nlattr *mask)
|
||||
{
|
||||
@@ -803,10 +848,13 @@ int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
}
|
||||
}
|
||||
|
||||
err = ovs_key_from_nlattrs(match, key_attrs, a, false);
|
||||
err = ovs_key_from_nlattrs(match, NULL, key_attrs, a, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (exact_5tuple)
|
||||
*exact_5tuple = true;
|
||||
|
||||
if (mask) {
|
||||
err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
|
||||
if (err)
|
||||
@@ -844,7 +892,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
}
|
||||
}
|
||||
|
||||
err = ovs_key_from_nlattrs(match, mask_attrs, a, true);
|
||||
err = ovs_key_from_nlattrs(match, exact_5tuple, mask_attrs, a, true);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
@@ -1128,19 +1176,11 @@ struct sw_flow_actions *ovs_nla_alloc_flow_actions(int size)
|
||||
return sfa;
|
||||
}
|
||||
|
||||
/* RCU callback used by ovs_nla_free_flow_actions. */
|
||||
static void rcu_free_acts_callback(struct rcu_head *rcu)
|
||||
{
|
||||
struct sw_flow_actions *sf_acts = container_of(rcu,
|
||||
struct sw_flow_actions, rcu);
|
||||
kfree(sf_acts);
|
||||
}
|
||||
|
||||
/* Schedules 'sf_acts' to be freed after the next RCU grace period.
|
||||
* The caller must hold rcu_read_lock for this to be sensible. */
|
||||
void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
|
||||
{
|
||||
call_rcu(&sf_acts->rcu, rcu_free_acts_callback);
|
||||
kfree_rcu(sf_acts, rcu);
|
||||
}
|
||||
|
||||
static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
|
||||
|
||||
@@ -45,6 +45,7 @@ int ovs_nla_put_flow(const struct sw_flow_key *,
|
||||
int ovs_nla_get_flow_metadata(struct sw_flow *flow,
|
||||
const struct nlattr *attr);
|
||||
int ovs_nla_get_match(struct sw_flow_match *match,
|
||||
bool *exact_5tuple,
|
||||
const struct nlattr *,
|
||||
const struct nlattr *);
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@
|
||||
#include <net/ipv6.h>
|
||||
#include <net/ndisc.h>
|
||||
|
||||
#include "datapath.h"
|
||||
|
||||
#define TBL_MIN_BUCKETS 1024
|
||||
#define REHASH_INTERVAL (10 * 60 * HZ)
|
||||
|
||||
@@ -72,19 +70,42 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
|
||||
*d++ = *s++ & *m++;
|
||||
}
|
||||
|
||||
struct sw_flow *ovs_flow_alloc(void)
|
||||
struct sw_flow *ovs_flow_alloc(bool percpu_stats)
|
||||
{
|
||||
struct sw_flow *flow;
|
||||
int cpu;
|
||||
|
||||
flow = kmem_cache_alloc(flow_cache, GFP_KERNEL);
|
||||
if (!flow)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
spin_lock_init(&flow->lock);
|
||||
flow->sf_acts = NULL;
|
||||
flow->mask = NULL;
|
||||
|
||||
flow->stats.is_percpu = percpu_stats;
|
||||
|
||||
if (!percpu_stats) {
|
||||
flow->stats.stat = kzalloc(sizeof(*flow->stats.stat), GFP_KERNEL);
|
||||
if (!flow->stats.stat)
|
||||
goto err;
|
||||
|
||||
spin_lock_init(&flow->stats.stat->lock);
|
||||
} else {
|
||||
flow->stats.cpu_stats = alloc_percpu(struct flow_stats);
|
||||
if (!flow->stats.cpu_stats)
|
||||
goto err;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct flow_stats *cpu_stats;
|
||||
|
||||
cpu_stats = per_cpu_ptr(flow->stats.cpu_stats, cpu);
|
||||
spin_lock_init(&cpu_stats->lock);
|
||||
}
|
||||
}
|
||||
return flow;
|
||||
err:
|
||||
kfree(flow);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
int ovs_flow_tbl_count(struct flow_table *table)
|
||||
@@ -118,6 +139,10 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets)
|
||||
static void flow_free(struct sw_flow *flow)
|
||||
{
|
||||
kfree((struct sf_flow_acts __force *)flow->sf_acts);
|
||||
if (flow->stats.is_percpu)
|
||||
free_percpu(flow->stats.cpu_stats);
|
||||
else
|
||||
kfree(flow->stats.stat);
|
||||
kmem_cache_free(flow_cache, flow);
|
||||
}
|
||||
|
||||
@@ -128,13 +153,6 @@ static void rcu_free_flow_callback(struct rcu_head *rcu)
|
||||
flow_free(flow);
|
||||
}
|
||||
|
||||
static void rcu_free_sw_flow_mask_cb(struct rcu_head *rcu)
|
||||
{
|
||||
struct sw_flow_mask *mask = container_of(rcu, struct sw_flow_mask, rcu);
|
||||
|
||||
kfree(mask);
|
||||
}
|
||||
|
||||
static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
|
||||
{
|
||||
if (!mask)
|
||||
@@ -146,7 +164,7 @@ static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
|
||||
if (!mask->ref_count) {
|
||||
list_del_rcu(&mask->list);
|
||||
if (deferred)
|
||||
call_rcu(&mask->rcu, rcu_free_sw_flow_mask_cb);
|
||||
kfree_rcu(mask, rcu);
|
||||
else
|
||||
kfree(mask);
|
||||
}
|
||||
@@ -429,11 +447,11 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
|
||||
struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
|
||||
const struct sw_flow_key *key,
|
||||
u32 *n_mask_hit)
|
||||
{
|
||||
struct table_instance *ti = rcu_dereference(tbl->ti);
|
||||
struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
|
||||
struct sw_flow_mask *mask;
|
||||
struct sw_flow *flow;
|
||||
|
||||
@@ -447,6 +465,14 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
|
||||
const struct sw_flow_key *key)
|
||||
{
|
||||
u32 __always_unused n_mask_hit;
|
||||
|
||||
return ovs_flow_tbl_lookup_stats(tbl, key, &n_mask_hit);
|
||||
}
|
||||
|
||||
int ovs_flow_tbl_num_masks(const struct flow_table *table)
|
||||
{
|
||||
struct sw_flow_mask *mask;
|
||||
@@ -514,11 +540,7 @@ static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a new mask into the mask list.
|
||||
* The caller needs to make sure that 'mask' is not the same
|
||||
* as any masks that are already on the list.
|
||||
*/
|
||||
/* Add 'mask' into the mask list, if it is not already there. */
|
||||
static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
|
||||
struct sw_flow_mask *new)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ struct flow_table {
|
||||
int ovs_flow_init(void);
|
||||
void ovs_flow_exit(void);
|
||||
|
||||
struct sw_flow *ovs_flow_alloc(void);
|
||||
struct sw_flow *ovs_flow_alloc(bool percpu_stats);
|
||||
void ovs_flow_free(struct sw_flow *, bool deferred);
|
||||
|
||||
int ovs_flow_tbl_init(struct flow_table *);
|
||||
@@ -69,9 +69,11 @@ 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 *,
|
||||
struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
|
||||
const struct sw_flow_key *,
|
||||
u32 *n_mask_hit);
|
||||
struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
|
||||
const struct sw_flow_key *);
|
||||
|
||||
bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
|
||||
struct sw_flow_match *match);
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "vport.h"
|
||||
#include "vport-internal_dev.h"
|
||||
|
||||
static void ovs_vport_record_error(struct vport *,
|
||||
enum vport_err_type err_type);
|
||||
|
||||
/* List of statically compiled vport implementations. Don't forget to also
|
||||
* add yours to the list at the bottom of vport.h. */
|
||||
static const struct vport_ops *vport_ops_list[] = {
|
||||
@@ -396,7 +399,8 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
|
||||
* If using the vport generic stats layer indicate that an error of the given
|
||||
* type has occurred.
|
||||
*/
|
||||
void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
|
||||
static void ovs_vport_record_error(struct vport *vport,
|
||||
enum vport_err_type err_type)
|
||||
{
|
||||
spin_lock(&vport->stats_lock);
|
||||
|
||||
|
||||
@@ -192,7 +192,6 @@ static inline struct vport *vport_from_priv(const void *priv)
|
||||
|
||||
void ovs_vport_receive(struct vport *, struct sk_buff *,
|
||||
struct ovs_key_ipv4_tunnel *);
|
||||
void ovs_vport_record_error(struct vport *, enum vport_err_type err_type);
|
||||
|
||||
/* List of statically compiled vport implementations. Don't forget to also
|
||||
* add yours to the list at the top of vport.c. */
|
||||
|
||||
Reference in New Issue
Block a user