1/* 2 * Copyright 2018, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13$esc:(#include <linux_hdrs.h>) 14$esc:(#include <wrapper.h>) 15#include <abstract.h> 16#include <generated.c> 17 18/* Forward declaration of C functions */ 19static void cg_loopback_setup_ac(struct net_device *dev); 20 21#include <plat/linux/linux_api.ac> 22 23/* The higher levels take care of making this non-reentrant (it's 24 * called with bh's disabled). 25 */ 26static netdev_tx_t cg_loopback_xmit(struct sk_buff *skb, 27 struct net_device *dev) 28{ 29 struct pcpu_lstats *lb_stats; 30 int len; 31 32 skb_tx_timestamp(skb); 33 skb_orphan(skb); 34 35 /* Before queueing this packet to netif_rx(), 36 * make sure dst is refcounted. 37 */ 38 skb_dst_force(skb); 39 40 skb->protocol = eth_type_trans(skb, dev); 41 42 /* it's OK to use per_cpu_ptr() because BHs are off */ 43 lb_stats = this_cpu_ptr(dev->lstats); 44 45 len = skb->len; 46 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { 47 u64_stats_update_begin(&lb_stats->syncp); 48 lb_stats->bytes += len; 49 lb_stats->packets++; 50 u64_stats_update_end(&lb_stats->syncp); 51 } 52 53 return NETDEV_TX_OK; 54} 55 56static void cg_loopback_get_stats64(struct net_device *dev, 57 struct rtnl_link_stats64 *stats) 58{ 59 u64 bytes = 0; 60 u64 packets = 0; 61 int i; 62 63 for (i = -1; i = cpumask_next(i, cpu_possible_mask), i < nr_cpu_ids;) { 64 const struct pcpu_lstats *lb_stats; 65 u64 tbytes, tpackets; 66 unsigned int start; 67 68 lb_stats = per_cpu_ptr(dev->lstats, i); 69 do { 70 start = u64_stats_fetch_begin_irq(&lb_stats->syncp); 71 tbytes = lb_stats->bytes; 72 tpackets = lb_stats->packets; 73 } while (u64_stats_fetch_retry_irq(&lb_stats->syncp, start)); 74 bytes += tbytes; 75 packets += tpackets; 76 } 77 stats->rx_packets = packets; 78 stats->tx_packets = packets; 79 stats->rx_bytes = bytes; 80 stats->tx_bytes = bytes; 81} 82 83static u32 cg_always_on_ac(struct net_device *dev) 84{ 85 $ty:((NetDeviceAbstractType!, U32)) ret; 86 87 ret = cg_always_on_cg(dev); 88 return ret.p2; 89} 90 91static int cg_loopback_get_ts_info(struct net_device *netdev, 92 struct ethtool_ts_info *ts_info) 93{ 94 $ty:(()) empty; 95 96 ts_info->so_timestamping = get_ts_info_timestamp_flags_cg(empty); 97 ts_info->phc_index = -1; 98 99 return 0; 100} 101 102static const struct ethtool_ops cg_loopback_ethtool_ops = { 103 .get_link = cg_always_on_ac, 104 .get_ts_info = cg_loopback_get_ts_info, 105}; 106 107static int cg_loopback_dev_init(struct net_device *dev) 108{ 109 SysState state; 110 $ty:((SysState, NetDeviceAbstractType)) args; 111 $ty:(RR (SysState, NetDeviceAbstractType) () ()) ret; 112 113 args.p1 = &state; 114 args.p2 = dev; 115 116 ret = cg_loopback_dev_init_cg(args); 117 if (ret.p2.tag == TAG_ENUM_Success) { 118 return 0; 119 } else { 120 return -ENOMEM; 121 } 122} 123 124static void cg_loopback_dev_free(struct net_device *dev) 125{ 126 SysState state; 127 $ty:((SysState, NetDeviceAbstractType)) args; 128 129 args.p1 = &state; 130 args.p2 = dev; 131 132 cg_loopback_dev_free_cg(args); 133} 134 135static const struct net_device_ops cg_loopback_ops = { 136 .ndo_init = cg_loopback_dev_init, 137 .ndo_start_xmit = cg_loopback_xmit, 138 .ndo_get_stats64 = cg_loopback_get_stats64, 139 .ndo_set_mac_address = eth_mac_addr, 140}; 141 142static void cg_loopback_setup_ac(struct net_device *dev) 143{ 144 dev->mtu = 64 * 1024; 145 dev->hard_header_len = ETH_HLEN; /* 14 */ 146 dev->min_header_len = ETH_HLEN; /* 14 */ 147 dev->addr_len = ETH_ALEN; /* 6 */ 148 dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ 149 dev->flags = IFF_LOOPBACK; 150 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; 151 netif_keep_dst(dev); 152 dev->hw_features = NETIF_F_GSO_SOFTWARE; 153 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST 154 | NETIF_F_GSO_SOFTWARE 155 | NETIF_F_HW_CSUM 156 | NETIF_F_RXCSUM 157 | NETIF_F_SCTP_CRC 158 | NETIF_F_HIGHDMA 159 | NETIF_F_LLTX 160 | NETIF_F_NETNS_LOCAL 161 | NETIF_F_VLAN_CHALLENGED 162 | NETIF_F_LOOPBACK; 163 dev->ethtool_ops = &cg_loopback_ethtool_ops; 164 ether_setup(dev); 165 dev->netdev_ops = &cg_loopback_ops; 166 dev->needs_free_netdev = true; 167 dev->priv_destructor = cg_loopback_dev_free; 168} 169 170int cg_loopback_net_init_ac(struct net *net) 171{ 172 SysState state; 173 $ty:((SysState, NetAbstractType)) args; 174 $ty:(RR (SysState, NetAbstractType) () ()) ret; 175 176 args.p1 = &state; 177 args.p2 = net; 178 179 ret = cg_loopback_net_init_cg(args); 180 if (ret.p2.tag == TAG_ENUM_Success) { 181 return 0; 182 } else { 183 return -ENOMEM; 184 } 185} 186