| --- a/include/net/netfilter/nf_flow_table.h |
| +++ b/include/net/netfilter/nf_flow_table.h |
| @@ -96,6 +96,7 @@ struct flow_offload { |
| #define FLOW_OFFLOAD_PATH_DSA BIT(3) |
| #define FLOW_OFFLOAD_PATH_DSLITE BIT(4) |
| #define FLOW_OFFLOAD_PATH_6RD BIT(5) |
| +#define FLOW_OFFLOAD_PATH_TNL BIT(6) |
| |
| struct flow_offload_hw_path { |
| struct net_device *dev; |
| --- a/net/l2tp/l2tp_ppp.c |
| +++ b/net/l2tp/l2tp_ppp.c |
| @@ -89,6 +89,7 @@ |
| #include <linux/nsproxy.h> |
| #include <net/net_namespace.h> |
| #include <net/netns/generic.h> |
| +#include <net/netfilter/nf_flow_table.h> |
| #include <net/ip.h> |
| #include <net/udp.h> |
| #include <net/inet_common.h> |
| @@ -124,9 +125,14 @@ struct pppol2tp_session { |
| }; |
| |
| static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); |
| +static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan, |
| + struct flow_offload_hw_path *path); |
| |
| static const struct ppp_channel_ops pppol2tp_chan_ops = { |
| .start_xmit = pppol2tp_xmit, |
| +#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) |
| + .flow_offload_check = l2tp_ppp_flow_offload_check, |
| +#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */ |
| }; |
| |
| static const struct proto_ops pppol2tp_ops; |
| @@ -335,6 +341,26 @@ error: |
| return error; |
| } |
| |
| +#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) |
| +static int l2tp_ppp_flow_offload_check(struct ppp_channel *chan, |
| + struct flow_offload_hw_path *path) |
| +{ |
| + struct sock *sk = (struct sock *)chan->private; |
| + struct l2tp_session *session; |
| + |
| + if (path->flags & FLOW_OFFLOAD_PATH_TNL) |
| + return -EEXIST; |
| + |
| + session = pppol2tp_sock_to_session(sk); |
| + if (!session) |
| + return -EINVAL; |
| + |
| + path->flags |= FLOW_OFFLOAD_PATH_TNL; |
| + |
| + return 0; |
| +} |
| +#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */ |
| + |
| /* Transmit function called by generic PPP driver. Sends PPP frame |
| * over PPPoL2TP socket. |
| * |