static int vcan_tx(struct sk_buff *skb, struct net_device *dev) { struct can_frame *cf = (struct can_frame *)skb->data; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) struct net_device_stats *stats = &dev->stats; #else struct net_device_stats *stats = netdev_priv(dev); #endif int loop; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; stats->tx_packets++; stats->tx_bytes += cf->can_dlc; /* set flag whether this packet has to be looped back */ loop = skb->pkt_type == PACKET_LOOPBACK; if (!echo) { /* no echo handling available inside this driver */ if (loop) { /* * only count the packets here, because the * CAN core already did the echo for us */ stats->rx_packets++; stats->rx_bytes += cf->can_dlc; } kfree_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { struct sock *srcsk = skb->sk; skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ skb->sk = srcsk; vcan_rx(skb, dev); } else { /* no looped packets => no counting */ kfree_skb(skb); } return NETDEV_TX_OK; }
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; struct net_device_stats *stats = &dev->stats; int loop; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; stats->tx_packets++; stats->tx_bytes += cfd->len; /* set flag whether this packet has to be looped back */ loop = skb->pkt_type == PACKET_LOOPBACK; if (!echo) { /* no echo handling available inside this driver */ if (loop) { /* * only count the packets here, because the * CAN core already did the echo for us */ stats->rx_packets++; stats->rx_bytes += cfd->len; } consume_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { skb = can_create_echo_skb(skb); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ vcan_rx(skb, dev); } else { /* no looped packets => no counting */ consume_skb(skb); } return NETDEV_TX_OK; }
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; int loop; stats->tx_packets++; stats->tx_bytes += skb->len; /* set flag whether this packet has to be looped back */ loop = skb->pkt_type == PACKET_LOOPBACK; if (!echo) { /* no echo handling available inside this driver */ if (loop) { /* * only count the packets here, because the * CAN core already did the echo for us */ stats->rx_packets++; stats->rx_bytes += skb->len; } kfree_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { struct sock *srcsk = skb->sk; skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ skb->sk = srcsk; vcan_rx(skb, dev); } else { /* no looped packets => no counting */ kfree_skb(skb); } return NETDEV_TX_OK; }
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; int loop; stats->tx_packets++; stats->tx_bytes += skb->len; loop = skb->pkt_type == PACKET_LOOPBACK; if (!echo) { if (loop) { stats->rx_packets++; stats->rx_bytes += skb->len; } kfree_skb(skb); return NETDEV_TX_OK; } if (loop) { struct sock *srcsk = skb->sk; skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) return NETDEV_TX_OK; skb->sk = srcsk; vcan_rx(skb, dev); } else { kfree_skb(skb); } return NETDEV_TX_OK; }