Skip to content

Commit

Permalink
igc: Add launch time support to XDP ZC
Browse files Browse the repository at this point in the history
Enable Launch Time Control (LTC) support to XDP zero copy via XDP Tx
metadata framework.

This patch is tested with tools/testing/selftests/bpf/xdp_hw_metadata on
Intel Tiger Lake platform. Below are the test steps and result.

Test Steps:
1. Add mqprio qdisc:
   $ sudo tc qdisc add dev enp2s0 handle 8001: parent root mqprio num_tc 4
     map 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 queues 1@0 1@1 1@2 1@3 hw 0

2. Enable launch time hardware offload on hardware queue 1:
   $ sudo tc qdisc replace dev enp2s0 parent 8001:2 etf offload clockid
     CLOCK_TAI delta 500000

3. Change RSS to route all incoming IP packets into hardware queue 1:
   $ sudo ethtool -X enp2s0 start 1 equal 1

4. Start xdp_hw_metadata selftest application:
   $ sudo ./xdp_hw_metadata enp2s0 -l 1000000000

5. Send an UDP packet to port 9091 of DUT.
   $ echo -n xdp | nc -u -q0 169.254.1.1 9091

When launch time is set to 1s in the future, the delta between launch time
and transmit hardware timestamp is equal to 0.016us, as shown in result
below:
  0x562ff5dc8880: rx_desc[4]->addr=84110 addr=84110 comp_addr=84110 EoP
  rx_hash: 0xE343384 with RSS type:0x1
  HW RX-time:   1734578015467548904 (sec:1734578015.4675) delta to User RX-time sec:0.0002 (183.103 usec)
  XDP RX-time:   1734578015467651698 (sec:1734578015.4677) delta to User RX-time sec:0.0001 (80.309 usec)
  No rx_vlan_tci or rx_vlan_proto, err=-95
  0x562ff5dc8880: ping-pong with csum=561c (want c7dd) csum_start=34 csum_offset=6
  HW RX-time:   1734578015467548904 (sec:1734578015.4675) delta to HW Launch-time sec:1.0000 (1000000.000 usec)
  0x562ff5dc8880: complete tx idx=4 addr=4018
  HW Launch-time:   1734578016467548904 (sec:1734578016.4675) delta to HW TX-complete-time sec:0.0000 (0.016 usec)
  HW TX-complete-time:   1734578016467548920 (sec:1734578016.4675) delta to User TX-complete-time sec:0.0000 (32.546 usec)
  XDP RX-time:   1734578015467651698 (sec:1734578015.4677) delta to User TX-complete-time sec:0.9999 (999929.768 usec)
  HW RX-time:   1734578015467548904 (sec:1734578015.4675) delta to HW TX-complete-time sec:1.0000 (1000000.016 usec)
  0x562ff5dc8880: complete rx idx=132 addr=84110

Signed-off-by: Song Yoong Siang <[email protected]>
  • Loading branch information
yoongsiang2 authored and Kernel Patches Daemon committed Jan 10, 2025
1 parent 927dd11 commit ee5357e
Showing 1 changed file with 56 additions and 22 deletions.
78 changes: 56 additions & 22 deletions drivers/net/ethernet/intel/igc/igc_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,26 @@ static bool igc_request_tx_tstamp(struct igc_adapter *adapter, struct sk_buff *s
return false;
}

static void igc_insert_empty_packet(struct igc_ring *tx_ring)
{
struct igc_tx_buffer *empty_info;
struct sk_buff *empty;
void *data;

empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
empty = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC);
if (!empty)
return;

data = skb_put(empty, IGC_EMPTY_FRAME_SIZE);
memset(data, 0, IGC_EMPTY_FRAME_SIZE);

igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0);

if (igc_init_tx_empty_descriptor(tx_ring, empty, empty_info) < 0)
dev_kfree_skb_any(empty);
}

static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
struct igc_ring *tx_ring)
{
Expand Down Expand Up @@ -1603,26 +1623,8 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
skb->tstamp = ktime_set(0, 0);
launch_time = igc_tx_launchtime(tx_ring, txtime, &first_flag, &insert_empty);

if (insert_empty) {
struct igc_tx_buffer *empty_info;
struct sk_buff *empty;
void *data;

empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
empty = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC);
if (!empty)
goto done;

data = skb_put(empty, IGC_EMPTY_FRAME_SIZE);
memset(data, 0, IGC_EMPTY_FRAME_SIZE);

igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0);

if (igc_init_tx_empty_descriptor(tx_ring,
empty,
empty_info) < 0)
dev_kfree_skb_any(empty);
}
if (insert_empty)
igc_insert_empty_packet(tx_ring);

done:
/* record the location of the first descriptor for this packet */
Expand Down Expand Up @@ -2955,9 +2957,33 @@ static u64 igc_xsk_fill_timestamp(void *_priv)
return *(u64 *)_priv;
}

static void igc_xsk_request_launch_time(u64 launch_time, void *_priv)
{
struct igc_metadata_request *meta_req = _priv;
struct igc_ring *tx_ring = meta_req->tx_ring;
__le32 launch_time_offset;
bool insert_empty = false;
bool first_flag = false;

if (!tx_ring->launchtime_enable)
return;

launch_time_offset = igc_tx_launchtime(tx_ring,
ns_to_ktime(launch_time),
&first_flag, &insert_empty);
if (insert_empty) {
igc_insert_empty_packet(tx_ring);
meta_req->tx_buffer =
&tx_ring->tx_buffer_info[tx_ring->next_to_use];
}

igc_tx_ctxtdesc(tx_ring, launch_time_offset, first_flag, 0, 0, 0);
}

const struct xsk_tx_metadata_ops igc_xsk_tx_metadata_ops = {
.tmo_request_timestamp = igc_xsk_request_timestamp,
.tmo_fill_timestamp = igc_xsk_fill_timestamp,
.tmo_request_launch_time = igc_xsk_request_launch_time,
};

static void igc_xdp_xmit_zc(struct igc_ring *ring)
Expand All @@ -2980,7 +3006,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
ntu = ring->next_to_use;
budget = igc_desc_unused(ring);

while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
while (xsk_tx_peek_desc(pool, &xdp_desc) && budget >= 4) {
struct igc_metadata_request meta_req;
struct xsk_tx_metadata *meta = NULL;
struct igc_tx_buffer *bi;
Expand All @@ -3004,6 +3030,12 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
xsk_tx_metadata_request(meta, &igc_xsk_tx_metadata_ops,
&meta_req);

/* xsk_tx_metadata_request() may have updated next_to_use */
ntu = ring->next_to_use;

/* xsk_tx_metadata_request() may have updated Tx buffer info */
bi = meta_req.tx_buffer;

tx_desc = IGC_TX_DESC(ring, ntu);
tx_desc->read.cmd_type_len = cpu_to_le32(meta_req.cmd_type);
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
Expand All @@ -3021,9 +3053,11 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
ntu++;
if (ntu == ring->count)
ntu = 0;

ring->next_to_use = ntu;
budget = igc_desc_unused(ring);
}

ring->next_to_use = ntu;
if (tx_desc) {
igc_flush_tx_descriptors(ring);
xsk_tx_release(pool);
Expand Down

0 comments on commit ee5357e

Please sign in to comment.