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. */
+ * add yours to the list at the bottom of vport.h.
+ */
static const struct vport_ops *vport_ops_list[] = {
&ovs_netdev_vport_ops,
&ovs_internal_vport_ops,
kfree(dev_table);
}
-static struct hlist_head *hash_bucket(struct net *net, const char *name)
+static struct hlist_head *hash_bucket(const struct net *net, const char *name)
{
unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
*
* Must be called with ovs or RCU read lock.
*/
-struct vport *ovs_vport_locate(struct net *net, const char *name)
+struct vport *ovs_vport_locate(const struct net *net, const char *name)
{
struct hlist_head *bucket = hash_bucket(net, name);
struct vport *vport;
{
struct vport *vport;
size_t alloc_size;
- int i;
alloc_size = sizeof(struct vport);
if (priv_size) {
return ERR_PTR(-EINVAL);
}
- vport->percpu_stats = alloc_percpu(struct pcpu_sw_netstats);
+ vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
if (!vport->percpu_stats) {
kfree(vport);
return ERR_PTR(-ENOMEM);
}
- for_each_possible_cpu(i) {
- struct pcpu_sw_netstats *vport_stats;
- vport_stats = per_cpu_ptr(vport->percpu_stats, i);
- u64_stats_init(&vport_stats->syncp);
- }
-
- spin_lock_init(&vport->stats_lock);
-
return vport;
}
*/
void ovs_vport_free(struct vport *vport)
{
- kfree((struct vport_portids __force *)vport->upcall_portids);
+ kfree(rcu_dereference_raw(vport->upcall_portids));
free_percpu(vport->percpu_stats);
kfree(vport);
}
vport->ops->destroy(vport);
}
-/**
- * ovs_vport_set_stats - sets offset device stats
- *
- * @vport: vport on which to set stats
- * @stats: stats to set
- *
- * Provides a set of transmit, receive, and error stats to be added as an
- * offset to the collected data when stats are retrieved. Some devices may not
- * support setting the stats, in which case the result will always be
- * -EOPNOTSUPP.
- *
- * Must be called with ovs_mutex.
- */
-void ovs_vport_set_stats(struct vport *vport, struct ovs_vport_stats *stats)
-{
- spin_lock_bh(&vport->stats_lock);
- vport->offset_stats = *stats;
- spin_unlock_bh(&vport->stats_lock);
-}
-
/**
* ovs_vport_get_stats - retrieve device stats
*
{
int i;
- /* We potentially have 3 sources of stats that need to be
+ /* We potentially have two surces of stats that need to be
* combined: those we have collected (split into err_stats and
- * percpu_stats), offset_stats from set_stats(), and device
- * error stats from netdev->get_stats() (for errors that happen
- * downstream and therefore aren't reported through our
- * vport_record_error() function).
- * Stats from first two sources are merged and reported by ovs over
+ * percpu_stats), and device error stats from netdev->get_stats()
+ * (for errors that happen downstream and therefore aren't
+ * reported through our vport_record_error() function).
+ * Stats from first source are reported by ovs over
* OVS_VPORT_ATTR_STATS.
* netdev-stats can be directly read over netlink-ioctl.
*/
- spin_lock_bh(&vport->stats_lock);
-
- *stats = vport->offset_stats;
+ stats->rx_errors = atomic_long_read(&vport->err_stats.rx_errors);
+ stats->tx_errors = atomic_long_read(&vport->err_stats.tx_errors);
+ stats->tx_dropped = atomic_long_read(&vport->err_stats.tx_dropped);
+ stats->rx_dropped = atomic_long_read(&vport->err_stats.rx_dropped);
- stats->rx_errors += vport->err_stats.rx_errors;
- stats->tx_errors += vport->err_stats.tx_errors;
- stats->tx_dropped += vport->err_stats.tx_dropped;
- stats->rx_dropped += vport->err_stats.rx_dropped;
-
- spin_unlock_bh(&vport->stats_lock);
+ stats->rx_bytes = 0;
+ stats->rx_packets = 0;
+ stats->tx_bytes = 0;
+ stats->tx_packets = 0;
for_each_possible_cpu(i) {
const struct pcpu_sw_netstats *percpu_stats;
*
* Must be called with ovs_mutex.
*/
-int ovs_vport_set_upcall_portids(struct vport *vport, struct nlattr *ids)
+int ovs_vport_set_upcall_portids(struct vport *vport, const struct nlattr *ids)
{
struct vport_portids *old, *vport_portids;
*
* Returns the portid of the target socket. Must be called with rcu_read_lock.
*/
-u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
+u32 ovs_vport_find_upcall_portid(const struct vport *vport, struct sk_buff *skb)
{
struct vport_portids *ids;
u32 hash;
- ids = rcu_dereference(p->upcall_portids);
+ ids = rcu_dereference(vport->upcall_portids);
if (ids->n_ids == 1 && ids->ids[0] == 0)
return 0;
* called compute_ip_summed() to initialize the checksumming fields.
*/
void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
- struct ovs_tunnel_info *tun_info)
+ const struct ovs_tunnel_info *tun_info)
{
struct pcpu_sw_netstats *stats;
struct sw_flow_key key;
stats = this_cpu_ptr(vport->percpu_stats);
u64_stats_update_begin(&stats->syncp);
stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ stats->rx_bytes += skb->len + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
u64_stats_update_end(&stats->syncp);
ovs_skb_init_inner_protocol(skb);
return;
}
- ovs_dp_process_packet(skb);
+ ovs_dp_process_packet(skb, &key);
}
/**
u64_stats_update_end(&stats->syncp);
} else if (sent < 0) {
ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
- kfree_skb(skb);
- } else
+ } else {
ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
+ }
return sent;
}
static void ovs_vport_record_error(struct vport *vport,
enum vport_err_type err_type)
{
- spin_lock(&vport->stats_lock);
-
switch (err_type) {
case VPORT_E_RX_DROPPED:
- vport->err_stats.rx_dropped++;
+ atomic_long_inc(&vport->err_stats.rx_dropped);
break;
case VPORT_E_RX_ERROR:
- vport->err_stats.rx_errors++;
+ atomic_long_inc(&vport->err_stats.rx_errors);
break;
case VPORT_E_TX_DROPPED:
- vport->err_stats.tx_dropped++;
+ atomic_long_inc(&vport->err_stats.tx_dropped);
break;
case VPORT_E_TX_ERROR:
- vport->err_stats.tx_errors++;
+ atomic_long_inc(&vport->err_stats.tx_errors);
break;
}
-
- spin_unlock(&vport->stats_lock);
}
static void free_vport_rcu(struct rcu_head *rcu)