/* record the flow_vm_vlan bits as they are a key part to the hash */
flow_vm_vlan = ntohl(input.dword);
/* generate common hash dword */
hi_hash_dword = ntohl(common.dword);
/* low dword is word swapped version of common */
lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
/* apply flow ID/VM pool/VLAN ID bits to hash words */
hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
/* Process bits 0 and 16 */
TXGBE_COMPUTE_SIG_HASH_ITERATION(0);
/* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to *delaythisbecausebit0ofthestreamshouldnotbeprocessed *sowedonotaddtheVLANuntilafterbit0wasprocessed
*/
lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
/* Process remaining 30 bit of the key */ for (i = 1; i <= 15; i++)
TXGBE_COMPUTE_SIG_HASH_ITERATION(i);
/* combine common_hash result with signature and bucket hashes */
bucket_hash ^= common_hash;
bucket_hash &= TXGBE_ATR_HASH_MASK;
/* Apply masks to input data */ for (i = 0; i < 11; i++)
input->dword_stream[i] &= input_mask->dword_stream[i];
/* record the flow_vm_vlan bits as they are a key part to the hash */
flow_vm_vlan = ntohl(input->dword_stream[0]);
/* generate common hash dword */ for (i = 1; i <= 10; i++)
hi_dword ^= input->dword_stream[i];
hi_hash_dword = ntohl(hi_dword);
/* low dword is word swapped version of common */
lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
/* apply flow ID/VM pool/VLAN ID bits to hash words */
hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
/* Process bits 0 and 16 */
TXGBE_COMPUTE_BKT_HASH_ITERATION(0);
/* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to *delaythisbecausebit0ofthestreamshouldnotbeprocessed *sowedonotaddtheVLANuntilafterbit0wasprocessed
*/
lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
/* Process remaining 30 bit of the key */ for (i = 1; i <= 15; i++)
TXGBE_COMPUTE_BKT_HASH_ITERATION(i);
/* Limit hash to 13 bits since max bucket count is 8K. *Storeresultattheendoftheinputstream.
*/
input->formatted.bkt_hash = (__force __be16)(bucket_hash & 0x1FFF);
}
/** *txgbe_fdir_add_signature_filter-Addsasignaturehashfilter *@wx:pointertohardwarestructure *@input:uniqueinputdword *@common:compressedcommoninputdword *@queue:queueindextodirecttrafficto * *@return:0onsuccessandnegativeonfailure
**/ staticint txgbe_fdir_add_signature_filter(struct wx *wx, union txgbe_atr_hash_dword input, union txgbe_atr_hash_dword common,
u8 queue)
{
u32 fdirhashcmd, fdircmd;
u8 flow_type; int err;
/* Get the flow_type in order to program FDIRCMD properly *lowest2bitsareFDIRCMD.L4TYPE,thirdlowestbitisFDIRCMD.IPV6 *fifthisFDIRCMD.TUNNEL_FILTER
*/
flow_type = input.formatted.flow_type; switch (flow_type) { case TXGBE_ATR_FLOW_TYPE_TCPV4: case TXGBE_ATR_FLOW_TYPE_UDPV4: case TXGBE_ATR_FLOW_TYPE_SCTPV4: case TXGBE_ATR_FLOW_TYPE_TCPV6: case TXGBE_ATR_FLOW_TYPE_UDPV6: case TXGBE_ATR_FLOW_TYPE_SCTPV6: break; default:
wx_err(wx, "Error on flow type input\n"); return -EINVAL;
}
/* skip this packet since it is invalid or the socket is closing */ if (!th || th->fin) return;
/* sample on all syn packets or once every atr sample count */ if (!th->syn && ring->atr_count < ring->atr_sample_rate) return;
/* reset sample count */
ring->atr_count = 0;
/* src and dst are inverted, think how the receiver sees them * *Theinputisbrokenintotwosections,anon-compressedsection *containingvm_pool,vlan_id,andflow_type.Therestofthedata *isXORedtogetherandstoredinthecompresseddword.
*/
input.formatted.vlan_id = htons((u16)ptype);
/* since src port and flex bytes occupy the same word XOR them together *andwritethevaluetosourceportportionofcompresseddword
*/ if (first->tx_flags & WX_TX_FLAGS_SW_VLAN)
common.port.src ^= th->dest ^ first->skb->protocol; elseif (first->tx_flags & WX_TX_FLAGS_HW_VLAN)
common.port.src ^= th->dest ^ first->skb->vlan_proto; else
common.port.src ^= th->dest ^ first->protocol;
common.port.dst ^= th->source;
/* This assumes the Rx queue and Tx queue are bound to the same CPU */
txgbe_fdir_add_signature_filter(q_vector->wx, input, common,
ring->queue_index);
}
int txgbe_fdir_set_input_mask(struct wx *wx, union txgbe_atr_input *input_mask)
{
u32 fdirm = 0, fdirtcpm = 0, flex = 0; int index, offset;
/* Program the relevant mask registers. If src/dst_port or src/dst_addr *arezero,thenassumeafullmaskforthatfield.Alsoassumethat *aVLANof0isunspecified,somaskthatoutaswell.L4type *cannotbemaskedoutinthisimplementation. * *ThisalsoassumesIPv4only.IPv6maskingisn'tsupportedatthis *pointintime.
*/
/* verify bucket hash is cleared on hash generation */ if (input_mask->formatted.bkt_hash)
wx_dbg(wx, "bucket hash should always be 0 in mask\n");
/* Program FDIRM and verify partial masks */ switch (input_mask->formatted.vm_pool & 0x7F) { case0x0:
fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_POOL; break; case0x7F: break; default:
wx_err(wx, "Error on vm pool mask\n"); return -EINVAL;
}
switch (input_mask->formatted.flow_type & TXGBE_ATR_L4TYPE_MASK) { case0x0:
fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_L4P; if (input_mask->formatted.dst_port ||
input_mask->formatted.src_port) {
wx_err(wx, "Error on src/dst port mask\n"); return -EINVAL;
} break; case TXGBE_ATR_L4TYPE_MASK: break; default:
wx_err(wx, "Error on flow type mask\n"); return -EINVAL;
}
/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
wr32(wx, TXGBE_RDB_FDIR_OTHER_MSK, fdirm);
/* store the TCP/UDP port masks, bit reversed from port layout */
fdirtcpm = ntohs(input_mask->formatted.dst_port);
fdirtcpm <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT;
fdirtcpm |= ntohs(input_mask->formatted.src_port);
/* write both the same so that UDP and TCP use the same mask */
wr32(wx, TXGBE_RDB_FDIR_TCP_MSK, ~fdirtcpm);
wr32(wx, TXGBE_RDB_FDIR_UDP_MSK, ~fdirtcpm);
wr32(wx, TXGBE_RDB_FDIR_SCTP_MSK, ~fdirtcpm);
/* store source and destination IP masks (little-enian) */
wr32(wx, TXGBE_RDB_FDIR_SA4_MSK,
ntohl(~input_mask->formatted.src_ip[0]));
wr32(wx, TXGBE_RDB_FDIR_DA4_MSK,
ntohl(~input_mask->formatted.dst_ip[0]));
return0;
}
int txgbe_fdir_write_perfect_filter(struct wx *wx, union txgbe_atr_input *input,
u16 soft_id, u8 queue)
{
u32 fdirport, fdirvlan, fdirhash, fdircmd; int err = 0;
/* currently IPv6 is not supported, must be programmed with 0 */
wr32(wx, TXGBE_RDB_FDIR_IP6(2), ntohl(input->formatted.src_ip[0]));
wr32(wx, TXGBE_RDB_FDIR_IP6(1), ntohl(input->formatted.src_ip[1]));
wr32(wx, TXGBE_RDB_FDIR_IP6(0), ntohl(input->formatted.src_ip[2]));
/* record the source address (little-endian) */
wr32(wx, TXGBE_RDB_FDIR_SA, ntohl(input->formatted.src_ip[0]));
/* record the first 32 bits of the destination address *(little-endian)
*/
wr32(wx, TXGBE_RDB_FDIR_DA, ntohl(input->formatted.dst_ip[0]));
/* record source and destination port (little-endian)*/
fdirport = ntohs(input->formatted.dst_port);
fdirport <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT;
fdirport |= ntohs(input->formatted.src_port);
wr32(wx, TXGBE_RDB_FDIR_PORT, fdirport);
/* record packet type and flex_bytes (little-endian) */
fdirvlan = ntohs(input->formatted.flex_bytes);
fdirvlan <<= TXGBE_RDB_FDIR_FLEX_FLEX_SHIFT;
fdirvlan |= ntohs(input->formatted.vlan_id);
wr32(wx, TXGBE_RDB_FDIR_FLEX, fdirvlan);
/* Prime the keys for hashing */
wr32(wx, TXGBE_RDB_FDIR_HKEY, TXGBE_ATR_BUCKET_HASH_KEY);
wr32(wx, TXGBE_RDB_FDIR_SKEY, TXGBE_ATR_SIGNATURE_HASH_KEY);
wr32(wx, TXGBE_RDB_FDIR_CTL, fdirctrl);
WX_WRITE_FLUSH(wx);
ret = read_poll_timeout(rd32, val, val & TXGBE_RDB_FDIR_CTL_INIT_DONE, 1000, 10000, false, wx, TXGBE_RDB_FDIR_CTL);
if (ret < 0)
wx_dbg(wx, "Flow Director poll time exceeded!\n");
}
/** *txgbe_init_fdir_signature-InitializeFlowDirectorsigfilters *@wx:pointertohardwarestructure
**/ staticvoid txgbe_init_fdir_signature(struct wx *wx)
{
u32 fdirctrl = TXGBE_FDIR_PBALLOC_64K; int index = VMDQ_P(0) / 4; int offset = VMDQ_P(0) % 4;
u32 flex = 0;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert. 2026-10-03)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.