Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f66fd2dd authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'skb_hash'



Tom Herbert says:

====================
net: Add rxhash utility hash functions

v3:

There's really nothing specific about rxhash that constrains
it to be a value just for these receive path. Drop the 'rx'
part in utility functions, including skb_get_rxhash. In subsequent
patches, we can change the rxhash and l4_rxhash names also, as
well as abstracting out the interface to the hash.

Added comments about hash types per feedback.

In this version I'm omitting the changes to drivers to make the
patch set manageable. Will add those changes in followup pathes.

-----
This patch series introduce skb_set_rxhash and skb_clear_rxhash
which are called to set the rxhash (from network drivers) and
to clear the rxhash. This API should be used instead of updating
fields in the skbuff directly.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1aee6cc2 3df7a74e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
		goto out;

	/* Check if we can use flow to select a queue */
	rxq = skb_get_rxhash(skb);
	rxq = skb_get_hash(skb);
	if (rxq) {
		tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
		goto out;
+2 −2
Original line number Diff line number Diff line
@@ -358,7 +358,7 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
	rcu_read_lock();
	numqueues = ACCESS_ONCE(tun->numqueues);

	txq = skb_get_rxhash(skb);
	txq = skb_get_hash(skb);
	if (txq) {
		e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
		if (e)
@@ -1146,7 +1146,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
	skb_reset_network_header(skb);
	skb_probe_transport_header(skb, 0);

	rxhash = skb_get_rxhash(skb);
	rxhash = skb_get_hash(skb);
	netif_rx_ni(skb);

	tun->dev->stats.rx_packets++;
+1 −1
Original line number Diff line number Diff line
@@ -1405,7 +1405,7 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
	unsigned int range = (port_max - port_min) + 1;
	u32 hash;

	hash = skb_get_rxhash(skb);
	hash = skb_get_hash(skb);
	if (!hash)
		hash = jhash(skb->data, 2 * ETH_ALEN,
			     (__force u32) skb->protocol);
+61 −3
Original line number Diff line number Diff line
@@ -703,15 +703,73 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
			   unsigned int to, struct ts_config *config,
			   struct ts_state *state);

void __skb_get_rxhash(struct sk_buff *skb);
static inline __u32 skb_get_rxhash(struct sk_buff *skb)
/*
 * Packet hash types specify the type of hash in skb_set_hash.
 *
 * Hash types refer to the protocol layer addresses which are used to
 * construct a packet's hash. The hashes are used to differentiate or identify
 * flows of the protocol layer for the hash type. Hash types are either
 * layer-2 (L2), layer-3 (L3), or layer-4 (L4).
 *
 * Properties of hashes:
 *
 * 1) Two packets in different flows have different hash values
 * 2) Two packets in the same flow should have the same hash value
 *
 * A hash at a higher layer is considered to be more specific. A driver should
 * set the most specific hash possible.
 *
 * A driver cannot indicate a more specific hash than the layer at which a hash
 * was computed. For instance an L3 hash cannot be set as an L4 hash.
 *
 * A driver may indicate a hash level which is less specific than the
 * actual layer the hash was computed on. For instance, a hash computed
 * at L4 may be considered an L3 hash. This should only be done if the
 * driver can't unambiguously determine that the HW computed the hash at
 * the higher layer. Note that the "should" in the second property above
 * permits this.
 */
enum pkt_hash_types {
	PKT_HASH_TYPE_NONE,	/* Undefined type */
	PKT_HASH_TYPE_L2,	/* Input: src_MAC, dest_MAC */
	PKT_HASH_TYPE_L3,	/* Input: src_IP, dst_IP */
	PKT_HASH_TYPE_L4,	/* Input: src_IP, dst_IP, src_port, dst_port */
};

static inline void
skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
{
	skb->l4_rxhash = (type == PKT_HASH_TYPE_L4);
	skb->rxhash = hash;
}

void __skb_get_hash(struct sk_buff *skb);
static inline __u32 skb_get_hash(struct sk_buff *skb)
{
	if (!skb->l4_rxhash)
		__skb_get_rxhash(skb);
		__skb_get_hash(skb);

	return skb->rxhash;
}

static inline void skb_clear_hash(struct sk_buff *skb)
{
	skb->rxhash = 0;
	skb->l4_rxhash = 0;
}

static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
{
	if (!skb->l4_rxhash)
		skb_clear_hash(skb);
}

static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
{
	to->rxhash = from->rxhash;
	to->l4_rxhash = from->l4_rxhash;
};

#ifdef NET_SKBUFF_DATA_USES_OFFSET
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
+2 −3
Original line number Diff line number Diff line
@@ -322,12 +322,11 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
	skb->dev = dev;

	/*
	 * Clear rxhash so that we can recalulate the hash for the
	 * Clear hash so that we can recalulate the hash for the
	 * encapsulated packet, unless we have already determine the hash
	 * over the L4 4-tuple.
	 */
	if (!skb->l4_rxhash)
		skb->rxhash = 0;
	skb_clear_hash_if_not_l4(skb);
	skb_set_queue_mapping(skb, 0);
	skb_scrub_packet(skb, !net_eq(net, dev_net(dev)));
}
Loading