Commit 7d85e9cb authored by Paolo Abeni's avatar Paolo Abeni
Browse files
Tony Nguyen says:

====================
ice: PPPoE offload support

Marcin Szycik says:

Add support for dissecting PPPoE and PPP-specific fields in flow dissector:
PPPoE session id and PPP protocol type. Add support for those fields in
tc-flower and support offloading PPPoE. Finally, add support for hardware
offload of PPPoE packets in switchdev mode in ice driver.

Example filter:
tc filter add dev $PF1 ingress protocol ppp_ses prio 1 flower pppoe_sid \
    1234 ppp_proto ip skip_sw action mirred egress redirect dev $VF1_PR

Changes in iproute2 are required to use the new fields (will be submitted
soon).

ICE COMMS DDP package is required to create a filter in ice.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  ice: Add support for PPPoE hardware offload
  flow_offload: Introduce flow_match_pppoe
  net/sched: flower: Add PPPoE filter
  flow_dissector: Add PPPoE dissectors
====================

Link: https://lore.kernel.org/r/20220726203133.2171332-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 5f10376b cd8efeee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#include <net/udp_tunnel.h>
#include <net/vxlan.h>
#include <net/gtp.h>
#include <linux/ppp_defs.h>
#include "ice_devids.h"
#include "ice_type.h"
#include "ice_txrx.h"
+4 −1
Original line number Diff line number Diff line
@@ -1964,8 +1964,11 @@ ice_get_sw_fv_list(struct ice_hw *hw, struct ice_prot_lkup_ext *lkups,
			}
		}
	} while (fv);
	if (list_empty(fv_list))
	if (list_empty(fv_list)) {
		dev_warn(ice_hw_to_dev(hw), "Required profiles not found in currently loaded DDP package");
		return -EIO;
	}

	return 0;

err:
+11 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ enum ice_protocol_type {
	ICE_NVGRE,
	ICE_GTP,
	ICE_GTP_NO_PAY,
	ICE_PPPOE,
	ICE_VLAN_EX,
	ICE_VLAN_IN,
	ICE_VXLAN_GPE,
@@ -109,6 +110,7 @@ enum ice_prot_id {
#define ICE_TCP_IL_HW		49
#define ICE_UDP_ILOS_HW		53
#define ICE_GRE_OF_HW		64
#define ICE_PPPOE_HW		103

#define ICE_UDP_OF_HW	52 /* UDP Tunnels */
#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
@@ -207,6 +209,14 @@ struct ice_udp_gtp_hdr {
	u8 rsvrd;
};

struct ice_pppoe_hdr {
	u8 rsrvd_ver_type;
	u8 rsrvd_code;
	__be16 session_id;
	__be16 length;
	__be16 ppp_prot_id; /* control and data only */
};

struct ice_nvgre_hdr {
	__be16 flags;
	__be16 protocol;
@@ -224,6 +234,7 @@ union ice_prot_hdr {
	struct ice_udp_tnl_hdr tnl_hdr;
	struct ice_nvgre_hdr nvgre_hdr;
	struct ice_udp_gtp_hdr gtp_hdr;
	struct ice_pppoe_hdr pppoe_hdr;
};

/* This is mapping table entry that maps every word within a given protocol
+165 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ enum {
	ICE_PKT_INNER_UDP	= BIT(7),
	ICE_PKT_GTP_NOPAY	= BIT(8),
	ICE_PKT_KMALLOC		= BIT(9),
	ICE_PKT_PPPOE		= BIT(10),
};

struct ice_dummy_pkt_offsets {
@@ -1109,6 +1110,154 @@ ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
	0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_tcp) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_PPPOE,		14 },
	{ ICE_IPV4_OFOS,	22 },
	{ ICE_TCP_IL,		42 },
	{ ICE_PROTOCOL_LAST,	0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_tcp) = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x88, 0x64,		/* ICE_ETYPE_OL 12 */

	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
	0x00, 0x16,

	0x00, 0x21,		/* PPP Link Layer 20 */

	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 22 */
	0x00, 0x01, 0x00, 0x00,
	0x00, 0x06, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 42 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_udp) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_PPPOE,		14 },
	{ ICE_IPV4_OFOS,	22 },
	{ ICE_UDP_ILOS,		42 },
	{ ICE_PROTOCOL_LAST,	0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_udp) = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x88, 0x64,		/* ICE_ETYPE_OL 12 */

	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
	0x00, 0x16,

	0x00, 0x21,		/* PPP Link Layer 20 */

	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */
	0x00, 0x01, 0x00, 0x00,
	0x00, 0x11, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_tcp) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_PPPOE,		14 },
	{ ICE_IPV6_OFOS,	22 },
	{ ICE_TCP_IL,		62 },
	{ ICE_PROTOCOL_LAST,	0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_tcp) = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x88, 0x64,		/* ICE_ETYPE_OL 12 */

	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
	0x00, 0x2a,

	0x00, 0x57,		/* PPP Link Layer 20 */

	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 62 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x50, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_udp) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_PPPOE,		14 },
	{ ICE_IPV6_OFOS,	22 },
	{ ICE_UDP_ILOS,		62 },
	{ ICE_PROTOCOL_LAST,	0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = {
	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x88, 0x64,		/* ICE_ETYPE_OL 12 */

	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
	0x00, 0x2a,

	0x00, 0x57,		/* PPP Link Layer 20 */

	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
	0x00, 0x08, 0x11, 0x00, /* Next header UDP*/
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */
	0x00, 0x08, 0x00, 0x00,

	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
};

static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
				  ICE_PKT_GTP_NOPAY),
@@ -1135,6 +1284,11 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
	ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 |
					ICE_PKT_INNER_UDP),
	ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6),
	ICE_PKT_PROFILE(pppoe_ipv4_udp, ICE_PKT_PPPOE | ICE_PKT_INNER_UDP),
	ICE_PKT_PROFILE(pppoe_ipv4_tcp, ICE_PKT_PPPOE),
	ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 |
				      ICE_PKT_INNER_TCP),
	ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP),
@@ -4480,6 +4634,7 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
	{ ICE_NVGRE,		{ 0, 2, 4, 6 } },
	{ ICE_GTP,		{ 8, 10, 12, 14, 16, 18, 20, 22 } },
	{ ICE_GTP_NO_PAY,	{ 8, 10, 12, 14 } },
	{ ICE_PPPOE,		{ 0, 2, 4, 6 } },
	{ ICE_VLAN_EX,          { 2, 0 } },
	{ ICE_VLAN_IN,          { 2, 0 } },
};
@@ -4502,6 +4657,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
	{ ICE_NVGRE,		ICE_GRE_OF_HW },
	{ ICE_GTP,		ICE_UDP_OF_HW },
	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
	{ ICE_PPPOE,		ICE_PPPOE_HW },
	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
};
@@ -5580,6 +5736,12 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
			match |= ICE_PKT_INNER_IPV6;
		else if (lkups[i].type == ICE_GTP_NO_PAY)
			match |= ICE_PKT_GTP_NOPAY;
		else if (lkups[i].type == ICE_PPPOE) {
			match |= ICE_PKT_PPPOE;
			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
			    htons(PPP_IPV6))
				match |= ICE_PKT_OUTER_IPV6;
		}
	}

	while (ret->match && (match & ret->match) != ret->match)
@@ -5677,6 +5839,9 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		case ICE_GTP:
			len = sizeof(struct ice_udp_gtp_hdr);
			break;
		case ICE_PPPOE:
			len = sizeof(struct ice_pppoe_hdr);
			break;
		default:
			return -EINVAL;
		}
+70 −1
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
	if (flags & ICE_TC_FLWR_FIELD_CVLAN)
		lkups_cnt++;

	/* are PPPoE options specified? */
	if (flags & (ICE_TC_FLWR_FIELD_PPPOE_SESSID |
		     ICE_TC_FLWR_FIELD_PPP_PROTO))
		lkups_cnt++;

	/* are IPv[4|6] fields specified? */
	if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 | ICE_TC_FLWR_FIELD_SRC_IPV4 |
		     ICE_TC_FLWR_FIELD_DEST_IPV6 | ICE_TC_FLWR_FIELD_SRC_IPV6))
@@ -350,6 +355,28 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
		i++;
	}

	if (flags & (ICE_TC_FLWR_FIELD_PPPOE_SESSID |
		     ICE_TC_FLWR_FIELD_PPP_PROTO)) {
		struct ice_pppoe_hdr *vals, *masks;

		vals = &list[i].h_u.pppoe_hdr;
		masks = &list[i].m_u.pppoe_hdr;

		list[i].type = ICE_PPPOE;

		if (flags & ICE_TC_FLWR_FIELD_PPPOE_SESSID) {
			vals->session_id = headers->pppoe_hdr.session_id;
			masks->session_id = cpu_to_be16(0xFFFF);
		}

		if (flags & ICE_TC_FLWR_FIELD_PPP_PROTO) {
			vals->ppp_prot_id = headers->pppoe_hdr.ppp_proto;
			masks->ppp_prot_id = cpu_to_be16(0xFFFF);
		}

		i++;
	}

	/* copy L3 (IPv[4|6]: src, dest) address */
	if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 |
		     ICE_TC_FLWR_FIELD_SRC_IPV4)) {
@@ -693,6 +720,31 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
	return ret;
}

/**
 * ice_tc_set_pppoe - Parse PPPoE fields from TC flower filter
 * @match: Pointer to flow match structure
 * @fltr: Pointer to filter structure
 * @headers: Pointer to outer header fields
 * @returns PPP protocol used in filter (ppp_ses or ppp_disc)
 */
static u16
ice_tc_set_pppoe(struct flow_match_pppoe *match,
		 struct ice_tc_flower_fltr *fltr,
		 struct ice_tc_flower_lyr_2_4_hdrs *headers)
{
	if (match->mask->session_id) {
		fltr->flags |= ICE_TC_FLWR_FIELD_PPPOE_SESSID;
		headers->pppoe_hdr.session_id = match->key->session_id;
	}

	if (match->mask->ppp_proto) {
		fltr->flags |= ICE_TC_FLWR_FIELD_PPP_PROTO;
		headers->pppoe_hdr.ppp_proto = match->key->ppp_proto;
	}

	return be16_to_cpu(match->key->type);
}

/**
 * ice_tc_set_ipv4 - Parse IPv4 addresses from TC flower filter
 * @match: Pointer to flow match structure
@@ -988,7 +1040,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
	      BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
	      BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) |
	      BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
	      BIT(FLOW_DISSECTOR_KEY_PORTS) |
	      BIT(FLOW_DISSECTOR_KEY_PPPOE))) {
		NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used");
		return -EOPNOTSUPP;
	}
@@ -1124,6 +1177,22 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
			headers->cvlan_hdr.vlan_prio = match.key->vlan_priority;
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PPPOE)) {
		struct flow_match_pppoe match;

		flow_rule_match_pppoe(rule, &match);
		n_proto_key = ice_tc_set_pppoe(&match, fltr, headers);

		/* If ethertype equals ETH_P_PPP_SES, n_proto might be
		 * overwritten by encapsulated protocol (ppp_proto field) or set
		 * to 0. To correct this, flow_match_pppoe provides the type
		 * field, which contains the actual ethertype (ETH_P_PPP_SES).
		 */
		headers->l2_key.n_proto = cpu_to_be16(n_proto_key);
		headers->l2_mask.n_proto = cpu_to_be16(0xFFFF);
		fltr->flags |= ICE_TC_FLWR_FIELD_ETH_TYPE_ID;
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
		struct flow_match_control match;

Loading