blob: a0632af88d8b6c4b3318ba87f17a04a356171d02 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Common code for low-level network console, dump, and debugger code
3 *
4 * Derived from netconsole, kgdb-over-ethernet, and netdump patches
5 */
6
7#ifndef _LINUX_NETPOLL_H
8#define _LINUX_NETPOLL_H
9
10#include <linux/netdevice.h>
11#include <linux/interrupt.h>
Matt Mackall53fb95d2005-08-11 19:27:43 -070012#include <linux/rcupdate.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/list.h>
14
Cong Wangb7394d22013-01-07 20:52:39 +000015union inet_addr {
16 __u32 all[4];
17 __be32 ip;
18 __be32 ip6[4];
19 struct in_addr in;
20 struct in6_addr in6;
21};
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023struct netpoll {
24 struct net_device *dev;
Stephen Hemmingerbf6bce72006-10-26 15:46:56 -070025 char dev_name[IFNAMSIZ];
26 const char *name;
Stephen Hemminger5de4a472006-10-26 15:46:55 -070027
Cong Wangb7394d22013-01-07 20:52:39 +000028 union inet_addr local_ip, remote_ip;
29 bool ipv6;
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 u16 local_port, remote_port;
Stephen Hemminger09538642007-11-19 19:23:29 -080031 u8 remote_mac[ETH_ALEN];
Daniel Borkmann508e14b2010-01-12 14:27:30 +000032
Neil Horman2cde6ac2013-02-11 10:25:30 +000033 struct work_struct cleanup_work;
Eric W. Biedermane1bd4d32014-03-14 20:50:58 -070034
35#ifdef CONFIG_NETPOLL_TRAP
36 void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb,
37 int offset, int len);
38 struct list_head rx; /* rx_np list element */
39#endif
Jeff Moyer115c1d62005-06-22 22:05:31 -070040};
41
42struct netpoll_info {
Stephen Hemminger93ec2c72006-10-26 15:46:50 -070043 atomic_t refcnt;
Daniel Borkmann508e14b2010-01-12 14:27:30 +000044
Neil Hormanbd7c4b62013-04-30 05:35:05 +000045 struct semaphore dev_lock;
Daniel Borkmann508e14b2010-01-12 14:27:30 +000046
Stephen Hemmingerb6cd27e2006-10-26 15:46:51 -070047 struct sk_buff_head txq;
Daniel Borkmann508e14b2010-01-12 14:27:30 +000048
David Howells6d5aefb2006-12-05 19:36:26 +000049 struct delayed_work tx_work;
WANG Cong0e34e932010-05-06 00:47:21 -070050
51 struct netpoll *netpoll;
Amerigo Wang38e6bc12012-08-10 01:24:38 +000052 struct rcu_head rcu;
Eric W. Biedermane1bd4d32014-03-14 20:50:58 -070053
54#ifdef CONFIG_NETPOLL_TRAP
55 spinlock_t rx_lock;
56 struct list_head rx_np; /* netpolls that registered an rx_skb_hook */
57 struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */
58#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070059};
60
Neil Hormanca99ca12013-02-05 08:05:43 +000061#ifdef CONFIG_NETPOLL
dingtianhongda6e3782013-05-27 19:53:31 +000062extern void netpoll_rx_disable(struct net_device *dev);
Neil Hormanca99ca12013-02-05 08:05:43 +000063extern void netpoll_rx_enable(struct net_device *dev);
64#else
dingtianhongda6e3782013-05-27 19:53:31 +000065static inline void netpoll_rx_disable(struct net_device *dev) { return; }
Neil Hormanca99ca12013-02-05 08:05:43 +000066static inline void netpoll_rx_enable(struct net_device *dev) { return; }
67#endif
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
Satyam Sharma0bcc1812007-08-10 15:35:05 -070070void netpoll_print_options(struct netpoll *np);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071int netpoll_parse_options(struct netpoll *np, char *opt);
Amerigo Wang47be03a22012-08-10 01:24:37 +000072int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073int netpoll_setup(struct netpoll *np);
Herbert Xu8fdd95e2010-06-10 16:12:48 +000074void __netpoll_cleanup(struct netpoll *np);
Neil Horman2cde6ac2013-02-11 10:25:30 +000075void __netpoll_free_async(struct netpoll *np);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076void netpoll_cleanup(struct netpoll *np);
Neil Hormanc2355e12010-10-13 16:01:49 +000077void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
78 struct net_device *dev);
79static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
80{
Amerigo Wang28996562012-08-10 01:24:42 +000081 unsigned long flags;
82 local_irq_save(flags);
Neil Hormanc2355e12010-10-13 16:01:49 +000083 netpoll_send_skb_on_dev(np, skb, np->dev);
Amerigo Wang28996562012-08-10 01:24:42 +000084 local_irq_restore(flags);
Neil Hormanc2355e12010-10-13 16:01:49 +000085}
86
Eric W. Biedermanff607632014-03-14 20:47:49 -070087#ifdef CONFIG_NETPOLL_TRAP
Eric W. Biedermanad8d4752014-03-14 20:49:43 -070088int netpoll_trap(void);
89void netpoll_set_trap(int trap);
Eric W. Biedermane1bd4d32014-03-14 20:50:58 -070090int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo);
Eric W. Biedermanff607632014-03-14 20:47:49 -070091static inline bool netpoll_rx_processing(struct netpoll_info *npinfo)
92{
93 return !list_empty(&npinfo->rx_np);
94}
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Amerigo Wang77ab8a52012-08-10 01:24:46 +000096static inline bool netpoll_rx_on(struct sk_buff *skb)
Amerigo Wang91fe4a42012-08-10 01:24:41 +000097{
98 struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo);
99
Eric W. Biedermanb6bacd52014-03-14 20:48:28 -0700100 return npinfo && netpoll_rx_processing(npinfo);
Amerigo Wang91fe4a42012-08-10 01:24:41 +0000101}
102
David S. Millerffb27362010-05-06 01:20:10 -0700103static inline bool netpoll_rx(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104{
Herbert Xude85d992010-06-10 16:12:44 +0000105 struct netpoll_info *npinfo;
Jeff Moyerfbeec2e2005-06-22 22:05:59 -0700106 unsigned long flags;
David S. Millerffb27362010-05-06 01:20:10 -0700107 bool ret = false;
Jeff Moyer115c1d62005-06-22 22:05:31 -0700108
Herbert Xuf0f9dea2010-09-17 16:55:03 -0700109 local_irq_save(flags);
Herbert Xude85d992010-06-10 16:12:44 +0000110
Amerigo Wang91fe4a42012-08-10 01:24:41 +0000111 if (!netpoll_rx_on(skb))
Herbert Xude85d992010-06-10 16:12:44 +0000112 goto out;
Jeff Moyer115c1d62005-06-22 22:05:31 -0700113
Amerigo Wang91fe4a42012-08-10 01:24:41 +0000114 npinfo = rcu_dereference_bh(skb->dev->npinfo);
Herbert Xuf0f9dea2010-09-17 16:55:03 -0700115 spin_lock(&npinfo->rx_lock);
Eric W. Biedermanff607632014-03-14 20:47:49 -0700116 /* check rx_processing again with the lock held */
117 if (netpoll_rx_processing(npinfo) && __netpoll_rx(skb, npinfo))
David S. Millerffb27362010-05-06 01:20:10 -0700118 ret = true;
Herbert Xuf0f9dea2010-09-17 16:55:03 -0700119 spin_unlock(&npinfo->rx_lock);
Jeff Moyerfbeec2e2005-06-22 22:05:59 -0700120
Herbert Xude85d992010-06-10 16:12:44 +0000121out:
Herbert Xuf0f9dea2010-09-17 16:55:03 -0700122 local_irq_restore(flags);
Jeff Moyerfbeec2e2005-06-22 22:05:59 -0700123 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124}
125
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700126static inline int netpoll_receive_skb(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700128 if (!list_empty(&skb->dev->napi_list))
129 return netpoll_rx(skb);
130 return 0;
131}
132
Eric W. Biedermane1bd4d32014-03-14 20:50:58 -0700133#else
134static inline int netpoll_trap(void)
135{
136 return 0;
137}
138static inline void netpoll_set_trap(int trap)
139{
140}
141static inline bool netpoll_rx_processing(struct netpoll_info *npinfo)
142{
143 return false;
144}
145static inline bool netpoll_rx(struct sk_buff *skb)
146{
147 return false;
148}
149static inline bool netpoll_rx_on(struct sk_buff *skb)
150{
151 return false;
152}
153static inline int netpoll_receive_skb(struct sk_buff *skb)
154{
155 return 0;
156}
157#endif
158
159#ifdef CONFIG_NETPOLL
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700160static inline void *netpoll_poll_lock(struct napi_struct *napi)
161{
162 struct net_device *dev = napi->dev;
163
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700164 if (dev && dev->npinfo) {
165 spin_lock(&napi->poll_lock);
166 napi->poll_owner = smp_processor_id();
167 return napi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 }
Matt Mackall53fb95d2005-08-11 19:27:43 -0700169 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170}
171
Matt Mackall53fb95d2005-08-11 19:27:43 -0700172static inline void netpoll_poll_unlock(void *have)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700174 struct napi_struct *napi = have;
Matt Mackall53fb95d2005-08-11 19:27:43 -0700175
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700176 if (napi) {
177 napi->poll_owner = -1;
178 spin_unlock(&napi->poll_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 }
180}
181
Amerigo Wang77ab8a52012-08-10 01:24:46 +0000182static inline bool netpoll_tx_running(struct net_device *dev)
Herbert Xuc18370f2010-06-10 16:12:49 +0000183{
184 return irqs_disabled();
185}
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187#else
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700188static inline void *netpoll_poll_lock(struct napi_struct *napi)
189{
190 return NULL;
191}
192static inline void netpoll_poll_unlock(void *have)
193{
194}
195static inline void netpoll_netdev_init(struct net_device *dev)
196{
197}
Amerigo Wang77ab8a52012-08-10 01:24:46 +0000198static inline bool netpoll_tx_running(struct net_device *dev)
Herbert Xuc18370f2010-06-10 16:12:49 +0000199{
Amerigo Wang77ab8a52012-08-10 01:24:46 +0000200 return false;
Herbert Xuc18370f2010-06-10 16:12:49 +0000201}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#endif
203
204#endif