static int pop_vlan(struct sk_buff *skb) { __be16 tci; int err; if (likely(vlan_tx_tag_present(skb))) { skb->vlan_tci = 0; } else { if (unlikely(skb->protocol != htons(ETH_P_8021Q) || skb->len < VLAN_ETH_HLEN)) return 0; err = __pop_vlan_tci(skb, &tci); if (err) return err; } /* move next vlan tag to hw accel tag */ if (likely(skb->protocol != htons(ETH_P_8021Q) || skb->len < VLAN_ETH_HLEN)) return 0; err = __pop_vlan_tci(skb, &tci); if (unlikely(err)) return err; __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(tci)); return 0; }
/* * netvsc_recv_callback - Callback when we receive a packet from the * "wire" on the specified device. */ int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, struct ndis_tcp_ip_checksum_info *csum_info) { struct net_device *net; struct sk_buff *skb; net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; if (!net || net->reg_state != NETREG_REGISTERED) { packet->status = NVSP_STAT_FAIL; return 0; } /* Allocate a skb - TODO direct I/O to pages? */ skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); if (unlikely(!skb)) { ++net->stats.rx_dropped; packet->status = NVSP_STAT_FAIL; return 0; } /* * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ memcpy(skb_put(skb, packet->total_data_buflen), packet->data, packet->total_data_buflen); skb->protocol = eth_type_trans(skb, net); if (csum_info) { /* We only look at the IP checksum here. * Should we be dropping the packet if checksum * failed? How do we deal with other checksums - TCP/UDP? */ if (csum_info->receive.ip_checksum_succeeded) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; } if (packet->vlan_tci & VLAN_TAG_PRESENT) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), packet->vlan_tci); skb_record_rx_queue(skb, packet->channel-> offermsg.offer.sub_channel_index); net->stats.rx_packets++; net->stats.rx_bytes += packet->total_data_buflen; /* * Pass the skb back up. Network stack will deallocate the skb when it * is done. * TODO - use NAPI? */ netif_rx(skb); return 0; }
/* Called under RCU */ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, struct sk_buff *skb, u16 *vid) { int err; /* If VLAN filtering is disabled on the bridge, all packets are * permitted. */ if (!br->vlan_enabled) return true; /* If there are no vlan in the permitted list, all packets are * rejected. */ if (!v) return false; err = br_vlan_get_tag(skb, vid); if (!*vid) { u16 pvid = br_get_pvid(v); /* Frame had a tag with VID 0 or did not have a tag. * See if pvid is set on this port. That tells us which * vlan untagged or priority-tagged traffic belongs to. */ if (pvid == VLAN_N_VID) return false; /* PVID is set on this port. Any untagged or priority-tagged * ingress frame is considered to belong to this vlan. */ *vid = pvid; if (likely(err)) /* Untagged Frame. */ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); else /* Priority-tagged Frame. * At this point, We know that skb->vlan_tci had * VLAN_TAG_PRESENT bit and its VID field was 0x000. * We update only VID field and preserve PCP field. */ skb->vlan_tci |= pvid; return true; } /* Frame had a valid vlan tag. See if vlan is allowed */ if (test_bit(*vid, v->vlan_bitmap)) return true; return false; }
a_status_t __adf_net_indicate_packet(adf_net_handle_t hdl, struct sk_buff *skb, uint32_t len) { struct net_device *netdev = hdl_to_netdev(hdl); __adf_softc_t *sc = hdl_to_softc(hdl); /** * For pseudo devices IP checksum has to computed */ if(adf_os_unlikely(skb->ip_summed == CHECKSUM_UNNECESSARY)) __adf_net_ip_cksum(skb); /** * also pulls the ether header */ skb->protocol = eth_type_trans(skb, netdev); skb->dev = netdev; netdev->last_rx = jiffies; #ifdef LIMIT_MTU_SIZE if (skb->len >= LIMITED_MTU) { skb->h.raw = skb->nh.raw = skb->data; skb->dst = (struct dst_entry *)&__fake_rtable; skb->pkt_type = PACKET_HOST; dst_hold(skb->dst); #if 0 printk("addrs : sa : %x : da:%x\n", skb->nh.iph->saddr, skb->nh.iph->daddr); printk("head : %p tail : %p iph %p %p\n", skb->head, skb->tail, skb->nh.iph, skb->mac.raw); #endif icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(LIMITED_MTU - 4 )); dev_kfree_skb_any(skb); return A_STATUS_OK; } #endif if(sc->vlgrp) __vlan_hwaccel_put_tag(skb, sc->vid); if (in_irq()) netif_rx(skb); else netif_receive_skb(skb); return A_STATUS_OK; }
static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); unsigned int len; int ret; /* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if ( #ifdef CONFIG_VLAN_8021Q_DOUBLE_TAG vlan_double_tag || #endif veth->h_vlan_proto != __constant_htons(ETH_P_8021Q) || (vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR)) { u16 vlan_tci; vlan_tci = vlan_dev_priv(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); } skb->dev = vlan_dev_priv(dev)->real_dev; len = skb->len; #ifdef CONFIG_NETPOLL if (netpoll_tx_running(dev)) return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); #endif ret = dev_queue_xmit(skb); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { struct vlan_pcpu_stats *stats; stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); u64_stats_update_begin(&stats->syncp); stats->tx_packets++; stats->tx_bytes += len; u64_stats_update_end(&stats->syncp); } else { this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); } return ret; }
a_status_t __adf_net_indicate_vlanpkt(adf_net_handle_t hdl, struct sk_buff *skb, uint32_t len, adf_net_vid_t *vid) { __adf_softc_t *sc = hdl_to_softc(hdl); struct net_device *netdev = hdl_to_netdev(hdl); skb->protocol = eth_type_trans(skb, netdev); skb->dev = netdev; netdev->last_rx = jiffies; if(sc->vlgrp) { __vlan_hwaccel_put_tag(skb, vid->val); } (in_irq() ? netif_rx(skb) : netif_receive_skb(skb)); return A_STATUS_OK; }
static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; u16 vlan_tci; vlan_tci = vlan_dev_info(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = vlan_dev_info(dev)->real_dev; dev_queue_xmit(skb); return NETDEV_TX_OK; }
static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci) { __be16 proto = htons(ETH_P_802_3); struct sk_buff *skb = NULL; if (tci < 256 || tci == MBIM_IPS0_VID) { /* IPS session? */ if (len < sizeof(struct iphdr)) goto err; switch (*buf & 0xf0) { case 0x40: proto = htons(ETH_P_IP); break; case 0x60: #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) if (is_neigh_solicit(buf, len)) do_neigh_solicit(dev, buf, tci); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) */ proto = htons(ETH_P_IPV6); break; default: goto err; } } skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN); if (!skb) goto err; /* add an ethernet header */ skb_put(skb, ETH_HLEN); skb_reset_mac_header(skb); eth_hdr(skb)->h_proto = proto; eth_zero_addr(eth_hdr(skb)->h_source); memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); /* add datagram */ memcpy(skb_put(skb, len), buf, len); /* map MBIM session to VLAN */ if (tci) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci); err: return skb; }
static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vlan) { if (unlikely(vlan_tx_tag_present(skb))) { u16 current_tag; /* push down current VLAN tag */ current_tag = vlan_tx_tag_get(skb); if (!__vlan_put_tag(skb, current_tag)) return -ENOMEM; if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) skb->csum = csum_add(skb->csum, csum_partial(skb->data + ETH_HLEN, VLAN_HLEN, 0)); } __vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); return 0; }
static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, struct napi_struct *napi, const struct ndis_tcp_ip_checksum_info *csum_info, const struct ndis_pkt_8021q_info *vlan, void *data, u32 buflen) { struct sk_buff *skb; skb = napi_alloc_skb(napi, buflen); if (!skb) return skb; /* * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ skb_put_data(skb, data, buflen); skb->protocol = eth_type_trans(skb, net); /* skb is already created with CHECKSUM_NONE */ skb_checksum_none_assert(skb); /* * In Linux, the IP checksum is always checked. * Do L4 checksum offload if enabled and present. */ if (csum_info && (net->features & NETIF_F_RXCSUM)) { if (csum_info->receive.tcp_checksum_succeeded || csum_info->receive.udp_checksum_succeeded) skb->ip_summed = CHECKSUM_UNNECESSARY; } if (vlan) { u16 vlan_tci = vlan->vlanid | (vlan->pri << VLAN_PRIO_SHIFT); __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); } return skb; }
static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); unsigned int len; int ret; /* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if (veth->h_vlan_proto != vlan->vlan_proto || vlan->flags & VLAN_FLAG_REORDER_HDR) { u16 vlan_tci; vlan_tci = vlan->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority); __vlan_hwaccel_put_tag(skb, vlan->vlan_proto, vlan_tci); } skb->dev = vlan->real_dev; len = skb->len; if (unlikely(netpoll_tx_running(dev))) return vlan_netpoll_send_skb(vlan, skb); ret = dev_queue_xmit(skb); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { struct vlan_pcpu_stats *stats; stats = this_cpu_ptr(vlan->vlan_pcpu_stats); u64_stats_update_begin(&stats->syncp); stats->tx_packets++; stats->tx_bytes += len; u64_stats_update_end(&stats->syncp); } else { this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped); } return ret; }
static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vlan) { if (unlikely(vlan_tx_tag_present(skb))) { u16 current_tag; /* push down current VLAN tag */ current_tag = vlan_tx_tag_get(skb); skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, current_tag); if (!skb) return -ENOMEM; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_add(skb->csum, csum_partial(skb->data + (2 * ETH_ALEN), VLAN_HLEN, 0)); } __vlan_hwaccel_put_tag(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); return 0; }
/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { if (netpoll_rx(skb)) return NET_RX_DROP; if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) goto drop; skb->skb_iif = skb->dev->ifindex; __vlan_hwaccel_put_tag(skb, vlan_tci); skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); if (!skb->dev) goto drop; return (polling ? netif_receive_skb(skb) : netif_rx(skb)); drop: dev_kfree_skb_any(skb); return NET_RX_DROP; }
static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, struct hv_netvsc_packet *packet, struct ndis_tcp_ip_checksum_info *csum_info, void *data, u16 vlan_tci) { struct sk_buff *skb; skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); if (!skb) return skb; /* * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ memcpy(skb_put(skb, packet->total_data_buflen), data, packet->total_data_buflen); skb->protocol = eth_type_trans(skb, net); /* skb is already created with CHECKSUM_NONE */ skb_checksum_none_assert(skb); /* * In Linux, the IP checksum is always checked. * Do L4 checksum offload if enabled and present. */ if (csum_info && (net->features & NETIF_F_RXCSUM)) { if (csum_info->receive.tcp_checksum_succeeded || csum_info->receive.udp_checksum_succeeded) skb->ip_summed = CHECKSUM_UNNECESSARY; } if (vlan_tci & VLAN_TAG_PRESENT) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); return skb; }
/* Called under RCU */ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, struct sk_buff *skb, u16 *vid) { /* If VLAN filtering is disabled on the bridge, all packets are * permitted. */ if (!br->vlan_enabled) return true; /* If there are no vlan in the permitted list, all packets are * rejected. */ if (!v) return false; if (br_vlan_get_tag(skb, vid)) { u16 pvid = br_get_pvid(v); /* Frame did not have a tag. See if pvid is set * on this port. That tells us which vlan untagged * traffic belongs to. */ if (pvid == VLAN_N_VID) return false; /* PVID is set on this port. Any untagged ingress * frame is considered to belong to this vlan. */ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); return true; } /* Frame had a valid vlan tag. See if vlan is allowed */ if (test_bit(*vid, v->vlan_bitmap)) return true; return false; }
struct sk_buff *vlan_untag(struct sk_buff *skb) { struct vlan_hdr *vhdr; u16 vlan_tci; if (unlikely(vlan_tx_tag_present(skb))) { /* vlan_tci is already set-up so leave this for another time */ return skb; } skb = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) goto err_free; if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) goto err_free; vhdr = (struct vlan_hdr *) skb->data; vlan_tci = ntohs(vhdr->h_vlan_TCI); __vlan_hwaccel_put_tag(skb, vlan_tci); skb_pull_rcsum(skb, VLAN_HLEN); vlan_set_encap_proto(skb, vhdr); skb = vlan_reorder_header(skb); if (unlikely(!skb)) goto err_free; skb_reset_network_header(skb); skb_reset_transport_header(skb); skb_reset_mac_len(skb); return skb; err_free: kfree_skb(skb); return NULL; }
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = vlan_dev_get_stats(dev); unsigned short veth_TCI; /* Construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) * CFI 1 bit * VLAN ID 12 bits (low bits) */ veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, veth_TCI); stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = VLAN_DEV_INFO(dev)->real_dev; dev_queue_xmit(skb); return 0; }
static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; u16 vlan_tci; vlan_tci = vlan_dev_info(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); /* Start of modified by f00120964 for qos function 2012-4-2*/ #ifdef CONFIG_DT_QOS vlan_tci |= (s_dtQosMarkto8021P[(skb->mark & 0x7)] << 13); #endif /* End of modified by f00120964 for qos function 2012-4-2*/ skb = __vlan_hwaccel_put_tag(skb, vlan_tci); stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = vlan_dev_info(dev)->real_dev; dev_queue_xmit(skb); return NETDEV_TX_OK; }
static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net, struct hv_netvsc_packet *packet, struct ndis_tcp_ip_checksum_info *csum_info, void *data, u16 vlan_tci) { struct sk_buff *skb; skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); if (!skb) return skb; /* * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ memcpy(skb_put(skb, packet->total_data_buflen), data, packet->total_data_buflen); skb->protocol = eth_type_trans(skb, net); if (csum_info) { /* We only look at the IP checksum here. * Should we be dropping the packet if checksum * failed? How do we deal with other checksums - TCP/UDP? */ if (csum_info->receive.ip_checksum_succeeded) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; } if (vlan_tci & VLAN_TAG_PRESENT) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); return skb; }
struct sk_buff * pfq_vlan_untag(struct sk_buff *skb) { struct vlan_hdr *vhdr; u16 vlan_tci; if (unlikely(vlan_tx_tag_present(skb))) { /* vlan_tci is already set-up so leave this for another time */ return skb; } if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) goto err_free; vhdr = (struct vlan_hdr *) skb->data; vlan_tci = ntohs(vhdr->h_vlan_TCI); __vlan_hwaccel_put_tag(skb, vlan_tci); skb_pull_rcsum(skb, VLAN_HLEN); pfq_vlan_set_encap_proto(skb, vhdr); skb = pfq_vlan_reorder_header(skb); if (unlikely(!skb)) goto err_free; skb_reset_network_header(skb); skb_reset_transport_header(skb); return skb; err_free: SPARSE_INC(&memory_stats.os_free); kfree_skb(skb); return NULL; }
/** Routine to push packets arriving on Octeon interface upto network layer. * @param oct_id - octeon device id. * @param skbuff - skbuff struct to be passed to network layer. * @param len - size of total data received. * @param rh - Control header associated with the packet * @param param - additional control data with the packet * @param arg - farg registered in droq_ops */ static void liquidio_push_packet(u32 octeon_id __attribute__((unused)), void *skbuff, u32 len, union octeon_rh *rh, void *param, void *arg) { struct net_device *netdev = (struct net_device *)arg; struct octeon_droq *droq = container_of(param, struct octeon_droq, napi); struct sk_buff *skb = (struct sk_buff *)skbuff; struct skb_shared_hwtstamps *shhwtstamps; struct napi_struct *napi = param; u16 vtag = 0; u32 r_dh_off; u64 ns; if (netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; /* Do not proceed if the interface is not in RUNNING state. */ if (!ifstate_check(lio, LIO_IFSTATE_RUNNING)) { recv_buffer_free(skb); droq->stats.rx_dropped++; return; } skb->dev = netdev; skb_record_rx_queue(skb, droq->q_no); if (likely(len > MIN_SKB_SIZE)) { struct octeon_skb_page_info *pg_info; unsigned char *va; pg_info = ((struct octeon_skb_page_info *)(skb->cb)); if (pg_info->page) { /* For Paged allocation use the frags */ va = page_address(pg_info->page) + pg_info->page_offset; memcpy(skb->data, va, MIN_SKB_SIZE); skb_put(skb, MIN_SKB_SIZE); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, pg_info->page, pg_info->page_offset + MIN_SKB_SIZE, len - MIN_SKB_SIZE, LIO_RXBUFFER_SZ); } } else { struct octeon_skb_page_info *pg_info = ((struct octeon_skb_page_info *)(skb->cb)); skb_copy_to_linear_data(skb, page_address(pg_info->page) + pg_info->page_offset, len); skb_put(skb, len); put_page(pg_info->page); } r_dh_off = (rh->r_dh.len - 1) * BYTES_PER_DHLEN_UNIT; if (oct->ptp_enable) { if (rh->r_dh.has_hwtstamp) { /* timestamp is included from the hardware at * the beginning of the packet. */ if (ifstate_check (lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED)) { /* Nanoseconds are in the first 64-bits * of the packet. */ memcpy(&ns, (skb->data + r_dh_off), sizeof(ns)); r_dh_off -= BYTES_PER_DHLEN_UNIT; shhwtstamps = skb_hwtstamps(skb); shhwtstamps->hwtstamp = ns_to_ktime(ns + lio->ptp_adjust); } } } if (rh->r_dh.has_hash) { __be32 *hash_be = (__be32 *)(skb->data + r_dh_off); u32 hash = be32_to_cpu(*hash_be); skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); r_dh_off -= BYTES_PER_DHLEN_UNIT; } skb_pull(skb, rh->r_dh.len * BYTES_PER_DHLEN_UNIT); skb->protocol = eth_type_trans(skb, skb->dev); if ((netdev->features & NETIF_F_RXCSUM) && (((rh->r_dh.encap_on) && (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) || (!(rh->r_dh.encap_on) && (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED)))) /* checksum has already been verified */ skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; /* Setting Encapsulation field on basis of status received * from the firmware */ if (rh->r_dh.encap_on) { skb->encapsulation = 1; skb->csum_level = 1; droq->stats.rx_vxlan++; } /* inbound VLAN tag */ if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && rh->r_dh.vlan) { u16 priority = rh->r_dh.priority; u16 vid = rh->r_dh.vlan; vtag = (priority << VLAN_PRIO_SHIFT) | vid; __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag); } napi_gro_receive(napi, skb); droq->stats.rx_bytes_received += len - rh->r_dh.len * BYTES_PER_DHLEN_UNIT; droq->stats.rx_pkts_received++; } else { recv_buffer_free(skb); } }
static int xlgmac_rx_poll(struct xlgmac_channel *channel, int budget) { struct xlgmac_pdata *pdata = channel->pdata; struct xlgmac_ring *ring = channel->rx_ring; struct net_device *netdev = pdata->netdev; unsigned int len, dma_desc_len, max_len; unsigned int context_next, context; struct xlgmac_desc_data *desc_data; struct xlgmac_pkt_info *pkt_info; unsigned int incomplete, error; struct xlgmac_hw_ops *hw_ops; unsigned int received = 0; struct napi_struct *napi; struct sk_buff *skb; int packet_count = 0; hw_ops = &pdata->hw_ops; /* Nothing to do if there isn't a Rx ring for this channel */ if (!ring) return 0; incomplete = 0; context_next = 0; napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; desc_data = XLGMAC_GET_DESC_DATA(ring, ring->cur); pkt_info = &ring->pkt_info; while (packet_count < budget) { /* First time in loop see if we need to restore state */ if (!received && desc_data->state_saved) { skb = desc_data->state.skb; error = desc_data->state.error; len = desc_data->state.len; } else { memset(pkt_info, 0, sizeof(*pkt_info)); skb = NULL; error = 0; len = 0; } read_again: desc_data = XLGMAC_GET_DESC_DATA(ring, ring->cur); if (xlgmac_rx_dirty_desc(ring) > XLGMAC_RX_DESC_MAX_DIRTY) xlgmac_rx_refresh(channel); if (hw_ops->dev_read(channel)) break; received++; ring->cur++; incomplete = XLGMAC_GET_REG_BITS( pkt_info->attributes, RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN); context_next = XLGMAC_GET_REG_BITS( pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN); context = XLGMAC_GET_REG_BITS( pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, RX_PACKET_ATTRIBUTES_CONTEXT_LEN); /* Earlier error, just drain the remaining data */ if ((incomplete || context_next) && error) goto read_again; if (error || pkt_info->errors) { if (pkt_info->errors) netif_err(pdata, rx_err, netdev, "error in received packet\n"); dev_kfree_skb(skb); goto next_packet; } if (!context) { /* Length is cumulative, get this descriptor's length */ dma_desc_len = desc_data->rx.len - len; len += dma_desc_len; if (dma_desc_len && !skb) { skb = xlgmac_create_skb(pdata, napi, desc_data, dma_desc_len); if (!skb) error = 1; } else if (dma_desc_len) { dma_sync_single_range_for_cpu( pdata->dev, desc_data->rx.buf.dma_base, desc_data->rx.buf.dma_off, desc_data->rx.buf.dma_len, DMA_FROM_DEVICE); skb_add_rx_frag( skb, skb_shinfo(skb)->nr_frags, desc_data->rx.buf.pa.pages, desc_data->rx.buf.pa.pages_offset, dma_desc_len, desc_data->rx.buf.dma_len); desc_data->rx.buf.pa.pages = NULL; } } if (incomplete || context_next) goto read_again; if (!skb) goto next_packet; /* Be sure we don't exceed the configured MTU */ max_len = netdev->mtu + ETH_HLEN; if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && (skb->protocol == htons(ETH_P_8021Q))) max_len += VLAN_HLEN; if (skb->len > max_len) { netif_err(pdata, rx_err, netdev, "packet length exceeds configured MTU\n"); dev_kfree_skb(skb); goto next_packet; } if (netif_msg_pktdata(pdata)) xlgmac_print_pkt(netdev, skb, false); skb_checksum_none_assert(skb); if (XLGMAC_GET_REG_BITS(pkt_info->attributes, RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN)) skb->ip_summed = CHECKSUM_UNNECESSARY; if (XLGMAC_GET_REG_BITS(pkt_info->attributes, RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN)) { __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pkt_info->vlan_ctag); pdata->stats.rx_vlan_packets++; } if (XLGMAC_GET_REG_BITS(pkt_info->attributes, RX_PACKET_ATTRIBUTES_RSS_HASH_POS, RX_PACKET_ATTRIBUTES_RSS_HASH_LEN)) skb_set_hash(skb, pkt_info->rss_hash, pkt_info->rss_hash_type); skb->dev = netdev; skb->protocol = eth_type_trans(skb, netdev); skb_record_rx_queue(skb, channel->queue_index); napi_gro_receive(napi, skb); next_packet: packet_count++; } /* Check if we need to save state before leaving */ if (received && (incomplete || context_next)) { desc_data = XLGMAC_GET_DESC_DATA(ring, ring->cur); desc_data->state_saved = 1; desc_data->state.skb = skb; desc_data->state.len = len; desc_data->state.error = error; } XLGMAC_PR("packet_count = %d\n", packet_count); return packet_count; }
/** * nfp_net_rx() - receive up to @budget packets on @rx_ring * @rx_ring: RX ring to receive from * @budget: NAPI budget * * Note, this function is separated out from the napi poll function to * more cleanly separate packet receive code from other bookkeeping * functions performed in the napi poll function. * * There are differences between the NFP-3200 firmware and the * NFP-6000 firmware. The NFP-3200 firmware uses a dedicated RX queue * to indicate that new packets have arrived. The NFP-6000 does not * have this queue and uses the DD bit in the RX descriptor. This * method cannot be used on the NFP-3200 as it causes a race * condition: The RX ring write pointer on the NFP-3200 is updated * after packets (and descriptors) have been DMAed. If the DD bit is * used and subsequently the read pointer is updated this may lead to * the RX queue to underflow (if the firmware has not yet update the * write pointer). Therefore we use slightly ugly conditional code * below to handle the differences. We may, in the future update the * NFP-3200 firmware to behave the same as the firmware on the * NFP-6000. * * Return: Number of packets received. */ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) { struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net *nn = r_vec->nfp_net; unsigned int data_len, meta_len; int avail = 0, pkts_polled = 0; struct sk_buff *skb, *new_skb; struct nfp_net_rx_desc *rxd; dma_addr_t new_dma_addr; u32 qcp_wr_p; int idx; if (nn->is_nfp3200) { /* Work out how many packets arrived */ qcp_wr_p = nfp_qcp_wr_ptr_read(rx_ring->qcp_rx); idx = rx_ring->rd_p % rx_ring->cnt; if (qcp_wr_p == idx) /* No new packets */ return 0; if (qcp_wr_p > idx) avail = qcp_wr_p - idx; else avail = qcp_wr_p + rx_ring->cnt - idx; } else { avail = budget + 1; } while (avail > 0 && pkts_polled < budget) { idx = rx_ring->rd_p % rx_ring->cnt; rxd = &rx_ring->rxds[idx]; if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) { if (nn->is_nfp3200) nn_dbg(nn, "RX descriptor not valid (DD)%d:%u rxd[0]=%#x rxd[1]=%#x\n", rx_ring->idx, idx, rxd->vals[0], rxd->vals[1]); break; } /* Memory barrier to ensure that we won't do other reads * before the DD bit. */ dma_rmb(); rx_ring->rd_p++; pkts_polled++; avail--; skb = rx_ring->rxbufs[idx].skb; new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, nn->fl_bufsz); if (!new_skb) { nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb, rx_ring->rxbufs[idx].dma_addr); u64_stats_update_begin(&r_vec->rx_sync); r_vec->rx_drops++; u64_stats_update_end(&r_vec->rx_sync); continue; } dma_unmap_single(&nn->pdev->dev, rx_ring->rxbufs[idx].dma_addr, nn->fl_bufsz, DMA_FROM_DEVICE); nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr); /* < meta_len > * <-- [rx_offset] --> * --------------------------------------------------------- * | [XX] | metadata | packet | XXXX | * --------------------------------------------------------- * <---------------- data_len ---------------> * * The rx_offset is fixed for all packets, the meta_len can vary * on a packet by packet basis. If rx_offset is set to zero * (_RX_OFFSET_DYNAMIC) metadata starts at the beginning of the * buffer and is immediately followed by the packet (no [XX]). */ meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK; data_len = le16_to_cpu(rxd->rxd.data_len); if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) skb_reserve(skb, meta_len); else skb_reserve(skb, nn->rx_offset); skb_put(skb, data_len - meta_len); nfp_net_set_hash(nn->netdev, skb, rxd); /* Pad small frames to minimum */ if (skb_put_padto(skb, 60)) break; /* Stats update */ u64_stats_update_begin(&r_vec->rx_sync); r_vec->rx_pkts++; r_vec->rx_bytes += skb->len; u64_stats_update_end(&r_vec->rx_sync); skb_record_rx_queue(skb, rx_ring->idx); skb->protocol = eth_type_trans(skb, nn->netdev); nfp_net_rx_csum(nn, r_vec, rxd, skb); if (rxd->rxd.flags & PCIE_DESC_RX_VLAN) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), le16_to_cpu(rxd->rxd.vlan)); napi_gro_receive(&rx_ring->r_vec->napi, skb); } if (nn->is_nfp3200) nfp_qcp_rd_ptr_add(rx_ring->qcp_rx, pkts_polled); return pkts_polled; }
gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci) { __vlan_hwaccel_put_tag(napi->skb, vlan_tci); return napi_gro_frags(napi); }
static int amd8111e_rx_poll(struct napi_struct *napi, int budget) { struct amd8111e_priv *lp = container_of(napi, struct amd8111e_priv, napi); struct net_device *dev = lp->amd8111e_net_dev; int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK; void __iomem *mmio = lp->mmio; struct sk_buff *skb,*new_skb; int min_pkt_len, status; unsigned int intr0; int num_rx_pkt = 0; short pkt_len; #if AMD8111E_VLAN_TAG_USED short vtag; #endif int rx_pkt_limit = budget; unsigned long flags; do{ while(1) { status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); if (status & OWN_BIT) break; if(status & ERR_BIT) { lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; goto err_next_pkt; } if(!((status & STP_BIT) && (status & ENP_BIT))){ lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; goto err_next_pkt; } pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; #if AMD8111E_VLAN_TAG_USED vtag = status & TT_MASK; if (vtag != 0) min_pkt_len =MIN_PKT_LEN - 4; else #endif min_pkt_len =MIN_PKT_LEN; if (pkt_len < min_pkt_len) { lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; lp->drv_rx_errors++; goto err_next_pkt; } if(--rx_pkt_limit < 0) goto rx_not_empty; new_skb = netdev_alloc_skb(dev, lp->rx_buff_len); if (!new_skb) { lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; lp->drv_rx_errors++; goto err_next_pkt; } skb_reserve(new_skb, 2); skb = lp->rx_skbuff[rx_index]; pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index], lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); skb_put(skb, pkt_len); lp->rx_skbuff[rx_index] = new_skb; lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev, new_skb->data, lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); skb->protocol = eth_type_trans(skb, dev); #if AMD8111E_VLAN_TAG_USED if (vtag == TT_VLAN_TAGGED){ u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info); __vlan_hwaccel_put_tag(skb, vlan_tag); } #endif netif_receive_skb(skb); lp->coal_conf.rx_packets++; lp->coal_conf.rx_bytes += pkt_len; num_rx_pkt++; err_next_pkt: lp->rx_ring[rx_index].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[rx_index]); lp->rx_ring[rx_index].buff_count = cpu_to_le16(lp->rx_buff_len-2); wmb(); lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; } intr0 = readl(mmio + INT0); writel(intr0 & RINT0,mmio + INT0); } while(intr0 & RINT0); if (rx_pkt_limit > 0) { spin_lock_irqsave(&lp->lock, flags); __napi_complete(napi); writel(VAL0|RINTEN0, mmio + INTEN0); writel(VAL2 | RDMD0, mmio + CMD0); spin_unlock_irqrestore(&lp->lock, flags); } rx_not_empty: return num_rx_pkt; }
static inline int pdma_recv(struct net_device* dev, END_DEVICE* ei_local, int work_todo) { struct PDMA_rxdesc *rxd_ring; struct sk_buff *new_skb, *rx_skb; int gmac_no = PSE_PORT_GMAC1; int work_done = 0; u32 rxd_dma_owner_idx; u32 rxd_info2, rxd_info4; #if defined (CONFIG_RAETH_HW_VLAN_RX) u32 rxd_info3; #endif #if defined (CONFIG_RAETH_SPECIAL_TAG) struct vlan_ethhdr *veth; #endif rxd_dma_owner_idx = le32_to_cpu(sysRegRead(RX_CALC_IDX0)); while (work_done < work_todo) { rxd_dma_owner_idx = (rxd_dma_owner_idx + 1) % NUM_RX_DESC; rxd_ring = &ei_local->rxd_ring[rxd_dma_owner_idx]; if (!(rxd_ring->rxd_info2 & RX2_DMA_DONE)) break; /* load completed skb pointer */ rx_skb = ei_local->rxd_buff[rxd_dma_owner_idx]; /* copy RX desc to CPU */ rxd_info2 = rxd_ring->rxd_info2; #if defined (CONFIG_RAETH_HW_VLAN_RX) rxd_info3 = rxd_ring->rxd_info3; #endif rxd_info4 = rxd_ring->rxd_info4; #if defined (CONFIG_PSEUDO_SUPPORT) gmac_no = RX4_DMA_SP(rxd_info4); #endif /* We have to check the free memory size is big enough * before pass the packet to cpu */ new_skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC); if (unlikely(new_skb == NULL)) { #if defined (RAETH_PDMA_V2) rxd_ring->rxd_info2 = RX2_DMA_SDL0_SET(MAX_RX_LENGTH); #else rxd_ring->rxd_info2 = RX2_DMA_LS0; #endif /* move CPU pointer to next RXD */ sysRegWrite(RX_CALC_IDX0, cpu_to_le32(rxd_dma_owner_idx)); inc_rx_drop(ei_local, gmac_no); #if !defined (CONFIG_RAETH_NAPI) /* mean need reschedule */ work_done = work_todo; #endif #if defined (CONFIG_RAETH_DEBUG) if (net_ratelimit()) printk(KERN_ERR "%s: Failed to alloc new RX skb! (GMAC: %d)\n", RAETH_DEV_NAME, gmac_no); #endif break; } #if !defined (RAETH_PDMA_V2) skb_reserve(new_skb, NET_IP_ALIGN); #endif /* store new empty skb pointer */ ei_local->rxd_buff[rxd_dma_owner_idx] = new_skb; /* map new skb to ring (unmap is not required on generic mips mm) */ rxd_ring->rxd_info1 = (u32)dma_map_single(NULL, new_skb->data, MAX_RX_LENGTH, DMA_FROM_DEVICE); #if defined (RAETH_PDMA_V2) rxd_ring->rxd_info2 = RX2_DMA_SDL0_SET(MAX_RX_LENGTH); #else rxd_ring->rxd_info2 = RX2_DMA_LS0; #endif wmb(); /* move CPU pointer to next RXD */ sysRegWrite(RX_CALC_IDX0, cpu_to_le32(rxd_dma_owner_idx)); /* skb processing */ rx_skb->len = RX2_DMA_SDL0_GET(rxd_info2); #if defined (RAETH_PDMA_V2) rx_skb->data += NET_IP_ALIGN; #endif rx_skb->tail = rx_skb->data + rx_skb->len; #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) FOE_MAGIC_TAG(rx_skb) = FOE_MAGIC_GE; DO_FILL_FOE_DESC(rx_skb, (rxd_info4 & ~(RX4_DMA_ALG_SET))); #endif #if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) if (rxd_info4 & RX4_DMA_L4FVLD) rx_skb->ip_summed = CHECKSUM_UNNECESSARY; #endif #if defined (CONFIG_RAETH_HW_VLAN_RX) if ((rxd_info2 & RX2_DMA_TAG) && rxd_info3) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) __vlan_hwaccel_put_tag(rx_skb, __constant_htons(ETH_P_8021Q), RX3_DMA_VID(rxd_info3)); #else __vlan_hwaccel_put_tag(rx_skb, RX3_DMA_VID(rxd_info3)); #endif } #endif #if defined (CONFIG_PSEUDO_SUPPORT) if (gmac_no == PSE_PORT_GMAC2) rx_skb->protocol = eth_type_trans(rx_skb, ei_local->PseudoDev); else #endif rx_skb->protocol = eth_type_trans(rx_skb, dev); #if defined (CONFIG_RAETH_SPECIAL_TAG) #if defined (CONFIG_MT7530_GSW) #define ESW_TAG_ID 0x00 #else #define ESW_TAG_ID 0x81 #endif // port0: 0x8100 => 0x8100 0001 // port1: 0x8101 => 0x8100 0002 // port2: 0x8102 => 0x8100 0003 // port3: 0x8103 => 0x8100 0004 // port4: 0x8104 => 0x8100 0005 // port5: 0x8105 => 0x8100 0006 veth = vlan_eth_hdr(rx_skb); if ((veth->h_vlan_proto & 0xFF) == ESW_TAG_ID) { veth->h_vlan_TCI = htons((((veth->h_vlan_proto >> 8) & 0xF) + 1)); veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); rx_skb->protocol = veth->h_vlan_proto; } #endif /* ra_sw_nat_hook_rx return 1 --> continue * ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx */ #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) if((ra_sw_nat_hook_rx == NULL) || (ra_sw_nat_hook_rx != NULL && ra_sw_nat_hook_rx(rx_skb))) #endif { #if defined (CONFIG_RAETH_NAPI) #if defined (CONFIG_RAETH_NAPI_GRO) if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) napi_gro_receive(&ei_local->napi, rx_skb); else #endif netif_receive_skb(rx_skb); #else netif_rx(rx_skb); #endif } work_done++; }
/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { __vlan_hwaccel_put_tag(skb, vlan_tci); return polling ? netif_receive_skb(skb) : netif_rx(skb); }
static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct fm10k_intfc *interface = netdev_priv(dev); unsigned int r_idx = skb->queue_mapping; int err; if ((skb->protocol == htons(ETH_P_8021Q)) && !vlan_tx_tag_present(skb)) { /* FM10K only supports hardware tagging, any tags in frame * are considered 2nd level or "outer" tags */ struct vlan_hdr *vhdr; __be16 proto; /* make sure skb is not shared */ skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) return NETDEV_TX_OK; /* make sure there is enough room to move the ethernet header */ if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN))) return NETDEV_TX_OK; /* verify the skb head is not shared */ err = skb_cow_head(skb, 0); if (err) return NETDEV_TX_OK; /* locate vlan header */ vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); /* pull the 2 key pieces of data out of it */ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(vhdr->h_vlan_TCI)); proto = vhdr->h_vlan_encapsulated_proto; skb->protocol = (ntohs(proto) >= 1536) ? proto : htons(ETH_P_802_2); /* squash it by moving the ethernet addresses up 4 bytes */ memmove(skb->data + VLAN_HLEN, skb->data, 12); __skb_pull(skb, VLAN_HLEN); skb_reset_mac_header(skb); } /* The minimum packet size for a single buffer is 17B so pad the skb * in order to meet this minimum size requirement. */ if (unlikely(skb->len < 17)) { int pad_len = 17 - skb->len; if (skb_pad(skb, pad_len)) return NETDEV_TX_OK; __skb_put(skb, pad_len); } /* prepare packet for hardware time stamping */ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) fm10k_ts_tx_enqueue(interface, skb); if (r_idx >= interface->num_tx_queues) r_idx %= interface->num_tx_queues; err = fm10k_xmit_frame_ring(skb, interface->tx_ring[r_idx]); return err; }
gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) { __vlan_hwaccel_put_tag(skb, vlan_tci); return napi_gro_receive(napi, skb); }