aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_main.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c107
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
6509static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, 6509static 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
6542static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size) 6597static 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++;