Skip to content

Commit 42e53b4

Browse files
author
Paolo Abeni
committed
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/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents ed48cfe + cd63454 commit 42e53b4

File tree

12 files changed

+179
-4
lines changed

12 files changed

+179
-4
lines changed

drivers/net/ethernet/intel/ice/ice_protocol_type.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum ice_protocol_type {
4444
ICE_GTP,
4545
ICE_GTP_NO_PAY,
4646
ICE_PPPOE,
47+
ICE_L2TPV3,
4748
ICE_VLAN_EX,
4849
ICE_VLAN_IN,
4950
ICE_VXLAN_GPE,
@@ -111,6 +112,7 @@ enum ice_prot_id {
111112
#define ICE_UDP_ILOS_HW 53
112113
#define ICE_GRE_OF_HW 64
113114
#define ICE_PPPOE_HW 103
115+
#define ICE_L2TPV3_HW 104
114116

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

222+
struct ice_l2tpv3_sess_hdr {
223+
__be32 session_id;
224+
__be64 cookie;
225+
};
226+
220227
struct ice_nvgre_hdr {
221228
__be16 flags;
222229
__be16 protocol;
@@ -235,6 +242,7 @@ union ice_prot_hdr {
235242
struct ice_nvgre_hdr nvgre_hdr;
236243
struct ice_udp_gtp_hdr gtp_hdr;
237244
struct ice_pppoe_hdr pppoe_hdr;
245+
struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr;
238246
};
239247

240248
/* This is mapping table entry that maps every word within a given protocol

drivers/net/ethernet/intel/ice/ice_switch.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum {
4242
ICE_PKT_GTP_NOPAY = BIT(8),
4343
ICE_PKT_KMALLOC = BIT(9),
4444
ICE_PKT_PPPOE = BIT(10),
45+
ICE_PKT_L2TPV3 = BIT(11),
4546
};
4647

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

1262+
ICE_DECLARE_PKT_OFFSETS(ipv4_l2tpv3) = {
1263+
{ ICE_MAC_OFOS, 0 },
1264+
{ ICE_ETYPE_OL, 12 },
1265+
{ ICE_IPV4_OFOS, 14 },
1266+
{ ICE_L2TPV3, 34 },
1267+
{ ICE_PROTOCOL_LAST, 0 },
1268+
};
1269+
1270+
ICE_DECLARE_PKT_TEMPLATE(ipv4_l2tpv3) = {
1271+
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1272+
0x00, 0x00, 0x00, 0x00,
1273+
0x00, 0x00, 0x00, 0x00,
1274+
1275+
0x08, 0x00, /* ICE_ETYPE_OL 12 */
1276+
1277+
0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
1278+
0x00, 0x00, 0x40, 0x00,
1279+
0x40, 0x73, 0x00, 0x00,
1280+
0x00, 0x00, 0x00, 0x00,
1281+
0x00, 0x00, 0x00, 0x00,
1282+
1283+
0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */
1284+
0x00, 0x00, 0x00, 0x00,
1285+
0x00, 0x00, 0x00, 0x00,
1286+
0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1287+
};
1288+
1289+
ICE_DECLARE_PKT_OFFSETS(ipv6_l2tpv3) = {
1290+
{ ICE_MAC_OFOS, 0 },
1291+
{ ICE_ETYPE_OL, 12 },
1292+
{ ICE_IPV6_OFOS, 14 },
1293+
{ ICE_L2TPV3, 54 },
1294+
{ ICE_PROTOCOL_LAST, 0 },
1295+
};
1296+
1297+
ICE_DECLARE_PKT_TEMPLATE(ipv6_l2tpv3) = {
1298+
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1299+
0x00, 0x00, 0x00, 0x00,
1300+
0x00, 0x00, 0x00, 0x00,
1301+
1302+
0x86, 0xDD, /* ICE_ETYPE_OL 12 */
1303+
1304+
0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */
1305+
0x00, 0x0c, 0x73, 0x40,
1306+
0x00, 0x00, 0x00, 0x00,
1307+
0x00, 0x00, 0x00, 0x00,
1308+
0x00, 0x00, 0x00, 0x00,
1309+
0x00, 0x00, 0x00, 0x00,
1310+
0x00, 0x00, 0x00, 0x00,
1311+
0x00, 0x00, 0x00, 0x00,
1312+
0x00, 0x00, 0x00, 0x00,
1313+
0x00, 0x00, 0x00, 0x00,
1314+
1315+
0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */
1316+
0x00, 0x00, 0x00, 0x00,
1317+
0x00, 0x00, 0x00, 0x00,
1318+
0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1319+
};
1320+
12611321
static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
12621322
ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
12631323
ICE_PKT_GTP_NOPAY),
@@ -1297,6 +1357,8 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
12971357
ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
12981358
ICE_PKT_INNER_IPV6 |
12991359
ICE_PKT_INNER_TCP),
1360+
ICE_PKT_PROFILE(ipv6_l2tpv3, ICE_PKT_L2TPV3 | ICE_PKT_OUTER_IPV6),
1361+
ICE_PKT_PROFILE(ipv4_l2tpv3, ICE_PKT_L2TPV3),
13001362
ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
13011363
ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
13021364
ICE_PKT_INNER_IPV6),
@@ -4490,6 +4552,7 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
44904552
{ ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } },
44914553
{ ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
44924554
{ ICE_PPPOE, { 0, 2, 4, 6 } },
4555+
{ ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } },
44934556
{ ICE_VLAN_EX, { 2, 0 } },
44944557
{ ICE_VLAN_IN, { 2, 0 } },
44954558
};
@@ -4513,6 +4576,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
45134576
{ ICE_GTP, ICE_UDP_OF_HW },
45144577
{ ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW },
45154578
{ ICE_PPPOE, ICE_PPPOE_HW },
4579+
{ ICE_L2TPV3, ICE_L2TPV3_HW },
45164580
{ ICE_VLAN_EX, ICE_VLAN_OF_HW },
45174581
{ ICE_VLAN_IN, ICE_VLAN_OL_HW },
45184582
};
@@ -5596,7 +5660,8 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
55965660
if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
55975661
htons(PPP_IPV6))
55985662
match |= ICE_PKT_OUTER_IPV6;
5599-
}
5663+
} else if (lkups[i].type == ICE_L2TPV3)
5664+
match |= ICE_PKT_L2TPV3;
56005665
}
56015666

56025667
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,
56975762
case ICE_PPPOE:
56985763
len = sizeof(struct ice_pppoe_hdr);
56995764
break;
5765+
case ICE_L2TPV3:
5766+
len = sizeof(struct ice_l2tpv3_sess_hdr);
5767+
break;
57005768
default:
57015769
return -EINVAL;
57025770
}

drivers/net/ethernet/intel/ice/ice_tc_lib.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
7171
if (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))
7272
lkups_cnt++;
7373

74+
/* are L2TPv3 options specified? */
75+
if (flags & ICE_TC_FLWR_FIELD_L2TPV3_SESSID)
76+
lkups_cnt++;
77+
7478
/* is L4 (TCP/UDP/any other L4 protocol fields) specified? */
7579
if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
7680
ICE_TC_FLWR_FIELD_SRC_L4_PORT))
@@ -515,6 +519,17 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
515519
i++;
516520
}
517521

522+
if (flags & ICE_TC_FLWR_FIELD_L2TPV3_SESSID) {
523+
list[i].type = ICE_L2TPV3;
524+
525+
list[i].h_u.l2tpv3_sess_hdr.session_id =
526+
headers->l2tpv3_hdr.session_id;
527+
list[i].m_u.l2tpv3_sess_hdr.session_id =
528+
cpu_to_be32(0xFFFFFFFF);
529+
530+
i++;
531+
}
532+
518533
/* copy L4 (src, dest) port */
519534
if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
520535
ICE_TC_FLWR_FIELD_SRC_L4_PORT)) {
@@ -1168,7 +1183,8 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
11681183
BIT(FLOW_DISSECTOR_KEY_IP) |
11691184
BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
11701185
BIT(FLOW_DISSECTOR_KEY_PORTS) |
1171-
BIT(FLOW_DISSECTOR_KEY_PPPOE))) {
1186+
BIT(FLOW_DISSECTOR_KEY_PPPOE) |
1187+
BIT(FLOW_DISSECTOR_KEY_L2TPV3))) {
11721188
NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used");
11731189
return -EOPNOTSUPP;
11741190
}
@@ -1351,6 +1367,15 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
13511367
ice_tc_set_tos_ttl(&match, fltr, headers, false);
13521368
}
13531369

1370+
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_L2TPV3)) {
1371+
struct flow_match_l2tpv3 match;
1372+
1373+
flow_rule_match_l2tpv3(rule, &match);
1374+
1375+
fltr->flags |= ICE_TC_FLWR_FIELD_L2TPV3_SESSID;
1376+
headers->l2tpv3_hdr.session_id = match.key->session_id;
1377+
}
1378+
13541379
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
13551380
struct flow_match_ports match;
13561381

drivers/net/ethernet/intel/ice/ice_tc_lib.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define ICE_TC_FLWR_FIELD_IP_TTL BIT(23)
3131
#define ICE_TC_FLWR_FIELD_ENC_IP_TOS BIT(24)
3232
#define ICE_TC_FLWR_FIELD_ENC_IP_TTL BIT(25)
33+
#define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26)
3334

3435
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
3536

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

90+
struct ice_tc_l2tpv3_hdr {
91+
__be32 session_id;
92+
};
93+
8994
struct ice_tc_l4_hdr {
9095
__be16 dst_port;
9196
__be16 src_port;
@@ -98,6 +103,7 @@ struct ice_tc_flower_lyr_2_4_hdrs {
98103
struct ice_tc_vlan_hdr vlan_hdr;
99104
struct ice_tc_vlan_hdr cvlan_hdr;
100105
struct ice_tc_pppoe_hdr pppoe_hdr;
106+
struct ice_tc_l2tpv3_hdr l2tpv3_hdr;
101107
/* L3 (IPv4[6]) layer fields with their mask */
102108
struct ice_tc_l3_hdr l3_key;
103109
struct ice_tc_l3_hdr l3_mask;

include/net/flow_dissector.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,14 @@ struct flow_dissector_key_pppoe {
289289
__be16 type;
290290
};
291291

292+
/**
293+
* struct flow_dissector_key_l2tpv3:
294+
* @session_id: identifier for a l2tp session
295+
*/
296+
struct flow_dissector_key_l2tpv3 {
297+
__be32 session_id;
298+
};
299+
292300
enum flow_dissector_key_id {
293301
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
294302
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
@@ -320,6 +328,7 @@ enum flow_dissector_key_id {
320328
FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */
321329
FLOW_DISSECTOR_KEY_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */
322330
FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */
331+
FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
323332

324333
FLOW_DISSECTOR_KEY_MAX,
325334
};

include/net/flow_offload.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ struct flow_match_pppoe {
8080
struct flow_dissector_key_pppoe *key, *mask;
8181
};
8282

83+
struct flow_match_l2tpv3 {
84+
struct flow_dissector_key_l2tpv3 *key, *mask;
85+
};
86+
8387
struct flow_rule;
8488

8589
void flow_rule_match_meta(const struct flow_rule *rule,
@@ -128,6 +132,8 @@ void flow_rule_match_ct(const struct flow_rule *rule,
128132
struct flow_match_ct *out);
129133
void flow_rule_match_pppoe(const struct flow_rule *rule,
130134
struct flow_match_pppoe *out);
135+
void flow_rule_match_l2tpv3(const struct flow_rule *rule,
136+
struct flow_match_l2tpv3 *out);
131137

132138
enum flow_action_id {
133139
FLOW_ACTION_ACCEPT = 0,

include/uapi/linux/in.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ enum {
6868
#define IPPROTO_PIM IPPROTO_PIM
6969
IPPROTO_COMP = 108, /* Compression Header Protocol */
7070
#define IPPROTO_COMP IPPROTO_COMP
71+
IPPROTO_L2TP = 115, /* Layer 2 Tunnelling Protocol */
72+
#define IPPROTO_L2TP IPPROTO_L2TP
7173
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
7274
#define IPPROTO_SCTP IPPROTO_SCTP
7375
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */

include/uapi/linux/l2tp.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include <linux/in.h>
1414
#include <linux/in6.h>
1515

16-
#define IPPROTO_L2TP 115
17-
1816
/**
1917
* struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets
2018
* @l2tp_family: address family number AF_L2TPIP.

include/uapi/linux/pkt_cls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,8 @@ enum {
592592
TCA_FLOWER_KEY_PPPOE_SID, /* be16 */
593593
TCA_FLOWER_KEY_PPP_PROTO, /* be16 */
594594

595+
TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */
596+
595597
__TCA_FLOWER_MAX,
596598
};
597599

net/core/flow_dissector.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,30 @@ static void __skb_flow_dissect_icmp(const struct sk_buff *skb,
204204
skb_flow_get_icmp_tci(skb, key_icmp, data, thoff, hlen);
205205
}
206206

207+
static void __skb_flow_dissect_l2tpv3(const struct sk_buff *skb,
208+
struct flow_dissector *flow_dissector,
209+
void *target_container, const void *data,
210+
int nhoff, int hlen)
211+
{
212+
struct flow_dissector_key_l2tpv3 *key_l2tpv3;
213+
struct {
214+
__be32 session_id;
215+
} *hdr, _hdr;
216+
217+
if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_L2TPV3))
218+
return;
219+
220+
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
221+
if (!hdr)
222+
return;
223+
224+
key_l2tpv3 = skb_flow_dissector_target(flow_dissector,
225+
FLOW_DISSECTOR_KEY_L2TPV3,
226+
target_container);
227+
228+
key_l2tpv3->session_id = hdr->session_id;
229+
}
230+
207231
void skb_flow_dissect_meta(const struct sk_buff *skb,
208232
struct flow_dissector *flow_dissector,
209233
void *target_container)
@@ -1501,6 +1525,10 @@ bool __skb_flow_dissect(const struct net *net,
15011525
__skb_flow_dissect_icmp(skb, flow_dissector, target_container,
15021526
data, nhoff, hlen);
15031527
break;
1528+
case IPPROTO_L2TP:
1529+
__skb_flow_dissect_l2tpv3(skb, flow_dissector, target_container,
1530+
data, nhoff, hlen);
1531+
break;
15041532

15051533
default:
15061534
break;

net/core/flow_offload.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ void flow_rule_match_pppoe(const struct flow_rule *rule,
237237
}
238238
EXPORT_SYMBOL(flow_rule_match_pppoe);
239239

240+
void flow_rule_match_l2tpv3(const struct flow_rule *rule,
241+
struct flow_match_l2tpv3 *out)
242+
{
243+
FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_L2TPV3, out);
244+
}
245+
EXPORT_SYMBOL(flow_rule_match_l2tpv3);
246+
240247
struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
241248
void *cb_ident, void *cb_priv,
242249
void (*release)(void *cb_priv))

0 commit comments

Comments
 (0)