> On 4 Dec 2015, at 06:44, Alexandr Nedvedicky <[email protected]>
> wrote:
>
> Hello,
>
> below is final patch I'm going to commit. Summary of changes:
> - softnettq declaration moved to net/if_var.h (by bluhm@)
> - lock order swapped: KERNEL_LOCK() goes first folllowed
> by spl (by bluhm@)
> - long line got fixed (by bluhm@)
> - ip_insertoptions() prototype deleted in ip_output.c (by bluhm@)
> - avoiding mix of tab/space at netinet6/ip6_var.h (by bluhm@)
> - static at ip*_send_dispatch() got removed (by mpi@)
> - ip*_send_dispatch() functions look more like if_input_process()
> now (by mpi@)
it might be better to add the task to systq instead of &softnettq. if you're
always going to take the kernel lock to send packets then any pending
ip_input_process work will end implicitly waiting for the kernel lock too.
ideally only mpsafe work should be pushed into the softnettq.
systq already runs with the kernel lock, so you wouldnt have to take it again
in your task either.
dlg
>
> thanks and
> regards
> sasha
>
> --------8<---------------8<---------------8<------------------8<--------
>
> Index: net/if_var.h
> ===================================================================
> RCS file: /cvs/src/sys/net/if_var.h,v
> retrieving revision 1.62
> diff -u -p -r1.62 if_var.h
> --- net/if_var.h 3 Dec 2015 16:27:32 -0000 1.62
> +++ net/if_var.h 3 Dec 2015 20:43:46 -0000
> @@ -361,6 +361,7 @@ int niq_enlist(struct niqueue *, struct
>
> extern struct ifnet_head ifnet;
> extern unsigned int lo0ifidx;
> +extern struct taskq *softnettq;
>
> void if_start(struct ifnet *);
> void if_start_barrier(struct ifnet *);
> Index: net/pf.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pf.c,v
> retrieving revision 1.956
> diff -u -p -r1.956 pf.c
> --- net/pf.c 3 Dec 2015 14:05:28 -0000 1.956
> +++ net/pf.c 3 Dec 2015 20:43:47 -0000
> @@ -2424,11 +2424,11 @@ pf_send_tcp(const struct pf_rule *r, sa_
>
> switch (af) {
> case AF_INET:
> - ip_output(m, NULL, NULL, 0, NULL, NULL, 0);
> + ip_send(m);
> break;
> #ifdef INET6
> case AF_INET6:
> - ip6_output(m, NULL, NULL, 0, NULL, NULL);
> + ip6_send(m);
> break;
> #endif /* INET6 */
> }
> Index: netinet/ip_icmp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
> retrieving revision 1.149
> diff -u -p -r1.149 ip_icmp.c
> --- netinet/ip_icmp.c 2 Dec 2015 16:35:53 -0000 1.149
> +++ netinet/ip_icmp.c 3 Dec 2015 20:43:47 -0000
> @@ -854,7 +854,10 @@ icmp_send(struct mbuf *m, struct mbuf *o
> printf("icmp_send dst %s src %s\n", dst, src);
> }
> #endif
> - ip_output(m, opts, NULL, 0, NULL, NULL, 0);
> + if (opts != NULL)
> + m = ip_insertoptions(m, opts, &hlen);
> +
> + ip_send(m);
> }
>
> u_int32_t
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.264
> diff -u -p -r1.264 ip_input.c
> --- netinet/ip_input.c 3 Dec 2015 15:12:59 -0000 1.264
> +++ netinet/ip_input.c 3 Dec 2015 20:43:47 -0000
> @@ -44,6 +44,7 @@
> #include <sys/socketvar.h>
> #include <sys/sysctl.h>
> #include <sys/pool.h>
> +#include <sys/task.h>
>
> #include <net/if.h>
> #include <net/if_var.h>
> @@ -121,6 +122,8 @@ struct pool ipq_pool;
>
> struct ipstat ipstat;
>
> +static struct mbuf_queue ipsend_mq;
> +
> void ip_ours(struct mbuf *);
> int ip_dooptions(struct mbuf *, struct ifnet *);
> int in_ouraddr(struct mbuf *, struct ifnet *, struct in_addr);
> @@ -130,6 +133,8 @@ int ip_input_ipsec_fwd_check(struct mbuf
> int ip_input_ipsec_ours_check(struct mbuf *, int);
> #endif /* IPSEC */
>
> +static void ip_send_dispatch(void *);
> +static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch,
> &ipsend_mq);
> /*
> * Used to save the IP options in case a protocol wants to respond
> * to an incoming packet over the same route if the packet got here
> @@ -188,6 +193,8 @@ ip_init(void)
> strlcpy(ipsec_def_enc, IPSEC_DEFAULT_DEF_ENC, sizeof(ipsec_def_enc));
> strlcpy(ipsec_def_auth, IPSEC_DEFAULT_DEF_AUTH, sizeof(ipsec_def_auth));
> strlcpy(ipsec_def_comp, IPSEC_DEFAULT_DEF_COMP, sizeof(ipsec_def_comp));
> +
> + mq_init(&ipsend_mq, 64, IPL_SOFTNET);
> }
>
> struct route ipforward_rt;
> @@ -1752,3 +1759,27 @@ ip_savecontrol(struct inpcb *inp, struct
> }
> }
>
> +void
> +ip_send_dispatch(void *xmq)
> +{
> + struct mbuf_queue *mq = xmq;
> + struct mbuf *m;
> + struct mbuf_list ml;
> + int s;
> +
> + mq_delist(mq, &ml);
> + KERNEL_LOCK();
> + s = splsoftnet();
> + while ((m = ml_dequeue(&ml)) != NULL) {
> + ip_output(m, NULL, NULL, 0, NULL, NULL, 0);
> + }
> + splx(s);
> + KERNEL_UNLOCK();
> +}
> +
> +void
> +ip_send(struct mbuf *m)
> +{
> + mq_enqueue(&ipsend_mq, m);
> + task_add(softnettq, &ipsend_task);
> +}
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.60
> diff -u -p -r1.60 ip_var.h
> --- netinet/ip_var.h 16 Jul 2015 21:14:21 -0000 1.60
> +++ netinet/ip_var.h 3 Dec 2015 20:43:47 -0000
> @@ -180,6 +180,8 @@ void ip_freef(struct ipq *);
> void ip_freemoptions(struct ip_moptions *);
> int ip_getmoptions(int, struct ip_moptions *, struct mbuf **);
> void ip_init(void);
> +struct mbuf*
> + ip_insertoptions(struct mbuf *, struct mbuf *, int *);
> int ip_mforward(struct mbuf *, struct ifnet *);
> int ip_optcopy(struct ip *, struct ip *);
> int ip_output(struct mbuf *, struct mbuf *, struct route *, int,
> @@ -191,6 +193,7 @@ struct in_ifaddr *
> ip_rtaddr(struct in_addr, u_int);
> u_int16_t
> ip_randomid(void);
> +void ip_send(struct mbuf *);
> int ip_setmoptions(int, struct ip_moptions **, struct mbuf *, u_int);
> void ip_slowtimo(void);
> struct mbuf *
> @@ -207,5 +210,6 @@ void rip_input(struct mbuf *, ...);
> int rip_output(struct mbuf *, ...);
> int rip_usrreq(struct socket *,
> int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
> +
> #endif /* _KERNEL */
> #endif /* _NETINET_IP_VAR_H_ */
> Index: netinet6/icmp6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/icmp6.c,v
> retrieving revision 1.181
> diff -u -p -r1.181 icmp6.c
> --- netinet6/icmp6.c 2 Dec 2015 16:35:53 -0000 1.181
> +++ netinet6/icmp6.c 3 Dec 2015 20:43:47 -0000
> @@ -1302,7 +1302,7 @@ icmp6_reflect(struct mbuf *m, size_t off
> #if NPF > 0
> pf_pkt_addr_changed(m);
> #endif
> - ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL);
> + ip6_send(m);
> return;
>
> bad:
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.151
> diff -u -p -r1.151 ip6_input.c
> --- netinet6/ip6_input.c 11 Nov 2015 10:23:23 -0000 1.151
> +++ netinet6/ip6_input.c 3 Dec 2015 20:43:47 -0000
> @@ -77,6 +77,7 @@
> #include <sys/timeout.h>
> #include <sys/kernel.h>
> #include <sys/syslog.h>
> +#include <sys/task.h>
>
> #include <net/if.h>
> #include <net/if_var.h>
> @@ -89,6 +90,7 @@
> #include <netinet/ip.h>
>
> #include <netinet/in_pcb.h>
> +#include <netinet/ip_var.h>
> #include <netinet6/in6_var.h>
> #include <netinet/ip6.h>
> #include <netinet6/ip6_var.h>
> @@ -123,6 +125,12 @@ int ip6_check_rh0hdr(struct mbuf *, int
> int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
> struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
>
> +static struct mbuf_queue ip6send_mq;
> +
> +static void ip6_send_dispatch(void *);
> +static struct task ip6send_task =
> + TASK_INITIALIZER(ip6_send_dispatch, &ip6send_mq);
> +
> /*
> * IP6 initialization: fill in IP6 protocol switch table.
> * All protocols not implemented in kernel go to raw IP6 protocol handler.
> @@ -149,6 +157,8 @@ ip6_init(void)
> nd6_init();
> frag6_init();
> ip6_init2((void *)0);
> +
> + mq_init(&ip6send_mq, 64, IPL_SOFTNET);
> }
>
> void
> @@ -1430,4 +1440,29 @@ ip6_sysctl(int *name, u_int namelen, voi
> return (EOPNOTSUPP);
> }
> /* NOTREACHED */
> +}
> +
> +void
> +ip6_send_dispatch(void *xmq)
> +{
> + struct mbuf_queue *mq = xmq;
> + struct mbuf *m;
> + struct mbuf_list ml;
> + int s;
> +
> + mq_delist(mq, &ml);
> + KERNEL_LOCK();
> + s = splsoftnet();
> + while ((m = ml_dequeue(&ml)) != NULL) {
> + ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL);
> + }
> + splx(s);
> + KERNEL_UNLOCK();
> +}
> +
> +void
> +ip6_send(struct mbuf *m)
> +{
> + mq_enqueue(&ip6send_mq, m);
> + task_add(softnettq, &ip6send_task);
> }
> Index: netinet6/ip6_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
> retrieving revision 1.56
> diff -u -p -r1.56 ip6_var.h
> --- netinet6/ip6_var.h 25 Oct 2015 14:43:06 -0000 1.56
> +++ netinet6/ip6_var.h 3 Dec 2015 20:43:47 -0000
> @@ -275,6 +275,7 @@ int ip6_setpktopts(struct mbuf *, struct
> void ip6_clearpktopts(struct ip6_pktopts *, int);
> void ip6_randomid_init(void);
> u_int32_t ip6_randomid(void);
> +void ip6_send(struct mbuf *);
>
> int route6_input(struct mbuf **, int *, int);
>
>