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

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.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents ed48cfed cd634549
...@@ -44,6 +44,7 @@ enum ice_protocol_type { ...@@ -44,6 +44,7 @@ enum ice_protocol_type {
ICE_GTP, ICE_GTP,
ICE_GTP_NO_PAY, ICE_GTP_NO_PAY,
ICE_PPPOE, ICE_PPPOE,
ICE_L2TPV3,
ICE_VLAN_EX, ICE_VLAN_EX,
ICE_VLAN_IN, ICE_VLAN_IN,
ICE_VXLAN_GPE, ICE_VXLAN_GPE,
...@@ -111,6 +112,7 @@ enum ice_prot_id { ...@@ -111,6 +112,7 @@ enum ice_prot_id {
#define ICE_UDP_ILOS_HW 53 #define ICE_UDP_ILOS_HW 53
#define ICE_GRE_OF_HW 64 #define ICE_GRE_OF_HW 64
#define ICE_PPPOE_HW 103 #define ICE_PPPOE_HW 103
#define ICE_L2TPV3_HW 104
#define ICE_UDP_OF_HW 52 /* UDP Tunnels */ #define ICE_UDP_OF_HW 52 /* UDP Tunnels */
#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */ #define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
...@@ -217,6 +219,11 @@ struct ice_pppoe_hdr { ...@@ -217,6 +219,11 @@ struct ice_pppoe_hdr {
__be16 ppp_prot_id; /* control and data only */ __be16 ppp_prot_id; /* control and data only */
}; };
struct ice_l2tpv3_sess_hdr {
__be32 session_id;
__be64 cookie;
};
struct ice_nvgre_hdr { struct ice_nvgre_hdr {
__be16 flags; __be16 flags;
__be16 protocol; __be16 protocol;
...@@ -235,6 +242,7 @@ union ice_prot_hdr { ...@@ -235,6 +242,7 @@ union ice_prot_hdr {
struct ice_nvgre_hdr nvgre_hdr; struct ice_nvgre_hdr nvgre_hdr;
struct ice_udp_gtp_hdr gtp_hdr; struct ice_udp_gtp_hdr gtp_hdr;
struct ice_pppoe_hdr pppoe_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 /* This is mapping table entry that maps every word within a given protocol
......
...@@ -42,6 +42,7 @@ enum { ...@@ -42,6 +42,7 @@ enum {
ICE_PKT_GTP_NOPAY = BIT(8), ICE_PKT_GTP_NOPAY = BIT(8),
ICE_PKT_KMALLOC = BIT(9), ICE_PKT_KMALLOC = BIT(9),
ICE_PKT_PPPOE = BIT(10), ICE_PKT_PPPOE = BIT(10),
ICE_PKT_L2TPV3 = BIT(11),
}; };
struct ice_dummy_pkt_offsets { struct ice_dummy_pkt_offsets {
...@@ -1258,6 +1259,65 @@ ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = { ...@@ -1258,6 +1259,65 @@ ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = {
0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 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[] = { 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_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
ICE_PKT_GTP_NOPAY), ICE_PKT_GTP_NOPAY),
...@@ -1297,6 +1357,8 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = { ...@@ -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_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
ICE_PKT_INNER_IPV6 | ICE_PKT_INNER_IPV6 |
ICE_PKT_INNER_TCP), 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_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP | ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
ICE_PKT_INNER_IPV6), ICE_PKT_INNER_IPV6),
...@@ -4490,6 +4552,7 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { ...@@ -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, { 8, 10, 12, 14, 16, 18, 20, 22 } },
{ ICE_GTP_NO_PAY, { 8, 10, 12, 14 } }, { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
{ ICE_PPPOE, { 0, 2, 4, 6 } }, { ICE_PPPOE, { 0, 2, 4, 6 } },
{ ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } },
{ ICE_VLAN_EX, { 2, 0 } }, { ICE_VLAN_EX, { 2, 0 } },
{ ICE_VLAN_IN, { 2, 0 } }, { ICE_VLAN_IN, { 2, 0 } },
}; };
...@@ -4513,6 +4576,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { ...@@ -4513,6 +4576,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
{ ICE_GTP, ICE_UDP_OF_HW }, { ICE_GTP, ICE_UDP_OF_HW },
{ ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW }, { ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW },
{ ICE_PPPOE, ICE_PPPOE_HW }, { ICE_PPPOE, ICE_PPPOE_HW },
{ ICE_L2TPV3, ICE_L2TPV3_HW },
{ ICE_VLAN_EX, ICE_VLAN_OF_HW }, { ICE_VLAN_EX, ICE_VLAN_OF_HW },
{ ICE_VLAN_IN, ICE_VLAN_OL_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, ...@@ -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 == if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
htons(PPP_IPV6)) htons(PPP_IPV6))
match |= ICE_PKT_OUTER_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) 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, ...@@ -5697,6 +5762,9 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
case ICE_PPPOE: case ICE_PPPOE:
len = sizeof(struct ice_pppoe_hdr); len = sizeof(struct ice_pppoe_hdr);
break; break;
case ICE_L2TPV3:
len = sizeof(struct ice_l2tpv3_sess_hdr);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -71,6 +71,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ...@@ -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)) if (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))
lkups_cnt++; 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? */ /* is L4 (TCP/UDP/any other L4 protocol fields) specified? */
if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT | if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
ICE_TC_FLWR_FIELD_SRC_L4_PORT)) ICE_TC_FLWR_FIELD_SRC_L4_PORT))
...@@ -515,6 +519,17 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, ...@@ -515,6 +519,17 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
i++; 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 */ /* copy L4 (src, dest) port */
if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT | if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
ICE_TC_FLWR_FIELD_SRC_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, ...@@ -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_IP) |
BIT(FLOW_DISSECTOR_KEY_ENC_IP) | BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
BIT(FLOW_DISSECTOR_KEY_PORTS) | 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"); NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1351,6 +1367,15 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, ...@@ -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); 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)) { if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
struct flow_match_ports match; struct flow_match_ports match;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define ICE_TC_FLWR_FIELD_IP_TTL BIT(23) #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_TOS BIT(24)
#define ICE_TC_FLWR_FIELD_ENC_IP_TTL BIT(25) #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 #define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
...@@ -86,6 +87,10 @@ struct ice_tc_l3_hdr { ...@@ -86,6 +87,10 @@ struct ice_tc_l3_hdr {
u8 ttl; u8 ttl;
}; };
struct ice_tc_l2tpv3_hdr {
__be32 session_id;
};
struct ice_tc_l4_hdr { struct ice_tc_l4_hdr {
__be16 dst_port; __be16 dst_port;
__be16 src_port; __be16 src_port;
...@@ -98,6 +103,7 @@ struct ice_tc_flower_lyr_2_4_hdrs { ...@@ -98,6 +103,7 @@ struct ice_tc_flower_lyr_2_4_hdrs {
struct ice_tc_vlan_hdr vlan_hdr; struct ice_tc_vlan_hdr vlan_hdr;
struct ice_tc_vlan_hdr cvlan_hdr; struct ice_tc_vlan_hdr cvlan_hdr;
struct ice_tc_pppoe_hdr pppoe_hdr; struct ice_tc_pppoe_hdr pppoe_hdr;
struct ice_tc_l2tpv3_hdr l2tpv3_hdr;
/* L3 (IPv4[6]) layer fields with their mask */ /* L3 (IPv4[6]) layer fields with their mask */
struct ice_tc_l3_hdr l3_key; struct ice_tc_l3_hdr l3_key;
struct ice_tc_l3_hdr l3_mask; struct ice_tc_l3_hdr l3_mask;
......
...@@ -289,6 +289,14 @@ struct flow_dissector_key_pppoe { ...@@ -289,6 +289,14 @@ struct flow_dissector_key_pppoe {
__be16 type; __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 { enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */ FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */ FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
...@@ -320,6 +328,7 @@ enum flow_dissector_key_id { ...@@ -320,6 +328,7 @@ enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */ 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_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */
FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */ FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */
FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
FLOW_DISSECTOR_KEY_MAX, FLOW_DISSECTOR_KEY_MAX,
}; };
......
...@@ -80,6 +80,10 @@ struct flow_match_pppoe { ...@@ -80,6 +80,10 @@ struct flow_match_pppoe {
struct flow_dissector_key_pppoe *key, *mask; struct flow_dissector_key_pppoe *key, *mask;
}; };
struct flow_match_l2tpv3 {
struct flow_dissector_key_l2tpv3 *key, *mask;
};
struct flow_rule; struct flow_rule;
void flow_rule_match_meta(const struct flow_rule *rule, void flow_rule_match_meta(const struct flow_rule *rule,
...@@ -128,6 +132,8 @@ void flow_rule_match_ct(const struct flow_rule *rule, ...@@ -128,6 +132,8 @@ void flow_rule_match_ct(const struct flow_rule *rule,
struct flow_match_ct *out); struct flow_match_ct *out);
void flow_rule_match_pppoe(const struct flow_rule *rule, void flow_rule_match_pppoe(const struct flow_rule *rule,
struct flow_match_pppoe *out); struct flow_match_pppoe *out);
void flow_rule_match_l2tpv3(const struct flow_rule *rule,
struct flow_match_l2tpv3 *out);
enum flow_action_id { enum flow_action_id {
FLOW_ACTION_ACCEPT = 0, FLOW_ACTION_ACCEPT = 0,
......
...@@ -68,6 +68,8 @@ enum { ...@@ -68,6 +68,8 @@ enum {
#define IPPROTO_PIM IPPROTO_PIM #define IPPROTO_PIM IPPROTO_PIM
IPPROTO_COMP = 108, /* Compression Header Protocol */ IPPROTO_COMP = 108, /* Compression Header Protocol */
#define IPPROTO_COMP IPPROTO_COMP #define IPPROTO_COMP IPPROTO_COMP
IPPROTO_L2TP = 115, /* Layer 2 Tunnelling Protocol */
#define IPPROTO_L2TP IPPROTO_L2TP
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
#define IPPROTO_SCTP IPPROTO_SCTP #define IPPROTO_SCTP IPPROTO_SCTP
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/in6.h> #include <linux/in6.h>
#define IPPROTO_L2TP 115
/** /**
* struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets * struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets
* @l2tp_family: address family number AF_L2TPIP. * @l2tp_family: address family number AF_L2TPIP.
......
...@@ -592,6 +592,8 @@ enum { ...@@ -592,6 +592,8 @@ enum {
TCA_FLOWER_KEY_PPPOE_SID, /* be16 */ TCA_FLOWER_KEY_PPPOE_SID, /* be16 */
TCA_FLOWER_KEY_PPP_PROTO, /* be16 */ TCA_FLOWER_KEY_PPP_PROTO, /* be16 */
TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */
__TCA_FLOWER_MAX, __TCA_FLOWER_MAX,
}; };
......
...@@ -204,6 +204,30 @@ static void __skb_flow_dissect_icmp(const struct sk_buff *skb, ...@@ -204,6 +204,30 @@ static void __skb_flow_dissect_icmp(const struct sk_buff *skb,
skb_flow_get_icmp_tci(skb, key_icmp, data, thoff, hlen); skb_flow_get_icmp_tci(skb, key_icmp, data, thoff, hlen);
} }
static void __skb_flow_dissect_l2tpv3(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container, const void *data,
int nhoff, int hlen)
{
struct flow_dissector_key_l2tpv3 *key_l2tpv3;
struct {
__be32 session_id;
} *hdr, _hdr;
if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_L2TPV3))
return;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
return;
key_l2tpv3 = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_L2TPV3,
target_container);
key_l2tpv3->session_id = hdr->session_id;
}
void skb_flow_dissect_meta(const struct sk_buff *skb, void skb_flow_dissect_meta(const struct sk_buff *skb,
struct flow_dissector *flow_dissector, struct flow_dissector *flow_dissector,
void *target_container) void *target_container)
...@@ -1501,6 +1525,10 @@ bool __skb_flow_dissect(const struct net *net, ...@@ -1501,6 +1525,10 @@ bool __skb_flow_dissect(const struct net *net,
__skb_flow_dissect_icmp(skb, flow_dissector, target_container, __skb_flow_dissect_icmp(skb, flow_dissector, target_container,
data, nhoff, hlen); data, nhoff, hlen);
break; break;
case IPPROTO_L2TP:
__skb_flow_dissect_l2tpv3(skb, flow_dissector, target_container,
data, nhoff, hlen);
break;
default: default:
break; break;
......
...@@ -237,6 +237,13 @@ void flow_rule_match_pppoe(const struct flow_rule *rule, ...@@ -237,6 +237,13 @@ void flow_rule_match_pppoe(const struct flow_rule *rule,
} }
EXPORT_SYMBOL(flow_rule_match_pppoe); EXPORT_SYMBOL(flow_rule_match_pppoe);
void flow_rule_match_l2tpv3(const struct flow_rule *rule,
struct flow_match_l2tpv3 *out)
{
FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_L2TPV3, out);
}
EXPORT_SYMBOL(flow_rule_match_l2tpv3);
struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb, struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
void *cb_ident, void *cb_priv, void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv)) void (*release)(void *cb_priv))
......
...@@ -69,6 +69,7 @@ struct fl_flow_key { ...@@ -69,6 +69,7 @@ struct fl_flow_key {
struct flow_dissector_key_hash hash; struct flow_dissector_key_hash hash;
struct flow_dissector_key_num_of_vlans num_of_vlans; struct flow_dissector_key_num_of_vlans num_of_vlans;
struct flow_dissector_key_pppoe pppoe; struct flow_dissector_key_pppoe pppoe;
struct flow_dissector_key_l2tpv3 l2tpv3;
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
struct fl_flow_mask_range { struct fl_flow_mask_range {
...@@ -712,6 +713,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { ...@@ -712,6 +713,7 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
[TCA_FLOWER_KEY_NUM_OF_VLANS] = { .type = NLA_U8 }, [TCA_FLOWER_KEY_NUM_OF_VLANS] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_PPPOE_SID] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_PPPOE_SID] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_PPP_PROTO] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_PPP_PROTO] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_L2TPV3_SID] = { .type = NLA_U32 },
}; };
...@@ -1790,6 +1792,11 @@ static int fl_set_key(struct net *net, struct nlattr **tb, ...@@ -1790,6 +1792,11 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
fl_set_key_val(tb, key->arp.tha, TCA_FLOWER_KEY_ARP_THA, fl_set_key_val(tb, key->arp.tha, TCA_FLOWER_KEY_ARP_THA,
mask->arp.tha, TCA_FLOWER_KEY_ARP_THA_MASK, mask->arp.tha, TCA_FLOWER_KEY_ARP_THA_MASK,
sizeof(key->arp.tha)); sizeof(key->arp.tha));
} else if (key->basic.ip_proto == IPPROTO_L2TP) {
fl_set_key_val(tb, &key->l2tpv3.session_id,
TCA_FLOWER_KEY_L2TPV3_SID,
&mask->l2tpv3.session_id, TCA_FLOWER_UNSPEC,
sizeof(key->l2tpv3.session_id));
} }
if (key->basic.ip_proto == IPPROTO_TCP || if (key->basic.ip_proto == IPPROTO_TCP ||
...@@ -1970,6 +1977,8 @@ static void fl_init_dissector(struct flow_dissector *dissector, ...@@ -1970,6 +1977,8 @@ static void fl_init_dissector(struct flow_dissector *dissector,
FLOW_DISSECTOR_KEY_NUM_OF_VLANS, num_of_vlans); FLOW_DISSECTOR_KEY_NUM_OF_VLANS, num_of_vlans);
FL_KEY_SET_IF_MASKED(mask, keys, cnt, FL_KEY_SET_IF_MASKED(mask, keys, cnt,
FLOW_DISSECTOR_KEY_PPPOE, pppoe); FLOW_DISSECTOR_KEY_PPPOE, pppoe);
FL_KEY_SET_IF_MASKED(mask, keys, cnt,
FLOW_DISSECTOR_KEY_L2TPV3, l2tpv3);
skb_flow_dissector_init(dissector, keys, cnt); skb_flow_dissector_init(dissector, keys, cnt);
} }
...@@ -3196,6 +3205,13 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net, ...@@ -3196,6 +3205,13 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
mask->arp.tha, TCA_FLOWER_KEY_ARP_THA_MASK, mask->arp.tha, TCA_FLOWER_KEY_ARP_THA_MASK,
sizeof(key->arp.tha)))) sizeof(key->arp.tha))))
goto nla_put_failure; goto nla_put_failure;
else if (key->basic.ip_proto == IPPROTO_L2TP &&
fl_dump_key_val(skb, &key->l2tpv3.session_id,
TCA_FLOWER_KEY_L2TPV3_SID,
&mask->l2tpv3.session_id,
TCA_FLOWER_UNSPEC,
sizeof(key->l2tpv3.session_id)))
goto nla_put_failure;
if ((key->basic.ip_proto == IPPROTO_TCP || if ((key->basic.ip_proto == IPPROTO_TCP ||
key->basic.ip_proto == IPPROTO_UDP || key->basic.ip_proto == IPPROTO_UDP ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment