X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fvport-internal_dev.c;h=d8e57fef85daa122ed9645219e3c8b0ef9fcf7a9;hb=bfb1f2d5cbb9ef82f2def2f41f5ff8a8f02b5bbc;hp=6d52db0f3881dd86ecdd547479d9998c6009c68a;hpb=f2459fe7d91c4c325dfaa3ed18f56200b63ae27e;p=openvswitch diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c index 6d52db0f..d8e57fef 100644 --- a/datapath/vport-internal_dev.c +++ b/datapath/vport-internal_dev.c @@ -11,12 +11,12 @@ #include #include #include -#include #include #include -#include #include "datapath.h" +#include "openvswitch/internal_dev.h" +#include "vport-generic.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -32,6 +32,12 @@ struct internal_dev { struct net_device_stats stats; struct pcpu_lstats *lstats; + + /* This is warty support for XAPI, which does not support summing bond + * device statistics itself. 'extra_stats' can be set by userspace via + * the DP_DEV_SET_STATS ioctl and, if they are, then they are added to + * the real device stats. */ + struct pcpu_lstats extra_stats; }; struct vport_ops internal_vport_ops; @@ -48,7 +54,10 @@ static struct net_device_stats *internal_dev_get_stats(struct net_device *netdev int i; stats = &internal_dev->stats; - memset(stats, 0, sizeof(struct net_device_stats)); + stats->rx_bytes = internal_dev->extra_stats.rx_bytes; + stats->rx_packets = internal_dev->extra_stats.rx_packets; + stats->tx_bytes = internal_dev->extra_stats.tx_bytes; + stats->tx_packets = internal_dev->extra_stats.tx_packets; for_each_possible_cpu(i) { const struct pcpu_lstats *lb_stats; @@ -71,8 +80,7 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p) return 0; } -/* Not reentrant (because it is called with BHs disabled), but may be called - * simultaneously on different CPUs. */ +/* Called with rcu_read_lock and bottom-halves disabled. */ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) { struct internal_dev *internal_dev = internal_dev_priv(netdev); @@ -89,9 +97,9 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) lb_stats->tx_bytes += skb->len; skb_reset_mac_header(skb); - rcu_read_lock_bh(); + compute_ip_summed(skb, true); + vport_receive(vport, skb); - rcu_read_unlock_bh(); return 0; } @@ -119,11 +127,14 @@ static void internal_dev_getinfo(struct net_device *netdev, } static struct ethtool_ops internal_dev_ethtool_ops = { - .get_drvinfo = internal_dev_getinfo, - .get_link = ethtool_op_get_link, - .get_sg = ethtool_op_get_sg, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_tso = ethtool_op_get_tso, + .get_drvinfo = internal_dev_getinfo, + .get_link = ethtool_op_get_link, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_hw_csum, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, }; static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu) @@ -134,13 +145,7 @@ static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; if (dp_port) { - int min_mtu; - - mutex_lock(&dp_port->dp->mutex); - min_mtu = dp_min_mtu(dp_port->dp); - mutex_unlock(&dp_port->dp->mutex); - - if (new_mtu > min_mtu) + if (new_mtu > dp_min_mtu(dp_port->dp)) return -EINVAL; } @@ -169,6 +174,22 @@ static void internal_dev_free(struct net_device *netdev) static int internal_dev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + struct internal_dev *internal_dev = internal_dev_priv(dev); + + if (cmd == INTERNAL_DEV_SET_STATS) { + struct internal_dev_stats stats; + + if (copy_from_user(&stats, ifr->ifr_data, sizeof(stats))) + return -EFAULT; + + internal_dev->extra_stats.rx_bytes = stats.rx_bytes; + internal_dev->extra_stats.rx_packets = stats.rx_packets; + internal_dev->extra_stats.tx_bytes = stats.tx_bytes; + internal_dev->extra_stats.tx_packets = stats.tx_packets; + + return 0; + } + if (dp_ioctl_hook) return dp_ioctl_hook(dev, ifr, cmd); return -EOPNOTSUPP; @@ -210,9 +231,10 @@ do_setup(struct net_device *netdev) netdev->tx_queue_len = 0; netdev->flags = IFF_BROADCAST | IFF_MULTICAST; - netdev->features = NETIF_F_LLTX; /* XXX other features? */ + netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_HIGHDMA + | NETIF_F_HW_CSUM | NETIF_F_TSO; - vport_gen_ether_addr(netdev->dev_addr); + vport_gen_rand_ether_addr(netdev->dev_addr); } static struct vport * @@ -314,11 +336,11 @@ internal_dev_recv(struct vport *vport, struct sk_buff *skb) netif_rx_ni(skb); netdev->last_rx = jiffies; - preempt_disable(); + local_bh_disable(); lb_stats = per_cpu_ptr(internal_dev->lstats, smp_processor_id()); lb_stats->rx_packets++; lb_stats->rx_bytes += len; - preempt_enable(); + local_bh_enable(); return len; }