Commit 42e53b44 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'ice-l2tpv3-offload-support'

Tony Nguyen says:

====================
ice: L2TPv3 offload support

Wojciech Drewek says:

Add support for dissecting L2TPv3 session id in flow dissector. Add support
for this field in tc-flower and support offloading L2TPv3. Finally, add
support for hardware offload of L2TPv3 packets based on session id in
switchdev mode in ice driver.

Example filter:
  # tc filter add dev $PF1 ingress prio 1 protocol ip \
      flower \
        ip_proto l2tp \
        l2tpv3_sid 1234 \
        skip_sw \
      action mirred egress redirect dev $VF1_PR

Changes in iproute2 are required to use the new fields.

ICE COMMS DDP package is required to create a filter in ice.
COMMS DDP package contains profiles of more advanced protocols.
Without COMMS DDP package hw offload will not work, however
sw offload will still work.
====================

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


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents ed48cfed cd634549
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ enum ice_protocol_type {
	ICE_GTP,
	ICE_GTP_NO_PAY,
	ICE_PPPOE,
	ICE_L2TPV3,
	ICE_VLAN_EX,
	ICE_VLAN_IN,
	ICE_VXLAN_GPE,
@@ -111,6 +112,7 @@ enum ice_prot_id {
#define ICE_UDP_ILOS_HW		53
#define ICE_GRE_OF_HW		64
#define ICE_PPPOE_HW		103
#define ICE_L2TPV3_HW		104

#define ICE_UDP_OF_HW	52 /* UDP Tunnels */
#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
@@ -217,6 +219,11 @@ struct ice_pppoe_hdr {
	__be16 ppp_prot_id; /* control and data only */
};

struct ice_l2tpv3_sess_hdr {
	__be32 session_id;
	__be64 cookie;
};

struct ice_nvgre_hdr {
	__be16 flags;
	__be16 protocol;
@@ -235,6 +242,7 @@ union ice_prot_hdr {
	struct ice_nvgre_hdr nvgre_hdr;
	struct ice_udp_gtp_hdr gtp_hdr;
	struct ice_pppoe_hdr pppoe_hdr;
	struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr;
};

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

struct ice_dummy_pkt_offsets {
@@ -1258,6 +1259,65 @@ ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = {
	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv4_l2tpv3) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_IPV4_OFOS,	14 },
	{ ICE_L2TPV3,		34 },
	{ ICE_PROTOCOL_LAST,	0 },
};

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

	0x08, 0x00,		/* ICE_ETYPE_OL 12 */

	0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
	0x00, 0x00, 0x40, 0x00,
	0x40, 0x73, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00,

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

ICE_DECLARE_PKT_OFFSETS(ipv6_l2tpv3) = {
	{ ICE_MAC_OFOS,		0 },
	{ ICE_ETYPE_OL,		12 },
	{ ICE_IPV6_OFOS,	14 },
	{ ICE_L2TPV3,		54 },
	{ ICE_PROTOCOL_LAST,	0 },
};

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

	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */

	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */
	0x00, 0x0c, 0x73, 0x40,
	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_L2TPV3 54 */
	0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 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),
@@ -1297,6 +1357,8 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
	ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
					  ICE_PKT_INNER_IPV6 |
					  ICE_PKT_INNER_TCP),
	ICE_PKT_PROFILE(ipv6_l2tpv3, ICE_PKT_L2TPV3 | ICE_PKT_OUTER_IPV6),
	ICE_PKT_PROFILE(ipv4_l2tpv3, ICE_PKT_L2TPV3),
	ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
	ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
					  ICE_PKT_INNER_IPV6),
@@ -4490,6 +4552,7 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
	{ 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_L2TPV3,		{ 0, 2, 4, 6, 8, 10 } },
	{ ICE_VLAN_EX,          { 2, 0 } },
	{ ICE_VLAN_IN,          { 2, 0 } },
};
@@ -4513,6 +4576,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
	{ ICE_GTP,		ICE_UDP_OF_HW },
	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
	{ ICE_PPPOE,		ICE_PPPOE_HW },
	{ ICE_L2TPV3,		ICE_L2TPV3_HW },
	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
};
@@ -5596,7 +5660,8 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
			    htons(PPP_IPV6))
				match |= ICE_PKT_OUTER_IPV6;
		}
		} else if (lkups[i].type == ICE_L2TPV3)
			match |= ICE_PKT_L2TPV3;
	}

	while (ret->match && (match & ret->match) != ret->match)
@@ -5697,6 +5762,9 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
		case ICE_PPPOE:
			len = sizeof(struct ice_pppoe_hdr);
			break;
		case ICE_L2TPV3:
			len = sizeof(struct ice_l2tpv3_sess_hdr);
			break;
		default:
			return -EINVAL;
		}
+26 −1
Original line number Diff line number Diff line
@@ -71,6 +71,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
	if (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))
		lkups_cnt++;

	/* are L2TPv3 options specified? */
	if (flags & ICE_TC_FLWR_FIELD_L2TPV3_SESSID)
		lkups_cnt++;

	/* is L4 (TCP/UDP/any other L4 protocol fields) specified? */
	if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
		     ICE_TC_FLWR_FIELD_SRC_L4_PORT))
@@ -515,6 +519,17 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
		i++;
	}

	if (flags & ICE_TC_FLWR_FIELD_L2TPV3_SESSID) {
		list[i].type = ICE_L2TPV3;

		list[i].h_u.l2tpv3_sess_hdr.session_id =
			headers->l2tpv3_hdr.session_id;
		list[i].m_u.l2tpv3_sess_hdr.session_id =
			cpu_to_be32(0xFFFFFFFF);

		i++;
	}

	/* copy L4 (src, dest) port */
	if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
		     ICE_TC_FLWR_FIELD_SRC_L4_PORT)) {
@@ -1168,7 +1183,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
	      BIT(FLOW_DISSECTOR_KEY_IP) |
	      BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
	      BIT(FLOW_DISSECTOR_KEY_PORTS) |
	      BIT(FLOW_DISSECTOR_KEY_PPPOE))) {
	      BIT(FLOW_DISSECTOR_KEY_PPPOE) |
	      BIT(FLOW_DISSECTOR_KEY_L2TPV3))) {
		NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used");
		return -EOPNOTSUPP;
	}
@@ -1351,6 +1367,15 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
		ice_tc_set_tos_ttl(&match, fltr, headers, false);
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_L2TPV3)) {
		struct flow_match_l2tpv3 match;

		flow_rule_match_l2tpv3(rule, &match);

		fltr->flags |= ICE_TC_FLWR_FIELD_L2TPV3_SESSID;
		headers->l2tpv3_hdr.session_id = match.key->session_id;
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
		struct flow_match_ports match;

+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define ICE_TC_FLWR_FIELD_IP_TTL		BIT(23)
#define ICE_TC_FLWR_FIELD_ENC_IP_TOS		BIT(24)
#define ICE_TC_FLWR_FIELD_ENC_IP_TTL		BIT(25)
#define ICE_TC_FLWR_FIELD_L2TPV3_SESSID		BIT(26)

#define ICE_TC_FLOWER_MASK_32   0xFFFFFFFF

@@ -86,6 +87,10 @@ struct ice_tc_l3_hdr {
	u8 ttl;
};

struct ice_tc_l2tpv3_hdr {
	__be32 session_id;
};

struct ice_tc_l4_hdr {
	__be16 dst_port;
	__be16 src_port;
@@ -98,6 +103,7 @@ struct ice_tc_flower_lyr_2_4_hdrs {
	struct ice_tc_vlan_hdr vlan_hdr;
	struct ice_tc_vlan_hdr cvlan_hdr;
	struct ice_tc_pppoe_hdr pppoe_hdr;
	struct ice_tc_l2tpv3_hdr l2tpv3_hdr;
	/* L3 (IPv4[6]) layer fields with their mask */
	struct ice_tc_l3_hdr l3_key;
	struct ice_tc_l3_hdr l3_mask;
+9 −0
Original line number Diff line number Diff line
@@ -289,6 +289,14 @@ struct flow_dissector_key_pppoe {
	__be16 type;
};

/**
 * struct flow_dissector_key_l2tpv3:
 * @session_id: identifier for a l2tp session
 */
struct flow_dissector_key_l2tpv3 {
	__be32 session_id;
};

enum flow_dissector_key_id {
	FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
	FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
@@ -320,6 +328,7 @@ enum flow_dissector_key_id {
	FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */
	FLOW_DISSECTOR_KEY_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */
	FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */
	FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */

	FLOW_DISSECTOR_KEY_MAX,
};
Loading