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

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

Merge branch 'cls_flower'



Jiri Pirko says:

====================
introduce programable flow dissector and cls_flower

Per Davem's request, I prepared this patchset which introduces programmable
flow dissector. For current users of flow_keys, there is a wrapper
skb_flow_dissect_flow_keys which maintains the previous behaviour.
For purposes of cls_flower, couple of new dissection keys were introduced.

Note that this dissector can be also eventually used by openvswitch code.

Also, as a next step, I plan to get rid of *skb_flow_get_ports(export)
and *__skb_get_poff as their functionality can be now implemented by
skb_flow_dissect as well.

v2->v3:
- remove TCA_FLOWER_POLICE attr suggested by Jamal

v1->v2:
- move __skb_tx_hash rather to dev.c as suggested by Alex
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 212da1fa 77b9900e
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@
#include <net/netns/generic.h>
#include <net/pkt_sched.h>
#include <linux/rculist.h>
#include <net/flow_keys.h>
#include <net/flow_dissector.h>
#include <net/switchdev.h>
#include <net/bonding.h>
#include <net/bond_3ad.h>
@@ -3051,16 +3051,16 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb,
	int noff, proto = -1;

	if (bond->params.xmit_policy > BOND_XMIT_POLICY_LAYER23)
		return skb_flow_dissect(skb, fk);
		return skb_flow_dissect_flow_keys(skb, fk);

	fk->ports = 0;
	fk->ports.ports = 0;
	noff = skb_network_offset(skb);
	if (skb->protocol == htons(ETH_P_IP)) {
		if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph))))
			return false;
		iph = ip_hdr(skb);
		fk->src = iph->saddr;
		fk->dst = iph->daddr;
		fk->addrs.src = iph->saddr;
		fk->addrs.dst = iph->daddr;
		noff += iph->ihl << 2;
		if (!ip_is_fragment(iph))
			proto = iph->protocol;
@@ -3068,15 +3068,15 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb,
		if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph6))))
			return false;
		iph6 = ipv6_hdr(skb);
		fk->src = (__force __be32)ipv6_addr_hash(&iph6->saddr);
		fk->dst = (__force __be32)ipv6_addr_hash(&iph6->daddr);
		fk->addrs.src = (__force __be32)ipv6_addr_hash(&iph6->saddr);
		fk->addrs.dst = (__force __be32)ipv6_addr_hash(&iph6->daddr);
		noff += sizeof(*iph6);
		proto = iph6->nexthdr;
	} else {
		return false;
	}
	if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34 && proto >= 0)
		fk->ports = skb_flow_get_ports(skb, noff, proto);
		fk->ports.ports = skb_flow_get_ports(skb, noff, proto);

	return true;
}
@@ -3102,8 +3102,8 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
	    bond->params.xmit_policy == BOND_XMIT_POLICY_ENCAP23)
		hash = bond_eth_hash(skb);
	else
		hash = (__force u32)flow.ports;
	hash ^= (__force u32)flow.dst ^ (__force u32)flow.src;
		hash = (__force u32)flow.ports.ports;
	hash ^= (__force u32)flow.addrs.dst ^ (__force u32)flow.addrs.src;
	hash ^= (hash >> 16);
	hash ^= (hash >> 8);

+15 −14
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
#include <linux/in.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <net/flow_keys.h>
#include <net/flow_dissector.h>
#include "enic_res.h"
#include "enic_clsf.h"

@@ -22,7 +22,7 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
	int res;
	struct filter data;

	switch (keys->ip_proto) {
	switch (keys->basic.ip_proto) {
	case IPPROTO_TCP:
		data.u.ipv4.protocol = PROTO_TCP;
		break;
@@ -33,10 +33,10 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
		return -EPROTONOSUPPORT;
	};
	data.type = FILTER_IPV4_5TUPLE;
	data.u.ipv4.src_addr = ntohl(keys->src);
	data.u.ipv4.dst_addr = ntohl(keys->dst);
	data.u.ipv4.src_port = ntohs(keys->port16[0]);
	data.u.ipv4.dst_port = ntohs(keys->port16[1]);
	data.u.ipv4.src_addr = ntohl(keys->addrs.src);
	data.u.ipv4.dst_addr = ntohl(keys->addrs.dst);
	data.u.ipv4.src_port = ntohs(keys->ports.src);
	data.u.ipv4.dst_port = ntohs(keys->ports.dst);
	data.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;

	spin_lock_bh(&enic->devcmd_lock);
@@ -158,11 +158,11 @@ static struct enic_rfs_fltr_node *htbl_key_search(struct hlist_head *h,
	struct enic_rfs_fltr_node *tpos;

	hlist_for_each_entry(tpos, h, node)
		if (tpos->keys.src == k->src &&
		    tpos->keys.dst == k->dst &&
		    tpos->keys.ports == k->ports &&
		    tpos->keys.ip_proto == k->ip_proto &&
		    tpos->keys.n_proto == k->n_proto)
		if (tpos->keys.addrs.src == k->addrs.src &&
		    tpos->keys.addrs.dst == k->addrs.dst &&
		    tpos->keys.ports.ports == k->ports.ports &&
		    tpos->keys.basic.ip_proto == k->basic.ip_proto &&
		    tpos->keys.basic.n_proto == k->basic.n_proto)
			return tpos;
	return NULL;
}
@@ -177,9 +177,10 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
	int res, i;

	enic = netdev_priv(dev);
	res = skb_flow_dissect(skb, &keys);
	if (!res || keys.n_proto != htons(ETH_P_IP) ||
	    (keys.ip_proto != IPPROTO_TCP && keys.ip_proto != IPPROTO_UDP))
	res = skb_flow_dissect_flow_keys(skb, &keys);
	if (!res || keys.basic.n_proto != htons(ETH_P_IP) ||
	    (keys.basic.ip_proto != IPPROTO_TCP &&
	     keys.basic.ip_proto != IPPROTO_UDP))
		return -EPROTONOSUPPORT;

	tbl_idx = skb_get_hash_raw(skb) & ENIC_RFS_FLW_MASK;
+5 −5
Original line number Diff line number Diff line
@@ -334,7 +334,7 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
	n = htbl_fltr_search(enic, (u16)fsp->location);
	if (!n)
		return -EINVAL;
	switch (n->keys.ip_proto) {
	switch (n->keys.basic.ip_proto) {
	case IPPROTO_TCP:
		fsp->flow_type = TCP_V4_FLOW;
		break;
@@ -346,16 +346,16 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
		break;
	}

	fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src;
	fsp->h_u.tcp_ip4_spec.ip4src = n->keys.addrs.src;
	fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;

	fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst;
	fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.addrs.dst;
	fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;

	fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0];
	fsp->h_u.tcp_ip4_spec.psrc = n->keys.ports.src;
	fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;

	fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1];
	fsp->h_u.tcp_ip4_spec.pdst = n->keys.ports.dst;
	fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;

	fsp->ring_cookie = n->rq_id;
+4 −4
Original line number Diff line number Diff line
@@ -196,12 +196,12 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
	struct flow_keys flow;
	int data_len;

	if (!skb_flow_dissect(skb, &flow) ||
	    !(flow.n_proto == htons(ETH_P_IP) ||
	      flow.n_proto == htons(ETH_P_IPV6)))
	if (!skb_flow_dissect_flow_keys(skb, &flow) ||
	    !(flow.basic.n_proto == htons(ETH_P_IP) ||
	      flow.basic.n_proto == htons(ETH_P_IPV6)))
		return false;

	if (flow.ip_proto == IPPROTO_TCP)
	if (flow.basic.ip_proto == IPPROTO_TCP)
		data_len = 12;
	else
		data_len = 8;
+3 −0
Original line number Diff line number Diff line
@@ -2832,6 +2832,9 @@ static inline int netif_set_xps_queue(struct net_device *dev,
}
#endif

u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
		  unsigned int num_tx_queues);

/*
 * Returns a Tx hash for the given packet when dev->real_num_tx_queues is used
 * as a distribution range limit for the returned value.
Loading