Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/usb/asix_common.c net/ipv4/inet_connection_sock.c net/switchdev/switchdev.c In the inet_connection_sock.c case the request socket hashing scheme is completely different in net-next. The other two conflicts were overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -684,7 +684,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
|
||||
{
|
||||
if (skb_network_offset(skb) > MAX_L2_LEN) {
|
||||
OVS_NLERR(1, "L2 header too long to fragment");
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ethertype == htons(ETH_P_IP)) {
|
||||
@@ -708,8 +708,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
|
||||
struct rt6_info ovs_rt;
|
||||
|
||||
if (!v6ops) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
prepare_frag(vport, skb);
|
||||
@@ -728,8 +727,12 @@ static void ovs_fragment(struct net *net, struct vport *vport,
|
||||
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
|
||||
ovs_vport_name(vport), ntohs(ethertype), mru,
|
||||
vport->dev->mtu);
|
||||
kfree_skb(skb);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return;
|
||||
err:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
|
||||
@@ -969,7 +972,7 @@ static int execute_masked_set_action(struct sk_buff *skb,
|
||||
case OVS_KEY_ATTR_CT_STATE:
|
||||
case OVS_KEY_ATTR_CT_ZONE:
|
||||
case OVS_KEY_ATTR_CT_MARK:
|
||||
case OVS_KEY_ATTR_CT_LABEL:
|
||||
case OVS_KEY_ATTR_CT_LABELS:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@@ -1100,6 +1103,12 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
|
||||
break;
|
||||
|
||||
case OVS_ACTION_ATTR_CT:
|
||||
if (!is_flow_key_valid(key)) {
|
||||
err = ovs_flow_key_update(skb, key);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
|
||||
nla_data(a));
|
||||
|
||||
|
@@ -37,9 +37,9 @@ struct md_mark {
|
||||
};
|
||||
|
||||
/* Metadata label for masked write to conntrack label. */
|
||||
struct md_label {
|
||||
struct ovs_key_ct_label value;
|
||||
struct ovs_key_ct_label mask;
|
||||
struct md_labels {
|
||||
struct ovs_key_ct_labels value;
|
||||
struct ovs_key_ct_labels mask;
|
||||
};
|
||||
|
||||
/* Conntrack action context for execution. */
|
||||
@@ -47,10 +47,10 @@ struct ovs_conntrack_info {
|
||||
struct nf_conntrack_helper *helper;
|
||||
struct nf_conntrack_zone zone;
|
||||
struct nf_conn *ct;
|
||||
u32 flags;
|
||||
u8 commit : 1;
|
||||
u16 family;
|
||||
struct md_mark mark;
|
||||
struct md_label label;
|
||||
struct md_labels labels;
|
||||
};
|
||||
|
||||
static u16 key_to_nfproto(const struct sw_flow_key *key)
|
||||
@@ -109,21 +109,21 @@ static u32 ovs_ct_get_mark(const struct nf_conn *ct)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ovs_ct_get_label(const struct nf_conn *ct,
|
||||
struct ovs_key_ct_label *label)
|
||||
static void ovs_ct_get_labels(const struct nf_conn *ct,
|
||||
struct ovs_key_ct_labels *labels)
|
||||
{
|
||||
struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
|
||||
|
||||
if (cl) {
|
||||
size_t len = cl->words * sizeof(long);
|
||||
|
||||
if (len > OVS_CT_LABEL_LEN)
|
||||
len = OVS_CT_LABEL_LEN;
|
||||
else if (len < OVS_CT_LABEL_LEN)
|
||||
memset(label, 0, OVS_CT_LABEL_LEN);
|
||||
memcpy(label, cl->bits, len);
|
||||
if (len > OVS_CT_LABELS_LEN)
|
||||
len = OVS_CT_LABELS_LEN;
|
||||
else if (len < OVS_CT_LABELS_LEN)
|
||||
memset(labels, 0, OVS_CT_LABELS_LEN);
|
||||
memcpy(labels, cl->bits, len);
|
||||
} else {
|
||||
memset(label, 0, OVS_CT_LABEL_LEN);
|
||||
memset(labels, 0, OVS_CT_LABELS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
|
||||
key->ct.state = state;
|
||||
key->ct.zone = zone->id;
|
||||
key->ct.mark = ovs_ct_get_mark(ct);
|
||||
ovs_ct_get_label(ct, &key->ct.label);
|
||||
ovs_ct_get_labels(ct, &key->ct.labels);
|
||||
}
|
||||
|
||||
/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
|
||||
@@ -167,7 +167,7 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
|
||||
|
||||
int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
|
||||
{
|
||||
if (nla_put_u8(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
|
||||
if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
|
||||
@@ -179,8 +179,8 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
|
||||
nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label),
|
||||
&key->ct.label))
|
||||
nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
|
||||
&key->ct.labels))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
@@ -213,9 +213,9 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
const struct ovs_key_ct_label *label,
|
||||
const struct ovs_key_ct_label *mask)
|
||||
static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
const struct ovs_key_ct_labels *labels,
|
||||
const struct ovs_key_ct_labels *mask)
|
||||
{
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn_labels *cl;
|
||||
@@ -235,15 +235,15 @@ static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
nf_ct_labels_ext_add(ct);
|
||||
cl = nf_ct_labels_find(ct);
|
||||
}
|
||||
if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN)
|
||||
if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
|
||||
return -ENOSPC;
|
||||
|
||||
err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask,
|
||||
OVS_CT_LABEL_LEN / sizeof(u32));
|
||||
err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
|
||||
OVS_CT_LABELS_LEN / sizeof(u32));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ovs_ct_get_label(ct, &key->ct.label);
|
||||
ovs_ct_get_labels(ct, &key->ct.labels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -465,12 +465,12 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool label_nonzero(const struct ovs_key_ct_label *label)
|
||||
static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(*label); i++)
|
||||
if (label->ct_label[i])
|
||||
for (i = 0; i < sizeof(*labels); i++)
|
||||
if (labels->ct_labels[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -493,7 +493,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (info->flags & OVS_CT_F_COMMIT)
|
||||
if (info->commit)
|
||||
err = ovs_ct_commit(net, key, info, skb);
|
||||
else
|
||||
err = ovs_ct_lookup(net, key, info, skb);
|
||||
@@ -506,9 +506,9 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
if (label_nonzero(&info->label.mask))
|
||||
err = ovs_ct_set_label(skb, key, &info->label.value,
|
||||
&info->label.mask);
|
||||
if (labels_nonzero(&info->labels.mask))
|
||||
err = ovs_ct_set_labels(skb, key, &info->labels.value,
|
||||
&info->labels.mask);
|
||||
err:
|
||||
skb_push(skb, nh_ofs);
|
||||
return err;
|
||||
@@ -539,14 +539,13 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
|
||||
}
|
||||
|
||||
static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
|
||||
[OVS_CT_ATTR_FLAGS] = { .minlen = sizeof(u32),
|
||||
.maxlen = sizeof(u32) },
|
||||
[OVS_CT_ATTR_COMMIT] = { .minlen = 0, .maxlen = 0 },
|
||||
[OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16),
|
||||
.maxlen = sizeof(u16) },
|
||||
[OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
|
||||
.maxlen = sizeof(struct md_mark) },
|
||||
[OVS_CT_ATTR_LABEL] = { .minlen = sizeof(struct md_label),
|
||||
.maxlen = sizeof(struct md_label) },
|
||||
[OVS_CT_ATTR_LABELS] = { .minlen = sizeof(struct md_labels),
|
||||
.maxlen = sizeof(struct md_labels) },
|
||||
[OVS_CT_ATTR_HELPER] = { .minlen = 1,
|
||||
.maxlen = NF_CT_HELPER_NAME_LEN }
|
||||
};
|
||||
@@ -576,8 +575,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case OVS_CT_ATTR_FLAGS:
|
||||
info->flags = nla_get_u32(a);
|
||||
case OVS_CT_ATTR_COMMIT:
|
||||
info->commit = true;
|
||||
break;
|
||||
#ifdef CONFIG_NF_CONNTRACK_ZONES
|
||||
case OVS_CT_ATTR_ZONE:
|
||||
@@ -593,10 +592,10 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_NF_CONNTRACK_LABELS
|
||||
case OVS_CT_ATTR_LABEL: {
|
||||
struct md_label *label = nla_data(a);
|
||||
case OVS_CT_ATTR_LABELS: {
|
||||
struct md_labels *labels = nla_data(a);
|
||||
|
||||
info->label = *label;
|
||||
info->labels = *labels;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -633,7 +632,7 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
|
||||
attr == OVS_KEY_ATTR_CT_MARK)
|
||||
return true;
|
||||
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
|
||||
attr == OVS_KEY_ATTR_CT_LABEL) {
|
||||
attr == OVS_KEY_ATTR_CT_LABELS) {
|
||||
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
|
||||
|
||||
return ovs_net->xt_label;
|
||||
@@ -701,7 +700,7 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
|
||||
if (!start)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u32(skb, OVS_CT_ATTR_FLAGS, ct_info->flags))
|
||||
if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
|
||||
return -EMSGSIZE;
|
||||
if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
|
||||
nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
|
||||
@@ -711,8 +710,8 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
|
||||
&ct_info->mark))
|
||||
return -EMSGSIZE;
|
||||
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
|
||||
nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label),
|
||||
&ct_info->label))
|
||||
nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
|
||||
&ct_info->labels))
|
||||
return -EMSGSIZE;
|
||||
if (ct_info->helper) {
|
||||
if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
|
||||
@@ -737,7 +736,7 @@ void ovs_ct_free_action(const struct nlattr *a)
|
||||
|
||||
void ovs_ct_init(struct net *net)
|
||||
{
|
||||
unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE;
|
||||
unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
|
||||
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
|
||||
|
||||
if (nf_connlabels_get(net, n_bits)) {
|
||||
|
@@ -34,6 +34,13 @@ int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *,
|
||||
void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
|
||||
int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
|
||||
void ovs_ct_free_action(const struct nlattr *a);
|
||||
|
||||
static inline bool ovs_ct_state_supported(u32 state)
|
||||
{
|
||||
return !(state & ~(OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED |
|
||||
OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR |
|
||||
OVS_CS_F_INVALID | OVS_CS_F_TRACKED));
|
||||
}
|
||||
#else
|
||||
#include <linux/errno.h>
|
||||
|
||||
@@ -46,6 +53,11 @@ static inline bool ovs_ct_verify(struct net *net, int attr)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool ovs_ct_state_supported(u32 state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla,
|
||||
const struct sw_flow_key *key,
|
||||
struct sw_flow_actions **acts, bool log)
|
||||
@@ -72,7 +84,7 @@ static inline void ovs_ct_fill_key(const struct sk_buff *skb,
|
||||
key->ct.state = 0;
|
||||
key->ct.zone = 0;
|
||||
key->ct.mark = 0;
|
||||
memset(&key->ct.label, 0, sizeof(key->ct.label));
|
||||
memset(&key->ct.labels, 0, sizeof(key->ct.labels));
|
||||
}
|
||||
|
||||
static inline int ovs_ct_put_key(const struct sw_flow_key *key,
|
||||
|
@@ -117,7 +117,7 @@ struct sw_flow_key {
|
||||
u16 zone;
|
||||
u32 mark;
|
||||
u8 state;
|
||||
struct ovs_key_ct_label label;
|
||||
struct ovs_key_ct_labels labels;
|
||||
} ct;
|
||||
|
||||
} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
|
||||
|
@@ -291,10 +291,10 @@ size_t ovs_key_attr_size(void)
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */
|
||||
+ nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_CT_STATE */
|
||||
+ nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
|
||||
+ nla_total_size(16) /* OVS_KEY_ATTR_CT_LABEL */
|
||||
+ nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
|
||||
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
|
||||
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
|
||||
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
|
||||
@@ -351,10 +351,10 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
|
||||
[OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
|
||||
.next = ovs_tunnel_key_lens, },
|
||||
[OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
|
||||
[OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) },
|
||||
[OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u32) },
|
||||
[OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
|
||||
[OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) },
|
||||
[OVS_KEY_ATTR_CT_LABEL] = { .len = sizeof(struct ovs_key_ct_label) },
|
||||
[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
|
||||
};
|
||||
|
||||
static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
|
||||
@@ -864,7 +864,13 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
||||
|
||||
if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
|
||||
ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
|
||||
u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
|
||||
u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
|
||||
|
||||
if (!is_mask && !ovs_ct_state_supported(ct_state)) {
|
||||
OVS_NLERR(log, "ct_state flags %08x unsupported",
|
||||
ct_state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
|
||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
|
||||
@@ -883,14 +889,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
||||
SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
|
||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
|
||||
}
|
||||
if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) &&
|
||||
ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) {
|
||||
const struct ovs_key_ct_label *cl;
|
||||
if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
|
||||
ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
|
||||
const struct ovs_key_ct_labels *cl;
|
||||
|
||||
cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]);
|
||||
SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label,
|
||||
cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
|
||||
SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
|
||||
sizeof(*cl), is_mask);
|
||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL);
|
||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2025,7 +2031,7 @@ static int validate_set(const struct nlattr *a,
|
||||
case OVS_KEY_ATTR_PRIORITY:
|
||||
case OVS_KEY_ATTR_SKB_MARK:
|
||||
case OVS_KEY_ATTR_CT_MARK:
|
||||
case OVS_KEY_ATTR_CT_LABEL:
|
||||
case OVS_KEY_ATTR_CT_LABELS:
|
||||
case OVS_KEY_ATTR_ETHERNET:
|
||||
break;
|
||||
|
||||
|
@@ -93,7 +93,8 @@ struct sw_flow *ovs_flow_alloc(void)
|
||||
|
||||
/* Initialize the default stat node. */
|
||||
stats = kmem_cache_alloc_node(flow_stats_cache,
|
||||
GFP_KERNEL | __GFP_ZERO, 0);
|
||||
GFP_KERNEL | __GFP_ZERO,
|
||||
node_online(0) ? 0 : NUMA_NO_NODE);
|
||||
if (!stats)
|
||||
goto err;
|
||||
|
||||
|
@@ -280,35 +280,19 @@ void ovs_vport_del(struct vport *vport)
|
||||
*/
|
||||
void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
|
||||
{
|
||||
struct net_device *dev = vport->dev;
|
||||
int i;
|
||||
const struct rtnl_link_stats64 *dev_stats;
|
||||
struct rtnl_link_stats64 temp;
|
||||
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->rx_errors = dev->stats.rx_errors;
|
||||
stats->tx_errors = dev->stats.tx_errors;
|
||||
stats->tx_dropped = dev->stats.tx_dropped;
|
||||
stats->rx_dropped = dev->stats.rx_dropped;
|
||||
dev_stats = dev_get_stats(vport->dev, &temp);
|
||||
stats->rx_errors = dev_stats->rx_errors;
|
||||
stats->tx_errors = dev_stats->tx_errors;
|
||||
stats->tx_dropped = dev_stats->tx_dropped;
|
||||
stats->rx_dropped = dev_stats->rx_dropped;
|
||||
|
||||
stats->rx_dropped += atomic_long_read(&dev->rx_dropped);
|
||||
stats->tx_dropped += atomic_long_read(&dev->tx_dropped);
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
const struct pcpu_sw_netstats *percpu_stats;
|
||||
struct pcpu_sw_netstats local_stats;
|
||||
unsigned int start;
|
||||
|
||||
percpu_stats = per_cpu_ptr(dev->tstats, i);
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
|
||||
local_stats = *percpu_stats;
|
||||
} while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
|
||||
|
||||
stats->rx_bytes += local_stats.rx_bytes;
|
||||
stats->rx_packets += local_stats.rx_packets;
|
||||
stats->tx_bytes += local_stats.tx_bytes;
|
||||
stats->tx_packets += local_stats.tx_packets;
|
||||
}
|
||||
stats->rx_bytes = dev_stats->rx_bytes;
|
||||
stats->rx_packets = dev_stats->rx_packets;
|
||||
stats->tx_bytes = dev_stats->tx_bytes;
|
||||
stats->tx_packets = dev_stats->tx_packets;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,6 +444,15 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
|
||||
|
||||
OVS_CB(skb)->input_vport = vport;
|
||||
OVS_CB(skb)->mru = 0;
|
||||
if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
|
||||
u32 mark;
|
||||
|
||||
mark = skb->mark;
|
||||
skb_scrub_packet(skb, true);
|
||||
skb->mark = mark;
|
||||
tun_info = NULL;
|
||||
}
|
||||
|
||||
/* Extract flow from 'skb' into 'key'. */
|
||||
error = ovs_flow_key_extract(tun_info, skb, &key);
|
||||
if (unlikely(error)) {
|
||||
|
Reference in New Issue
Block a user