-
-
Notifications
You must be signed in to change notification settings - Fork 24
jaguar3 8822E: match SVPcom monitor injection retry policy #334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,7 @@ constexpr size_t RXDESC_SIZE_8822C = 24; /* RX_DESC_SIZE_88XX */ | |
| #define SET_TX_DESC_RATE_ID_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x04, 16, 5, v) | ||
| #define SET_TX_DESC_PKT_OFFSET_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x04, 24, 5, v) | ||
| #define SET_TX_DESC_USE_RATE_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x0C, 8, 1, v) | ||
| #define SET_TX_DESC_DISRTSFB_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x0C, 9, 1, v) | ||
| #define SET_TX_DESC_DISDATAFB_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x0C, 10, 1, v) | ||
| #define SET_TX_DESC_NAVUSEHDR_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x0C, 15, 1, v) | ||
| #define SET_TX_DESC_NDPA_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x0C, 22, 2, v) | ||
|
|
@@ -82,6 +83,7 @@ constexpr size_t RXDESC_SIZE_8822C = 24; /* RX_DESC_SIZE_88XX */ | |
| * cal_txdesc_chksum_8822c. */ | ||
| #define SET_TX_DESC_DMA_TXAGG_NUM_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x1C, 24, 8, v) | ||
| #define SET_TX_DESC_EN_HWSEQ_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x20, 15, 1, v) | ||
| #define SET_TX_DESC_SW_SEQ_8822C(d, v) SET_BITS_TO_LE_4BYTE((d) + 0x24, 12, 12, v) | ||
| #define GET_TX_DESC_PKT_OFFSET_8822C(d) LE_BITS_TO_4BYTE((d) + 0x04, 24, 5) | ||
|
|
||
| /* --- RX descriptor fields --- */ | ||
|
|
@@ -125,38 +127,35 @@ inline void cal_txdesc_chksum_8822c(uint8_t *txdesc) { | |
| /* Fill an 8822C data/monitor-inject TX descriptor (48 bytes, zeroed by caller) | ||
| * and finalise its checksum. `bw` is the descriptor BW code (0=20,1=40,2=80), | ||
| * `rate_hw` the DESC_RATE* index (MRateToHwRate output), `rate_id` 8(HT)/9(VHT). | ||
| * Field choices mirror the Jaguar1 monitor-inject path (MACID 1, USE_RATE, | ||
| * DISDATAFB, HW sequence). */ | ||
| * Field choices mirror SVPcom rtl8812eu's RTL8822E monitor-inject path | ||
| * (MACID 1, USE_RATE, DISRTSFB, DISDATAFB, supplied 802.11 sequence). */ | ||
| inline void fill_data_tx_desc_8822c(uint8_t *d, uint16_t pkt_size, | ||
| uint8_t rate_hw, uint8_t rate_id, uint8_t bw, | ||
| bool short_gi, bool ldpc, uint8_t stbc, | ||
| bool bmc = false, bool ndpa = false, | ||
| uint8_t data_sc = 0, | ||
| uint8_t pwr_ofset_type = 0, | ||
| uint8_t pkt_offset = 0) { | ||
| uint8_t pkt_offset = 0, | ||
| bool retry = false, | ||
| uint16_t seqnum = 0) { | ||
| SET_TX_DESC_TXPKTSIZE_8822C(d, pkt_size); | ||
| SET_TX_DESC_OFFSET_8822C(d, static_cast<uint32_t>(TXDESC_SIZE_8822C)); | ||
| SET_TX_DESC_LS_8822C(d, 1); | ||
| /* Broadcast/multicast marker: the kernel sets this whenever addr1 is a group | ||
| * address, so mark group-addressed frames the same way for a faithful port. */ | ||
| SET_TX_DESC_BMC_8822C(d, bmc ? 1 : 0); | ||
| /* Remaining fields mirror the kernel's 8822e data/inject descriptor so the | ||
| * on-wire TXDESC is byte-identical (verified against a usbmon capture of the | ||
| * kernel's MCS7 inject): hw-managed sequence (DISQSELSEQ), SU/broadcast group | ||
| * (G_ID=63), a bounded per-frame retry limit (RTY_LMT_EN + RTS_DATA_RTY_LMT), | ||
| * RA-group 9, and a non-zero SW_DEFINE. NB: these do not change on-air | ||
| * throughput (the chip already airs a saturating MCS7 flood at ~77% duty with | ||
| * or without them) — they are here for a faithful port, not a fix. */ | ||
| SET_TX_DESC_DISQSELSEQ_8822C(d, 1); | ||
| SET_TX_DESC_G_ID_8822C(d, 0x3f); | ||
| /* SVPcom monitor injection keeps the frame's 802.11 sequence number: | ||
| * EN_HWSEQ is clear and SW_SEQ is copied from the header. */ | ||
| SET_TX_DESC_RTY_LMT_EN_8822C(d, 1); | ||
| SET_TX_DESC_RTS_DATA_RTY_LMT_8822C(d, 12); | ||
| /* RADIOTAP_F_TX_NOACK means zero MAC retries; other injected frames use | ||
| * SVPcom's six-attempt limit. */ | ||
| SET_TX_DESC_RTS_DATA_RTY_LMT_8822C(d, retry ? 6 : 0); | ||
| SET_TX_DESC_MACID_8822C(d, 0x01); | ||
| SET_TX_DESC_QSEL_8822C(d, 0x12); /* MGMT queue (mirrors Jaguar1 inject) */ | ||
| SET_TX_DESC_RATE_ID_8822C(d, 9); /* kernel uses RA-group 9 for the inject path */ | ||
| SET_TX_DESC_USE_RATE_8822C(d, 1); | ||
| SET_TX_DESC_DISDATAFB_8822C(d, 0); | ||
| SET_TX_DESC_SW_DEFINE_8822C(d, 1); | ||
| SET_TX_DESC_DISRTSFB_8822C(d, 1); | ||
| SET_TX_DESC_DISDATAFB_8822C(d, 1); | ||
| SET_TX_DESC_DATARATE_8822C(d, rate_hw); | ||
| SET_TX_DESC_DATA_BW_8822C(d, bw); | ||
| /* Data sub-channel: which 20/40 MHz slice of a wider configured channel the | ||
|
|
@@ -170,7 +169,8 @@ inline void fill_data_tx_desc_8822c(uint8_t *d, uint16_t pkt_size, | |
| * descriptor). Inside the checksummed span (0x14) — before the checksum. */ | ||
| if (pwr_ofset_type) | ||
| SET_TX_DESC_TXPWR_OFSET_TYPE_8822C(d, pwr_ofset_type & 0x3); | ||
| SET_TX_DESC_EN_HWSEQ_8822C(d, 1); | ||
| SET_TX_DESC_EN_HWSEQ_8822C(d, 0); | ||
| SET_TX_DESC_SW_SEQ_8822C(d, seqnum & 0x0fff); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocking: wfb-ng manages its own 802.11 sequence numbers, so copying the header seq is correct there. But devourer's demos hardcode seq Suggestion: fall back to the old hwseq behavior when the caller's header seq is 0 ( |
||
| /* USB-agg boundary shim: pkt_offset × 8 bytes of pad between this descriptor | ||
| * and its frame (halmac PKT_OFFSET, unit 8 B). 0 = none (byte-identical). | ||
| * MUST precede the checksum: on the 8822C the checksum span itself extends | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1813,6 +1813,7 @@ size_t RtlJaguar3Device::build_tx_block(const uint8_t *packet, size_t length, | |
|
|
||
| uint8_t fixed_rate = MGN_1M; | ||
| uint8_t sgi = 0, ldpc = 0, stbc = 0; | ||
| uint16_t tx_flags = 0; | ||
| ChannelWidth_t bwidth = CHANNEL_WIDTH_20; | ||
| bool vht = (radiotap_length != 0x0d); | ||
| bool rate_from_radiotap = false; /* did the frame's radiotap carry a rate? */ | ||
|
|
@@ -1837,6 +1838,9 @@ size_t RtlJaguar3Device::build_tx_block(const uint8_t *packet, size_t length, | |
| fixed_rate = *it.this_arg; | ||
| rate_from_radiotap = true; | ||
| break; | ||
| case IEEE80211_RADIOTAP_TX_FLAGS: | ||
| tx_flags = get_unaligned_le16(it.this_arg); | ||
| break; | ||
| case IEEE80211_RADIOTAP_CHANNEL: | ||
| /* 2 x __le16: frequency (MHz), then flags. Frequency is authoritative | ||
| * for the per-packet hop target; flags are ignored (rate/BW come from | ||
|
|
@@ -1964,6 +1968,9 @@ size_t RtlJaguar3Device::build_tx_block(const uint8_t *packet, size_t length, | |
| * the kernel's descriptor for group-addressed frames. */ | ||
| const uint8_t *dot11 = packet + radiotap_length; | ||
| bool bmc = frame_len >= 6 && (dot11[4] & 0x01); | ||
| uint16_t seqnum = 0; | ||
| if (frame_len >= 24) | ||
| seqnum = (get_unaligned_le16(dot11 + 22) >> 4) & 0x0fff; | ||
| /* STBC guard (IRtlDevice contract) — 8822C/8822E are 2T2R so this never | ||
| * fires today, but keeps the invariant uniform across families: never air an | ||
| * STBC frame the chip can't do. */ | ||
|
|
@@ -1975,10 +1982,14 @@ size_t RtlJaguar3Device::build_tx_block(const uint8_t *packet, size_t length, | |
| uint8_t pwr_type = _txpkt_dflt_type.load(std::memory_order_relaxed); | ||
| if (radiotap_pkt_pwr_db != INT_MIN) | ||
| pwr_type = txpkt_type_for_idx(txpkt_idx_for_qdb(radiotap_pkt_pwr_db * 4)); | ||
| /* SVPcom monitor injection maps RADIOTAP_F_TX_NOACK to no MAC retry. | ||
| * wfb-ng sets this for raw-link packets, avoiding a repeated TX burst. */ | ||
| constexpr uint16_t kRadiotapTxNoAck = 0x0008; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Related observation (fine as a follow-up, not this PR): jaguar1 parses |
||
| const bool retry = (tx_flags & kRadiotapTxNoAck) == 0; | ||
| jaguar3::fill_data_tx_desc_8822c( | ||
| out, static_cast<uint16_t>(frame_len), MRateToHwRate(fixed_rate), rate_id, | ||
| bw_desc, sgi != 0, ldpc != 0, stbc, bmc, ndpa, data_sc, pwr_type, | ||
| pkt_offset); | ||
| pkt_offset, retry, seqnum); | ||
| if (_cfg.tx.report) { | ||
| /* DEVOURER_TX_REPORT: SPE_RPT asks the fw for a per-frame CCX TX report; | ||
| * the report echoes SW_DEFINE's low byte, so stamp a rotating tag for | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -220,7 +220,21 @@ static void test_desc_8822c() { | |
| jaguar3::fill_data_tx_desc_8822c(blk, 1500, 7, 9, 0, false, false, 0, | ||
| /*bmc=*/false, /*ndpa=*/false, | ||
| /*data_sc=*/0, /*pwr_ofset_type=*/0, | ||
| /*pkt_offset=*/1); | ||
| /*pkt_offset=*/1, /*retry=*/false, | ||
| /*seqnum=*/0xabc); | ||
| CHECK((blk[0x0d] & 0x06) == 0x06, | ||
| "8822e: forced-rate fallback bits=0x%02x want DISRTSFB|DISDATAFB", | ||
| blk[0x0d] & 0x06); | ||
| CHECK((blk[0x12] & 0x02) != 0 && (blk[0x12] & 0xfc) == 0, | ||
| "8822e: TX_NOACK retry descriptor byte=0x%02x want enable/limit=0", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good coverage of the |
||
| blk[0x12]); | ||
| CHECK((blk[0x21] & 0x80) == 0 && | ||
| LE_BITS_TO_4BYTE(blk + 0x24, 12, 12) == 0xabc, | ||
| "8822e: SW sequence mismatch (hwseq=%u swseq=%u)", | ||
| (blk[0x21] >> 7) & 1, LE_BITS_TO_4BYTE(blk + 0x24, 12, 12)); | ||
| CHECK(LE_BITS_TO_4BYTE(blk + 0x08, 24, 6) == 0 && | ||
| LE_BITS_TO_4BYTE(blk + 0x18, 0, 12) == 0, | ||
| "8822e: injected frame must leave G_ID/SW_DEFINE at the SVP defaults"); | ||
| CHECK((blk[0x07] & 0x1f) == 1, "8822c: pkt_offset field=%u want 1", | ||
| blk[0x07] & 0x1f); | ||
| const uint16_t ck_pad0 = static_cast<uint16_t>(blk[0x1C] | (blk[0x1D] << 8)); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocking: this silently disables the jaguar3 hardware-ARQ loop for every devourer consumer.
All in-tree radiotap producers stamp
TX_FLAGSNOACK unconditionally (RadiotapBuilder'skTxFlagsNoAck, andexamples/tx's hand-rolled headers with0x08) — including the QoS-Data soliciting path thatSetAckResponder+tests/ack_txreport_matrix.shbuild on, where the MAC is supposed to retransmit until the hardware ACK arrives. Measured on an 8812CU: master pinsretries_max=12on unanswered unicast, this branch readsretries_max=0, and the matrix's off-phase check (retries_max >= 8) now fails.The NOACK semantics are right for wfb-ng (it sets the flag deliberately per link). The problem is only that devourer's demos treat NOACK as boilerplate. Suggested resolution — either:
ack_txreport_matrix.shin this PR, orTX_FLAGSfield (keep the current 12, or 6, when the field is absent), so existing consumers keep their contract and wfb-ng gets the new one.Either is fine — it just has to be a deliberate change, not a side effect.