diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_main.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 107 |
1 files changed, 77 insertions, 30 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 26718abd5ce4..490818c46d74 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -6506,37 +6506,92 @@ static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring, | |||
6506 | writel(i, tx_ring->tail); | 6506 | writel(i, tx_ring->tail); |
6507 | } | 6507 | } |
6508 | 6508 | ||
6509 | static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, | 6509 | static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb, |
6510 | u8 queue, u32 tx_flags, __be16 protocol) | 6510 | u32 tx_flags, __be16 protocol) |
6511 | { | 6511 | { |
6512 | union ixgbe_atr_input atr_input; | 6512 | struct ixgbe_q_vector *q_vector = ring->q_vector; |
6513 | struct iphdr *iph = ip_hdr(skb); | 6513 | union ixgbe_atr_hash_dword input = { .dword = 0 }; |
6514 | struct ethhdr *eth = (struct ethhdr *)skb->data; | 6514 | union ixgbe_atr_hash_dword common = { .dword = 0 }; |
6515 | union { | ||
6516 | unsigned char *network; | ||
6517 | struct iphdr *ipv4; | ||
6518 | struct ipv6hdr *ipv6; | ||
6519 | } hdr; | ||
6515 | struct tcphdr *th; | 6520 | struct tcphdr *th; |
6516 | __be16 vlan_id; | 6521 | __be16 vlan_id; |
6517 | 6522 | ||
6518 | /* Right now, we support IPv4 w/ TCP only */ | 6523 | /* if ring doesn't have a interrupt vector, cannot perform ATR */ |
6519 | if (protocol != htons(ETH_P_IP) || | 6524 | if (!q_vector) |
6520 | iph->protocol != IPPROTO_TCP) | 6525 | return; |
6526 | |||
6527 | /* do nothing if sampling is disabled */ | ||
6528 | if (!ring->atr_sample_rate) | ||
6521 | return; | 6529 | return; |
6522 | 6530 | ||
6523 | memset(&atr_input, 0, sizeof(union ixgbe_atr_input)); | 6531 | ring->atr_count++; |
6524 | 6532 | ||
6525 | vlan_id = htons(tx_flags >> IXGBE_TX_FLAGS_VLAN_SHIFT); | 6533 | /* snag network header to get L4 type and address */ |
6534 | hdr.network = skb_network_header(skb); | ||
6535 | |||
6536 | /* Currently only IPv4/IPv6 with TCP is supported */ | ||
6537 | if ((protocol != __constant_htons(ETH_P_IPV6) || | ||
6538 | hdr.ipv6->nexthdr != IPPROTO_TCP) && | ||
6539 | (protocol != __constant_htons(ETH_P_IP) || | ||
6540 | hdr.ipv4->protocol != IPPROTO_TCP)) | ||
6541 | return; | ||
6526 | 6542 | ||
6527 | th = tcp_hdr(skb); | 6543 | th = tcp_hdr(skb); |
6528 | 6544 | ||
6529 | ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id); | 6545 | /* skip this packet since the socket is closing */ |
6530 | ixgbe_atr_set_src_port_82599(&atr_input, th->dest); | 6546 | if (th->fin) |
6531 | ixgbe_atr_set_dst_port_82599(&atr_input, th->source); | 6547 | return; |
6532 | ixgbe_atr_set_flex_byte_82599(&atr_input, eth->h_proto); | 6548 | |
6533 | ixgbe_atr_set_l4type_82599(&atr_input, IXGBE_ATR_FLOW_TYPE_TCPV4); | 6549 | /* sample on all syn packets or once every atr sample count */ |
6534 | /* src and dst are inverted, think how the receiver sees them */ | 6550 | if (!th->syn && (ring->atr_count < ring->atr_sample_rate)) |
6535 | ixgbe_atr_set_src_ipv4_82599(&atr_input, iph->daddr); | 6551 | return; |
6536 | ixgbe_atr_set_dst_ipv4_82599(&atr_input, iph->saddr); | 6552 | |
6553 | /* reset sample count */ | ||
6554 | ring->atr_count = 0; | ||
6555 | |||
6556 | vlan_id = htons(tx_flags >> IXGBE_TX_FLAGS_VLAN_SHIFT); | ||
6557 | |||
6558 | /* | ||
6559 | * src and dst are inverted, think how the receiver sees them | ||
6560 | * | ||
6561 | * The input is broken into two sections, a non-compressed section | ||
6562 | * containing vm_pool, vlan_id, and flow_type. The rest of the data | ||
6563 | * is XORed together and stored in the compressed dword. | ||
6564 | */ | ||
6565 | input.formatted.vlan_id = vlan_id; | ||
6566 | |||
6567 | /* | ||
6568 | * since src port and flex bytes occupy the same word XOR them together | ||
6569 | * and write the value to source port portion of compressed dword | ||
6570 | */ | ||
6571 | if (vlan_id) | ||
6572 | common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q); | ||
6573 | else | ||
6574 | common.port.src ^= th->dest ^ protocol; | ||
6575 | common.port.dst ^= th->source; | ||
6576 | |||
6577 | if (protocol == __constant_htons(ETH_P_IP)) { | ||
6578 | input.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; | ||
6579 | common.ip ^= hdr.ipv4->saddr ^ hdr.ipv4->daddr; | ||
6580 | } else { | ||
6581 | input.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6; | ||
6582 | common.ip ^= hdr.ipv6->saddr.s6_addr32[0] ^ | ||
6583 | hdr.ipv6->saddr.s6_addr32[1] ^ | ||
6584 | hdr.ipv6->saddr.s6_addr32[2] ^ | ||
6585 | hdr.ipv6->saddr.s6_addr32[3] ^ | ||
6586 | hdr.ipv6->daddr.s6_addr32[0] ^ | ||
6587 | hdr.ipv6->daddr.s6_addr32[1] ^ | ||
6588 | hdr.ipv6->daddr.s6_addr32[2] ^ | ||
6589 | hdr.ipv6->daddr.s6_addr32[3]; | ||
6590 | } | ||
6537 | 6591 | ||
6538 | /* This assumes the Rx queue and Tx queue are bound to the same CPU */ | 6592 | /* This assumes the Rx queue and Tx queue are bound to the same CPU */ |
6539 | ixgbe_fdir_add_signature_filter_82599(&adapter->hw, &atr_input, queue); | 6593 | ixgbe_fdir_add_signature_filter_82599(&q_vector->adapter->hw, |
6594 | input, common, ring->queue_index); | ||
6540 | } | 6595 | } |
6541 | 6596 | ||
6542 | static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size) | 6597 | static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size) |
@@ -6707,16 +6762,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, | |||
6707 | count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len); | 6762 | count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len); |
6708 | if (count) { | 6763 | if (count) { |
6709 | /* add the ATR filter if ATR is on */ | 6764 | /* add the ATR filter if ATR is on */ |
6710 | if (tx_ring->atr_sample_rate) { | 6765 | if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state)) |
6711 | ++tx_ring->atr_count; | 6766 | ixgbe_atr(tx_ring, skb, tx_flags, protocol); |
6712 | if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) && | ||
6713 | test_bit(__IXGBE_TX_FDIR_INIT_DONE, | ||
6714 | &tx_ring->state)) { | ||
6715 | ixgbe_atr(adapter, skb, tx_ring->queue_index, | ||
6716 | tx_flags, protocol); | ||
6717 | tx_ring->atr_count = 0; | ||
6718 | } | ||
6719 | } | ||
6720 | txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); | 6767 | txq = netdev_get_tx_queue(netdev, tx_ring->queue_index); |
6721 | txq->tx_bytes += skb->len; | 6768 | txq->tx_bytes += skb->len; |
6722 | txq->tx_packets++; | 6769 | txq->tx_packets++; |