ipq806x_nss: Updated PPPoE,PPTP,L2TP and GRE patches.
This commit is contained in:
		| @@ -90,7 +90,7 @@ | |||||||
|  { |  { | ||||||
| --- a/include/linux/netdevice.h
 | --- a/include/linux/netdevice.h
 | ||||||
| +++ b/include/linux/netdevice.h
 | +++ b/include/linux/netdevice.h
 | ||||||
| @@ -4699,6 +4699,15 @@ void dev_uc_flush(struct net_device *dev
 | @@ -4681,6 +4681,15 @@ void dev_uc_flush(struct net_device *dev
 | ||||||
|  void dev_uc_init(struct net_device *dev); |  void dev_uc_init(struct net_device *dev); | ||||||
|   |   | ||||||
|  /** |  /** | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -105,7 +105,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  static inline __be16 vlan_proto(const struct sk_buff *skb) |  static inline __be16 vlan_proto(const struct sk_buff *skb) | ||||||
|  { |  { | ||||||
|  	if (skb_vlan_tag_present(skb)) |  	if (skb_vlan_tag_present(skb)) | ||||||
| @@ -1238,6 +1247,12 @@ static struct ctl_table brnf_table[] = { | @@ -1240,6 +1249,12 @@ static struct ctl_table brnf_table[] = { | ||||||
|  		.mode		= 0644, |  		.mode		= 0644, | ||||||
|  		.proc_handler	= brnf_sysctl_call_tables, |  		.proc_handler	= brnf_sysctl_call_tables, | ||||||
|  	}, |  	}, | ||||||
| @@ -118,7 +118,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  	{ } |  	{ } | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -1246,6 +1261,7 @@ static inline void br_netfilter_sysctl_d | @@ -1248,6 +1263,7 @@ static inline void br_netfilter_sysctl_d | ||||||
|  	brnf->call_iptables = 1; |  	brnf->call_iptables = 1; | ||||||
|  	brnf->call_ip6tables = 1; |  	brnf->call_ip6tables = 1; | ||||||
|  	brnf->call_arptables = 1; |  	brnf->call_arptables = 1; | ||||||
| @@ -126,7 +126,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  	brnf->filter_vlan_tagged = 0; |  	brnf->filter_vlan_tagged = 0; | ||||||
|  	brnf->filter_pppoe_tagged = 0; |  	brnf->filter_pppoe_tagged = 0; | ||||||
|  	brnf->pass_vlan_indev = 0; |  	brnf->pass_vlan_indev = 0; | ||||||
| @@ -1269,6 +1285,7 @@ static int br_netfilter_sysctl_init_net( | @@ -1271,6 +1287,7 @@ static int br_netfilter_sysctl_init_net( | ||||||
|  	table[3].data = &brnet->filter_vlan_tagged; |  	table[3].data = &brnet->filter_vlan_tagged; | ||||||
|  	table[4].data = &brnet->filter_pppoe_tagged; |  	table[4].data = &brnet->filter_pppoe_tagged; | ||||||
|  	table[5].data = &brnet->pass_vlan_indev; |  	table[5].data = &brnet->pass_vlan_indev; | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com> | |||||||
|  |  | ||||||
| --- a/include/linux/netdevice.h | --- a/include/linux/netdevice.h | ||||||
| +++ b/include/linux/netdevice.h | +++ b/include/linux/netdevice.h | ||||||
| @@ -3181,6 +3181,8 @@ static inline int dev_direct_xmit(struct | @@ -3163,6 +3163,8 @@ static inline int dev_direct_xmit(struct | ||||||
|  	return ret; |  	return ret; | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  	const struct dst_entry *dst = skb_dst(skb); |  	const struct dst_entry *dst = skb_dst(skb); | ||||||
| --- a/include/net/route.h | --- a/include/net/route.h | ||||||
| +++ b/include/net/route.h | +++ b/include/net/route.h | ||||||
| @@ -237,6 +237,9 @@ struct rtable *rt_dst_alloc(struct net_d | @@ -238,6 +238,9 @@ struct rtable *rt_dst_alloc(struct net_d | ||||||
|  			    unsigned int flags, u16 type, bool noxfrm); |  			    unsigned int flags, u16 type, bool noxfrm); | ||||||
|  struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt); |  struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt); | ||||||
|   |   | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  |  | ||||||
| --- a/include/linux/netdevice.h | --- a/include/linux/netdevice.h | ||||||
| +++ b/include/linux/netdevice.h | +++ b/include/linux/netdevice.h | ||||||
| @@ -2959,6 +2959,8 @@ enum netdev_cmd { | @@ -2939,6 +2939,8 @@ enum netdev_cmd { | ||||||
|  	NETDEV_OFFLOAD_XSTATS_REPORT_USED, |  	NETDEV_OFFLOAD_XSTATS_REPORT_USED, | ||||||
|  	NETDEV_OFFLOAD_XSTATS_REPORT_DELTA, |  	NETDEV_OFFLOAD_XSTATS_REPORT_DELTA, | ||||||
|  	NETDEV_XDP_FEAT_CHANGE, |  	NETDEV_XDP_FEAT_CHANGE, | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  } |  } | ||||||
|   |   | ||||||
|  static inline __be16 vlan_proto(const struct sk_buff *skb) |  static inline __be16 vlan_proto(const struct sk_buff *skb) | ||||||
| @@ -1253,6 +1254,12 @@ static struct ctl_table brnf_table[] = { | @@ -1255,6 +1256,12 @@ static struct ctl_table brnf_table[] = { | ||||||
|  		.mode           = 0644, |  		.mode           = 0644, | ||||||
|  		.proc_handler   = brnf_sysctl_call_tables, |  		.proc_handler   = brnf_sysctl_call_tables, | ||||||
|  	}, |  	}, | ||||||
| @@ -48,7 +48,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  	{ } |  	{ } | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -1262,6 +1269,7 @@ static inline void br_netfilter_sysctl_d | @@ -1264,6 +1271,7 @@ static inline void br_netfilter_sysctl_d | ||||||
|  	brnf->call_ip6tables = 1; |  	brnf->call_ip6tables = 1; | ||||||
|  	brnf->call_arptables = 1; |  	brnf->call_arptables = 1; | ||||||
|  	brnf->call_ebtables = 1; |  	brnf->call_ebtables = 1; | ||||||
| @@ -56,7 +56,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  	brnf->filter_vlan_tagged = 0; |  	brnf->filter_vlan_tagged = 0; | ||||||
|  	brnf->filter_pppoe_tagged = 0; |  	brnf->filter_pppoe_tagged = 0; | ||||||
|  	brnf->pass_vlan_indev = 0; |  	brnf->pass_vlan_indev = 0; | ||||||
| @@ -1286,6 +1294,7 @@ static int br_netfilter_sysctl_init_net( | @@ -1288,6 +1296,7 @@ static int br_netfilter_sysctl_init_net( | ||||||
|  	table[4].data = &brnet->filter_pppoe_tagged; |  	table[4].data = &brnet->filter_pppoe_tagged; | ||||||
|  	table[5].data = &brnet->pass_vlan_indev; |  	table[5].data = &brnet->pass_vlan_indev; | ||||||
|  	table[6].data = &brnet->call_ebtables; |  	table[6].data = &brnet->call_ebtables; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | |||||||
|  |  | ||||||
| --- a/net/bridge/br_netfilter_hooks.c | --- a/net/bridge/br_netfilter_hooks.c | ||||||
| +++ b/net/bridge/br_netfilter_hooks.c | +++ b/net/bridge/br_netfilter_hooks.c | ||||||
| @@ -1268,8 +1268,8 @@ static inline void br_netfilter_sysctl_d | @@ -1270,8 +1270,8 @@ static inline void br_netfilter_sysctl_d | ||||||
|  	brnf->call_iptables = 1; |  	brnf->call_iptables = 1; | ||||||
|  	brnf->call_ip6tables = 1; |  	brnf->call_ip6tables = 1; | ||||||
|  	brnf->call_arptables = 1; |  	brnf->call_arptables = 1; | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | |||||||
|  	dev->needs_free_netdev = true; |  	dev->needs_free_netdev = true; | ||||||
| --- a/include/linux/netdevice.h | --- a/include/linux/netdevice.h | ||||||
| +++ b/include/linux/netdevice.h | +++ b/include/linux/netdevice.h | ||||||
| @@ -1781,6 +1781,32 @@ enum netdev_priv_flags { | @@ -1761,6 +1761,32 @@ enum netdev_priv_flags { | ||||||
|  	IFF_NO_IP_ALIGN			= BIT_ULL(34), |  	IFF_NO_IP_ALIGN			= BIT_ULL(34), | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
| @@ -87,7 +87,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | |||||||
|  #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN |  #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN | ||||||
|  #define IFF_EBRIDGE			IFF_EBRIDGE |  #define IFF_EBRIDGE			IFF_EBRIDGE | ||||||
|  #define IFF_BONDING			IFF_BONDING |  #define IFF_BONDING			IFF_BONDING | ||||||
| @@ -1901,6 +1927,8 @@ enum netdev_stat_type { | @@ -1881,6 +1907,8 @@ enum netdev_stat_type { | ||||||
|   *	@xdp_features:	XDP capability supported by the device |   *	@xdp_features:	XDP capability supported by the device | ||||||
|   *	@priv_flags:	Like 'flags' but invisible to userspace, |   *	@priv_flags:	Like 'flags' but invisible to userspace, | ||||||
|   *			see if.h for the definitions |   *			see if.h for the definitions | ||||||
| @@ -96,7 +96,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | |||||||
|   *	@gflags:	Global flags ( kept as legacy ) |   *	@gflags:	Global flags ( kept as legacy ) | ||||||
|   *	@padded:	How much padding added by alloc_netdev() |   *	@padded:	How much padding added by alloc_netdev() | ||||||
|   *	@operstate:	RFC2863 operstate |   *	@operstate:	RFC2863 operstate | ||||||
| @@ -2146,6 +2174,7 @@ struct net_device { | @@ -2126,6 +2154,7 @@ struct net_device { | ||||||
|  	unsigned int		flags; |  	unsigned int		flags; | ||||||
|  	xdp_features_t		xdp_features; |  	xdp_features_t		xdp_features; | ||||||
|  	unsigned long long	priv_flags; |  	unsigned long long	priv_flags; | ||||||
| @@ -104,7 +104,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | |||||||
|  	const struct net_device_ops *netdev_ops; |  	const struct net_device_ops *netdev_ops; | ||||||
|  	const struct xdp_metadata_ops *xdp_metadata_ops; |  	const struct xdp_metadata_ops *xdp_metadata_ops; | ||||||
|  	int			ifindex; |  	int			ifindex; | ||||||
| @@ -4304,7 +4333,6 @@ static inline bool netif_dormant(const s | @@ -4286,7 +4315,6 @@ static inline bool netif_dormant(const s | ||||||
|  	return test_bit(__LINK_STATE_DORMANT, &dev->state); |  	return test_bit(__LINK_STATE_DORMANT, &dev->state); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -112,7 +112,7 @@ Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | |||||||
|  /** |  /** | ||||||
|   *	netif_testing_on - mark device as under test. |   *	netif_testing_on - mark device as under test. | ||||||
|   *	@dev: network device |   *	@dev: network device | ||||||
| @@ -5256,6 +5284,11 @@ static inline bool netif_is_failover_sla | @@ -5238,6 +5266,11 @@ static inline bool netif_is_failover_sla | ||||||
|  	return dev->priv_flags & IFF_FAILOVER_SLAVE; |  	return dev->priv_flags & IFF_FAILOVER_SLAVE; | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   | |||||||
| @@ -0,0 +1,104 @@ | |||||||
|  | From 7d3846d95a5b5fa800031411d53078f2d775d2e6 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Date: Fri, 16 Jan 2015 16:54:08 -0800 | ||||||
|  | Subject: [PATCH 301/500] ppp: Add PPP channel specific methods for PPTP and | ||||||
|  |  L2TP types. | ||||||
|  |  | ||||||
|  | These methods are required for handling these types of PPP protocols | ||||||
|  | in the acceleration subsystem. | ||||||
|  |  | ||||||
|  | Change-Id: I7967573ee440a96af3f842300e2f021465a0a62c | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/pptp.c | 27 +++++++++++++++++++++++++++ | ||||||
|  |  net/l2tp/l2tp_ppp.c    | 30 ++++++++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 57 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/pptp.c | ||||||
|  | +++ b/drivers/net/ppp/pptp.c | ||||||
|  | @@ -603,9 +603,36 @@ static int pptp_ppp_ioctl(struct ppp_cha | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* pptp_hold_chan() */ | ||||||
|  | +static void pptp_hold_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_hold(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pptp_release_chan() */ | ||||||
|  | +static void pptp_release_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_put(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pptp_get_channel_protocol() | ||||||
|  | + *     Return the protocol type of the PPTP over PPP protocol | ||||||
|  | + */ | ||||||
|  | +static int pptp_get_channel_protocol(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	return PX_PROTO_PPTP; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static const struct ppp_channel_ops pptp_chan_ops = { | ||||||
|  |  	.start_xmit = pptp_xmit, | ||||||
|  |  	.ioctl      = pptp_ppp_ioctl, | ||||||
|  | +	.get_channel_protocol = pptp_get_channel_protocol, | ||||||
|  | +	.hold = pptp_hold_chan, | ||||||
|  | +	.release = pptp_release_chan, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static struct proto pptp_sk_proto __read_mostly = { | ||||||
|  | --- a/net/l2tp/l2tp_ppp.c | ||||||
|  | +++ b/net/l2tp/l2tp_ppp.c | ||||||
|  | @@ -123,9 +123,15 @@ struct pppol2tp_session { | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); | ||||||
|  | +static int pppol2tp_get_channel_protocol(struct ppp_channel *); | ||||||
|  | +static void pppol2tp_hold_chan(struct ppp_channel *); | ||||||
|  | +static void pppol2tp_release_chan(struct ppp_channel *); | ||||||
|  |   | ||||||
|  |  static const struct ppp_channel_ops pppol2tp_chan_ops = { | ||||||
|  |  	.start_xmit =  pppol2tp_xmit, | ||||||
|  | +	.get_channel_protocol = pppol2tp_get_channel_protocol, | ||||||
|  | +	.hold = pppol2tp_hold_chan, | ||||||
|  | +	.release = pppol2tp_release_chan, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const struct proto_ops pppol2tp_ops; | ||||||
|  | @@ -328,6 +334,30 @@ error: | ||||||
|  |  	return error; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* pppol2tp_hold_chan() */ | ||||||
|  | +static void pppol2tp_hold_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_hold(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pppol2tp_release_chan() */ | ||||||
|  | +static void pppol2tp_release_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_put(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pppol2tp_get_channel_protocol() | ||||||
|  | + * Return the protocol type of the L2TP over PPP protocol | ||||||
|  | + */ | ||||||
|  | +static int pppol2tp_get_channel_protocol(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	return PX_PROTO_OL2TP; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* Transmit function called by generic PPP driver.  Sends PPP frame | ||||||
|  |   * over PPPoL2TP socket. | ||||||
|  |   * | ||||||
| @@ -0,0 +1,608 @@ | |||||||
|  | From 16de3e75ec92f88a454725c2e33e22b501c1a873 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Murat Sezgin <quic_msezgin@quicinc.com> | ||||||
|  | Date: Wed, 10 May 2023 13:16:09 -0700 | ||||||
|  | Subject: [PATCH 183/500] ppp: PPPoE acceleration support. | ||||||
|  |  | ||||||
|  | pppoe: Add return value to pppoe addressing get function | ||||||
|  |  | ||||||
|  | If the addressing doesn't have a netdevice, this should be | ||||||
|  | handled as a failure, so that the caller considers that | ||||||
|  | the get function failed. | ||||||
|  |  | ||||||
|  | Change-Id: Ia9a6b0e0f036a3434519d9f2194763486ca04583 | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  |  | ||||||
|  | Added some new APIs to the PPP/PPPoE kernel modules | ||||||
|  | for using from the hardware acceleration connection managers. | ||||||
|  |  | ||||||
|  | Change-Id: I2c16c6d6ccba8ffa14aec077c8dad1681535ae0b | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  |  | ||||||
|  | net: ppp: rx/tx error and dropped pkt stats support | ||||||
|  |  | ||||||
|  | ppp_update_stats functions accepts rx/tx errors and dropped | ||||||
|  | pkt stats args. | ||||||
|  |  | ||||||
|  | Change-Id: Iba2f6ea2114d8a4678254332fec0ef7bc35bed2c | ||||||
|  | Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  |  | ||||||
|  | ppp: Update the last_recv and last_xmit times. | ||||||
|  |  | ||||||
|  | These need to be updated for accelerated connections, so that | ||||||
|  | on demand mode will recognize the active traffic. | ||||||
|  |  | ||||||
|  | Change-Id: I3c0ee4e8f4c3bc4c7ce221e6109bfd82046d11b4 | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  |  | ||||||
|  | ppp: Add channel connect/disconnect notifier. | ||||||
|  |  | ||||||
|  | When a channel is connected or disconnected to a PPP | ||||||
|  | unit, a notification will be sent to the kernel subsystems | ||||||
|  | which are registered to this notifier. Notifier sends | ||||||
|  | the event type (connect or disconnect) along with the | ||||||
|  | PPP netdevice pointer. | ||||||
|  |  | ||||||
|  | Change-Id: I0d592084744c86e1c114ac66da68b214ddff5b5a | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 220 ++++++++++++++++++++++++++++++++++ | ||||||
|  |  drivers/net/ppp/pppoe.c       |  83 ++++++++++++- | ||||||
|  |  include/linux/if_pppox.h      |  16 ++- | ||||||
|  |  include/linux/ppp_channel.h   |  52 ++++++++ | ||||||
|  |  net/l2tp/l2tp_core.c          |  24 ++++ | ||||||
|  |  net/l2tp/l2tp_core.h          |   2 + | ||||||
|  |  6 files changed, 391 insertions(+), 6 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -255,6 +255,24 @@ struct ppp_net { | ||||||
|  |  #define seq_before(a, b)	((s32)((a) - (b)) < 0) | ||||||
|  |  #define seq_after(a, b)		((s32)((a) - (b)) > 0) | ||||||
|  |   | ||||||
|  | +/* | ||||||
|  | + * Registration/Unregistration methods | ||||||
|  | + * for PPP channel connect and disconnect event notifications. | ||||||
|  | + */ | ||||||
|  | +RAW_NOTIFIER_HEAD(ppp_channel_connection_notifier_list); | ||||||
|  | + | ||||||
|  | +void ppp_channel_connection_register_notify(struct notifier_block *nb) | ||||||
|  | +{ | ||||||
|  | +	raw_notifier_chain_register(&ppp_channel_connection_notifier_list, nb); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL_GPL(ppp_channel_connection_register_notify); | ||||||
|  | + | ||||||
|  | +void ppp_channel_connection_unregister_notify(struct notifier_block *nb) | ||||||
|  | +{ | ||||||
|  | +	raw_notifier_chain_unregister(&ppp_channel_connection_notifier_list, nb); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL_GPL(ppp_channel_connection_unregister_notify); | ||||||
|  | + | ||||||
|  |  /* Prototypes. */ | ||||||
|  |  static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, | ||||||
|  |  			struct file *file, unsigned int cmd, unsigned long arg); | ||||||
|  | @@ -3468,6 +3486,7 @@ ppp_connect_channel(struct channel *pch, | ||||||
|  |  	struct ppp_net *pn; | ||||||
|  |  	int ret = -ENXIO; | ||||||
|  |  	int hdrlen; | ||||||
|  | +	int notify = 0; | ||||||
|  |   | ||||||
|  |  	pn = ppp_pernet(pch->chan_net); | ||||||
|  |   | ||||||
|  | @@ -3500,6 +3519,8 @@ ppp_connect_channel(struct channel *pch, | ||||||
|  |  	++ppp->n_channels; | ||||||
|  |  	pch->ppp = ppp; | ||||||
|  |  	refcount_inc(&ppp->file.refcnt); | ||||||
|  | +	notify = 1; | ||||||
|  | + | ||||||
|  |  	ppp_unlock(ppp); | ||||||
|  |  	ret = 0; | ||||||
|  |   | ||||||
|  | @@ -3507,6 +3528,14 @@ ppp_connect_channel(struct channel *pch, | ||||||
|  |  	write_unlock_bh(&pch->upl); | ||||||
|  |   out: | ||||||
|  |  	mutex_unlock(&pn->all_ppp_mutex); | ||||||
|  | + | ||||||
|  | +	if (notify && ppp && ppp->dev) { | ||||||
|  | +		dev_hold(ppp->dev); | ||||||
|  | +		raw_notifier_call_chain(&ppp_channel_connection_notifier_list, | ||||||
|  | +					   PPP_CHANNEL_CONNECT, ppp->dev); | ||||||
|  | +		dev_put(ppp->dev); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -3524,6 +3553,13 @@ ppp_disconnect_channel(struct channel *p | ||||||
|  |  	pch->ppp = NULL; | ||||||
|  |  	write_unlock_bh(&pch->upl); | ||||||
|  |  	if (ppp) { | ||||||
|  | +		if (ppp->dev) { | ||||||
|  | +			dev_hold(ppp->dev); | ||||||
|  | +			raw_notifier_call_chain(&ppp_channel_connection_notifier_list, | ||||||
|  | +					   PPP_CHANNEL_DISCONNECT, ppp->dev); | ||||||
|  | +			dev_put(ppp->dev); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		/* remove it from the ppp unit's list */ | ||||||
|  |  		ppp_lock(ppp); | ||||||
|  |  		list_del(&pch->clist); | ||||||
|  | @@ -3603,6 +3639,188 @@ static void *unit_find(struct idr *p, in | ||||||
|  |  	return idr_find(p, n); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* Updates the PPP interface statistics. */ | ||||||
|  | +void ppp_update_stats(struct net_device *dev, unsigned long rx_packets, | ||||||
|  | +		      unsigned long rx_bytes, unsigned long tx_packets, | ||||||
|  | +		      unsigned long tx_bytes, unsigned long rx_errors, | ||||||
|  | +		      unsigned long tx_errors, unsigned long rx_dropped, | ||||||
|  | +		      unsigned long tx_dropped) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | + | ||||||
|  | +	ppp_xmit_lock(ppp); | ||||||
|  | +	ppp->stats64.tx_packets += tx_packets; | ||||||
|  | +	ppp->stats64.tx_bytes += tx_bytes; | ||||||
|  | +	ppp->dev->stats.tx_errors += tx_errors; | ||||||
|  | +	ppp->dev->stats.tx_dropped += tx_dropped; | ||||||
|  | +	if (tx_packets) | ||||||
|  | +		ppp->last_xmit = jiffies; | ||||||
|  | +	ppp_xmit_unlock(ppp); | ||||||
|  | + | ||||||
|  | +	ppp_recv_lock(ppp); | ||||||
|  | +	ppp->stats64.rx_packets += rx_packets; | ||||||
|  | +	ppp->stats64.rx_bytes += rx_bytes; | ||||||
|  | +	ppp->dev->stats.rx_errors += rx_errors; | ||||||
|  | +	ppp->dev->stats.rx_dropped += rx_dropped; | ||||||
|  | +	if (rx_packets) | ||||||
|  | +		ppp->last_recv = jiffies; | ||||||
|  | +	ppp_recv_unlock(ppp); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 if | ||||||
|  | + * the device is not PPP. | ||||||
|  | + */ | ||||||
|  | +int ppp_is_multilink(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | +	unsigned int flags; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | +	ppp_lock(ppp); | ||||||
|  | +	flags = ppp->flags; | ||||||
|  | +	ppp_unlock(ppp); | ||||||
|  | + | ||||||
|  | +	if (flags & SC_MULTILINK) | ||||||
|  | +		return 1; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_is_multilink); | ||||||
|  | + | ||||||
|  | +/* ppp_channel_get_protocol() | ||||||
|  | + *	Call this to obtain the underlying protocol of the PPP channel, | ||||||
|  | + *	e.g. PX_PROTO_OE | ||||||
|  | + * | ||||||
|  | + * NOTE: Some channels do not use PX sockets so the protocol value may be very | ||||||
|  | + * different for them. | ||||||
|  | + * NOTE: -1 indicates failure. | ||||||
|  | + * NOTE: Once you know the channel protocol you may then either cast 'chan' to | ||||||
|  | + * its sub-class or use the channel protocol specific API's as provided by that | ||||||
|  | + * channel sub type. | ||||||
|  | + */ | ||||||
|  | +int ppp_channel_get_protocol(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	if (!chan->ops->get_channel_protocol) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	return chan->ops->get_channel_protocol(chan); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_channel_get_protocol); | ||||||
|  | + | ||||||
|  | +/* ppp_channel_hold() | ||||||
|  | + *	Call this to hold a channel. | ||||||
|  | + * | ||||||
|  | + * Returns true on success or false if the hold could not happen. | ||||||
|  | + * | ||||||
|  | + * NOTE: chan must be protected against destruction during this call - | ||||||
|  | + * either by correct locking etc. or because you already have an implicit | ||||||
|  | + * or explicit hold to the channel already and this is an additional hold. | ||||||
|  | + */ | ||||||
|  | +bool ppp_channel_hold(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	if (!chan->ops->hold) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	chan->ops->hold(chan); | ||||||
|  | +	return true; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_channel_hold); | ||||||
|  | + | ||||||
|  | +/* ppp_channel_release() | ||||||
|  | + *	Call this to release a hold you have upon a channel | ||||||
|  | + */ | ||||||
|  | +void ppp_channel_release(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	chan->ops->release(chan); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_channel_release); | ||||||
|  | + | ||||||
|  | +/* ppp_hold_channels() | ||||||
|  | + *	Returns the PPP channels of the PPP device, storing each one into | ||||||
|  | + *	channels[]. | ||||||
|  | + * | ||||||
|  | + * channels[] has chan_sz elements. | ||||||
|  | + * This function returns the number of channels stored, up to chan_sz. | ||||||
|  | + * It will return < 0 if the device is not PPP. | ||||||
|  | + * | ||||||
|  | + * You MUST release the channels using ppp_release_channels(). | ||||||
|  | + */ | ||||||
|  | +int ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[], | ||||||
|  | +		      unsigned int chan_sz) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | +	int c; | ||||||
|  | +	struct channel *pch; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | + | ||||||
|  | +	c = 0; | ||||||
|  | +	ppp_lock(ppp); | ||||||
|  | +	list_for_each_entry(pch, &ppp->channels, clist) { | ||||||
|  | +		struct ppp_channel *chan; | ||||||
|  | + | ||||||
|  | +		if (!pch->chan) { | ||||||
|  | +			/* Channel is going / gone away */ | ||||||
|  | +			continue; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		if (c == chan_sz) { | ||||||
|  | +			/* No space to record channel */ | ||||||
|  | +			ppp_unlock(ppp); | ||||||
|  | +			return c; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		/* Hold the channel, if supported */ | ||||||
|  | +		chan = pch->chan; | ||||||
|  | +		if (!chan->ops->hold) | ||||||
|  | +			continue; | ||||||
|  | + | ||||||
|  | +		chan->ops->hold(chan); | ||||||
|  | + | ||||||
|  | +		 /* Record the channel */ | ||||||
|  | +		channels[c++] = chan; | ||||||
|  | +	} | ||||||
|  | +	ppp_unlock(ppp); | ||||||
|  | +	return c; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_hold_channels); | ||||||
|  | + | ||||||
|  | +/* ppp_release_channels() | ||||||
|  | + *	Releases channels | ||||||
|  | + */ | ||||||
|  | +void ppp_release_channels(struct ppp_channel *channels[], unsigned int chan_sz) | ||||||
|  | +{ | ||||||
|  | +	unsigned int c; | ||||||
|  | + | ||||||
|  | +	for (c = 0; c < chan_sz; ++c) { | ||||||
|  | +		struct ppp_channel *chan; | ||||||
|  | + | ||||||
|  | +		chan = channels[c]; | ||||||
|  | +		chan->ops->release(chan); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_release_channels); | ||||||
|  | + | ||||||
|  |  /* Module/initialization stuff */ | ||||||
|  |   | ||||||
|  |  module_init(ppp_init); | ||||||
|  | @@ -3619,6 +3837,8 @@ EXPORT_SYMBOL(ppp_input_error); | ||||||
|  |  EXPORT_SYMBOL(ppp_output_wakeup); | ||||||
|  |  EXPORT_SYMBOL(ppp_register_compressor); | ||||||
|  |  EXPORT_SYMBOL(ppp_unregister_compressor); | ||||||
|  | +EXPORT_SYMBOL(ppp_update_stats); | ||||||
|  | + | ||||||
|  |  MODULE_LICENSE("GPL"); | ||||||
|  |  MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0); | ||||||
|  |  MODULE_ALIAS_RTNL_LINK("ppp"); | ||||||
|  | --- a/drivers/net/ppp/pppoe.c | ||||||
|  | +++ b/drivers/net/ppp/pppoe.c | ||||||
|  | @@ -62,6 +62,7 @@ | ||||||
|  |  #include <linux/inetdevice.h> | ||||||
|  |  #include <linux/etherdevice.h> | ||||||
|  |  #include <linux/skbuff.h> | ||||||
|  | +#include <linux/if_arp.h> | ||||||
|  |  #include <linux/init.h> | ||||||
|  |  #include <linux/if_ether.h> | ||||||
|  |  #include <linux/if_pppox.h> | ||||||
|  | @@ -87,7 +88,7 @@ | ||||||
|  |  static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); | ||||||
|  |   | ||||||
|  |  static const struct proto_ops pppoe_ops; | ||||||
|  | -static const struct ppp_channel_ops pppoe_chan_ops; | ||||||
|  | +static const struct pppoe_channel_ops pppoe_chan_ops; | ||||||
|  |   | ||||||
|  |  /* per-net private data for this module */ | ||||||
|  |  static unsigned int pppoe_net_id __read_mostly; | ||||||
|  | @@ -645,6 +646,7 @@ static int pppoe_connect(struct socket * | ||||||
|  |  	if (stage_session(po->pppoe_pa.sid)) { | ||||||
|  |  		pppox_unbind_sock(sk); | ||||||
|  |  		pn = pppoe_pernet(sock_net(sk)); | ||||||
|  | + | ||||||
|  |  		delete_item(pn, po->pppoe_pa.sid, | ||||||
|  |  			    po->pppoe_pa.remote, po->pppoe_ifindex); | ||||||
|  |  		if (po->pppoe_dev) { | ||||||
|  | @@ -692,7 +694,7 @@ static int pppoe_connect(struct socket * | ||||||
|  |   | ||||||
|  |  		po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2; | ||||||
|  |  		po->chan.private = sk; | ||||||
|  | -		po->chan.ops = &pppoe_chan_ops; | ||||||
|  | +		po->chan.ops = (struct ppp_channel_ops *)&pppoe_chan_ops; | ||||||
|  |   | ||||||
|  |  		error = ppp_register_net_channel(dev_net(dev), &po->chan); | ||||||
|  |  		if (error) { | ||||||
|  | @@ -995,9 +997,80 @@ static int pppoe_fill_forward_path(struc | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static const struct ppp_channel_ops pppoe_chan_ops = { | ||||||
|  | -	.start_xmit = pppoe_xmit, | ||||||
|  | -	.fill_forward_path = pppoe_fill_forward_path, | ||||||
|  | +/************************************************************************ | ||||||
|  | + * | ||||||
|  | + * function called by generic PPP driver to hold channel | ||||||
|  | + * | ||||||
|  | + ***********************************************************************/ | ||||||
|  | +static void pppoe_hold_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_hold(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/************************************************************************ | ||||||
|  | + * | ||||||
|  | + * function called by generic PPP driver to release channel | ||||||
|  | + * | ||||||
|  | + ***********************************************************************/ | ||||||
|  | +static void pppoe_release_chan(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	sock_put(sk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/************************************************************************ | ||||||
|  | + * | ||||||
|  | + * function called to get the channel protocol type | ||||||
|  | + * | ||||||
|  | + ***********************************************************************/ | ||||||
|  | +static int pppoe_get_channel_protocol(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	return PX_PROTO_OE; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/************************************************************************ | ||||||
|  | + * | ||||||
|  | + * function called to get the PPPoE channel addressing | ||||||
|  | + * NOTE: This function returns a HOLD to the netdevice | ||||||
|  | + * | ||||||
|  | + ***********************************************************************/ | ||||||
|  | +static int pppoe_get_addressing(struct ppp_channel *chan, | ||||||
|  | +				 struct pppoe_opt *addressing) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | +	struct pppox_sock *po = pppox_sk(sk); | ||||||
|  | +	int err = 0; | ||||||
|  | + | ||||||
|  | +	*addressing = po->proto.pppoe; | ||||||
|  | +	if (!addressing->dev) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	dev_hold(addressing->dev); | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pppoe_channel_addressing_get() | ||||||
|  | + *	Return PPPoE channel specific addressing information. | ||||||
|  | + */ | ||||||
|  | +int pppoe_channel_addressing_get(struct ppp_channel *chan, | ||||||
|  | +				  struct pppoe_opt *addressing) | ||||||
|  | +{ | ||||||
|  | +	return pppoe_get_addressing(chan, addressing); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pppoe_channel_addressing_get); | ||||||
|  | + | ||||||
|  | +static const struct pppoe_channel_ops pppoe_chan_ops = { | ||||||
|  | +	/* PPPoE specific channel ops */ | ||||||
|  | +	.get_addressing = pppoe_get_addressing, | ||||||
|  | +	/* General ppp channel ops */ | ||||||
|  | +	.ops.start_xmit = pppoe_xmit, | ||||||
|  | +	.ops.fill_forward_path = pppoe_fill_forward_path, | ||||||
|  | +	.ops.get_channel_protocol = pppoe_get_channel_protocol, | ||||||
|  | +	.ops.hold = pppoe_hold_chan, | ||||||
|  | +	.ops.release = pppoe_release_chan, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, | ||||||
|  | --- a/include/linux/if_pppox.h | ||||||
|  | +++ b/include/linux/if_pppox.h | ||||||
|  | @@ -1,11 +1,12 @@ | ||||||
|  |  /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||||
|  |  /*************************************************************************** | ||||||
|  |   * Linux PPP over X - Generic PPP transport layer sockets | ||||||
|  | - * Linux PPP over Ethernet (PPPoE) Socket Implementation (RFC 2516)  | ||||||
|  | + * Linux PPP over Ethernet (PPPoE) Socket Implementation (RFC 2516) | ||||||
|  |   * | ||||||
|  |   * This file supplies definitions required by the PPP over Ethernet driver | ||||||
|  |   * (pppox.c).  All version information wrt this file is located in pppox.c | ||||||
|  |   */ | ||||||
|  | + | ||||||
|  |  #ifndef __LINUX_IF_PPPOX_H | ||||||
|  |  #define __LINUX_IF_PPPOX_H | ||||||
|  |   | ||||||
|  | @@ -91,4 +92,17 @@ enum { | ||||||
|  |      PPPOX_DEAD		= 16  /* dead, useless, please clean me up!*/ | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/* | ||||||
|  | + * PPPoE Channel specific operations | ||||||
|  | + */ | ||||||
|  | +struct pppoe_channel_ops { | ||||||
|  | +	/* Must be first - general to all PPP channels */ | ||||||
|  | +	struct ppp_channel_ops ops; | ||||||
|  | +	int (*get_addressing)(struct ppp_channel *, struct pppoe_opt *); | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* Return PPPoE channel specific addressing information */ | ||||||
|  | +extern int pppoe_channel_addressing_get(struct ppp_channel *chan, | ||||||
|  | +					 struct pppoe_opt *addressing); | ||||||
|  | + | ||||||
|  |  #endif /* !(__LINUX_IF_PPPOX_H) */ | ||||||
|  | --- a/include/linux/ppp_channel.h | ||||||
|  | +++ b/include/linux/ppp_channel.h | ||||||
|  | @@ -19,6 +19,11 @@ | ||||||
|  |  #include <linux/skbuff.h> | ||||||
|  |  #include <linux/poll.h> | ||||||
|  |  #include <net/net_namespace.h> | ||||||
|  | +#include <linux/notifier.h> | ||||||
|  | + | ||||||
|  | +/* PPP channel connection event types */ | ||||||
|  | +#define PPP_CHANNEL_DISCONNECT	0 | ||||||
|  | +#define PPP_CHANNEL_CONNECT	1 | ||||||
|  |   | ||||||
|  |  struct net_device_path; | ||||||
|  |  struct net_device_path_ctx; | ||||||
|  | @@ -33,6 +38,15 @@ struct ppp_channel_ops { | ||||||
|  |  	int	(*fill_forward_path)(struct net_device_path_ctx *, | ||||||
|  |  				     struct net_device_path *, | ||||||
|  |  				     const struct ppp_channel *); | ||||||
|  | + | ||||||
|  | +	/* Get channel protocol type, one of PX_PROTO_XYZ or specific to | ||||||
|  | +	 * the channel subtype | ||||||
|  | +	 */ | ||||||
|  | +	int (*get_channel_protocol)(struct ppp_channel *); | ||||||
|  | +	/* Hold the channel from being destroyed */ | ||||||
|  | +	void (*hold)(struct ppp_channel *); | ||||||
|  | +	/* Release hold on the channel */ | ||||||
|  | +	void (*release)(struct ppp_channel *); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct ppp_channel { | ||||||
|  | @@ -47,6 +61,38 @@ struct ppp_channel { | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  #ifdef __KERNEL__ | ||||||
|  | +/* Call this to obtain the underlying protocol of the PPP channel, | ||||||
|  | + * e.g. PX_PROTO_OE | ||||||
|  | + */ | ||||||
|  | +extern int ppp_channel_get_protocol(struct ppp_channel *); | ||||||
|  | + | ||||||
|  | +/* Call this to hold a channel */ | ||||||
|  | +extern bool ppp_channel_hold(struct ppp_channel *); | ||||||
|  | + | ||||||
|  | +/* Call this to release a hold you have upon a channel */ | ||||||
|  | +extern void ppp_channel_release(struct ppp_channel *); | ||||||
|  | + | ||||||
|  | +/* Release hold on PPP channels */ | ||||||
|  | +extern void ppp_release_channels(struct ppp_channel *channels[], | ||||||
|  | +				 unsigned int chan_sz); | ||||||
|  | + | ||||||
|  | +/* Hold PPP channels for the PPP device */ | ||||||
|  | +extern int ppp_hold_channels(struct net_device *dev, | ||||||
|  | +			     struct ppp_channel *channels[], | ||||||
|  | +			     unsigned int chan_sz); | ||||||
|  | + | ||||||
|  | +/* Test if the ppp device is a multi-link ppp device */ | ||||||
|  | +extern int ppp_is_multilink(struct net_device *dev); | ||||||
|  | + | ||||||
|  | +/* Update statistics of the PPP net_device by incrementing related | ||||||
|  | + * statistics field value with corresponding parameter | ||||||
|  | + */ | ||||||
|  | +extern void ppp_update_stats(struct net_device *dev, unsigned long rx_packets, | ||||||
|  | +			     unsigned long rx_bytes, unsigned long tx_packets, | ||||||
|  | +			     unsigned long tx_bytes, unsigned long rx_errors, | ||||||
|  | +			     unsigned long tx_errors, unsigned long rx_dropped, | ||||||
|  | +			     unsigned long tx_dropped); | ||||||
|  | + | ||||||
|  |  /* Called by the channel when it can send some more data. */ | ||||||
|  |  extern void ppp_output_wakeup(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | @@ -76,6 +122,12 @@ extern int ppp_unit_number(struct ppp_ch | ||||||
|  |  /* Get the device name associated with a channel, or NULL if none */ | ||||||
|  |  extern char *ppp_dev_name(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | +/* Register the PPP channel connect notifier */ | ||||||
|  | +extern void ppp_channel_connection_register_notify(struct notifier_block *nb); | ||||||
|  | + | ||||||
|  | +/* Unregister the PPP channel connect notifier */ | ||||||
|  | +extern void ppp_channel_connection_unregister_notify(struct notifier_block *nb); | ||||||
|  | + | ||||||
|  |  /* | ||||||
|  |   * SMP locking notes: | ||||||
|  |   * The channel code must ensure that when it calls ppp_unregister_channel, | ||||||
|  | --- a/net/l2tp/l2tp_core.c | ||||||
|  | +++ b/net/l2tp/l2tp_core.c | ||||||
|  | @@ -403,6 +403,30 @@ err_tlock: | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(l2tp_session_register); | ||||||
|  |   | ||||||
|  | +void l2tp_stats_update(struct l2tp_tunnel *tunnel, | ||||||
|  | +		       struct l2tp_session *session, | ||||||
|  | +		       struct l2tp_stats *stats) | ||||||
|  | +{ | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->rx_packets), | ||||||
|  | +			&tunnel->stats.rx_packets); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->rx_bytes), | ||||||
|  | +			&tunnel->stats.rx_bytes); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->tx_packets), | ||||||
|  | +			&tunnel->stats.tx_packets); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->tx_bytes), | ||||||
|  | +			&tunnel->stats.tx_bytes); | ||||||
|  | + | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->rx_packets), | ||||||
|  | +			&session->stats.rx_packets); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->rx_bytes), | ||||||
|  | +			&session->stats.rx_bytes); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->tx_packets), | ||||||
|  | +			&session->stats.tx_packets); | ||||||
|  | +	atomic_long_add(atomic_long_read(&stats->tx_bytes), | ||||||
|  | +			&session->stats.tx_bytes); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL_GPL(l2tp_stats_update); | ||||||
|  | + | ||||||
|  |  /***************************************************************************** | ||||||
|  |   * Receive data handling | ||||||
|  |   *****************************************************************************/ | ||||||
|  | --- a/net/l2tp/l2tp_core.h | ||||||
|  | +++ b/net/l2tp/l2tp_core.h | ||||||
|  | @@ -231,6 +231,8 @@ struct l2tp_session *l2tp_session_get(co | ||||||
|  |  struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth); | ||||||
|  |  struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, | ||||||
|  |  						const char *ifname); | ||||||
|  | +void l2tp_stats_update(struct l2tp_tunnel *tunnel, struct l2tp_session *session, | ||||||
|  | +		       struct l2tp_stats *stats); | ||||||
|  |   | ||||||
|  |  /* Tunnel and session lifetime management. | ||||||
|  |   * Creation of a new instance is a two-step process: create, then register. | ||||||
| @@ -0,0 +1,139 @@ | |||||||
|  | From bd2254aed96e33fc84c24d54894fe606f474360d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Date: Fri, 26 Feb 2016 15:26:07 -0800 | ||||||
|  | Subject: [PATCH 302/500] inet: pptp: Added API to get PPTP session info for | ||||||
|  |  NSS acceleration | ||||||
|  |  | ||||||
|  | The API are needed by NSS modules to query PPTP session information | ||||||
|  | using the PPTP channel or session ID. The information is needed for | ||||||
|  | accelerating PPTP flows by NSS | ||||||
|  |  | ||||||
|  | Change-Id: I27408e9bee58f186a4ab99fa360bbef26b02c81b | ||||||
|  | Signed-off-by: Shyam Sunder <ssunde@codeaurora.org> | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/pptp.c   | 75 ++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/if_pppox.h |  8 +++++ | ||||||
|  |  2 files changed, 83 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/pptp.c | ||||||
|  | +++ b/drivers/net/ppp/pptp.c | ||||||
|  | @@ -91,6 +91,31 @@ static int lookup_chan_dst(u16 call_id, | ||||||
|  |  	return i < MAX_CALLID; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* Search a pptp session based on peer call id and peer ip address */ | ||||||
|  | +static int lookup_session_dst(struct pptp_opt *opt, u16 call_id, __be32 d_addr) | ||||||
|  | +{ | ||||||
|  | +	struct pppox_sock *sock; | ||||||
|  | +	int i = 1; | ||||||
|  | + | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | +	for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) { | ||||||
|  | +		sock = rcu_dereference(callid_sock[i]); | ||||||
|  | +		if (!sock) | ||||||
|  | +			continue; | ||||||
|  | + | ||||||
|  | +		if (sock->proto.pptp.dst_addr.call_id == call_id && | ||||||
|  | +		    sock->proto.pptp.dst_addr.sin_addr.s_addr == d_addr) { | ||||||
|  | +			sock_hold(sk_pppox(sock)); | ||||||
|  | +			memcpy(opt, &sock->proto.pptp, sizeof(struct pptp_opt)); | ||||||
|  | +			sock_put(sk_pppox(sock)); | ||||||
|  | +			rcu_read_unlock(); | ||||||
|  | +			return 0; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  | +	return -EINVAL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int add_chan(struct pppox_sock *sock, | ||||||
|  |  		    struct pptp_addr *sa) | ||||||
|  |  { | ||||||
|  | @@ -258,7 +283,12 @@ static int pptp_xmit(struct ppp_channel | ||||||
|  |  	ip_select_ident(net, skb, NULL); | ||||||
|  |  	ip_send_check(iph); | ||||||
|  |   | ||||||
|  | +	/* set incoming interface as the ppp interface */ | ||||||
|  | +	if (skb->skb_iif) | ||||||
|  | +		skb->skb_iif = ppp_dev_index(chan); | ||||||
|  | + | ||||||
|  |  	ip_local_out(net, skb->sk, skb); | ||||||
|  | + | ||||||
|  |  	return 1; | ||||||
|  |   | ||||||
|  |  tx_error: | ||||||
|  | @@ -371,6 +401,7 @@ static int pptp_rcv(struct sk_buff *skb) | ||||||
|  |  	if (po) { | ||||||
|  |  		skb_dst_drop(skb); | ||||||
|  |  		nf_reset_ct(skb); | ||||||
|  | +		skb->skb_iif = ppp_dev_index(&po->chan); | ||||||
|  |  		return sk_receive_skb(sk_pppox(po), skb, 0); | ||||||
|  |  	} | ||||||
|  |  drop: | ||||||
|  | @@ -603,6 +634,50 @@ static int pptp_ppp_ioctl(struct ppp_cha | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* pptp_channel_addressing_get() | ||||||
|  | + *	Return PPTP channel specific addressing information. | ||||||
|  | + */ | ||||||
|  | +void pptp_channel_addressing_get(struct pptp_opt *opt, struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk; | ||||||
|  | +	struct pppox_sock *po; | ||||||
|  | + | ||||||
|  | +	if (!opt) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	sk = (struct sock *)chan->private; | ||||||
|  | +	if (!sk) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	sock_hold(sk); | ||||||
|  | + | ||||||
|  | +	/* This is very unlikely, but check the socket is connected state */ | ||||||
|  | +	if (unlikely(sock_flag(sk, SOCK_DEAD) || | ||||||
|  | +		     !(sk->sk_state & PPPOX_CONNECTED))) { | ||||||
|  | +		sock_put(sk); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	po = pppox_sk(sk); | ||||||
|  | +	memcpy(opt, &po->proto.pptp, sizeof(struct pptp_opt)); | ||||||
|  | +	sock_put(sk); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_channel_addressing_get); | ||||||
|  | + | ||||||
|  | +/* pptp_session_find() | ||||||
|  | + *	Search and return a PPTP session info based on peer callid and IP | ||||||
|  | + *	address. The function accepts the parameters in network byte order. | ||||||
|  | + */ | ||||||
|  | +int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id, | ||||||
|  | +		      __be32 peer_ip_addr) | ||||||
|  | +{ | ||||||
|  | +	if (!opt) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	return lookup_session_dst(opt, ntohs(peer_call_id), peer_ip_addr); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_session_find); | ||||||
|  | + | ||||||
|  |  /* pptp_hold_chan() */ | ||||||
|  |  static void pptp_hold_chan(struct ppp_channel *chan) | ||||||
|  |  { | ||||||
|  | --- a/include/linux/if_pppox.h | ||||||
|  | +++ b/include/linux/if_pppox.h | ||||||
|  | @@ -105,4 +105,12 @@ struct pppoe_channel_ops { | ||||||
|  |  extern int pppoe_channel_addressing_get(struct ppp_channel *chan, | ||||||
|  |  					 struct pppoe_opt *addressing); | ||||||
|  |   | ||||||
|  | +/* Lookup PPTP session info and return PPTP session */ | ||||||
|  | +extern int pptp_session_find(struct pptp_opt *opt, __be16 peer_call_id, | ||||||
|  | +			     __be32 peer_ip_addr); | ||||||
|  | + | ||||||
|  | +/* Return PPTP session information given the channel */ | ||||||
|  | +extern void pptp_channel_addressing_get(struct pptp_opt *opt, | ||||||
|  | +					struct ppp_channel *chan); | ||||||
|  | + | ||||||
|  |  #endif /* !(__LINUX_IF_PPPOX_H) */ | ||||||
| @@ -0,0 +1,36 @@ | |||||||
|  | From fb2393132ddf7af47b6b5dd67b57048f4b914faa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | Date: Mon, 13 Nov 2017 15:10:10 +0530 | ||||||
|  | Subject: [PATCH 298/500] net :gre : Set skb->skb_iif number | ||||||
|  |  | ||||||
|  | skb->skb_iif should be set to GRE netdevice to accelerate | ||||||
|  | packet | ||||||
|  |  | ||||||
|  | Change-Id: I0af542d2fa64b87c51b9bf3803bb874299299026 | ||||||
|  | Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | Signed-off-by: Subhash Kumar Katnpally <skatnapa@codeaurora.org> | ||||||
|  | Signed-off-by: Pavithra R <pavir@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  net/ipv4/ip_gre.c | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/net/ipv4/ip_gre.c | ||||||
|  | +++ b/net/ipv4/ip_gre.c | ||||||
|  | @@ -687,6 +687,8 @@ static netdev_tx_t ipgre_xmit(struct sk_ | ||||||
|  |  	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) | ||||||
|  |  		goto free_skb; | ||||||
|  |   | ||||||
|  | +	skb->skb_iif = dev->ifindex; | ||||||
|  | + | ||||||
|  |  	__gre_xmit(skb, dev, tnl_params, skb->protocol); | ||||||
|  |  	return NETDEV_TX_OK; | ||||||
|  |   | ||||||
|  | @@ -770,6 +772,8 @@ static netdev_tx_t gre_tap_xmit(struct s | ||||||
|  |  	if (skb_cow_head(skb, dev->needed_headroom)) | ||||||
|  |  		goto free_skb; | ||||||
|  |   | ||||||
|  | +	skb->skb_iif = dev->ifindex; | ||||||
|  | + | ||||||
|  |  	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); | ||||||
|  |  	return NETDEV_TX_OK; | ||||||
|  |   | ||||||
| @@ -0,0 +1,56 @@ | |||||||
|  | From cad2cc2ca7c6cb9b4428a0333c46713f82d2424d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ratheesh Kannoth <rkannoth@codeaurora.org> | ||||||
|  | Date: Fri, 6 Nov 2020 12:56:12 +0530 | ||||||
|  | Subject: [PATCH 244/500] net: ppp: API to check compression enabled on PPP | ||||||
|  |  device | ||||||
|  |  | ||||||
|  | Change-Id: I574c688a9299531263061534a51cc88fef5e069f | ||||||
|  | Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org> | ||||||
|  | Signed-off-by: Pavithra R <quic_pavir@quicinc.com> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 22 ++++++++++++++++++++++ | ||||||
|  |  include/linux/ppp_channel.h   |  2 ++ | ||||||
|  |  2 files changed, 24 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -3675,6 +3675,28 @@ void ppp_update_stats(struct net_device | ||||||
|  |  	ppp_recv_unlock(ppp); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* Returns true if Compression is enabled on PPP device | ||||||
|  | + */ | ||||||
|  | +bool ppp_is_cp_enabled(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | +	bool flag = false; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | +	ppp_lock(ppp); | ||||||
|  | +	flag = !!ppp->xcomp || !!ppp->rcomp; | ||||||
|  | +	ppp_unlock(ppp); | ||||||
|  | + | ||||||
|  | +	return flag; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_is_cp_enabled); | ||||||
|  | + | ||||||
|  |  /* Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 if | ||||||
|  |   * the device is not PPP. | ||||||
|  |   */ | ||||||
|  | --- a/include/linux/ppp_channel.h | ||||||
|  | +++ b/include/linux/ppp_channel.h | ||||||
|  | @@ -81,6 +81,8 @@ extern int ppp_hold_channels(struct net_ | ||||||
|  |  			     struct ppp_channel *channels[], | ||||||
|  |  			     unsigned int chan_sz); | ||||||
|  |   | ||||||
|  | +bool ppp_is_cp_enabled(struct net_device *dev); | ||||||
|  | + | ||||||
|  |  /* Test if the ppp device is a multi-link ppp device */ | ||||||
|  |  extern int ppp_is_multilink(struct net_device *dev); | ||||||
|  |   | ||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | From 74702bfe2627baa572303a4d4281bafa2cfa2464 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ratheesh Kannoth <rkannoth@codeaurora.org> | ||||||
|  | Date: Mon, 16 Nov 2020 17:34:25 +0530 | ||||||
|  | Subject: [PATCH 264/500] net: ppp: Use flag to detect TX/RX compression | ||||||
|  |  | ||||||
|  | Change-Id: I3068377565fe172b2771b7878a6c933322f6c69e | ||||||
|  | Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org> | ||||||
|  | Signed-off-by: Pavithra R <quic_pavir@quicinc.com> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -3690,7 +3690,7 @@ bool ppp_is_cp_enabled(struct net_device | ||||||
|  |   | ||||||
|  |  	ppp = netdev_priv(dev); | ||||||
|  |  	ppp_lock(ppp); | ||||||
|  | -	flag = !!ppp->xcomp || !!ppp->rcomp; | ||||||
|  | +	flag = !!(ppp->xstate & SC_COMP_RUN) || !!(ppp->rstate & SC_DECOMP_RUN); | ||||||
|  |  	ppp_unlock(ppp); | ||||||
|  |   | ||||||
|  |  	return flag; | ||||||
| @@ -0,0 +1,84 @@ | |||||||
|  | From a7f74f20856f3076d57cb2a986cfbe1d26cead41 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | Date: Wed, 8 Jul 2015 11:13:57 +0530 | ||||||
|  | Subject: [PATCH 306/500] net: l2tp: set skb->iif for pkt thru l2tp interface | ||||||
|  |  | ||||||
|  | Change-Id: I20eed270083ba9ac167d9672928483396e488133 | ||||||
|  | Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 15 +++++++++++++++ | ||||||
|  |  include/linux/ppp_channel.h   |  4 ++++ | ||||||
|  |  net/l2tp/l2tp_ppp.c           |  4 ++++ | ||||||
|  |  3 files changed, 23 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -2986,6 +2986,20 @@ char *ppp_dev_name(struct ppp_channel *c | ||||||
|  |  	return name; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* Return the PPP net device index */ | ||||||
|  | +int ppp_dev_index(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct channel *pch = chan->ppp; | ||||||
|  | +	int ifindex = 0; | ||||||
|  | + | ||||||
|  | +	if (pch) { | ||||||
|  | +		read_lock_bh(&pch->upl); | ||||||
|  | +		if (pch->ppp && pch->ppp->dev) | ||||||
|  | +			ifindex = pch->ppp->dev->ifindex; | ||||||
|  | +		read_unlock_bh(&pch->upl); | ||||||
|  | +	} | ||||||
|  | +	return ifindex; | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  |   * Disconnect a channel from the generic layer. | ||||||
|  | @@ -3854,6 +3868,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); | ||||||
|  |  EXPORT_SYMBOL(ppp_channel_index); | ||||||
|  |  EXPORT_SYMBOL(ppp_unit_number); | ||||||
|  |  EXPORT_SYMBOL(ppp_dev_name); | ||||||
|  | +EXPORT_SYMBOL(ppp_dev_index); | ||||||
|  |  EXPORT_SYMBOL(ppp_input); | ||||||
|  |  EXPORT_SYMBOL(ppp_input_error); | ||||||
|  |  EXPORT_SYMBOL(ppp_output_wakeup); | ||||||
|  | --- a/include/linux/ppp_channel.h | ||||||
|  | +++ b/include/linux/ppp_channel.h | ||||||
|  | @@ -19,6 +19,7 @@ | ||||||
|  |  #include <linux/skbuff.h> | ||||||
|  |  #include <linux/poll.h> | ||||||
|  |  #include <net/net_namespace.h> | ||||||
|  | +#include <linux/ppp_defs.h> | ||||||
|  |  #include <linux/notifier.h> | ||||||
|  |   | ||||||
|  |  /* PPP channel connection event types */ | ||||||
|  | @@ -118,6 +119,9 @@ extern void ppp_unregister_channel(struc | ||||||
|  |  /* Get the channel number for a channel */ | ||||||
|  |  extern int ppp_channel_index(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | +/* Get the device index  associated with a channel, or 0, if none */ | ||||||
|  | +extern int ppp_dev_index(struct ppp_channel *); | ||||||
|  | + | ||||||
|  |  /* Get the unit number associated with a channel, or -1 if none */ | ||||||
|  |  extern int ppp_unit_number(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | --- a/net/l2tp/l2tp_ppp.c | ||||||
|  | +++ b/net/l2tp/l2tp_ppp.c | ||||||
|  | @@ -243,6 +243,7 @@ static void pppol2tp_recv(struct l2tp_se | ||||||
|  |  		struct pppox_sock *po; | ||||||
|  |   | ||||||
|  |  		po = pppox_sk(sk); | ||||||
|  | +		skb->skb_iif = ppp_dev_index(&po->chan); | ||||||
|  |  		ppp_input(&po->chan, skb); | ||||||
|  |  	} else { | ||||||
|  |  		if (sock_queue_rcv_skb(sk, skb) < 0) { | ||||||
|  | @@ -402,6 +403,9 @@ static int pppol2tp_xmit(struct ppp_chan | ||||||
|  |  	__skb_push(skb, 2); | ||||||
|  |  	skb->data[0] = PPP_ALLSTATIONS; | ||||||
|  |  	skb->data[1] = PPP_UI; | ||||||
|  | +	/* set incoming interface as the ppp interface */ | ||||||
|  | +	if (skb->skb_iif) | ||||||
|  | +		skb->skb_iif = ppp_dev_index(chan); | ||||||
|  |   | ||||||
|  |  	local_bh_disable(); | ||||||
|  |  	l2tp_xmit_skb(session, skb); | ||||||
| @@ -0,0 +1,239 @@ | |||||||
|  | From 974e8f230c2294f54d5151fe0dbbc68a3aecb347 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Date: Fri, 26 Feb 2016 15:18:08 -0800 | ||||||
|  | Subject: [PATCH 307/500] net :l2tp: l2tp chan ops support get_addressing | ||||||
|  |  | ||||||
|  | l2tp channel ops support get_addressing() function. This | ||||||
|  | function can get l2tp tunnel/session/ip/port info. | ||||||
|  |  | ||||||
|  | Change-Id: Ica87438505c20376478092b95faaa3ecb8251596 | ||||||
|  | Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org> | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 79 +++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/if_pppol2tp.h   | 23 ++++++++++ | ||||||
|  |  include/linux/ppp_channel.h   |  7 ++++ | ||||||
|  |  net/l2tp/l2tp_ppp.c           | 53 +++++++++++++++++++---- | ||||||
|  |  4 files changed, 155 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -3737,6 +3737,32 @@ int ppp_is_multilink(struct net_device * | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(ppp_is_multilink); | ||||||
|  |   | ||||||
|  | +/* __ppp_is_multilink() | ||||||
|  | + *	Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 | ||||||
|  | + *	if the device is not PPP. Caller should acquire ppp_lock before calling | ||||||
|  | + *	this function | ||||||
|  | + */ | ||||||
|  | +int __ppp_is_multilink(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | +	unsigned int flags; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | +	flags = ppp->flags; | ||||||
|  | + | ||||||
|  | +	if (flags & SC_MULTILINK) | ||||||
|  | +		return 1; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(__ppp_is_multilink); | ||||||
|  | + | ||||||
|  |  /* ppp_channel_get_protocol() | ||||||
|  |   *	Call this to obtain the underlying protocol of the PPP channel, | ||||||
|  |   *	e.g. PX_PROTO_OE | ||||||
|  | @@ -3841,6 +3867,59 @@ int ppp_hold_channels(struct net_device | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(ppp_hold_channels); | ||||||
|  |   | ||||||
|  | +/* __ppp_hold_channels() | ||||||
|  | + *	Returns the PPP channels of the PPP device, storing each one | ||||||
|  | + *	into channels[]. | ||||||
|  | + * | ||||||
|  | + * channels[] has chan_sz elements. | ||||||
|  | + * This function returns the number of channels stored, up to chan_sz. | ||||||
|  | + * It will return < 0 if the device is not PPP. | ||||||
|  | + * | ||||||
|  | + * You MUST acquire ppp_lock and  release the channels using | ||||||
|  | + * ppp_release_channels(). | ||||||
|  | + */ | ||||||
|  | +int __ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[], | ||||||
|  | +			unsigned int chan_sz) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | +	int c; | ||||||
|  | +	struct channel *pch; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | + | ||||||
|  | +	c = 0; | ||||||
|  | +	list_for_each_entry(pch, &ppp->channels, clist) { | ||||||
|  | +		struct ppp_channel *chan; | ||||||
|  | + | ||||||
|  | +		if (!pch->chan) { | ||||||
|  | +			/* Channel is going / gone away*/ | ||||||
|  | +			continue; | ||||||
|  | +		} | ||||||
|  | +		if (c == chan_sz) { | ||||||
|  | +			/* No space to record channel */ | ||||||
|  | +			return c; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		/* Hold the channel, if supported */ | ||||||
|  | +		chan = pch->chan; | ||||||
|  | +		if (!chan->ops->hold) | ||||||
|  | +			continue; | ||||||
|  | + | ||||||
|  | +		chan->ops->hold(chan); | ||||||
|  | + | ||||||
|  | +		/* Record the channel */ | ||||||
|  | +		channels[c++] = chan; | ||||||
|  | +	} | ||||||
|  | +	return c; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(__ppp_hold_channels); | ||||||
|  | + | ||||||
|  |  /* ppp_release_channels() | ||||||
|  |   *	Releases channels | ||||||
|  |   */ | ||||||
|  | --- a/include/linux/if_pppol2tp.h | ||||||
|  | +++ b/include/linux/if_pppol2tp.h | ||||||
|  | @@ -12,4 +12,27 @@ | ||||||
|  |  #include <linux/in6.h> | ||||||
|  |  #include <uapi/linux/if_pppol2tp.h> | ||||||
|  |   | ||||||
|  | +/* | ||||||
|  | + * Holds L2TP channel info | ||||||
|  | + */ | ||||||
|  | +struct  pppol2tp_common_addr { | ||||||
|  | +	int tunnel_version;				/* v2 or v3 */ | ||||||
|  | +	__u32 local_tunnel_id, remote_tunnel_id;	/* tunnel id */ | ||||||
|  | +	__u32 local_session_id, remote_session_id;	/* session id */ | ||||||
|  | +	struct sockaddr_in local_addr, remote_addr; /* ip address and port */ | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * L2TP channel operations | ||||||
|  | + */ | ||||||
|  | +struct pppol2tp_channel_ops { | ||||||
|  | +	struct ppp_channel_ops ops; /* ppp channel ops */ | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * exported function which calls pppol2tp channel's get addressing | ||||||
|  | + * function | ||||||
|  | + */ | ||||||
|  | +extern int pppol2tp_channel_addressing_get(struct ppp_channel *, | ||||||
|  | +					   struct pppol2tp_common_addr *); | ||||||
|  |  #endif | ||||||
|  | --- a/include/linux/ppp_channel.h | ||||||
|  | +++ b/include/linux/ppp_channel.h | ||||||
|  | @@ -83,10 +83,17 @@ extern int ppp_hold_channels(struct net_ | ||||||
|  |  			     unsigned int chan_sz); | ||||||
|  |   | ||||||
|  |  bool ppp_is_cp_enabled(struct net_device *dev); | ||||||
|  | +/* Hold PPP channels for the PPP device */ | ||||||
|  | +extern int __ppp_hold_channels(struct net_device *dev, | ||||||
|  | +			       struct ppp_channel *channels[], | ||||||
|  | +			       unsigned int chan_sz); | ||||||
|  |   | ||||||
|  |  /* Test if the ppp device is a multi-link ppp device */ | ||||||
|  |  extern int ppp_is_multilink(struct net_device *dev); | ||||||
|  |   | ||||||
|  | +/* Test if the ppp device is a multi-link ppp device */ | ||||||
|  | +extern int __ppp_is_multilink(struct net_device *dev); | ||||||
|  | + | ||||||
|  |  /* Update statistics of the PPP net_device by incrementing related | ||||||
|  |   * statistics field value with corresponding parameter | ||||||
|  |   */ | ||||||
|  | --- a/net/l2tp/l2tp_ppp.c | ||||||
|  | +++ b/net/l2tp/l2tp_ppp.c | ||||||
|  | @@ -126,12 +126,11 @@ static int pppol2tp_xmit(struct ppp_chan | ||||||
|  |  static int pppol2tp_get_channel_protocol(struct ppp_channel *); | ||||||
|  |  static void pppol2tp_hold_chan(struct ppp_channel *); | ||||||
|  |  static void pppol2tp_release_chan(struct ppp_channel *); | ||||||
|  | - | ||||||
|  | -static const struct ppp_channel_ops pppol2tp_chan_ops = { | ||||||
|  | -	.start_xmit =  pppol2tp_xmit, | ||||||
|  | -	.get_channel_protocol = pppol2tp_get_channel_protocol, | ||||||
|  | -	.hold = pppol2tp_hold_chan, | ||||||
|  | -	.release = pppol2tp_release_chan, | ||||||
|  | +static const struct pppol2tp_channel_ops pppol2tp_chan_ops = { | ||||||
|  | +	.ops.start_xmit =  pppol2tp_xmit, | ||||||
|  | +	.ops.get_channel_protocol = pppol2tp_get_channel_protocol, | ||||||
|  | +	.ops.hold = pppol2tp_hold_chan, | ||||||
|  | +	.ops.release = pppol2tp_release_chan, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const struct proto_ops pppol2tp_ops; | ||||||
|  | @@ -359,6 +358,46 @@ static int pppol2tp_get_channel_protocol | ||||||
|  |  	return PX_PROTO_OL2TP; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* pppol2tp_get_addressing() */ | ||||||
|  | +static int pppol2tp_get_addressing(struct ppp_channel *chan, | ||||||
|  | +				   struct pppol2tp_common_addr *addr) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk = (struct sock *)chan->private; | ||||||
|  | +	struct l2tp_session *session; | ||||||
|  | +	struct l2tp_tunnel *tunnel; | ||||||
|  | +	struct inet_sock *isk = NULL; | ||||||
|  | +	int err = -ENXIO; | ||||||
|  | + | ||||||
|  | +	/* Get session and tunnel contexts from the socket */ | ||||||
|  | +	session = pppol2tp_sock_to_session(sk); | ||||||
|  | +	if (!session) | ||||||
|  | +		return err; | ||||||
|  | + | ||||||
|  | +	tunnel = session->tunnel; | ||||||
|  | +	isk = inet_sk(tunnel->sock); | ||||||
|  | + | ||||||
|  | +	addr->local_tunnel_id = tunnel->tunnel_id; | ||||||
|  | +	addr->remote_tunnel_id = tunnel->peer_tunnel_id; | ||||||
|  | +	addr->local_session_id = session->session_id; | ||||||
|  | +	addr->remote_session_id = session->peer_session_id; | ||||||
|  | + | ||||||
|  | +	addr->local_addr.sin_port = isk->inet_sport; | ||||||
|  | +	addr->remote_addr.sin_port = isk->inet_dport; | ||||||
|  | +	addr->local_addr.sin_addr.s_addr = isk->inet_saddr; | ||||||
|  | +	addr->remote_addr.sin_addr.s_addr = isk->inet_daddr; | ||||||
|  | + | ||||||
|  | +	sock_put(sk); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* pppol2tp_channel_addressing_get() */ | ||||||
|  | +int pppol2tp_channel_addressing_get(struct ppp_channel *chan, | ||||||
|  | +				    struct pppol2tp_common_addr *addr) | ||||||
|  | +{ | ||||||
|  | +	return pppol2tp_get_addressing(chan, addr); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pppol2tp_channel_addressing_get); | ||||||
|  | + | ||||||
|  |  /* Transmit function called by generic PPP driver.  Sends PPP frame | ||||||
|  |   * over PPPoL2TP socket. | ||||||
|  |   * | ||||||
|  | @@ -852,7 +891,7 @@ static int pppol2tp_connect(struct socke | ||||||
|  |  	po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | ||||||
|  |   | ||||||
|  |  	po->chan.private = sk; | ||||||
|  | -	po->chan.ops	 = &pppol2tp_chan_ops; | ||||||
|  | +	po->chan.ops	 = &pppol2tp_chan_ops.ops; | ||||||
|  |  	po->chan.mtu	 = pppol2tp_tunnel_mtu(tunnel); | ||||||
|  |   | ||||||
|  |  	error = ppp_register_net_channel(sock_net(sk), &po->chan); | ||||||
| @@ -0,0 +1,241 @@ | |||||||
|  | From 98f71e72955490c9a1dcdb0f290e4a874a92ae4e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: pavir <pavir@codeaurora.org> | ||||||
|  | Date: Mon, 26 Dec 2016 14:41:20 +0530 | ||||||
|  | Subject: [PATCH 308/500] net: l2tp: ppp_channel_proto_version API | ||||||
|  |  | ||||||
|  | New API added to retrieve channel version info | ||||||
|  |  | ||||||
|  | Change-Id: Ia4fd236c7cf6170a5034609e75de8c6e4ef79f7b | ||||||
|  | Signed-off-by: Shyam Sunder <ssunde@codeaurora.org> | ||||||
|  | Signed-off-by: pavir <pavir@codeaurora.org> | ||||||
|  |  | ||||||
|  | ppp: Fix ppp_connect_channel function's return value | ||||||
|  |  | ||||||
|  | The function should return 0 after all the successful | ||||||
|  | checks. The patch fixes failed PPPoE connections. | ||||||
|  |  | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Change-Id: I6c4755b0b158ca9bd75403e01cb3c0dda193e9e0 | ||||||
|  | Signed-off-by: Amruth S <quic_amrus@quicinc.com> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/ppp_generic.c | 61 +++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/netdevice.h     |  1 - | ||||||
|  |  include/linux/ppp_channel.h   |  9 ++++++ | ||||||
|  |  net/l2tp/l2tp_ppp.c           | 40 ++++++++++++++++++++++- | ||||||
|  |  4 files changed, 109 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/ppp_generic.c | ||||||
|  | +++ b/drivers/net/ppp/ppp_generic.c | ||||||
|  | @@ -48,6 +48,7 @@ | ||||||
|  |  #include <net/slhc_vj.h> | ||||||
|  |  #include <linux/atomic.h> | ||||||
|  |  #include <linux/refcount.h> | ||||||
|  | +#include <linux/if_pppox.h> | ||||||
|  |   | ||||||
|  |  #include <linux/nsproxy.h> | ||||||
|  |  #include <net/net_namespace.h> | ||||||
|  | @@ -3500,6 +3501,8 @@ ppp_connect_channel(struct channel *pch, | ||||||
|  |  	struct ppp_net *pn; | ||||||
|  |  	int ret = -ENXIO; | ||||||
|  |  	int hdrlen; | ||||||
|  | +	int ppp_proto; | ||||||
|  | +	int version; | ||||||
|  |  	int notify = 0; | ||||||
|  |   | ||||||
|  |  	pn = ppp_pernet(pch->chan_net); | ||||||
|  | @@ -3533,6 +3536,30 @@ ppp_connect_channel(struct channel *pch, | ||||||
|  |  	++ppp->n_channels; | ||||||
|  |  	pch->ppp = ppp; | ||||||
|  |  	refcount_inc(&ppp->file.refcnt); | ||||||
|  | + | ||||||
|  | +	ppp_proto = ppp_channel_get_protocol(pch->chan); | ||||||
|  | +	switch (ppp_proto) { | ||||||
|  | +	case PX_PROTO_OL2TP: | ||||||
|  | +		version = ppp_channel_get_proto_version(pch->chan); | ||||||
|  | +		switch (version) { | ||||||
|  | +		case 2: | ||||||
|  | +			ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV2; | ||||||
|  | +			break; | ||||||
|  | +		case 3: | ||||||
|  | +			ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV3; | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		break; | ||||||
|  | + | ||||||
|  | +	case PX_PROTO_PPTP: | ||||||
|  | +		ppp->dev->priv_flags_ext |= IFF_EXT_PPP_PPTP; | ||||||
|  | +		break; | ||||||
|  | + | ||||||
|  | +	default: | ||||||
|  | +		break; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	notify = 1; | ||||||
|  |   | ||||||
|  |  	ppp_unlock(ppp); | ||||||
|  | @@ -3783,6 +3810,18 @@ int ppp_channel_get_protocol(struct ppp_ | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(ppp_channel_get_protocol); | ||||||
|  |   | ||||||
|  | +/* ppp_channel_get_proto_version() | ||||||
|  | + *	Call this to get channel protocol version | ||||||
|  | + */ | ||||||
|  | +int ppp_channel_get_proto_version(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	if (!chan->ops->get_channel_protocol_ver) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	return chan->ops->get_channel_protocol_ver(chan); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_channel_get_proto_version); | ||||||
|  | + | ||||||
|  |  /* ppp_channel_hold() | ||||||
|  |   *	Call this to hold a channel. | ||||||
|  |   * | ||||||
|  | @@ -3936,6 +3975,28 @@ void ppp_release_channels(struct ppp_cha | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(ppp_release_channels); | ||||||
|  |   | ||||||
|  | +/* Check if ppp xmit lock is on hold */ | ||||||
|  | +bool ppp_is_xmit_locked(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ppp *ppp; | ||||||
|  | + | ||||||
|  | +	if (!dev) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	if (dev->type != ARPHRD_PPP) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	ppp = netdev_priv(dev); | ||||||
|  | +	if (!ppp) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	if (spin_is_locked(&(ppp)->wlock)) | ||||||
|  | +		return true; | ||||||
|  | + | ||||||
|  | +	return false; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(ppp_is_xmit_locked); | ||||||
|  | + | ||||||
|  |  /* Module/initialization stuff */ | ||||||
|  |   | ||||||
|  |  module_init(ppp_init); | ||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -2259,7 +2259,6 @@ struct net_device { | ||||||
|  |  	unsigned char		nested_level; | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | - | ||||||
|  |  	/* Protocol-specific pointers */ | ||||||
|  |   | ||||||
|  |  	struct in_device __rcu	*ip_ptr; | ||||||
|  | --- a/include/linux/ppp_channel.h | ||||||
|  | +++ b/include/linux/ppp_channel.h | ||||||
|  | @@ -44,6 +44,8 @@ struct ppp_channel_ops { | ||||||
|  |  	 * the channel subtype | ||||||
|  |  	 */ | ||||||
|  |  	int (*get_channel_protocol)(struct ppp_channel *); | ||||||
|  | +	/* Get channel protocol version */ | ||||||
|  | +	int (*get_channel_protocol_ver)(struct ppp_channel *); | ||||||
|  |  	/* Hold the channel from being destroyed */ | ||||||
|  |  	void (*hold)(struct ppp_channel *); | ||||||
|  |  	/* Release hold on the channel */ | ||||||
|  | @@ -67,6 +69,9 @@ struct ppp_channel { | ||||||
|  |   */ | ||||||
|  |  extern int ppp_channel_get_protocol(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | +/* Call this get protocol version */ | ||||||
|  | +extern int ppp_channel_get_proto_version(struct ppp_channel *); | ||||||
|  | + | ||||||
|  |  /* Call this to hold a channel */ | ||||||
|  |  extern bool ppp_channel_hold(struct ppp_channel *); | ||||||
|  |   | ||||||
|  | @@ -83,6 +88,10 @@ extern int ppp_hold_channels(struct net_ | ||||||
|  |  			     unsigned int chan_sz); | ||||||
|  |   | ||||||
|  |  bool ppp_is_cp_enabled(struct net_device *dev); | ||||||
|  | + | ||||||
|  | +/* Test if ppp xmit lock is locked */ | ||||||
|  | +extern bool ppp_is_xmit_locked(struct net_device *dev); | ||||||
|  | + | ||||||
|  |  /* Hold PPP channels for the PPP device */ | ||||||
|  |  extern int __ppp_hold_channels(struct net_device *dev, | ||||||
|  |  			       struct ppp_channel *channels[], | ||||||
|  | --- a/net/l2tp/l2tp_ppp.c | ||||||
|  | +++ b/net/l2tp/l2tp_ppp.c | ||||||
|  | @@ -92,6 +92,7 @@ | ||||||
|  |  #include <net/ip.h> | ||||||
|  |  #include <net/udp.h> | ||||||
|  |  #include <net/inet_common.h> | ||||||
|  | +#include <linux/if_pppox.h> | ||||||
|  |   | ||||||
|  |  #include <asm/byteorder.h> | ||||||
|  |  #include <linux/atomic.h> | ||||||
|  | @@ -124,11 +125,13 @@ struct pppol2tp_session { | ||||||
|  |   | ||||||
|  |  static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); | ||||||
|  |  static int pppol2tp_get_channel_protocol(struct ppp_channel *); | ||||||
|  | +static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *); | ||||||
|  |  static void pppol2tp_hold_chan(struct ppp_channel *); | ||||||
|  |  static void pppol2tp_release_chan(struct ppp_channel *); | ||||||
|  |  static const struct pppol2tp_channel_ops pppol2tp_chan_ops = { | ||||||
|  |  	.ops.start_xmit =  pppol2tp_xmit, | ||||||
|  |  	.ops.get_channel_protocol = pppol2tp_get_channel_protocol, | ||||||
|  | +	.ops.get_channel_protocol_ver = pppol2tp_get_channel_protocol_ver, | ||||||
|  |  	.ops.hold = pppol2tp_hold_chan, | ||||||
|  |  	.ops.release = pppol2tp_release_chan, | ||||||
|  |  }; | ||||||
|  | @@ -358,6 +361,40 @@ static int pppol2tp_get_channel_protocol | ||||||
|  |  	return PX_PROTO_OL2TP; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* pppol2tp_get_channel_protocol_ver() | ||||||
|  | + * Return the protocol version of the L2TP over PPP protocol | ||||||
|  | + */ | ||||||
|  | +static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *chan) | ||||||
|  | +{ | ||||||
|  | +	struct sock *sk; | ||||||
|  | +	struct l2tp_session *session; | ||||||
|  | +	struct l2tp_tunnel *tunnel; | ||||||
|  | +	int version = 0; | ||||||
|  | + | ||||||
|  | +	if (!(chan && chan->private)) { | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	sk = (struct sock *)chan->private; | ||||||
|  | + | ||||||
|  | +	/* Get session and tunnel contexts from the socket */ | ||||||
|  | +	session = pppol2tp_sock_to_session(sk); | ||||||
|  | +	if (!session) { | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	tunnel = session->tunnel; | ||||||
|  | +	if (!tunnel) { | ||||||
|  | +		sock_put(sk); | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	version = tunnel->version; | ||||||
|  | + | ||||||
|  | +	sock_put(sk); | ||||||
|  | +	return version; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* pppol2tp_get_addressing() */ | ||||||
|  |  static int pppol2tp_get_addressing(struct ppp_channel *chan, | ||||||
|  |  				   struct pppol2tp_common_addr *addr) | ||||||
|  | @@ -443,7 +480,8 @@ static int pppol2tp_xmit(struct ppp_chan | ||||||
|  |  	skb->data[0] = PPP_ALLSTATIONS; | ||||||
|  |  	skb->data[1] = PPP_UI; | ||||||
|  |  	/* set incoming interface as the ppp interface */ | ||||||
|  | -	if (skb->skb_iif) | ||||||
|  | +	if ((skb->protocol == htons(ETH_P_IP)) || | ||||||
|  | +	    (skb->protocol == htons(ETH_P_IPV6))) | ||||||
|  |  		skb->skb_iif = ppp_dev_index(chan); | ||||||
|  |   | ||||||
|  |  	local_bh_disable(); | ||||||
| @@ -0,0 +1,254 @@ | |||||||
|  | From 8b2fc28f1a1280663d30466c788ae80774fa1f29 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | Date: Fri, 24 Apr 2020 11:00:19 -0700 | ||||||
|  | Subject: [PATCH 303/500] inet: pptp: Enable offload mode for PPTP GRE sequence | ||||||
|  |  number handling | ||||||
|  |  | ||||||
|  | Changes in this patch will allow all PPTP Data and LCP packets | ||||||
|  | to go via packet acceleration hardware. The hardware will take | ||||||
|  | care of Seq/Ack numbers update. | ||||||
|  |  | ||||||
|  | Change-Id: Ia5cd7893d9fda180174f78c3468279678422794d | ||||||
|  | Signed-off-by: Shyam Sunder <ssunde@codeaurora.org> | ||||||
|  | Signed-off-by: Murat Sezgin <msezgin@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ppp/pptp.c   | 136 +++++++++++++++++++++++++++++++++++++-- | ||||||
|  |  include/linux/if_pppox.h |  21 ++++++ | ||||||
|  |  2 files changed, 153 insertions(+), 4 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ppp/pptp.c | ||||||
|  | +++ b/drivers/net/ppp/pptp.c | ||||||
|  | @@ -50,6 +50,8 @@ static struct proto pptp_sk_proto __read | ||||||
|  |  static const struct ppp_channel_ops pptp_chan_ops; | ||||||
|  |  static const struct proto_ops pptp_ops; | ||||||
|  |   | ||||||
|  | +static pptp_gre_seq_offload_callback_t __rcu pptp_gre_offload_xmit_cb; | ||||||
|  | + | ||||||
|  |  static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) | ||||||
|  |  { | ||||||
|  |  	struct pppox_sock *sock; | ||||||
|  | @@ -116,6 +118,28 @@ static int lookup_session_dst(struct ppt | ||||||
|  |  	return -EINVAL; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* If offload mode set then this function sends all packets to | ||||||
|  | + * offload module instead of network stack | ||||||
|  | + */ | ||||||
|  | +static int pptp_client_skb_xmit(struct sk_buff *skb, | ||||||
|  | +				struct net_device *pptp_dev) | ||||||
|  | +{ | ||||||
|  | +	pptp_gre_seq_offload_callback_t pptp_gre_offload_cb_f; | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | +	pptp_gre_offload_cb_f = rcu_dereference(pptp_gre_offload_xmit_cb); | ||||||
|  | + | ||||||
|  | +	if (!pptp_gre_offload_cb_f) { | ||||||
|  | +		rcu_read_unlock(); | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = pptp_gre_offload_cb_f(skb, pptp_dev); | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int add_chan(struct pppox_sock *sock, | ||||||
|  |  		    struct pptp_addr *sa) | ||||||
|  |  { | ||||||
|  | @@ -188,8 +212,11 @@ static int pptp_xmit(struct ppp_channel | ||||||
|  |   | ||||||
|  |  	struct rtable *rt; | ||||||
|  |  	struct net_device *tdev; | ||||||
|  | +	struct net_device *pptp_dev; | ||||||
|  |  	struct iphdr  *iph; | ||||||
|  |  	int    max_headroom; | ||||||
|  | +	int    pptp_ifindex; | ||||||
|  | +	int ret; | ||||||
|  |   | ||||||
|  |  	if (sk_pppox(po)->sk_state & PPPOX_DEAD) | ||||||
|  |  		goto tx_error; | ||||||
|  | @@ -283,14 +310,33 @@ static int pptp_xmit(struct ppp_channel | ||||||
|  |  	ip_select_ident(net, skb, NULL); | ||||||
|  |  	ip_send_check(iph); | ||||||
|  |   | ||||||
|  | +	pptp_ifindex = ppp_dev_index(chan); | ||||||
|  | + | ||||||
|  |  	/* set incoming interface as the ppp interface */ | ||||||
|  |  	if (skb->skb_iif) | ||||||
|  | -		skb->skb_iif = ppp_dev_index(chan); | ||||||
|  | +		skb->skb_iif = pptp_ifindex; | ||||||
|  |   | ||||||
|  | -	ip_local_out(net, skb->sk, skb); | ||||||
|  | +	/* If the PPTP GRE seq number offload module is not enabled yet | ||||||
|  | +	 * then sends all PPTP GRE packets through linux network stack | ||||||
|  | +	 */ | ||||||
|  | +	if (!opt->pptp_offload_mode) { | ||||||
|  | +		ip_local_out(net, skb->sk, skb); | ||||||
|  | +		return 1; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -	return 1; | ||||||
|  | +	pptp_dev = dev_get_by_index(&init_net, pptp_ifindex); | ||||||
|  | +	if (!pptp_dev) | ||||||
|  | +		goto tx_error; | ||||||
|  |   | ||||||
|  | +	 /* If PPTP offload module is enabled then forward all PPTP GRE | ||||||
|  | +	  * packets to PPTP GRE offload module | ||||||
|  | +	  */ | ||||||
|  | +	ret = pptp_client_skb_xmit(skb, pptp_dev); | ||||||
|  | +	dev_put(pptp_dev); | ||||||
|  | +	if (ret < 0) | ||||||
|  | +		goto tx_error; | ||||||
|  | + | ||||||
|  | +	return 1; | ||||||
|  |  tx_error: | ||||||
|  |  	kfree_skb(skb); | ||||||
|  |  	return 1; | ||||||
|  | @@ -344,6 +390,13 @@ static int pptp_rcv_core(struct sock *sk | ||||||
|  |  		goto drop; | ||||||
|  |   | ||||||
|  |  	payload = skb->data + headersize; | ||||||
|  | + | ||||||
|  | +	 /* If offload is enabled, we expect the offload module | ||||||
|  | +	  * to handle PPTP GRE sequence number checks | ||||||
|  | +	  */ | ||||||
|  | +	if (opt->pptp_offload_mode) | ||||||
|  | +		goto allow_packet; | ||||||
|  | + | ||||||
|  |  	/* check for expected sequence number */ | ||||||
|  |  	if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) { | ||||||
|  |  		if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) && | ||||||
|  | @@ -504,7 +557,7 @@ static int pptp_connect(struct socket *s | ||||||
|  |   | ||||||
|  |  	opt->dst_addr = sp->sa_addr.pptp; | ||||||
|  |  	sk->sk_state |= PPPOX_CONNECTED; | ||||||
|  | - | ||||||
|  | +	opt->pptp_offload_mode = false; | ||||||
|  |   end: | ||||||
|  |  	release_sock(sk); | ||||||
|  |  	return error; | ||||||
|  | @@ -678,6 +731,81 @@ int pptp_session_find(struct pptp_opt *o | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(pptp_session_find); | ||||||
|  |   | ||||||
|  | + /* Function to change the offload mode true/false for a PPTP session */ | ||||||
|  | +static int pptp_set_offload_mode(bool accel_mode, | ||||||
|  | +				 __be16 peer_call_id, __be32 peer_ip_addr) | ||||||
|  | +{ | ||||||
|  | +	struct pppox_sock *sock; | ||||||
|  | +	int i = 1; | ||||||
|  | + | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | +	for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) { | ||||||
|  | +		sock = rcu_dereference(callid_sock[i]); | ||||||
|  | +		if (!sock) | ||||||
|  | +			continue; | ||||||
|  | + | ||||||
|  | +		if (sock->proto.pptp.dst_addr.call_id == peer_call_id && | ||||||
|  | +		    sock->proto.pptp.dst_addr.sin_addr.s_addr == peer_ip_addr) { | ||||||
|  | +			sock_hold(sk_pppox(sock)); | ||||||
|  | +			sock->proto.pptp.pptp_offload_mode = accel_mode; | ||||||
|  | +			sock_put(sk_pppox(sock)); | ||||||
|  | +			rcu_read_unlock(); | ||||||
|  | +			return 0; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  | +	return -EINVAL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* Enable the PPTP session offload flag */ | ||||||
|  | +int pptp_session_enable_offload_mode(__be16 peer_call_id, __be32 peer_ip_addr) | ||||||
|  | +{ | ||||||
|  | +	return pptp_set_offload_mode(true, peer_call_id, peer_ip_addr); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_session_enable_offload_mode); | ||||||
|  | + | ||||||
|  | +/* Disable the PPTP session offload flag */ | ||||||
|  | +int pptp_session_disable_offload_mode(__be16 peer_call_id, __be32 peer_ip_addr) | ||||||
|  | +{ | ||||||
|  | +	return pptp_set_offload_mode(false, peer_call_id, peer_ip_addr); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_session_disable_offload_mode); | ||||||
|  | + | ||||||
|  | +/* Register the offload callback function on behalf of the module which | ||||||
|  | + * will own the sequence and acknowledgment number updates for all | ||||||
|  | + * PPTP GRE packets. All PPTP GRE packets are then transmitted to this | ||||||
|  | + * module after encapsulation in order to ensure the correct seq/ack | ||||||
|  | + * fields are set in the packets before transmission. This is required | ||||||
|  | + * when PPTP flows are offloaded to acceleration engines, in-order to | ||||||
|  | + * ensure consistency in sequence and ack numbers between PPTP control | ||||||
|  | + * (PPP LCP) and data packets | ||||||
|  | + */ | ||||||
|  | +int pptp_register_gre_seq_offload_callback(pptp_gre_seq_offload_callback_t | ||||||
|  | +					   pptp_gre_offload_cb) | ||||||
|  | +{ | ||||||
|  | +	pptp_gre_seq_offload_callback_t pptp_gre_offload_cb_f; | ||||||
|  | + | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | +	pptp_gre_offload_cb_f = rcu_dereference(pptp_gre_offload_xmit_cb); | ||||||
|  | + | ||||||
|  | +	if (pptp_gre_offload_cb_f) { | ||||||
|  | +		rcu_read_unlock(); | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	rcu_assign_pointer(pptp_gre_offload_xmit_cb, pptp_gre_offload_cb); | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_register_gre_seq_offload_callback); | ||||||
|  | + | ||||||
|  | +/* Unregister the PPTP GRE packets sequence number offload callback */ | ||||||
|  | +void pptp_unregister_gre_seq_offload_callback(void) | ||||||
|  | +{ | ||||||
|  | +	rcu_assign_pointer(pptp_gre_offload_xmit_cb, NULL); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(pptp_unregister_gre_seq_offload_callback); | ||||||
|  | + | ||||||
|  |  /* pptp_hold_chan() */ | ||||||
|  |  static void pptp_hold_chan(struct ppp_channel *chan) | ||||||
|  |  { | ||||||
|  | --- a/include/linux/if_pppox.h | ||||||
|  | +++ b/include/linux/if_pppox.h | ||||||
|  | @@ -37,6 +37,7 @@ struct pptp_opt { | ||||||
|  |  	u32 ack_sent, ack_recv; | ||||||
|  |  	u32 seq_sent, seq_recv; | ||||||
|  |  	int ppp_flags; | ||||||
|  | +	bool pptp_offload_mode; | ||||||
|  |  }; | ||||||
|  |  #include <net/sock.h> | ||||||
|  |   | ||||||
|  | @@ -101,6 +102,10 @@ struct pppoe_channel_ops { | ||||||
|  |  	int (*get_addressing)(struct ppp_channel *, struct pppoe_opt *); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/* PPTP client callback */ | ||||||
|  | +typedef int (*pptp_gre_seq_offload_callback_t)(struct sk_buff *skb, | ||||||
|  | +					       struct net_device *pptp_dev); | ||||||
|  | + | ||||||
|  |  /* Return PPPoE channel specific addressing information */ | ||||||
|  |  extern int pppoe_channel_addressing_get(struct ppp_channel *chan, | ||||||
|  |  					 struct pppoe_opt *addressing); | ||||||
|  | @@ -113,4 +118,20 @@ extern int pptp_session_find(struct pptp | ||||||
|  |  extern void pptp_channel_addressing_get(struct pptp_opt *opt, | ||||||
|  |  					struct ppp_channel *chan); | ||||||
|  |   | ||||||
|  | +/* Enable the PPTP session offload flag */ | ||||||
|  | +extern int pptp_session_enable_offload_mode(__be16 peer_call_id, | ||||||
|  | +					    __be32 peer_ip_addr); | ||||||
|  | + | ||||||
|  | +/* Disable the PPTP session offload flag */ | ||||||
|  | +extern int pptp_session_disable_offload_mode(__be16 peer_call_id, | ||||||
|  | +					     __be32 peer_ip_addr); | ||||||
|  | + | ||||||
|  | +/* Register the PPTP GRE packets sequence number offload callback */ | ||||||
|  | +extern int | ||||||
|  | +pptp_register_gre_seq_offload_callback(pptp_gre_seq_offload_callback_t | ||||||
|  | +				       pptp_client_cb); | ||||||
|  | + | ||||||
|  | +/* Unregister the PPTP GRE packets sequence number offload callback */ | ||||||
|  | +extern void pptp_unregister_gre_seq_offload_callback(void); | ||||||
|  | + | ||||||
|  |  #endif /* !(__LINUX_IF_PPPOX_H) */ | ||||||
		Reference in New Issue
	
	Block a user
	 Lucas Asvio
					Lucas Asvio